“触动人心的设计”的方法研究

By heiry on 2017-10-17 [ in 设计 ]

原文作者: 阿里 B2B_UED团队

原文标题:《“触动人心的设计”方法初步探究》

————————————————————————————-

用户体验设计的精髓,在于恰到好处的设计出最合适的用户场景体验,而这种体验是不知不觉给予用户同时能让用户在触点的那个瞬间怦然心动,那如何让用户心动呢?

古人云:“动人心者,莫先乎情。”,同样的我们从约翰.奈斯比特的语言中窥见:”无论何处都需要高补偿的情感,社会中高技术的越多,我们就越渴望高情感的环境,用设计软性的一面来平衡技术硬的一面。设计作为人的创造性活动,不是摒除激情或者情感,而是要创造一种中性的、能容纳和激起使用者情感的东西,这种东西是一种境界。”

因此,我们1688UED在2014年组建了人文情怀课题研究小组专门来探讨如何进行“触动人心的设计”,课题研究的范围从马斯诺需求到各种效应理论以及设计心理学,大家在浩瀚的知识学说中徜徉,并不断碰撞产生了各种的灵感火花,最后得到了一个关于“DesignO2O”的设计思路以及“CORE”的方法模型,同时找到了如何验证我们“触动人心的设计”是否有效方法。

DesignO2O这个思路是由课题小组不离同学提出的也是我们整个设计方法的理论基石。(见下图)

人的大脑是个超级存储器,总是通过五感接受信息,被大脑识记,并且保存在记忆当中,五感由于我们是从事互联网设计行业,都是偏电脑页面的一些设计,所以主要能发挥的是视觉和听觉,线下某些实物的工业设计还会有嗅觉,味觉,触觉等等。图中的“识记-保存-重现”是人类记忆的主要过程,重现包括回忆和再认两个环节,我们这里提到的主要是指回忆,是在一定诱因的作用下,过去经历的事物在头脑中的再现过程。拥有记忆的人通过看见了一些事物或者听见了某些信息,和大脑保存的过去进行了重合配对,唤醒了记忆,那些画面会被重现,在这个过程中你的大脑已经不知不觉中招了、被刺激了,重现的画面在你的脑海里久久不能离去,以至于让你做出一些意想不到的事,就是我们说的情绪行为,以我们自身为例,影响的就是购买决策,在我们的平台上就有一群这样的用户,人称“月光族,剁手党”…所以我们发现对于一个完全没有记忆的人来说,其实是很难触动情感的。通过大量的案例收集和讨论给这样的方式在设计中的运用总结为“DESIGNO2O”,offline2online,就是刚才所说的过程,这个过程转化为设计就是把线下的场景或者人物或者事件等等还原到我们的设计中,公式就是要简单好记,才能被广泛引用,这也是O2O业务模式的设计延伸,也同样印证了一句哲学思想:everything is connected。万事万物都是互相联系的。 (更多…)

>> 阅读全文  >>

超大流量网站PHP到Node 的迁移

By heiry on 2017-10-15 [ in 技术 ]

转自:http://taobaofed.org/blog/2016/06/02/thing-about-taobao-homepage/

作者:淘宝前端团队阎王       原题《聊一聊淘宝首页和它背后的一套》

 

一、相关背景介绍

 

淘宝首页是淘宝的门面,承载着几乎淘系所有业务的入口,流量很大,量级单位为亿。近几年无线端崛起,业务重点开始向无线终端偏移(目前不能叫偏移,基本以无线为主了),所以淘宝 PC 端首页的流量也有削减,不过即便如此,它的日均 PV 依然相当高。

淘宝首页一向是内部平台和技术的试验田,它一直在变化着。最新的框架和系统都会找淘宝首页试点,可以试想下,如果某一项需要推动的升级或者优化措施在淘宝首页已经上线,并且拿到了良好的数据和稳定性,其他业务还有什么理由不去尝试和更迭呢?同时,去年一年身在淘宝前端的技术架构组,自然而然也会主动去 push 一些实验性的内容到业务上。

淘系的站点页面包括首页、其他频道页和活动页等,这些页面并不都由淘宝前端一行一行的代码码出来,业务如此之多,这种玩法即便人数 double 也忙不过来。事实上,大多数页面都是依托内部的搭建平台——运营或者前端通过模块搭建的方式——构建的,而前端 focus 的重点在于搭建平台的建设自身以及模块的通用性和复用率的保障,当然,还有一些工程化的东西。

使用搭建平台搭建的页面,前端只需要考虑组成页面的原子模块的开发,整体的渲染由搭建平台提供的统一脚本全权负责。而在淘宝首页上,考虑到页面模块数量巨多,加上还有少量跨部门、跨团队的沟通,渲染模型略微不同。

二、淘宝首页的整体变迁

背景中提到,淘宝首页依托于内部搭建平台,它的变迁自然也是跟着搭建系统的变化而变化的。

1. PHP 下的淘宝首页

接手淘宝首页不久,便遇到了一年一度的改版,那时它还运行在 PHP 环境中。这里需要说明的是,淘宝首页的所有代码完全由前端掌控,前端不会直接跟数据库打交道,其数据来源分为两部分。

数据来源

一是 运营填写的数据。 采用前端挖坑的形式,预留坑位让运营获取填写数据,如(伪代码):

  
<?php $info = Person('name:String:姓名,age:Number:年龄', '个人信息坑位填写');?>

<div>
<?php $info.forEach(index) { ?>
  Name: <?= info[index].name ?>, Age: <?= info[index].age ?>
<?php } ?>
</div>

(更多…)

>> 阅读全文  >>

设计中的视觉误差

By heiry on 2017-10-15 [ in 设计 ]

转自:http://www.shejidaren.com/ui-shi-jie-wu-cha.html

1. 物理尺寸与视觉尺寸

长宽 400px 的正方形与长宽 400px 的圆形哪一个更大?假如这样问你的话,那么正确答案当然是一样大。但是来看看下面这张图,长宽各 400px 的两个图形看起来并不一样大。你的眼睛告诉你 400px 的正方形比 400px 的圆形更大一些。物体的物理尺寸是一样的,但视觉尺寸却有可能不一样的。

为了更加准确地证明这个现象的存在,下面这张图给出辅助线,大家好好看看。

我们改变一下圆形的尺寸,看看现在这两个图形的视觉尺寸有没有更接近一些?

每个人的感官可能都不一样,但对于我来说,调整尺寸的后的两个图形看起来才是一样大的,至少也不会像图一一样,让人第一眼就认为正方形比较大。为啥会这样?因为我将圆的直径增加了 50px。

现在我们将图形都叠起来看,看看为什么会产生这种那么明显的误差。400px 的两个图形叠在一起,你会发现整个圆形都被包裹在了正方形之内,而正方形多出的四个面积巨大的 a 区域就是造成这种视觉误差的原因。再将 400px 的正方形与 450px 的圆形叠在一起,正方形无法将整个圆形包裹在内了,圆形超出的四个 b 区域又与 正方形多出来的 a 区域在视觉上互相抵消,所以 450px 的圆形与 400px 的正方形在视觉尺寸上更接近,也就是我们常说的“一样大”。

不仅是圆与方,所有的图形都能够造成这样的偏差。当我们追求“看起来一样大”这个目标的时候,某些形状的物理尺寸应该更大一些。

这个现象对于界面造成的设计会有哪一些呢?譬如说,当绘制一套 icon 的时候,我们当然是追求每个 icon 都看起来一样大对吧?但假如我们只通过物理尺寸来进行量度的画,画出来的 icon 必然会个大个小,乌七八糟,更伤的是,这种问题经常发生,手机里随便打开个 app 都能发现这样的问题。
(更多…)

>> 阅读全文  >>

Android开发之parseInclude方法分析

By heiry on 2017-10-12 [ in 技术 ]
// 参数说明:
// parser      解析布局的解析器
// context     当前加载布局的上下文对象
// parent      父容器
// attrs       属性集合(XML该节点的属性集合)
private void parseInclude(XmlPullParser parser, Context context, View parent,
           AttributeSet attrs) throws XmlPullParserException, IOException {
       int type;

       // 判断 Include标签是否在 ViewGroup容器之内,因为 include 标签只能存在于 ViewGroup 容器之内。

       if (parent instanceof ViewGroup) {

           //------------------&lt;第一部分&gt;-------------------//

           //当开发者设置 include 主题属性时,可以覆盖被 include 包裹View的主题属性。
           //但是这种操作很少会使用。
           //所以如果被包裹 View 设置主题属性,我们在设置就会出现覆盖效果。
           //以 include 标签的主题属性为最终的主题属性

           //提取出 include 的 thme 属性,如果设置了 them 属性,那么include 包裹的View 设置的 theme 将会无效
           final TypedArray ta = context.obtainStyledAttributes(attrs, ATTRS_THEME);
           final int themeResId = ta.getResourceId(0, 0);
           final boolean hasThemeOverride = themeResId != 0;
           if (hasThemeOverride) {
               context = new ContextThemeWrapper(context, themeResId);
           }
           ta.recycle();


           //------------------&lt;第二部分&gt;-------------------//

           //如果这个属性是指向主题中的某个属性,我们必须设法得到主题中layout 的资源标识符
           //先获取 layout 属性(资源 id)是否设置
           int layout = attrs.getAttributeResourceValue(null, ATTR_LAYOUT, 0);
           if (layout == 0) {
           //如果没直接设置布局的资源 id,那么就检索?attr/name这一类的 layout 属性
               final String value = attrs.getAttributeValue(null, ATTR_LAYOUT);
               if (value == null || value.length() &lt;= 0) {
                   throw new InflateException("You must specify a layout in the"
                           + " include tag: ");
               }

               //从  ?attr/name 这一类的属性中,获取布局属性  
               layout = context.getResources().getIdentifier(value.substring(1), null, null);
           }

           //这个布局资源也许存在主题属性中,所以需要去主题属性中解析
           if (mTempValue == null) {
               mTempValue = new TypedValue();
           }
           if (layout != 0 &amp;&amp; context.getTheme().resolveAttribute(layout, mTempValue, true)) {
               layout = mTempValue.resourceId;
           }


           //------------------&lt;第三部分&gt;-------------------//

           if (layout == 0) {
               final String value = attrs.getAttributeValue(null, ATTR_LAYOUT);
               throw new InflateException("You must specify a valid layout "
                       + "reference. The layout ID " + value + " is not valid.");
           } else {
               final XmlResourceParser childParser = context.getResources().getLayout(layout);

               try {
                   final AttributeSet childAttrs = Xml.asAttributeSet(childParser);

                   while ((type = childParser.next()) != XmlPullParser.START_TAG &amp;&amp;
                           type != XmlPullParser.END_DOCUMENT) {
                       // Empty.
                   }

                   if (type != XmlPullParser.START_TAG) {
                       throw new InflateException(childParser.getPositionDescription() +
                               ": No start tag found!");
                   }

                   final String childName = childParser.getName();

                   if (TAG_MERGE.equals(childName)) {
                       //解析 Meger 标签
                       rInflate(childParser, parent, context, childAttrs, false);
                   } else {
                       //根据 name名称来创建View
                       final View view = createViewFromTag(parent, childName,
                               context, childAttrs, hasThemeOverride);
                       final ViewGroup group = (ViewGroup) parent;


                       //获取 View 的 id 和其 Visiable 属性
                       final TypedArray a = context.obtainStyledAttributes(
                               attrs, R.styleable.Include);
                       final int id = a.getResourceId(R.styleable.Include_id, View.NO_ID);
                       final int visibility = a.getInt(R.styleable.Include_visibility, -1);
                       a.recycle();

                       //需要将 Parent中的 LayoutParams 设置为其 Params 属性。
                       //如果 Parent 没有通用的 Params,那么就会抛出Runtime 异常

                       //然后会为其设置 include 包裹内容的通用 Params,

                       ViewGroup.LayoutParams params = null;
                       try {
                           params = group.generateLayoutParams(attrs);
                       } catch (RuntimeException e) {
                           // Ignore, just fail over to child attrs.
                       }
                       if (params == null) {
                           params = group.generateLayoutParams(childAttrs);
                       }
                       view.setLayoutParams(params);

                       // 解析子标签
                       rInflateChildren(childParser, view, childAttrs, true);

                       if (id != View.NO_ID) {
                           view.setId(id);
                       }

                       // 加载include内容时,需要直接设置其 可见性
                       switch (visibility) {
                           case 0:
                               view.setVisibility(View.VISIBLE);
                               break;
                           case 1:
                               view.setVisibility(View.INVISIBLE);
                               break;
                           case 2:
                               view.setVisibility(View.GONE);
                               break;
                       }
                       //添加至父容器中
                       group.addView(view);
                   }
               } finally {
                   childParser.close();
               }
           }
       } else {
           throw new InflateException(" can only be used inside of a ViewGroup");
       }

       LayoutInflater.consumeChildElements(parser);
   }

 

>> 阅读全文  >>

锵锵四人行

By heiry on 2017-10-06 [ in 生活 ]

人生总有起落,生活总需要面对,有时候我们需要一些激情。

 

 

 

>> 阅读全文  >>

登恒山

By heiry on 2017-10-06 [ in 生活 ]

感觉恒山是五岳中最差的一个,不过山顶的蓝天白云还是很不错的

 

>> 阅读全文  >>

新项目开发计划顺利通过

By heiry on 2017-10-06 [ in 技术 ]

项目开发计划顺利通过审核,进入实施阶段

>> 阅读全文  >>


© 2009-2021 MOSANG.NET DESIGNED BY HEIRY