在这之前我得先提及一本书──《简约至上:交互式设计四策略》。这本书基本算得上是交互设计的入门必读书籍了,非常适合身处项目环节中上游的人员阅读与学习。
作者 Giles Colborne 在书中提出了四个令交互设计成果最大化的简易策略:合理删除、分层组织、适时隐藏和巧妙转移。这四个策略几乎成为我设计与优化每一个页面时的自我指导方针。
我参阅了大量的应用,想总结出它们是如何运用导航栏来给产品赋能的。竟然很巧地发现,再花式的导航栏设计也难逃「四策略」手法。
首先,导航栏作为一个独立控件,它本身就已经是「分层组织」策略的一种表现形式。接下来我们来看看,优秀的产品设计是如何运用另外三种策略来设计好导航栏的。
导航栏不能轻易删除,但凡事没有绝对。什么时候我们可以合理地删除导航栏呢?
Nike Run Club(下文简称NRC)是耐克官方出品的一款跑步记录 APP。既然做产品要站在用户角度出发,那我们就来复原一下主要功能的用户使用场景。
当你的老板要求你一天出 150 个界面设计的时候,你怕了,准备跑路,同时又不想浪费一天中任何一次记录运动的机会。于是你打开 NRC,你的目的很明确:认真地跑路,并记录运动。
点击「开始」按钮,当你一旦开始跑步,手机基本就不再使用了,直到跑步结束。
△ NRC在运动状态下的界面删除了导航栏
在用户记录跑步这样一个单一事件中,NRC 知道你会专注运动,很少存在关注其他功能、浏览其他页面的可能性。于是 NRC 可以很干脆地删掉导航栏,而返回按钮用了界面中的「结束」按钮代替。
滴滴出行在呼叫快车时也做了删除导航栏的处理。用户一旦发单,开始呼叫司机时,呼叫页面内的所有操作都只聚集在界面下方的一个视觉区域内。
△ 滴滴出行在呼叫过程中删除了导航栏
上面两个删除导航栏的示例有什么共通点呢?
第一,用户在当前页面的事件状态明确,不需要导航标题提醒用户当前在什么位置,用户也极少可能在当前页面发生其他事件操作,于是完全可以去除导航标题与内容控件。
第二,虽然删除了返回按钮,但都采用了很典型的「费茨定律」,就算用户误操作,也能便捷地撤销正在发生的事件。反而这比循规蹈矩地运用导航栏来承载返回按钮合理了许多。
△ 费茨定律简易图解
既然导航栏内所有的规范元素都有可取代方案,为什么不删除它呢?正如 Giles Colborne 在书中告诉我们的:大胆地删除,但也不要极端到盲目删除。
隐藏和删除看起来十分相似,但其实不然。我们如何区分这两个技巧呢?
隐藏最常见的情况是,当导航栏的出现会成为打扰用户沉浸体验的障碍时,我们会选择隐藏,例如看视频、浏览图片等显示全屏媒体的场景,有导航栏反而会分散用户的注意力。
△ 显示全屏媒体时需要隐藏导航栏
不知道你有没有发现到一个细节,在大多数情况下,需要沉浸体验的页面不但会隐藏导航栏,同时也会隐藏状态栏,导航栏中载有当前页面的标题、导航按钮和内容控件;状态栏中会载有时间、Wi-Fi 等系统设备信息。
iOS 在人机交互指南中提醒我们,显示全屏媒体时,请考虑暂时隐藏状态栏,但请避免永久隐藏。如果没有状态栏,当用户需要查看时间或其他设备信息时必须离开应用。设计师应该让用户可以使用简单的手势重新显示隐藏的状态栏。
△ 用户可以方便地查看时间或其他设备信息
另一种情况是当前页面非常注重一屏内容展现时,我们会隐藏导航栏。
京东在用户搜索了商品之后,头部有三个信息栏,非常冗长。分别是:
△ 京东搜索商品后屏幕头部的信息栏
用户在搜索了商品之后,向上滑动页面,京东会隐藏导航栏和全局筛选栏。
一是因为用户搜索关键词后,滑动页面大概率表示已经开始在挑选商品,这时候可以大胆地猜测用户行为,认为搜索与排序的重要级下降了,搜索结果垂直内容筛选的重要级上升了,便可以只保留下重要的操作。
二是可以让内容区域高度增加,隐藏顶部两个栏目区域可以大致增加一个商品位的提前露出,增大了商品触达用户的可能性。这不就是 UI 设计为商业目标赋能的一个案例吗?
△ 隐藏导航栏,增加了屏幕利用率
基于导航栏层级始终高于页面内容的特性,随着用户划出第一屏,许多 APP 做了重要内容或重要控件转移到导航栏的设计。
豆瓣在影评讨论区,用户上滑页面时,会将当前影片的信息转移到导航栏。其实这种转移很常见,许多内容社区 APP 都有这样的交互设计,比如浏览的公众号文章,再回到顶部试试。方便用户时刻知道自己当前所浏览的内容是关于哪一个主题的。这一类转移是单纯站在用户体验角度的考量。
△ 豆瓣在屏幕滚动后转移影片信息到导航栏
但如果你仔细观察,有一类转移却是综合了用户体验与产品目标的共同抉择。如果你再稍微了解一点该产品背后的故事,甚至可以让你洞悉到,为了巩固产品的调性和目标,PM 和 UI 们在页面设计时做了多少细枝末节的引导。
知乎在用户浏览当前问题时向上滑动页面,也会像豆瓣一样,将当前问题标题转移到导航栏上,但与此同时会将「写回答」的操作也转移到导航栏。标题转移是出于用户体验,和大多数内容社区的做法大同小异;而「写回答」的按钮转移,正符合知乎想要打造一个内容交流社区的产品调性,他们希望刺激用户进行问答互动,多输出 UGC 内容,希望用「写回答」的按钮转移进一步激发用户创作内容的可能性。
△ 知乎转移「写回答」让用户更方便地进行问答互动
京东在店铺首页上滑页面时,会将「关注」按钮转移到导航栏,方便用户在浏览的过程中可以随时收藏店铺,增加了用户对品牌店铺的关注度和复购的可能性。京东靠自营模式发家,近几年来开始慢慢重视 B2C 市场,在这个小小的关注按钮上,是不是可以算略显端倪呢?虽然我不能非常肯定,可能提高用户收藏操作只是为了辅助京东更好地进行营销权重划分,不过「关注」按钮的转移,确实能为 B2C 业务的渗透提供一份助力。
△ 京东转移「关注」让用户更方便地收藏店铺
所以我这里说到的「转移」的目的,其实和 Giles Colborne 在书中讲到的并不十分一致,Giles Colborne 是希望设计师将当前页面低频、冗杂的操作转移到另一个页面中去,而我提到的「转移」反而是产品越注重什么功能,越可以利用导航栏层级的先天优势来实现转移。
合理删除、分层组织、适时隐藏和巧妙转移已经是我做设计和分析界面常用的一个手法,它并不一定是万能的,但是它多多少少可以辅助我们做出更合理的设计。
这篇文章想要告诉大家的是,在平台规范里的导航栏是死板又相对静态的,但在四个策略的辅助下,结合用户的操作手势,也可以将它变得十分灵活,帮助页面实现更好的用户体验。不要被规范限制的太死,转换设计师的角色变成用户,你可以研究出更多好玩的操作。随便打开一个应用,去研究研究,你可能会乐在其中的。
文章来源:优设 作者:UCD耍家
知名的免费图标网站 Iconfinder 要和大家一起对抗新冠病毒,和图标设计师联手推出一系列「防疫免费图标集」(Coronavirus awareness icons),超过 200 个与公共卫生、病毒传播相关图标,这些图案包括常见的 PNG 和 SVG 格式,可以将它们加入标志、海报、传单或类似的内容使用。
如果你想要制作广告牌,提醒在这个区域要洗手或戴口罩,这里有免费图标可让信息更容易被阅读。
依照 Iconfinder 网站说明,这些图标可用于洗手说明、卫生建议或是其他预防病毒传染散播的提醒信息,所有图标采用 Creative Commons BY-SA 3.0 授权释出,使用时需要标示出处,并以相同方式分享。
网站链接:https://www.iconfinder.com/p/coronavirus-awareness-icons
值得一试的三个理由:
前往 Iconfider 的「Coronavirus awareness icons」网站,就能看到这套专为对抗新冠病毒提供的免费图标集,点选 Download all icons 下载打包好的完整图标。
在网站中展示一些收录在这套图标集的防疫相关图案,每套图案都有不同风格,例如以单纯线条为主的设计,或是采用平面化设计的彩色图标,可以依照自己的需求选择。当然你也可以按下右上角的按钮前往 Iconfinder 找到这套图标的完整版本。
下载后就能取得完整的图标集,依照不同名称分类,有些是 SVG 格式,有些则包括 SVG 和不同大小的 PNG 文件,其中有个 iconfider_freebies.zip 在解压缩后还能取得一些和防疫相关的图标。
值得一试的三个理由:
文章来源:优设 作者:Pseric
Persona,在国内通常被称为「用户画像」,其概念最初由 Alan Cooper 在 1999 年提出。由于用户画像具备帮助人们在设计过程中聚焦于目标用户的需求,促进团队中不同利益相关者的沟通等作用,而逐渐成为被广泛使用的经典设计工具。也正是由于其经典地位,我们往往对用户画像在各类设计场景中的出现习以为常,却很少去对这一工具进行反思。本文将基于用户画像的研究现状,对其存在的问题与局限进行综述和归纳。
Matthews 等学者为了探究设计师以及经验丰富的用户体验专家对用户画像的实际看法,从北美一家科技公司招募了 14 名设计师作为参与者。值得一提的是,这家公司拥有庞大且富有影响力的设计团队,另外这 14 名参与者中,在设计领域有 10 年以上工作经验的人数过半。通过访谈的方式,Matthews 发现,大多数参与者在实际工作中都不会使用到用户画像,并分析了为何不用的 4 类原因。我将 Matthews 等原文中的 4 类原因归纳为以下 3 条。(下文中出现的 D1、M3、B1 等序号是参与者的编号)
1. 太过抽象
D1:如果你只向他们(指开发团队)展示用户画像,他们是不会相信的。只有当他们看到用户画像背后有足够的数据支撑,他们才可能相信。
其实,不止是设计师有这样的看法,Basecamp(原37signals)的创始人 Jason Fried 在他的一篇博文里曾这样说:它们(指用户画像)是模拟的、抽象的、虚构的,我不认为你能为一个压根不存在的人创造出优秀的产品。
2. 缺少人情味
M3:我认为,有很多细节和微妙之处是无法通过对用户画像的描述而传达的,我也不认为有人能像用户画像那样思考或行事。坦白地说,我一直对用户画像以及它的用途充满怀疑,我觉得它更像一个沟通工具。
缺少人情味的另一点在于:用户画像太过理想化。
B1:他们(指用户画像)描述了最为完美的用户(对所设计的系统有着超乎寻常的热情),以及最为匹配的情节。而真实的用户并不像这样,因此,用户画像并没有很多作用。
3. 属性无用,甚至有误导作用
我们知道,一个用户画像在被创建的过程中,往往会被赋予若干个属性,常见的基本属性包括:年龄、职业、居住地等等。在访谈中,有些参与者表示,那些被赋予在用户画像身上的属性没什么用处。
A1:用户画像的数据完全没有用。如果它是一个真实的人,我可能还会关注,但它本身不是一个真实的人,是那些添加在它身上的装饰让其看起来像真实的人,我觉得这是无用的。
还有一些参与者认为,用户画像身上的属性和细节太过分散,导致偏离了本应关注的重点。
L1:在创建用户画像的过程中,我常常发现,那些原本次要的方面反而变得更加突出了。你会发现,那些与关键维度并非真正相关的细节,像技能、工作职责、对软件和工具的熟悉程度,这些细节很容易提出,因为它们也同样容易去沟通和理解。然而,随之而来的代价是,把更为重要的细节给丢掉了。
1. 代表多少
Chapman 等学者指出,任何一个用户画像都仅仅只能代表潜在用户群体中的某一小部分。那创建多个用户画像是否可行呢?可行是可行,但这又引出了一个新的问题:当用户画像的数量增多时,它的可记忆性是降低的,相应也降低了它在设计中起到的作用。多个用户画像往往存在着信息冗余的问题,过多的用户画像还会大大增加设计决策的成本。对于通过大数据自动生成的用户画像,数量过多这一问题尤为明显:有时会产出成千上百个用户画像。
2. 属性越多,涵盖面越窄
既然用户画像所代表的是真实用户,那么,它涵盖的真实用户数量能否通过某种方法预估出来呢?上文中我们提到的属性(如年龄、职业、居住地等),为用户数量的预估提供了可能。基于以上问题,Chapman 等展开了定量分析的研究。他们一共选取了 8 个数据库,其中 6 个是通过市场调研得出的真实用户细分与特征数据库,另外 2 个则通过多元数据模拟出来。然后,逐一地去增加用户画像的属性数量,并依次与数据库进行匹配。实验的结果如下图所示。不难发现:当用户画像被赋予的属性增加时,它涵盖的真实用户比例是降低的;而属性数量增加至 9 个以上后,各个数据库的匹配率都很低。对此,Chapman 等的建议是在创建用户画像时,最好能对其涵盖的用户数量进行大致的评估,而不是简单的假设。
△ 属性越多,涵盖面越窄
1. 偏低的投入产出比
前文中有提到,Matthews 等通过访谈去了解设计师对用户画像的看法,但这项研究还不足以观察到设计师是如何将用户画像运用到实际工作中的。基于这块研究的缺失,学者 Friess 另辟蹊径,从民族学的角度出发进行了探索。她采用的方法是:选取了一家位于美国的设计公司,对它其中一个团队的设计决策过程进行全程地观察与录音。该设计团队由 4 名核心成员组成,在设计决策开始前,其中 2 名团队成员已经花费了数周时间,通过调研创建了 8 个用户画像,并输出了长达 20 页的用户画像文档,供团队其他成员阅读。Friess 对收集到的录音片段进行话语分析后发现:在整个设计决策过程的话轮中,用户画像被提及的比例仅为 3% 左右。而且,在这为数不多的 3% 中,85.3% 的比例又是由那 2 名创建用户画像的成员提出。长达数周时间所创建的用户画像,换来设计决策过程中约为 3% 的提及率,这个投入产出比或许值得我们对用户画像的运用重新进行思考。
2. 过于主观的代入
有这样一种用户画像,它完全源于设计师对问题的主观看法与偏见。更为通俗地讲,是设计师先主观地提出了设计概念,然后创建用户画像去支撑其概念,美其名曰「以用户为中心」的设计。这种类型的用户画像由 Jones 等学者提出,他们称其为「promotional personas」。Jones 等在伊利诺伊大学香槟分校教授设计类的课程,在长达 5 年的时间里,通过对学生们在课程所创建的用户画像进行观察,他们对用户画像的几种模式进行了归类,而「promotional personas」就被归在了「bad personas」这一类别中。Jones 等还举出了一个他们在课程中观察到的例子:有学生设计了一款闹钟,这款闹钟可以让用户以天为单位自定义规划一整个月的闹铃时间。然后她做了一些调研,调研后发现身边朋友们的作息都很规律,在时间管理工具上的使用频次也较低,因此不太可能去用她所设计的那款闹钟。然而,她之后却提出了一个与调研结果完全相反的用户画像,该用户画像每天醒来的时间都很不同,而且经常由于睡过头而错过重要的事情。
设计师凭借自己的直觉与经验去创建用户画像这种方式,尽管也能在设计中起到一定作用,但如果将用户画像完全当做支撑主观设计概念的工具,甚至不惜背离调研结果,用户画像就彻底地沦为一种形式了。这样的用户画像,对整个设计过程都是有害无益的。
3. 无法取代真实用户的参与
既然用户画像能作为真实用户的代表,那么,对于参与式设计(participatory design)这种需要真实用户直接参与的方式,用户画像是否能替代真实用户呢?Bodker 等学者基于电子政务的项目,探究了用户画像对参与式设计是否有支撑作用。通过 4 个案例进行观察,Bodker 等发现:尽管用户画像能促进设计师在实际的参与式设计开始之前去更多地聚焦于用户,但在参与式设计的过程中,并不能让设计师更贴近真实用户的处境,反而可能分散设计师的注意力,让其偏离对真实用户参与情况的关注。这样一来,也无法说明用户画像本身对参与式设计具有支撑作用。因此,如果要采用参与式设计,在条件允许的情况下,建议还是让真实用户参与其中,用户画像可能并不能取代真实用户。
尽管上文总结和归纳了用户画像的种种问题与局限,但这些并不能否认用户画像作为一种工具,对设计过程所起到的帮助。问题和局限的提出,旨在帮助我们更多地去理解这一工具,细分它适合的设计场景,探索能否结合其他工具以弥补它的短板和不足,从而达到更好的使用效果。
文章来源:优设 作者:陈梦蝶 驴妈妈UED
CSS 函数大家多多少少都使用过,比如 rgb() , rgba() , linear-gradient(), radial-gradient() , 等。
今天小编给大家介绍几个特殊的 css 函数。
attr() 这是一个很强的函数,他可以让数据传输到你的 css 中,不需要借助其他东西。
用法:
<style>
div::before {
content : attr(data-abc);
}
</style>
<div data-abc='我是attr'></div>
calc() 用与动态计算长度值
给大家展示快速让子盒子在父盒子中居中的另一种方法:
<style>
.father {
position: relative;
width: 300px;
height: 300px;
background-color: pink;
}
.child {
position: absolute;
/ 这里的 50px 为子盒子宽(高)的一半 /
top: calc(50% - 50px);
left: calc(50% - 50px);
width: 100px;
height: 100px;
background-color: blue;
}
</style>
<div class="father">
<div class="child"></div>
</div>
cubic-bezier() 定义了一个贝塞尔曲线(Cubic Bezier)。在这我就不多描述了,关于贝塞尔曲线,感兴趣的同学可以自行去了解。
var() 用于插入自定义的 css 属性值。
用法:和 sass,less 中定义变量的语法相似
<style>
:root {
--abc-- : red;
}
div {
width: 100px;
height: 100px;
background-color: var(--abc--);
}
</style>
<div></div>
counters() 这是一个古老但实用的属性,用与 css 中计数
用法:
counter-reset : item 1;
给定计数器 item 的初始值1,也可用与复位。参数 ‘item’ 为计数器的名称,后面的 ‘1’ 参数如果不写,默认是 0。
counter-increment: item 2;
设定当一个 item 计算器发生时计数器增加的值。参数 ‘2’为每次计数增长 2。
counters(item,’-’);
写在content中,显示计数器的值,‘-’ 设定俩计算器拼接时中间的符号为’-‘。它还有第三个参数,是list-style-type , 与 css 属性 list-style-type 是一模一样的。用与设定计数器以什么形式显示(阿拉伯数字,英文大小写,等)
<style>
ul {
counter-reset: item 1;
}
li:before {
counter-increment: item 2;
content: counters(item, "-");
}
</style>
<ul class="test">
<li> html
<ul>
<li> css</li>
<li> js</li>
</ul>
</li>
<li> Node</li>
<li> ts</li>
</ul>
bootstrap-multiselect动态加载数据,首先要引用bootstrap-multiselect.css和bootstrap-multiselect.js
<select id="demo" name="demo" multiple></select>
JS代码
$("#demo").multiselect({
// 自定义参数,按自己需求定义
nonSelectedText : '--请选择--',
inheritClass : true,
maxHeight : 350,
includeSelectAllOption : true,
numberDisplayed : 5,
//下拉回调函数
onDropdownShow : function(event) {
$.ajax({
url : "${ctx}/xx/xx",
async : false,
type : "get",
dataType : "json",
success : function(data) {
var mark = new Array();
for (var i = 0; i < data.length; i++) {
mark.push({
value : data[i].markId,
label : data[i].markName
});
}
$("#demo").multiselect('dataprovider', mark);
}
})
},
});
获取选中的值的集合
var selectList = $('#demo option:selected');
1
遍历集合得到选中的value和label
for (var i = 0; i < selectList.length; i++) {
value = siteList[i].value;
label = siteList[i].label;
}
希望这篇文章可以帮助到你
一、首先找到第一次发起网络请求的地址,将服务器返回set-cookie当全局变量存储起来
wx.request({
......
success: function(res) {
console.log(res.header);
//set-cookie:PHPSESSID=ic4vj84aaavqgb800k82etisu0; path=/; domain=.fengkui.net
// 登录成功,获取第一次的sessionid,存储起来
// 注意:Set-Cookie(开发者工具中调试全部小写)(远程调试和线上首字母大写)
wx.setStorageSync("sessionid", res.header["Set-Cookie"]);
}
})
三、后台获取cookie中的PHPSESSID,将PHPSESSID当作session_id使用
<?php
// 判断$_COOKIE['PHPSESSID']是否存在,存在则作session_id使用
if ($_COOKIE['PHPSESSID']) {
session_id($_COOKIE['PHPSESSID']);
}
session_start();
echo session_id();
html5的新特点
1.语法更简单
a) 头部声明
<!doctype html>
b) 简化了字符集声明
<meta charset="utf-8">
2.语法更宽松
a) 可以省略结束符的标签
li、dt、dd、p、optgroup、option、tr、td、th
b) 可以完全省略的标签
html、head、body
3.标签语义化
增加了很多标签,在作页面的时候更加具有语义(定义了一些原本没有语义的div模块为有鲜明结构的语义模块)
a) <header>标记定义一个页面或一个区域的头部
b) <nav>标记定义导航链接
c) <article>标记定义一篇文章内容
d) <section>标记定义网页中一块区域
e) <aside>标记定义页面内容部分的侧边栏
f) <footer>标记定义一个页面或一个区域的底部
语义化标签图示
4.表单新增常用属性------要求掌握
required:必填
placeholder:输入内容提示
autofocus:自动获取焦点-----自动帮我们将光标点进去
<form method="post" action="http://www.baidu.com">
<!-- required 必填,必须的 -->
<!-- 自动获取焦点----自动将光标定位到表单中 -->
<input type="text" placeholder="请输入用户名" autofocus="autofocus" required="required" />
<input type="submit" />
</form>
5.input新增type属性值
a) type=“email”,文本框中只能输入email地址
b) type=“date”,日期控件
c) type=“time”
d) type=“month”
e) type=“week”
f) type=“number”,唤醒数字键盘
g) type=“range”,滑块
h) type=“color”
最近在做一个手机站,要求点击分享可以直接打开微信分享出去。而不是jiathis,share分享这种的点击出来二维码。在网上看了很多,都说APP能唤起微信,手机网页实现不了。也找了很多都不能直接唤起微信。
总结出来一个可以直接唤起微信的。适应手机qq浏览器和uc浏览器。
下面上代码,把这些直接放到要转发的页面里就可以了:
html部分:
-
<script src="mshare.js"></script>//引进mshare.js
-
<button data-mshare="0">点击弹出原生分享面板</button>
-
<button data-mshare="1">点击触发朋友圈分享</button>
-
<button data-mshare="2">点击触发发送给微信朋友</button>
js部分:
-
<script>
-
var mshare = new mShare({
-
title: 'Lorem ipsum dolor sit.',
-
url: 'http://m.ly.com',
-
desc: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quaerat inventore minima voluptates.',
-
img: 'http://placehold.it/150x150'
-
});
-
$('button').click(function () {
-
// 1 ==> 朋友圈 2 ==> 朋友 0 ==> 直接弹出原生
-
mshare.init(+$(this).data('mshare'));
-
});
-
</script>
下面是mshare.js的代码分享,把这些代码新建一个js文件放进去,然后在页面中引进就ok了。
-
/**
-
* 此插件主要作用是在UC和QQ两个主流浏览器
-
* 上面触发微信分享到朋友圈或发送给朋友的功能
-
*/
-
'use strict';
-
var UA = navigator.appVersion;
-
-
/**
-
* 是否是 UC 浏览器
-
*/
-
var uc = UA.split('UCBrowser/').length > 1 ? 1 : 0;
-
-
/**
-
* 判断 qq 浏览器
-
* 然而qq浏览器分高低版本
-
* 2 代表高版本
-
* 1 代表低版本
-
*/
-
var qq = UA.split('MQQBrowser/').length > 1 ? 2 : 0;
-
-
/**
-
* 是否是微信
-
*/
-
var wx = /micromessenger/i.test(UA);
-
-
/**
-
* 浏览器版本
-
*/
-
var qqVs = qq ? parseFloat(UA.split('MQQBrowser/')[1]) : 0;
-
var ucVs = uc ? parseFloat(UA.split('UCBrowser/')[1]) : 0;
-
-
/**
-
* 获取操作系统信息 iPhone(1) Android(2)
-
*/
-
var os = (function () {
-
var ua = navigator.userAgent;
-
-
if (/iphone|ipod/i.test(ua)) {
-
return 1;
-
} else if (/android/i.test(ua)) {
-
return 2;
-
} else {
-
return 0;
-
}
-
}());
-
-
/**
-
* qq浏览器下面 是否加载好了相应的api文件
-
*/
-
var qqBridgeLoaded = false;
-
-
// 进一步细化版本和平台判断
-
if ((qq && qqVs < 5.4 && os == 1) || (qq && qqVs < 5.3 && os == 1)) {
-
qq = 0;
-
} else {
-
if (qq && qqVs < 5.4 && os == 2) {
-
qq = 1;
-
} else {
-
if (uc && ((ucVs < 10.2 && os == 1) || (ucVs < 9.7 && os == 2))) {
-
uc = 0;
-
}
-
}
-
}
-
/**
-
* qq浏览器下面 根据不同版本 加载对应的bridge
-
* @method loadqqApi
-
* @param {Function} cb 回调函数
-
*/
-
function loadqqApi(cb) {
-
// qq == 0
-
if (!qq) {
-
return cb && cb();
-
}
-
var script = document.createElement('script');
-
script.src = (+qq === 1) ? '//3gimg.qq.com/html5/js/qb.js' : '//jsapi.qq.com/get?api=app.share';
-
/**
-
* 需要等加载过 qq 的 bridge 脚本之后
-
* 再去初始化分享组件
-
*/
-
script.onload = function () {
-
cb && cb();
-
};
-
document.body.appendChild(script);
-
}
-
/**
-
* UC浏览器分享
-
* @method ucShare
-
*/
-
function ucShare(config) {
-
// ['title', 'content', 'url', 'platform', 'disablePlatform', 'source', 'htmlID']
-
// 关于platform
-
// ios: kWeixin || kWeixinFriend;
-
// android: WechatFriends || WechatTimeline
-
// uc 分享会直接使用截图
-
var platform = '';
-
var shareInfo = null;
-
// 指定了分享类型
-
if (config.type) {
-
if (os == 2) {
-
platform = config.type == 1 ? 'WechatTimeline' : 'WechatFriends';
-
} else if (os == 1) {
-
platform = config.type == 1 ? 'kWeixinFriend' : 'kWeixin';
-
}
-
}
-
shareInfo = [config.title, config.desc, config.url, platform, '', '', ''];
-
// android
-
if (window.ucweb) {
-
ucweb.startRequest && ucweb.startRequest('shell.page_share', shareInfo);
-
return;
-
}
-
if (window.ucbrowser) {
-
ucbrowser.web_share && ucbrowser.web_share.apply(null, shareInfo);
-
return;
-
}
-
}
-
/**
-
* qq 浏览器分享函数
-
* @method qqShare
-
*/
-
function qqShare(config) {
-
var type = config.type;
-
//微信好友 1, 微信朋友圈 8
-
type = type ? ((type == 1) ? 8 : 1) : '';
-
var share = function () {
-
var shareInfo = {
-
'url': config.url,
-
'title': config.title,
-
'description': config.desc,
-
'img_url': config.img,
-
'img_title': config.title,
-
'to_app': type,
-
'cus_txt': ''
-
};
-
if (window.browser) {
-
browser.app && browser.app.share(shareInfo);
-
} else if (window.qb) {
-
qb.share && qb.share(shareInfo);
-
}
-
};
-
if (qqBridgeLoaded) {
-
share();
-
} else {
-
loadqqApi(share);
-
}
-
}
-
/**
-
* 对外暴露的接口函数
-
* @method mShare
-
* @param {Object} config 配置对象
-
*/
-
function mShare(config) {
-
this.config = config;
-
this.init = function (type) {
-
if (typeof type != 'undefined') this.config.type = type;
-
try {
-
if (uc) {
-
ucShare(this.config);
-
} else if (qq && !wx) {
-
qqShare(this.config);
-
}
-
} catch (e) {}
-
}
-
}
-
// 预加载 qq bridge
-
loadqqApi(function () {
-
qqBridgeLoaded = true;
-
});
-
if (typeof module === 'object' && module.exports) {
-
module.exports = mShare;
-
} else {
-
window.mShare = mShare;
-
}
好了,这样就可以直接唤起微信进行分享啦
jQuery超详细总结
文章目录
jQuery超详细总结
一 选择器
特殊选择器
二 筛选器
用在 jQuery 选择的元素后面
都是方法,对选择出来的元素进行二次筛选
三 文本操作
总结
四 元素类名操作
五 元素属性操作
在 H5 的标准下, 给了一个定义, 当你需要写自定义属性的时候,最好写成 data-xxx="值",当大家看到 data-xxx 的时候, 就知道这是一个自定义属性
六 元素样式操作
七 绑定事件
on()
方法是专门用来绑定事件one()
方法是专门用来绑定一个只能执行一次的方法off()
方法是专门用来解绑一个元素的事件的trigger()
方法是专门用来触发事件的方法hover()
常用事件
offset()
position()
scrollTop()
scrollLeft()
ready()
事件each()
方法jQuery 发送一个 GET 请求
jQuery 发送一个 POST 请求
jQuery 的 $.ajax 方法
position()
postition: 定位
只读的方法
读取:
元素相对于定位父级的位置关系
得到的也是一个对象 { left: xxx, top: xxx }
如果你写的是 right 或者 bottom, 会自动计算成 left 和 top 值给你
十一 获取卷去的尺寸(页面滚动条)
scrollTop()
原生 js 里面 document.documentElement.scrollTop
读写的方法
不传递参数的时候就是获取卷去的高度
传递一个参数就是设置卷去的高度
scrollLeft()
原生 js 里面 document.documentElement.scrollLeft
读写的方法
不传递参数的时候就是获取卷去的宽度
传递一个参数的时候就是设置卷去的宽度
十二 jQuery中的函数
ready() 事件
类似于 window.onload 事件,但是有所不同
window.onload 会在页面所有资源加载行
ready() 会在页面 html 结构加载完毕后执行
也叫做 jQuery 的入口函数
有一个简写的形式 $(function () {})
each() 方法
类似于 forEach(), 遍历数组的
jQuery 的元素集合, 是一个 jQuery 数组, 不是一个数组, 不能使用 forEach()
forEach语法: forEach(function (item, index) {})
each语法:each(function (index, item) {})
比较少用到, 因为 jQuery 隐式迭代 自动遍历
十三 jQuery中的动画
让元素出现不同的移动, 改变
transition -> 过渡动画
animation -> 帧动画
标准动画
show() 显示元素
语法: show(时间, 运动曲线, 运动结束的函数)
hide() 隐藏元素
语法: hide(时间, 运动曲线, 运动结束的函数)
toggle() 改变元素显示或隐藏(如果显示就隐藏,如果隐藏就显示)
语法: toggle(时间, 运动曲线, 运动结束的函数)
三个方法的参数都可以选填,不需要每个都填写
折叠动画
slideDown() 下滑显示
语法: slideDown(时间, 运动曲线, 运动结束的函数)
slideUp() 上滑隐藏
语法: slideUp(时间, 运动曲线, 运动结束的函数)
slideToggle() 切换滑动和隐藏
语法: slideToggle(时间, 运动曲线, 运动结束的函数)
渐隐渐显动画
实质是透明的opacity的变化
fadeIn() 逐渐显示
fadeIn(时间, 运动曲线, 运动结束的函数)
fadeOut() 逐渐消失
fadeOut(时间, 运动曲线, 运动结束的函数)
fadeToggle() 切换显示和消失
fadeToggle(时间, 运动曲线, 运动结束的函数)
以上三个方法的参数,均有默认值
fadeTo() 设置元素透明度变为你指定的数字
fadeTo(时间, 你指定的透明度, 运动曲线, 运动结束的函数)
综合动画
animate()
基本上大部分的 css 样式都可以动画
transform 不行, 颜色不行
语法: animate({}, 时间, 运动曲线, 运动结束的函数)
{ }里面就写你要运动的 css 属性,默认单位为px
停止动画
让当前的动画结束
因为 jQuery 的动画你一直点击,就会一直触发。即使不再点击让事件发生,还是会把没执行完的动画执行完毕。
你点击 10 次, 他就会触发 10 次, 直到 10 次全都完毕才结束
stop()
当这个函数触发的时候, 就会让运动立刻停下来
你运动到哪一个位置了就停止在哪一个位置
finish()
当这个函数触发的时候, 就会让运动立刻停下来
不管你运动到了哪一个位置, 瞬间到达运动完成位置
十四 jQuery发送ajax请求
jQuery 里面帮我们封装好了几个方法
专门用来发送 ajax 请求的
$.get() -> 专门用来发送 get 请求的
$.post() -> 专门用来发送 post 请求的
$.ajax() ->
发送什么请求都可以(get, post, put, delete)
并且还可以发送一个 jsonp 请求
jQuery 发送一个 GET 请求
语法: $.get(请求地址, 需要携带到后端的参数, 成功的回调函数, 期望后端返回的数据类型)
请求地址: 你要请求的后端接口地址(必填)
携带参数: 你需要给后端传递的参数
可以是一个固定格式的字符串 ‘key=value&key=value’
也可以是一个对象 { a: 100, b: 200 }
成功回调: 当请求成功的时候会执行的函数
期望数据类型: 就是你是不是需要 jQuery 帮你解析响应体
$.ajax({
url: '', // => 请求地址(必填)
type: '', // => 请求方式(GET, POST, ...) 默认是 GET
data: '', // => 携带到后端的参数
dataType: '', // => 期望后端返回的数据类型, 默认不解析
async: true, // => 是否异步, 默认是 true
success: function () {}, // => 成功的回调
error: function () {}, // => 失败的回调
timeout: 数字, // 单位是 ms, 超时时间(超过你写的时间没有响应, 那么就算失败)
cache: true, // 是否缓存, 默认是 true
context: 上下文, // 改变回调函数里面的 this 指向
...
})
$.ajax 里面失败的回调
不光是请求失败的时候会触发
jQuery 认定失败就是失败
当 dataType 写成 json 的时候, jQuery 会帮我们执行 JSON.parse()
当后端返回一个不是 json 格式的字符串的时候
执行 JSON.parse() 就会报错
也会执行失败的回调, 请求虽然成功, 但是解析失败了, 也是失败
JSON.parse(‘你好 世界’) -> 就会报错了
$.ajax 里面是否缓存的问题
这个请求要不要缓存
当两次请求地址一样的时候, 就会缓存
如果你写成 false, 表示不要缓存
jQuery 就会自动再你的请求后面加一个参数 =时间戳
第一次请求 ./server/get.php?=11:10:01.325的时间戳
第二次请求 ./server/get.php?_=11:10:02.326的时间戳
$.ajax 里面的回调 this 指向问题
ajax 的回调里面默认 this 指向被 jQuery 加工过的 ajax 对象
context 的值你写的是谁, 回调函数里面的 this 就时谁
$.ajax 里面的请求方式的问题
$.ajax 这个方法里面, type 表示请求方式
jQuery 还给了我们一个参数叫做 method,也表示请求方式
当你写请求方式的时候
可以写成 type: ‘POST’
也可以写成 method: ‘POST’
$.ajax 里面的接收响应的问题(2015年以后的版本才有 promise 的形式)
jQuery 默认把 ajax 封装成了 promsie 的形式
你可以用 success 选项接收成功的回调
也可以用 .then() 的方式接收响应
jQuery 的 ajax 全局钩子函数
钩子: 挂在你的身上, 你的所有动作都和它有关系
这些全局函数都是挂在 ajax 身上的, 这个 ajax 的每一个动作都和全局函数有关系
全局的钩子函数
1.ajaxStart()
会在同一个作用域下多个 ajax 的时候, 第一个 ajax 之前开始的时候触发
如果有多个 ajax 他只触发一次
2.ajaxSend()
每一个 ajax 再发送出去之前, 都会触发一下
xhr.send() 之前触发
ajaxSuccess()
每一个 ajax 再成功的时候触发
只要有一个 ajax 成功了就会触发
ajaxError()
每一个 ajax 再失败的时候触发
只要有一个 ajax 失败了就会触发
ajaxComplete()
每一个 ajax 完成的时候触发
只要有一个 ajax 完成了, 不管成功还是失败, 都会触发
ajaxStop()
会在同一个作用域内多个 ajax 的时候, 最后一个 ajax 完成以后触发
如果有多个 ajax 它只触发一次
作用: 通常用来做 loading 效果
<img src="./loading.gif" alt="">
// 利用ajax钩子函数 做一个lading效果 等待页面
// 提前利用钩子函数准备 loading 效果
// 每一次发送出去的时候都要显示图片
$(window).ajaxSend(() => {
$('img').show()
})
// 每一次完成的时候都要图片再隐藏起来
$(window).ajaxComplete(() => {
$('img').hide()
})
// 每次点击按钮的时候都会发送一个 ajax 请求
$('button').click(() => {
// 发送一个 ajax 请求
$.ajax({
url: './server/get.php',
data: { a: 100, b: 200 },
dataType: 'json',
success: function (res) {
console.log('请求成功了')
console.log(res)
}
})
})
十五 jQuery 发送一个 jsonp 请求
jQuery 也提供给我们发送 jsonp 请求的方式
jsonp: 利用 script 标签的 src 属性来请求
返回值: 是一个字符串, 字符串里面写了一个 函数名(后端传递给前端的参数)
使用 $.ajax() 这个方法
必须写的:dataType: 'jsonp'
发送 jsonp 请求
jQuery 帮我们准备好了一个函数名, 并且以参数的形式带到了后端
jQuery 帮我们带过去的 callback 参数, 就是它准备好的函数名
后端就应该返回一个 jQuery 准备好的函数名()
其他参数
jsonp: '', 你带到后端表示你函数名的那个 key, 默认值是 callback
cache: false, 当 dataType === ‘jsonp’ 的时候, 默认 cache 就是 false
// 发送一个 jsonp 请求
$.ajax({
url: 'http://127.0.0.1/server/jsonp.php',
dataType: 'jsonp', // 表示我要发送一个 jsonp 请求
jsonp: 'cb', // 表示参数里面的 cb 属性时我准备好的函数名
cache: true, // 表示缓存本次请求
success: function (res) {
console.log(res)
}
})
// jQuery 准备好的函数名
// + jQuery34108160883644340862_1582255906750
// + 变量名包含 数字 字母 下划线 $
// + function jQuery34108160883644340862_1582255906750() {}
十六 jQuery 的多库并存机制
因为 jQuery 引入页面以后, 向全局添加了两个名字
一个叫做 $
一个叫做 jQuery
万一有别的类库也起名叫做 jQuery 或者$ 怎么办
当我两个库都需要使用的时候
因为向全局暴露的名字一样, 就会发生冲突了
谁的文件引再后面, 谁的名字就占主要位置了
两个只能选择一个使用
jQuery 提供了一个方法
我可以不占用$ 或者 jQuery 这个名字
noConflict()
语法: $.noConflict() 或者jQuery.noConflict()
当你执行了 noConflict() 以后, jQuery 就交出了$的控制权。
jQuery向全局暴露的不在有$ 这个名字了。当你执行了noConflict(true) 以后, jQuery就交出了 $ 和jQuery 的控制权。
交出去以后, 我的 jQuery 就用不了
noConflict() 的返回值: 就是一个新的控制权
你只要接收一个返回值, 你定好的变量是什么,jQuery 的控制权就是什么
// 交出 $ 的控制权
// $.noConflict()
// 交出 $ 和 jQuery 的控制权
// $.noConflict(true)
// 改变 jQuery 的控制权
var $$ = $.noConflict(true)
十七 jQuery 的插件扩展机制
jQuery 还提供给我们了一个机制, 就是你可以向 jQuery 里面扩展一些方法
两个方法
$.extend()
扩展给 jQuery本身使用的
语法:
$.extend({ 你要扩展的方法名: function () {}, 你要扩展的方法名: function () {}, ... })
使用的时候就是 $.你扩展的方法名()
$.fn.extend() => $.extend($.fn, { 你扩展的方面名 })
扩展给 jQuery 元素集合使用的
语法 $.fn.extend({ 你要扩展的方法名: function () {}, 你要扩展的方法名: function () {}, ... })
使用的时候就是 $(选择器).你扩展的方法名()
$('div').html()
// 1. 扩展给 jQuery 本身
// jQuery 本身没有操作 cookie 的方法
// $.extend({
// setCookie: function (key, value, expires) {
// // 写上设置 cookie 的方法
// if (expires) {
// var time = new Date()
// time.setTime(time.getTime() - 1000 60 60 8 + 1000 expires)
// document.cookie = ${key}=${value};expires=${time}
// } else {
// document.cookie = ${key}=${value}
// }
// },
// getCookie: function (key) {
// // ...
// }
// })
// 使用我们扩展的方法去设置 cookie
// $.setCookie('a', 100)
// $.setCookie('b', 200, 10)
// 2. 扩展给元素集合
// 扩展一个全选的方法
// 方法以执行, 就能让 input checkbox 变成选中状态或者不选中状态
$.fn.extend({
selectAll: function (type = true) {
// type 就是你传递进来的选中或者不选中一个标志
// 你不传递的时候, 我默认是 true, 你传递了就用你传递的
// console.log(this) // 就是你调用的时候前面的哪个元素集合
this.each(function (index, item) {
// 让元素集合中的每一个 input 的 checked 属性为 true
item.checked = type
})
// return 这个元素集合, 达到一个链式编程的效果
return this
}
})
$('button').click(() => {
// 让所有 input 框变成选中状态
console.log($('input').selectAll().attr('hello', 'world'))
})
十八 jQuery 的拷贝对象问题
$.extend() 深拷贝 与 浅拷贝
传递一个对象的时候, 可以做到插件扩展机制
传递多个对象的时候, 可以将后面几个对象的内容复制到第一个对象里面
语法:
$.extend(是否深拷贝, 对象1, 对象2, 对象3, ...)
是否深拷贝: 默认是 false, 可以不写
从 对象2 开始, 后面所有对象的内容都会被拷贝到 对象1 里面
再拷贝的时候, 如果有重复的 key, 那么以写在后面的为准(后来者居上)
十九 jQuery 的插件
基于 jQuery 使用的, 别人封装好的插件
我们拿来使用就可以了, 前提就是要有 jQuery
例子 一个叫做 jquery-validate 的插件
专门用来做表单验证的
你输入的内容是不是符合规则
下载
引入文件
去复制粘贴
<!-- 引入文件 --> <!-- 注意: 先引入 jQuery, 后引入 jquery-validate --> <script src="./jquery/jquery.min.js"></script> <!-- jquery-validate 这个文件依赖的 jquery --> <script src="./jquery-validate/jquery.validate.min.js"></script> <!-- 引入中文信息提示包, 必须在 jquery-validate 的后面 --> <script src="./jquery-validate/localization/messages_zh.min.js"></script> <script>
// 选择到你要验证的表单的 form 标签 // 执行 validate 方法 // {} 里面就写我们的验证规则 $('#login').validate({ // 你需要的验证规则 rules: { // key 就是你要验证的哪个 input 框的 name 属性 username: 'required', // 用户名必填 password: { // 一个字段可以写多个验证方式 required: true, minlength: 6, // 最少是六个 maxlength: 12, // 最多十二个 } }, // 你自定义提示的文本内容 messages: { // key 就是你验证的哪个 input 框的 name 属性 username: '请输入用户名! ^_^', password: { required: '请输入密码!', minlength: '最少要输入 6 个字符噢!' } }, // 表单的提交事件 // 这个函数会在表单验证通过以后执行 submitHandler: function (form) { // form 接收的就是你的 form 标签 // console.log(form) // console.log('表单验证通过了, 我需要使用 ajax 去提交数据了') // 有一个 jQuery 的方法 // serialize() 快速获取表单输入的数据 // $(form).serialize() 就能拿到这个 form 标签里面的表单数据 // console.log($(form).serialize()) // username=admin&password=123456 // 发送请求到后端 $.post('./server/login.php', $(form).serialize(), res => { console.log(res) }, 'json') } })————————————————
不管是做 UI 设计还是画插画,有很多同学觉得自己是因为天赋不够所以对色彩的敏感度不够,其实不然。一个可能是大家总结的太少,从来都是凭感觉和运气去配色,但配色都是有讲究的。本文不会给大家重复讲解什么是 rgb,什么是 hsb,什么是 cmyk 或者什么三原色,这些大家都可以从网上直接搜到。我今天要给大家分享的是人们是如何认识色彩,并且在产品设计中使用的。
大家都知道,对于不同的颜色,我们对其的感知是不同的,有人觉得暖色在前,冷色在后。暖色更醒目,冷色不醒目。那这是什么原因呢?首先我们要知道眼睛内存在两种感光细胞:视锥细胞和视杆细胞,视杆细胞能够感知光线强弱但无法感知颜色,而视锥细胞却相反,视锥细胞内还有 3 种对不同频率光敏感的细胞。我们经常会用到视锥细胞,而视杆细胞却用的少,更多的是在黑暗的环境中使用的多。
视锥细胞的三种类型分别是低频、中频和高频视锥细胞,分别对红、绿、蓝三种颜色的光敏感。而且这三个视锥细胞分别也有重合的部分。低频视锥细胞对整个可见光频谱都敏感,它的范围包含的比较广,特别是对于频谱中段的黄色到红色部分更加敏感。但是像高频的紫色几乎只有蓝视锥细胞可以感知。
大家在平时生活中都能看到,在马路上、机动车道上以及一些警示牌都会采用黄色、橙色等标识,因为这些非常醒目。更容易被红视锥细胞感知到,但如果你的标识用的是冷色调那这个交通事故可能要发生的频繁得多。
1. 人对色彩边缘的对比更加敏感
我们来做个实验,如下图,大家觉得在中间的灰色块是纯色还是渐变色,可能很多同学看上去都会觉得是个渐变色,但其实它就是一个纯色,不信的同学可以自己在工具中尝试一下。
但如果你把这个色块拿出来后,不在这个环境中直接进行边缘对比,那就不会出现渐变的情况了。光说原理,我们也来看一下在产品设计中需要注意的地方,因为在 UI 界面设计中我们通常需要把一些图片、卡片叠加放置,这样就会造成边缘视觉的对比,本来不明显的两个元素重叠之后变的很明显,例如一些标签的背景色和页面整体的背景色。
如果你想要让两个颜色接近的元素具有识别度,那么最好将这两个元素进行重叠摆放而不是分开摆放。另外,如果是卡片样式的设计,背景色一定不要过于灰暗也不要过于浅白,过于深的话会让卡片轮廓过于明显而导致整体看上去显脏以及很明显的对比,显得不自然和舒适。如果过于浅的话也会导致信息的不聚焦。
还有,为什么被框起来的文字会看上去更加有点击的欲望其实也是这个道理,因为文字和背景叠加产生的轮廓只是文字的轮廓,在我们的第一印象中只是一种符号。当它被赋予颜色之后,我们才会意识到它需要我们去注意或者可被点击,但依然不够明显,所以为了强化可点击这个感觉,我们才用了线框、背景色、箭头等方式。
1. 加深品牌印象与品牌感
一般来说,产品都会有一个品牌的主色。而这个品牌的主色也通常会运用在外面的产品界面中,所以例如闲鱼、马蜂窝等,主色都采用了黄色,黄色具有非常活泼、有趣、好玩的特性,无论是线上还是线下都使用了这个品牌黄色,从每一个线上元素的主色,到线下包装的印刷色。
但一定要注意的是,如果品牌的主色偏灰偏暗的话,可能不太适合线上的产品进行通用。例如之前的严选、云集、711便利店、宜家等产品的主色都是偏深和暗的,所以在线上的界面用起来会非常不和谐,和整体偏浅色、轻的风格对比起来太强烈,引起不适。
而且线上觉得还不错的颜色,由于印刷的原理,实物也会更加偏低饱和和偏暗。
2. 引导用户视觉凹增加易读性
我们在《如何有理有据做设计,而不是凭感觉?》里提到了人们如何阅读信息,提到了一个视觉凹的概念。所以在界面中,什么样的地方使用色彩是有讲究的。所以在这里通常会需要使用颜色的地方在于希望引导用户和吸引用户注意的地方才会使用色彩。例如下方产品,使用了高亮色来引导用户视觉。
当然色彩的运用也会将整个页面的层级凸显出来,而不单纯的用中性色来区分层级。
3. 区分信息交互的状态
同样是上两张图,大家可以清晰的看到,美团中的附近热卖好点、满减标签、价格,其实都只具备信息的呈现,但不具备交互的特征和状态。但淘票票中的「4.7万」和「展开」却不一样,「展开」使用了辅助蓝色,这里的展开就具备这个文案所描述的这个控件具备的交互特性──点击后将隐藏的文字展示出来。蓝色一般我们都会使用在某个可点的链接上,当然也会有其他的色彩来表示可点击。
所以不是所有的元素都要赋予颜色,这样会使整个页面非常混乱。
另外,UI 设计中主色除了引导用户的作用外,也可以表示当前正被激活的信息状态。例如爱奇艺 app 中播放详情页面,当前版块标签和正在播放剧集的激活状态。
4. 营造氛围传递热度
色彩除了上方所述的字段中的不同使用,在图片和整体氛围营造中也起了很大的作用,目前很多 2c 的产品往往会在界面氛围的营造中运用一些手段。例如导航栏、底部标签栏上的图标,或者在首页营销版块的瓷片区域都会用品牌色在活动时段内进行氛围打造。
在色彩的心理学上,大家都知道每个颜色具有一定的性格特征和表达。而且都会有正反两面,可以看下方多种色彩的描述。
然而其实很多的产品使用的色彩和我们所认知的会有一些差别,比如咖啡品牌的主色选择,在我们常规人之中,咖啡应该是褐色、棕色,但是大家看到星巴克、瑞幸、漫咖啡其实都用了和咖啡本质没什么关系的颜色。
在瑞幸刚出来的时候,很多人其实不太习惯把这个蓝色和咖啡结合起来,但是为了塑造品牌差异化,瑞幸一直将「蓝色」作为品牌的主基调,「小蓝杯」这一称呼不但让消费者感到亲切,也在众多的咖啡中有了属于自己的记忆点。在这支广告片中,主基调同样是使用蓝色,不但符合了当下消费者的视觉偏好,也在为用户留下记忆点之后,让用户在看到蓝色时自然而然地想到瑞幸咖啡。
但凡各位使用了这样的配色,保证各位过不了试用期,相信我。所以大家千万要避开。
高饱和度的色彩
高饱和度的色彩,会让人产生「幻觉」!让人产生视觉疲劳,例如我将饿了么这个界面的色调调整一下大家看一下,不亮瞎算我输。
灰部使用过多的配色
为什么很多时候我们总觉得界面脏兮兮的。是因为我们在界面或者配色中使用了过多的低饱和度、灰度较多的配色,所以这也是要避免的。
没有规律且过多的配色
让界面或者插画看起来非常混乱。一般来说颜色的使用也需要有侧重点,所以我们常用的方法是6、3、1的色彩配比。
荧光色
荧光色绝对不可以使用在 UI 界面中,尤其是主色。
太轻柔的颜色
在很多 dribbble 的飞机稿中,经常能看到这样的配色和练习。无论是在练习中还是实际项目中,这样的界面也完全无法让用户看到想看的信息,没有重点且轻飘飘的感觉。
现在很火的新拟物化设计
说真的,这样的风格确实耳目一新,但个人觉得可能不会成为主流。因为它就和第五种一样:信息可识别性很差。且不谈色弱的人群,就正常的用户来说大面积的白色+饱和度低的元素结合,感觉就是得了「白内障」。另外我们常说的一点就是所有元素都强调就等于什么都没有强调,这样的风格在每一个元素都具有阴影的情况下都在争先恐后让用户感知,原则是轻量化却又需要那么多阴影,这样就有点自相矛盾的感觉。
为了营造这样的「新拟物」的轻量氛围,还不得不在整个界面中简化大部分元素,能不加文字就不能加文字。有一句话一直非常影响我做设计:「设计是需要被简化的,但是简化的过程一定不简单」。所以不是单纯的简化所有元素为了达到这个风格的目的。
不要将对抗色重叠
例如下方,两种对抗色重叠后会引起视觉闪烁的感觉。
1. 定义主色
首先我们必须要说,色彩肯定是需要结合产品和用户的定位去指定和提炼的,所以前期会需要去做一些研究,例如用户画像,品牌冲刺或者是情绪板等方法。得到几类「真实的虚拟用户」,从而确定一些主色的方案。然后我们在主色的选择中需要避开上面提到的坑,并且对市面上的 app 进行总结,我们发现大部分的产品色,简单来讲在我们 HSB 模式中取色都在一个固定的范围,就像这样。
在上文中也说到用色比例的 631 法则,所以在选取辅助色的时候我们需要定义好辅助色可以用在什么地方。例如知乎,其实辅助色没有非常明显的一种或者两种,都是多色的辅助色方案,都在一个配色的系统中选取颜色即可。大部分产品目前都是这样的策略,一个主色搭配多个辅色,如果有其他独立的板块可能需要重新定义专属的配色策略。
2. 定义中性色
其次再定义中性色,比如字体和线条以及背景色。字体是为了让信息有对比,显示层级,那么通常给 2-3 种层级即可,至少 2 种,至多 3 种。在选择 3 个层次的中性色文字时,给大家一个建议:标题/正文文字颜色 HSB 的 B 值不要大于 20,备注和次要文字 b 值不要大于 50,默认文字不要大于 80,大家可以去尝试一下,且中性色不得使用纯黑。
文章来源:优设 作者:应俊
蓝蓝设计的小编 http://www.lanlanwork.com