拟物设计和Angular的实现 - Material Design(持续更新)
Material Design是Google最新发布的跨平台统一视觉设计语言。直接翻译是物质设计,但是我更倾向于使用"拟物设计"更为准确。
据谷歌介绍,Material Design基于“真实的触感,灵感源自对纸和墨水的研究,” 能够让用户 “理解那些用于替代真实世界的可视线索,”“而又不违背力学原理。”另外,光线、表面和移动的基本原理是表现对象如何移动、交互和相互关联地存在于空间中的关键。逼真的光影效果可以显示区块间的接缝、划分空间、以及标识移动的部件。
Material Design在动画、风格和布局方面提出了一系列的原则,并且为大量的视觉组件,包括按钮、卡片、网格和对话框等,以及相关的动作和手势提供了建议,另外还包含了一些与可访问性有关的指引。
原理
拟物就隐喻
拟物是对空间和动作的一致整体的模拟。拟物系统的设计基于触摸感,得力于纸墨原理,借力高科技, 最终为我们打开了一道想象之门。
系统正交分解
- 组件 - UI Component (Directives, Services, ARIA)
- 布局 - Layout CSS (FlexBox, Attribute, Child Aligment)
- 风格 - Theme (Color Palettes)
拟物的世界
3D世界
拟物的世界是3D世界,每个物体都有X, Y, Z三个方向的坐标。其中,Z是垂直于屏幕的轴,每一层在Z方向上都有标准的1dp厚度。
光和影
拟物的世界还引入了虚拟光源,而实际上我们是看不到这个光源的,我们看到是这个光源在物体上留下的影子。
拟物世界仅仅引入了两种光源,所有的物体的影子都是由这两种光源照射的结果。
主光
主光源在物体上留下的是单方向的影子。
散光
散光源在物体上留下的是多方向均匀而一致的模糊影子。
两种光源同时照射
物质的特性
物质一些内在的特性和行为,理解这些特性可以帮助我们更好理解拟物设计。
物理特性
- 我们的物质可以有不同的长度和宽度(X轴和Y轴的度量),但是厚度是统一的(1dp),而且厚度永远不为0。
- 物质的阴影总是来源于它的相对(其它元素)高度 (Z轴的度量)
- 显示在物质上的内容不受物质本身的限制,可以是任何形状,任何颜色。
- 内容的行为与物质的行为是解耦的,但是物质的边界仍然能够限制内容的显示。
- 物质是实体,任何操作时间不能透过最上层物质应用到被挡住的下一层去。
- 多个物质元素不能在空间中占据同一个点,他们是互斥的。
- 一个物质元素不能穿过其他物质元素。
布局
Angular Material的 响应式CSS布局是基于flexbox实现的。整个布局体系是用元素的属性来标示,而不用CSS类。这也是正交设计的一个体现:属性来定义布局,类定义风格。
例子:使用layout
属性来定义内部元素的布局,横向排列(layout="row"
)或者竖向排列 (layout="column"
)
<div layout="row">
<div>I'm left.</div>
<div>I'm right.</div>
</div>
<div layout="column">
<div>I'm above.</div>
<div>I'm below.</div>
</div>
手势
iPhone的出现让手势操作大为流行,也使得手势编程成为开发人员的挑战。 拟物设计也把手势编程纳入在内,大概也想制定一个在交互模型标准。现阶段因为MD还在预发布阶段,因此还只实现了单点手势(一个指头),可是已经有足够的东西值得学习,无论对我们应用还是自己设计手势编程都是大有裨益。
MD有两个手划控件mdSwipeLeft
和mdSwipeRight
,然而真正的代码支持却不在这两个控件的定义中,而是在核心代码中,文件位置src\core\services\gesture\gesture.js
。
基本屏幕事件
做过界面的人都熟悉mousedown, mouseup, mousemove
等事件,很多后台函数多与这些事件绑定,从而能够与用户交互。但是这些事件都有些单薄而僵硬,手势事件却更友好和人性化,这也是其大受欢迎的根本原因。
手势事件不是空中楼阁,它们本身是需要这些基本事件的支持,这些基本屏幕事件也就成为了手势模型的一个组成部分,成为最底的一层。
这些事件首先被划分为三类,说是三类,理解成三个事件更为恰当,它们与手指与屏幕的交互一一对应:开始事件就是手指按下屏幕;移动事件就是手指在屏幕移动;结束事件就是手指离开屏幕。非常简单而直观。
从下面MD对这三类事件的定义,我们也可以看到每类事件中的变体大都与设备的不同有关而不是真正的不同事件,如鼠标的按下,和手指的按下。这也是我上面说的把它们理解为三个事件更为恰当。
- START_EVENTS =>'mousedown touchstart pointerdown';
- MOVE_EVENTS => 'mousemove touchmove pointermove';
- END_EVENTS => 'mouseup mouseleave touchend touchcancel pointerup pointercancel';
手势归纳
基本事件都是瞬间事件,不存在延时和逻辑判断,按下就是按下,松开就是松开;这也是称之为基本事件的原因。
而手势却恰恰相反,
- 手势是综合事件,如滑动手势,直观的感觉就是手指按下快速向左(右)滑动,并同时松开手指,这整个过程完成才是一个滑动手势。
- 手势还有逻辑判断,还是滑动手势,不仅仅要在以上的全过程之后才激发,手指的还要超过一定的速度才能算是滑动手势。
因此,可以把手势看作在基本事件之上的一个封装,在MD的实现也是用GestureHandler的函数还侦听基本事件然后作出综合处理。
侦听
这里是MD绑定基本事件的代码:
angular.element(document)
.on(START_EVENTS, gestureStart)
.on(MOVE_EVENTS, gestureMove)
.on(END_EVENTS, gestureEnd)
MD移动事件的侦听处理函数:
function gestureMove(ev) {
if (!pointer || !typesMatch(ev, pointer)) return;
updatePointerState(ev, pointer);
runHandlers('move', ev);
}
其它两个(开始和结束事件)都与此类似,只不过有更多的处理过程。这个因为简单,可以用来好好分析关键过程。我们可以看到,这个侦听函数的关键一步就是调用处理器(runHandler
)。这个函数内部并不复杂,只是简单的遍历预存处理器,然后调用该处理器定义的对应的基本事件处理器。这个处理器就是手势处理器,它会分析归纳基本事件当条件满足时触发手势事件。
手势处理器$$MdGestureHandler
MD用工厂(factory
)的方式定义了手势处理器的模板(或者可以理解为基类帮助理解),这个factory名称就是$$MdGestureHandler,为了便于理解,我们把它分解成三部分来看。
基本屏幕事件处理
第一部分:4个方法,分别与三类基本屏幕事件对应(cancel是辅助方法),也是用来分别处理三类屏幕事件的,上面的runHandler
就是调用的源头。
start: function(ev, pointer) {
if (this.state.isRunning) return;
var parentTarget = this.getNearestParent(ev.target);
var parentTargetOptions = parentTarget && parentTarget.$mdGesture[this.name] || {};
this.state = {
isRunning: true,
options: angular.extend({}, this.options, parentTargetOptions),
registeredParent: parentTarget
};
this.onStart(ev, pointer);
},
move: function(ev, pointer) {
if (!this.state.isRunning) return;
this.onMove(ev, pointer);
},
end: function(ev, pointer) {
if (!this.state.isRunning) return;
this.onEnd(ev, pointer);
this.state.isRunning = false;
},
cancel: function(ev, pointer) {
this.onCancel(ev, pointer);
this.state = {};
},
优化的屏幕事件
第二部分:4个内部事件,也是基本与以上4个方法对应,并在4个方法中适当的时机触发,可以看作是对原始基本事件的梳理之后的重新抛出。 你如果创建自己的手势处理器,要做的也就是重载这4个事件。从以下代码我们也可以看到,MD为每一个事件给出了空实现(`angular.noop'),目的就是为了让自定义处理器自己重载实现。
onStart: angular.noop,
onMove: angular.noop,
onEnd: angular.noop,
onCancel: angular.noop,
手势的触发
第三部分:也是最后最关键的一个方法,手势事件的触发dispatchEvent
。自定义的手势处理器最终都是要调用这个方法来触发手势事件。大部分触发时机都在onEnd
中,当是不是必须的,要根据你具体的手势的含义来定。
dispatchEvent的实现:
dispatchEvent: dispatchEvent,
...
/*
* NOTE: dispatchEvent is very performance sensitive.
*/
function dispatchEvent(srcEvent, eventType, eventPointer, /*original DOMEvent */ev) {
eventPointer = eventPointer || pointer;
var eventObj;
if (eventType === 'click') {
eventObj = document.createEvent('MouseEvents');
eventObj.initMouseEvent(
'click', true, true, window, ev.detail,
ev.screenX, ev.screenY, ev.clientX, ev.clientY,
ev.ctrlKey, ev.altKey, ev.shiftKey, ev.metaKey,
ev.button, ev.relatedTarget || null
);
} else {
eventObj = document.createEvent('CustomEvent');
eventObj.initCustomEvent(eventType, true, true, {});
}
eventObj.$material = true;
eventObj.pointer = eventPointer;
eventObj.srcEvent = srcEvent;
eventPointer.target.dispatchEvent(eventObj);
}
手势实例解析
手势内部实现过程虽然较为复杂,以上的流程解析也是为了更好的理解从而有个直观的感觉。到了每一个手势的实现时,真正用到的却不算多,主要就是那4个优化的事件onStart, onMove, onEnd, onCancel
和一个触发的方法'dispatchEvent`。我们来看看一些手势实例,亲身感受一下,良好建模以后的手势实现。
滑动手势 - Swipe
屏幕事件 | 触发条件 | 触发事件 |
---|---|---|
[无] | ||
按下 | ||
移动 | ||
移动 | ||
移动 | ||
移动 | ||
松开 | 超过最低速度和位移 | $md.swiperight |
[无] |
拖动手势 - Drag
屏幕事件 | 触发条件 | 触发事件 |
---|---|---|
[无] | ||
按下 | ||
移动 | ||
移动 | 当前触点与起点位移超过阀值 | $md.dragstart |
移动 | $md.drag | |
移动 | $md.drag | |
松开 | $md.dragend | |
[无] |
[AngularJS的实现] (https://material.angularjs.org )
拟物设计和Angular的实现 - Material Design(持续更新)的更多相关文章
- 拟物设计和Angular的实现 - Material Design
Material Design是Google最新发布的跨平台统一视觉设计语言.直接翻译是物质设计,但是我更倾向于使用"拟物设计"更为准确. 据谷歌介绍,Material Desig ...
- 经典信息图表:2013 扁平设计 VS 拟物设计
inTacto 是一家互动数字公司,由 Alejandro Lazos 和 Sebastian Caramés 成立于2001年.他们刚刚发布一个信息图表:<平面设计 VS 现实主义>.这 ...
- 从拟物化到扁平,再到Material Design
Google I/O 2014提出Material Design,这段时间听到不少关于Material Design的解读,至此Google已经定位了自己的设计语言,我个人看来就是Android和iO ...
- ANDROID L——Material Design综合应用(Demo)
转载请注明本文出自大苞米的博客(http://blog.csdn.net/a396901990),谢谢支持! Material Design: Material Design是Google推出的一个全 ...
- Android群英传笔记——第十二章:Android5.X 新特性详解,Material Design UI的新体验
Android群英传笔记--第十二章:Android5.X 新特性详解,Material Design UI的新体验 第十一章为什么不写,因为我很早之前就已经写过了,有需要的可以去看 Android高 ...
- Material Design Lite,简洁惊艳的前端工具箱。
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,博客地址为http://www.cnblogs.com/jasonnode/ .网站上有对应每一 ...
- Jquery之家5个顶级Material Design框架
谷歌Material Design在如今的前端页面设计中非常流行.Material Design的设计风格向我们展示了一个简单而有内涵的现代UI设计方案. Material Design是如此的简洁美 ...
- 聊聊 Material Design 里,阴影的那些事儿!
当你的设计师要求你在某个 View 上增加阴影效果,那你只需要认真阅读本文,阴影的问题就不再是问题. 一.前言 设计师的世界,与常人不同,有时候想要扁平化的风格,有时候又想要拟物化的风格.而在 Mat ...
- Material Design风格的水波涟漪效果(Ripple Effect)的实现
Material Design是Google在2014年Google I/O大会上推出的一套全新的设计语言,经过接近两年的发展,可谓是以燎原之势影响着整个设计交互生态,和Material Design ...
随机推荐
- 【Django】Django model与数据库操作对应关系(转)
Django对数据库的操作分用到三个类:Manager.QuerySet.Model. Manager的主要功能定义表级方法(表级方法就是影响一条或多条记录的方法),我们可以以models.Manag ...
- __future__
[__future__] __future__用于改变python特性. 参考:http://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb4 ...
- Rstudio代码的快捷键
按tab键:有自动补全的功能 Ctrl+Enter:运行改行代码 Ctrl+1: 移动焦点到source编辑区 Ctrl+2: 移动焦点到控制台 Ctrl+enter Ctrl+L:删除该控制台的所有 ...
- Android Studio鼠标悬停显示注释
Android Studio鼠标悬停显示注释 在AS中配置 如果你想从网上查看注释,到这一步就操作完成. 下面说明让软件使用本地注释: 使用本地注释 以Windows为例: 找到下面文件 C:\Use ...
- Visual Studio VS2010统计代码行数(转载)
本文转自:http://blog.csdn.net/zhouworld16/article/details/9292851 在网上看到别人用的方法: 按CTRL+SHIFT+F (Find in fi ...
- HttpClient请求网络数据的Post请求
new Thread(){ public void run() { try { //获得输入框内容 ...
- C# 从excel里面复制的1万6千多条记录粘贴到FCKeditor里面,点保存的时候,保存不了,页面没有反应
客户那边添加公告,是直接从excel里面复制的,有1万6千多条记录,excel文件有6M多. 编辑器用的FCKeditor,也能粘贴上,就是点保存的时候,执行了一段时间就没有反映了,保存不了. 想着可 ...
- sessionFactory
SessionFactory接口:SessionFactory接口负责初始化Hibernate.它充当数据存储源的代理,并负责创建Session对象.这里用到了工厂模式.需要注意的是SessionFa ...
- 剑指offer题目61-67
面试题61:把二叉树打印成多行 public class Solution { public ArrayList<ArrayList<Integer> > Print(Tree ...
- eclipse里面设置JVM参数的问题
在run----run configuration---Agruments里面设置JVM的参数: -Xms256m -Xmx1024m 肯定还有别的方式设置,今天就先写这一种方法.待续...