如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里
按照这个来配置就好了,这里相当于是帮你把webpack需要的繁琐的配置给你都弄好了,然后你直接从那里全部下下来就可以
记得先下好nodejs,安装的代码记得全都c v,不要自己敲
安装完nodejs之后再安装淘宝npm镜像,安装完了之后后面的安装速度会快一点
npm install -g cnpm --registry=https://registry.npm.taobao.org
1
然后按照下面的五步流程一个一个来
1、全局安装vuecli
npm install -g vue-cli
1
2、进入目录–初始化项目
vue init webpack my-project //这个要进入项目目录再用,会创建一个my-project的文件夹
1
3、进入项目
cd my-project
1
4、安装依赖
npm install
1
5、启动项目
npm run dev
1
以上执行完后会出现一个 my-project 项目文件夹,用vscode打开后会看到以下目录
下面解释一下这些文件及目录分别是干什么的
目录结构的分析
1、bind
├── build // 项目构建(webpack)相关代码 记忆:(够贱) 9个
│ ├── build.js // 生产环境构建代码
│ ├── checkversions.js // 检查node&npm等版本
│ ├── devclient.js // 热加载相关
│ ├── devserver.js // 构建本地服务器
│ ├── utils.js // 构建配置公用工具
│ ├── vueloader.conf.js // vue加载器
│ ├── webpack.base.conf.js // webpack基础环境配置
│ ├── webpack.dev.conf.js // webpack开发环境配置
│ └── webpack.prod.conf.js // webpack生产环境配置
2、config
├── config// 项目开发环境配置相关代码 记忆: (环配) 3个
│ ├── dev.env.js // 开发环境变量(看词明意)
│ ├── index.js //项目一些配置变量
│ └── prod.env.js // 生产环境变量
3、node_modules
├──node_modules// 项目依赖的模块 记忆: (依赖) *个
4、src
├── src// 源码目录 5
1
│ ├── assets// 资源目录
│ │ └── logo.png
2
│ ├── components// vue公共组件
│ │ └── Hello.vue
3
│ ├──router// 前端路由
│ │ └── index.js// 路由配置文件
4
│ ├── App.vue// 页面入口文件(根组件)
5
│ └── main.js// 程序入口文件(入口js文件)
5、static
└── static// 静态文件,比如一些图片,json数据等
│ ├── .gitkeep
6、剩余的文件
├── .babelrc// ES6语法编译配置
├── .editorconfig// 定义代码格式
├── .gitignore// git上传需要忽略的文件格式
├── index.html// 入口页面
├── package.json// 项目基本信息
├── README.md// 项目说明
---------------------
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务。
如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里
项目概述QQ 20周年,是互联网产品长青的一个传说,就在 20 周年的时间节点,QQ 向用户提供一份关于他自己的、真诚热切的 QQ 数据总结。通过数字,汇集出每个人自己的 QQ 时光历程,从而牵引出每个人对于成长、青春、沟通、时代流动的感知与回忆,引发 2019 年一场集体的情感共鸣。
△ QQ 20年来的一路变迁
项目历时两个月,从项目初期,视觉和产品密集沟通,了解需求,进行头脑风暴,输出多个视觉方案纵向对比,最后确定视觉风格,分配视觉工作(插画,动画,3D)。项目后期,包括开发还原,数据调配等众多环节,环环相扣,缺一不可,一路过关斩将,整个 H5 需要不同岗位的高度配合和各专业的高度默契。
△ H5的项目流程图
1. 异地合作
本次 H5 联动了动效,3D,插画设计师的共同合作,由于支持 3D 的设计师在韩办公,所以大部分都是在线上全英沟通,包括前期的项目进度同步,还有后期的模型调整等环节都能及时反馈,快速反应,最后如期打磨出五款 spaceQQ。算是一次顺利的异地合作。
△ 五款3D spaceQQ最终效果
2. 3D spaceQQ视觉还原
3D 鹅从设计软件转化为 H5 展示过程中,存在模型文件过大、材质缺失等问题,直接影响用户体验。在开发的过程中同学通过模型减面、重新选择材质,还有模型拆分等解决方法,在视觉观感和性能中建立了平衡的杠杆,最终实现了 15 个 SPACE QQ 的视觉还原。
△ 五款3D spaceQQ最终视觉还原效果
3. 视觉工作的同步进行
由于项目时间比较紧迫,而且 H5 加入了 3D 模型,还有需要大量的动效,所以需要在同一时间线上,同步进行,视觉稿输出,动画制作和 3D 模型打磨。考验设计师的沟通和执行能力。与此同时,需要随时和开发同步动画 demo 以确保动画可实现。和产品密集沟通,及时根据文案调整画面。
因为 QQ 是陪伴了大多数用户的一个产品,见证了整个互联网社交的演变过程,容易引起用户的情感共鸣。设计的初期,围绕「个人轨迹」的主题发散了不同方向的视觉概念,在引起客户共鸣感的复古元素和传递不断「探索」未来的概念间寻找平衡点。最后沿用了 20 周年的太空概念贴合「探索」的主题,结合有年代特征的代表性视觉符号来引起「个人轨迹」的这一概念的用户情感共鸣。另外,H5 运用了 3D 打造了 15 只太空鹅,打造「个人轨迹」的专属感,既联动用户温暖的回忆之余,也增添了一些小惊喜。
1. H5整体视觉风格
QQ,是陪伴了大多数人成长的一个互联网产品,其本身带有很多高辨识度的视觉元素,例如对话框,提醒上线的音效等。因为 H5 本身是一个大数据总结,专属感非常强的一个产物,所以希望是唤醒用户一些封尘已久的记忆,就像打开时间胶囊般的期待和感动。同时也象征着 QQ 一直陪伴在身边,从而引起用户的共鸣。
设计方面,除了通过一些标志性的视觉元素唤醒用户的回忆之外,也加入 QQ 20周年的太空「探索」主题的元素,响应 20 周年的主题之余,也寓意 QQ 不断地对外探索,从多个维度来看世界,寻找有趣的内容。
对话框,是承载数据的视觉符号,也是贯穿整个 H5 的重要视觉符号之一。寓意着 QQ 一直致力于「沟通」,而且不同时代的 QQ 对话框都各有特点,也是见证 QQ 时代变迁的重要元素,所以提取了三个阶段代表性的对话框样式来承载数据,并且加入有时代特征的视觉元素(如bb机,像素化的小箭头等)作为辅助,增加 H5 的氛围感,也算是视觉上的「小彩蛋」。
△ QQ原始对话框
H5 加入一些趣味感的元素,如笑脸,爱心等元素,背景辅以流动的彩色不规则图案,来增加对话框的玩味。也寓意 QQ 20年来给用户带来源源不断的乐趣,留下了不可取代的时代印记。
△ 重绘对话框
H5 中也加入了很多好玩的元素,不同时代所用的移动设备,融合贴近太空「探索」主题的背景;利用带手套的手和不同的元素进行互动;增加重绘经典头像的互动动画,加入 QQ 空间的植物等怀旧元素,增加 H5 的可玩性和惊喜感。
△ 经典头像的重绘
△ 经典头像穿插在H5中的小彩蛋
△ 带手套的手和有时代标签的元素互动
1. 视觉动态化方案
在动画制作前期会出一份详细的动态化分页策划,以及一份尽可能表达完整的动画 demo,能便于设计与开发能准确的估算出制作周期。在开发完成预研测试后,基于动画 demo 共同制定一个大致的动态化方案──对话框等大面积使用代码实现,其他装饰性小元素全部使用序列帧。在观众每滑一页即可触发当前页的动画,且能保证大体动画的流畅度。
2. 动画制作
为了尽可能减少 H5 的运算体积,又保证画面动态的流畅程度,导出的序列必须满足以下所有条件:
△ 设计了4个不同的色块流动loop,方便开发安插在每页合适的位置
3. 导出与同步
在配合开发导出的阶段,为了能明确序列的标记,所有序列文件命名为 xx-in/xx-loop/xx-out。使用同步工具以实现 AE 动画序列导出和开发提取素材能同步进行,并保持实时更新和迭代。
△ 第6页动画导出序列
创建了四款全新的 spaceQQ,根据用户的 QQ 年龄而设计。根据用户的 QQ 年龄,分了四个款式的鹅:奢华,智能,闪亮和神秘四个概念,一个递进的尊贵程度,刺激用户分享欲。包括基础款的 QQ 在内,共创造了 5 个类型的 spaceQQ。每个设计都基于基本 spaceQQ 的形式,但是套装的颜色和细节根据各自的概念各有特色。
△ spaceQQ总览图
用户可以根据自己的喜好更改这 5 款 spaceQQ 的装扮颜色。
1. 专属感
整个 H5 始终紧扣 QQ 20周年的太空「探索」主题,整个 H5,除了用数据唤醒用户和 QQ 多年的点点滴滴之外,5 个 spaceQQ 概念设定,既能增加用户的新鲜感,又能刺激用户的分享欲,C4D 建立的 3D 形象丰富了整个 H5 的视觉层次,深化了 QQ 品牌的影响力,寓意鹅厂一直与时俱进,紧贴潮流。
2. 情绪调动
对于当下的运营活动来说,趣味性是引爆转发量的重要元素,H5 结合 QQ 用户创作的背景音乐和能够调动用户情感的设计语言来释放用户的情绪,比如惊喜感(用户结合 QQ 的标志性音效创作的背景音乐),荣誉感(不同 Q 龄获取相应的 spaceQQ)等,让用户产生持续的惊喜感,在怀旧和新鲜感中得到满足,提升用户活跃性。
QQ 20周年 H5 设计,尝试结合了 3D,动画,插画等设计形态,为每一位用户打造专属的「个人轨迹」,通过数字,拼凑出和 QQ 的过往朝夕,引起用户共鸣。鹅厂不断创新探索的同时,也为用户温存属于用户自己的专属回忆,深化 QQ 的品牌价值。
福利
考虑到部分同学想更仔细地查看、保存或收藏高清大图的需求,我们设置了关键词,微信公众号后台以「spaceQQ+序号」的方式回复,例如「spaceQQ1」,即可逐一获取对应的高清头像和壁纸。
扫码领取专属「个人轨迹」:
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务。
如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里
加粗样式
***@TOC
欢迎使用Markdown编辑器
你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章,了解一下Markdown的基本语法知识。
新的改变
我们对Markdown编辑器进行了一些功能拓展与语法支持,除了标准的Markdown编辑器功能,我们增加了如下几点新功能,帮助你用它写博客:
全新的界面设计 ,将会带来全新的写作体验;
在创作中心设置你喜爱的代码高亮样式,Markdown 将代码片显示选择的高亮样式 进行展示;
增加了 图片拖拽 功能,你可以将本地的图片直接拖拽到编辑区域直接展示;
全新的 KaTeX数学公式 语法;
增加了支持甘特图的mermaid语法1 功能;
增加了 多屏幕编辑 Markdown文章功能;
增加了 焦点写作模式、预览模式、简洁写作模式、左右区域同步滚轮设置 等功能,功能按钮位于编辑区域与预览区域中间;
增加了 检查列表 功能。
功能快捷键
撤销:Ctrl/Command + Z
重做:Ctrl/Command + Y
加粗:Ctrl/Command + B
斜体:Ctrl/Command + I
标题:Ctrl/Command + Shift + H
无序列表:Ctrl/Command + Shift + U
有序列表:Ctrl/Command + Shift + O
检查列表:Ctrl/Command + Shift + C
插入代码:Ctrl/Command + Shift + K
插入链接:Ctrl/Command + Shift + L
插入图片:Ctrl/Command + Shift + G
合理的创建标题,有助于目录的生成
直接输入1次#,并按下space后,将生成1级标题。
输入2次#,并按下space后,将生成2级标题。
以此类推,我们支持6级标题。有助于使用TOC语法后生成一个完美的目录。
如何改变文本的样式
强调文本 强调文本
加粗文本 加粗文本
标记文本
删除文本
引用文本
H2O is是液体。
210 运算结果是 1024.
插入链接与图片
链接: link.
图片:
带尺寸的图片:
居中的图片:
居中并且带尺寸的图片:
当然,我们为了让用户更加便捷,我们增加了图片拖拽功能。
如何插入一段漂亮的代码片
去博客设置页面,选择一款你喜欢的代码片高亮样式,下面展示同样高亮的 代码片.
// An highlighted block
var foo = 'bar';
1
2
生成一个适合你的列表
项目
项目
项目
项目1
项目2
项目3
计划任务
完成任务
创建一个表格
一个简单的表格是这么创建的:
项目 Value
电脑 $1600
手机 $12
导管 $1
设定内容居中、居左、居右
使用:---------:居中
使用:----------居左
使用----------:居右
第一列 第二列 第三列
第一列文本居中 第二列文本居右 第三列文本居左
SmartyPants
SmartyPants将ASCII标点字符转换为“智能”印刷标点HTML实体。例如:
TYPE ASCII HTML
Single backticks 'Isn't this fun?' ‘Isn’t this fun?’
Quotes "Isn't this fun?" “Isn’t this fun?”
Dashes -- is en-dash, --- is em-dash – is en-dash, — is em-dash
创建一个自定义列表
Markdown
Text-to-HTML conversion tool
Authors
John
Luke
如何创建一个注脚
一个具有注脚的文本。2
注释也是必不可少的
Markdown将文本转换为 HTML。
KaTeX数学公式
您可以使用渲染LaTeX数学表达式 KaTeX:
Gamma公式展示 Γ(n)=(n−1)!∀n∈N \Gamma(n) = (n-1)!\quad\foralln\in\mathbb NΓ(n)=(n−1)!∀n∈N 是通过欧拉积分
Unexpected text node: ' 'Unexpected text node: ' '
Γ(z)=∫
0
∞
t
z−1
e
−t
dt.
你可以找到更多关于的信息 LaTeX 数学表达式here.
新的甘特图功能,丰富你的文章
Mon 06
Mon 13
Mon 20
已完成
进行中
计划一
计划二
现有任务
Adding GANTT diagram functionality to mermaid
关于 甘特图 语法,参考 这儿,
UML 图表
可以使用UML图表进行渲染。 Mermaid. 例如下面产生的一个序列图::
张三
李四
王五
你好!李四, 最近怎么样?
你最近怎么样,王五?
我很好,谢谢!
我很好,谢谢!
李四想了很长时间,文字太长了不适合放在一行.
打量着王五...
很好... 王五, 你怎么样?
张三
李四
王五
这将产生一个流程图。:
链接
长方形
圆
圆角长方形
菱形
关于 Mermaid 语法,参考 这儿,
FLowchart流程图
我们依旧会支持flowchart的流程图:
开始
我的操作
确认?
结束
yes
no
关于 Flowchart流程图 语法,参考 这儿.
导出与导入
导出
如果你想尝试使用此编辑器, 你可以在此篇文章任意编辑。当你完成了一篇文章的写作, 在上方工具栏找到 文章导出 ,生成一个.md文件或者.html文件进行本地保存。
导入
如果你想加载一篇你写过的.md文件或者.html文件,在上方工具栏可以选择导入功能进行对应扩展名的文件导入,
继续你的创作。
mermaid语法说明 ↩︎
注脚的解释 ↩︎
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务。
如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里
1. 如何实现一个响应式对象
最近在看 Vue 的源码,其中最核心基础的一块就是 Observer/Watcher/Dep, 简而言之就是,Vue 是如何拦截数据的读写, 如果实现对应的监听,并且特定的监听执行特定的回调或者渲染逻辑的。总的可以拆成三大块来说。这一块,主要说的是 Vue 是如何将一个 plain object 给处理成 reactive object 的,也就是,Vue 是如何拦截拦截对象的 get/set 的
我们知道,用 Object.defineProperty 拦截数据的 get/set 是 vue 的核心逻辑之一。这里我们先考虑一个最简单的情况 一个 plain obj 的数据,经过你的程序之后,使得这个 obj 变成 Reactive Obj (不考虑数组等因素,只考虑最简单的基础数据类型,和对象):
如果这个 obj 的某个 key 被 get, 则打印出 get ${key} - ${val} 的信息
如果这个 obj 的某个 key 被 set, 如果监测到这个 key 对应的 value 发生了变化,则打印出 set ${key} - ${val} - ${newVal} 的信息。
对应的简要代码如下:
Observer.js
export class Observer {
constructor(obj) {
this.obj = obj;
this.transform(obj);
}
// 将 obj 里的所有层级的 key 都用 defineProperty 重新定义一遍, 使之 reactive
transform(obj) {
const _this = this;
for (let key in obj) {
const value = obj[key];
makeItReactive(obj, key, value);
}
}
}
function makeItReactive(obj, key, val) {
// 如果某个 key 对应的 val 是 object, 则重新迭代该 val, 使之 reactive
if (isObject(val)) {
const childObj = val;
new Observer(childObj);
}
// 如果某个 key 对应的 val 不是 Object, 而是基础类型,我们则对这个 key 进行 defineProperty 定义
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get: () => {
console.info(`get ${key}-${val}`)
return val;
},
set: (newVal) => {
// 如果 newVal 和 val 相等,则不做任何操作(不执行渲染逻辑)
if (newVal === val) {
return;
}
// 如果 newVal 和 val 不相等,且因为 newVal 为 Object, 所以先用 Observer迭代 newVal, 使之 reactive, 再用 newVal 替换掉 val, 再执行对应操作(渲染逻辑)
else if (isObject(newVal)) {
console.info(`set ${key} - ${val} - ${newVal} - newVal is Object`);
new Observer(newVal);
val = newVal;
}
// 如果 newVal 和 val 不相等,且因为 newVal 为基础类型, 所以用 newVal 替换掉 val, 再执行对应操作(渲染逻辑)
else if (!isObject(newVal)) {
console.info(`set ${key} - ${val} - ${newVal} - newVal is Basic Value`);
val = newVal;
}
}
})
}
function isObject(data) {
if (typeof data === 'object' && data != 'null') {
return true;
}
return false;
}
index.js
import { Observer } from './source/Observer.js';
// 声明一个 obj,为 plain Object
const obj = {
a: {
aa: 1
},
b: 2,
}
// 将 obj 整体 reactive 化
new Observer(obj);
// 无输出
obj.b = 2;
// set b - 2 - 3 - newVal is Basic Value
obj.b = 3;
// set b - 3 - [object Object] - newVal is Object
obj.b = {
bb: 4
}
// get b-[object Object]
obj.b;
// get a-[object Object]
obj.a;
// get aa-1
obj.a.aa
// set aa - 1 - 3 - newVal is Basic Value
obj.a.aa = 3
这样,我们就完成了 Vue 的第一个核心逻辑, 成功把一个任意层级的 plain object 转化成 reactive object
2. 如何实现一个 watcher
前面讲的是如何将 plain object 转换成 reactive object. 接下来讲一下,如何实现一个watcher.
实现的伪代码应如下:
伪代码
// 传入 data 参数新建新建一个 vue 对象
const v = new Vue({
data: {
a:1,
b:2,
}
});
// watch data 里面某个 a 节点的变动了,如果变动,则执行 cb
v.$watch('a',function(){
console.info('the value of a has been changed !');
});
// watch data 里面某个 b 节点的变动了,如果变动,则执行 cb
v.$watch('b',function(){
console.info('the value of b has been changed !');
})
Vue.js
// 引入将上面中实现的 Observer
import { Observer } from './Observer.js';
import { Watcher } from './Watcher.js';
export default class Vue {
constructor(options) {
// 在 this 上挂载一个公有变量 $options ,用来暂存所有参数
this.$options = options
// 声明一个私有变量 _data ,用来暂存 data
let data = this._data = this.$options.data
// 在 this 上挂载所有 data 里的 key 值, 这些 key 值对应的 get/set 都被代理到 this._data 上对应的同名 key 值
Object.keys(data).forEach(key => this._proxy(key));
// 将 this._data 进行 reactive 化
new Observer(data, this)
}
// 对外暴露 $watch 的公有方法,可以对某个 this._data 里的 key 值创建一个 watcher 实例
$watch(expOrFn, cb) {
// 注意,每一个 watcher 的实例化都依赖于 Vue 的实例化对象, 即 this
new Watcher(this, expOrFn, cb)
}
// 将 this.keyName 的某个 key 值的 get/set 代理到 this._data.keyName 的具体实现
_proxy(key) {
var self = this
Object.defineProperty(self, key, {
configurable: true,
enumerable: true,
get: function proxyGetter() {
return self._data[key]
},
set: function proxySetter(val) {
self._data[key] = val
}
})
}
}
Watch.js
// 引入Dep.js, 是什么我们待会再说
import { Dep } from './Dep.js';
export class Watcher {
constructor(vm, expOrFn, cb) {
this.cb = cb;
this.vm = vm;
this.expOrFn = expOrFn;
// 初始化 watcher 时, vm._data[this.expOrFn] 对应的 val
this.value = this.get();
}
// 用于获取当前 vm._data 对应的 key = expOrFn 对应的 val 值
get() {
Dep.target = this;
const value = this.vm._data[this.expOrFn];
Dep.target = null;
return value;
}
// 每次 vm._data 里对应的 expOrFn, 即 key 的 setter 被触发,都会调用 watcher 里对应的 update方法
update() {
this.run();
}
run() {
// 这个 value 是 key 被 setter 调用之后的 newVal, 然后比较 this.value 和 newVal, 如果不相等,则替换 this.value 为 newVal, 并执行传入的cb.
const value = this.get();
if (value !== this.value) {
this.value = value;
this.cb.call(this.vm);
}
}
}
对于什么是 Dep, 和 Watcher 里的 update() 方法到底是在哪个时候被谁调用的,后面会说
3. 如何收集 watcher 的依赖
前面我们讲了 watcher 的大致实现,以及 Vue 代理 data 到 this 上的原理。现在我们就来梳理一下,Observer/Watcher 之间的关系,来说明它们是如何调用的.
首先, 我们要来理解一下 watcher 实例的概念。实际上 Vue 的 v-model, v-bind , {{ mustache }}, computed, watcher 等等本质上是分别对 data 里的某个 key 节点声明了一个 watcher 实例.
<input v-model="abc">
<span>{{ abc }}</span>
<p :data-key="abc"></p>
...
const v = new Vue({
data:{
abc: 111,
}
computed:{
cbd:function(){
return `${this.abc} after computed`;
}
watch:{
abc:function(val){
console.info(`${val} after watch`)
}
}
}
})
这里,Vue 一共声明了 4 个 watcher 实例来监听abc, 1个 watcher 实例来监听 cbd. 如果 abc 的值被更改,那么 4 个 abc - watcher 的实例会执行自身对应的特定回调(比如重新渲染dom,或者是打印信息等等)
不过,Vue 是如何知道,某个 key 对应了多少个 watcher, 而 key 对应的 value 发生变化后,又是如何通知到这些 watcher 来执行对应的不同的回调的呢?
实际上更深层次的逻辑是:
在 Observer阶段,会为每个 key 都创建一个 dep 实例。并且,如果该 key 被某个 watcher 实例 get, 把该 watcher 实例加入 dep 实例的队列里。如果该 key 被 set, 则通知该 key 对应的 dep 实例, 然后 dep 实例会将依次通知队列里的 watcher 实例, 让它们去执行自身的回调方法
dep 实例是收集该 key 所有 watcher 实例的地方.
watcher 实例用来监听某个 key ,如果该 key 产生变化,便会执行 watcher 实例自身的回调
相关代码如下:
Dep.js
export class Dep {
constructor() {
this.subs = [];
}
// 将 watcher 实例置入队列
addSub(sub) {
this.subs.push(sub);
}
// 通知队列里的所有 watcher 实例,告知该 key 的 对应的 val 被改变
notify() {
this.subs.forEach((sub, index, arr) => sub.update());
}
}
// Dep 类的的某个静态属性,用于指向某个特定的 watcher 实例.
Dep.target = null
observer.js
import {Dep} from './dep'
function makeItReactive(obj, key, val) {
var dep = new Dep()
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get: () => {
// 收集依赖! 如果该 key 被某个 watcher 实例依赖,则将该 watcher 实例置入该 key 对应的 dep 实例里
if(Dep.target){
dep.addSub(Dep.target)
}
return val
},
set: (newVal) => {
if (newVal === val) {
return;
}
else if (isObject(newVal)) {
new Observer(newVal);
val = newVal;
// 通知 dep 实例, 该 key 被 set,让 dep 实例向所有收集到的该 key 的 watcher 实例发送通知
dep.notify()
}
else if (!isObject(newVal)) {
val = newVal;
// 通知 dep 实例, 该 key 被 set,让 dep 实例向所有收集到的该 key 的 watcher 发送通知
dep.notify()
}
}
})
}
watcher.js
import { Dep } from './Dep.js';
export class Watcher {
constructor(vm, expOrFn, cb) {
this.cb = cb;
this.vm = vm;
this.expOrFn = expOrFn;
this.value = this.get();
}
get() {
// 在实例化某个 watcher 的时候,会将Dep类的静态属性 Dep.target 指向这个 watcher 实例
Dep.target = this;
// 在这一步 this.vm._data[this.expOrFn] 调用了 data 里某个 key 的 getter, 然后 getter 判断类的静态属性 Dep.target 不为null, 而为 watcher 的实例, 从而把这个 watcher 实例添加到 这个 key 对应的 dep 实例里。 巧妙!
const value = this.vm._data[this.expOrFn];
// 重置类属性 Dep.target
Dep.target = null;
return value;
}
// 如果 data 里的某个 key 的 setter 被调用,则 key 会通知到 该 key 对应的 dep 实例, 该Dep实例, 该 dep 实例会调用所有 依赖于该 key 的 watcher 实例的 update 方法。
update() {
this.run();
}
run() {
const value = this.get();
if (value !== this.value) {
this.value = value;
// 执行 cb 回调
this.cb.call(this.vm);
}
}
}
总结:
至此, Watcher, Observer , Dep 的关系全都梳理完成。而这些也是 Vue 实现的核心逻辑之一。再来简单总结一下三者的关系,其实是一个简单的 观察-订阅 的设计模式, 简单来说就是, 观察者观察数据状态变化, 一旦数据发生变化,则会通知对应的订阅者,让订阅者执行对应的业务逻辑 。我们熟知的事件机制,就是一种典型的观察-订阅的模式
Observer, 观察者,用来观察数据源变化.
Dep, 观察者和订阅者是典型的 一对多 的关系,所以这里设计了一个依赖中心,来管理某个观察者和所有这个观察者对应的订阅者的关系, 消息调度和依赖管理都靠它。
Watcher, 订阅者,当某个观察者观察到数据发生变化的时候,这个变化经过消息调度中心,最终会传递到所有该观察者对应的订阅者身上,然后这些订阅者分别执行自身的业务回调即可
参考
Vue源码解读-滴滴FED
代码参考
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务。
如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里
视觉设计师作为展示产品最终形态的执行层,产品上线前走查视觉与交互还原是必经环节,而留给设计师走查修改的时间其实非常少,有时候为了配合产品上线时间,通常只能牺牲一些细节,在下一次迭代进行优化。为了每一次上线的产品都能够得到更好地还原,这就需要设计师去了解开发到底是根据哪些规则还原我们的设计稿,以及在每一次制作和交付设计稿的时候,我们应如何设定好每一个细节的规则。开发:这里已经完全对齐了。
视觉:看起来还没完全对齐,我的图也没有切错吧?
开发:字体大小和间距都是按照视觉稿来的。
视觉:这里间距偏差这么大,为什么不按照视觉稿?
开发:视觉样式好多,每个设计师的间距好像都不一样。
视觉:……
我们经常会听到身边的设计师与开发小哥的一些对话,关于对齐、大小、间距等设计还原问题经常会讨论很久,有时甚至会觉得,几个像素的间距是不是没有必要这么纠结。以我较常接触的云产品官网为例,云产品官网体量庞大,单个页面或信息模块的样式复用可高达上百个子产品页面,此时第一个模块设计的规范性、扩展性、复用性则变得尤为重要,所以为了让设计方案更加合理,为了让合作更加,这里总结一些设计经验,与大家一起探讨。
本文将从以下三个方面,思考作为视觉设计师,应当如何让设计更加合理有效:
1. 字体结构
网页设计中,我们总避免不了与字体打交道,字体也是我们在设计中经常容易忽视的部分,而经常出错的原因往往是因为我们对文字的理解不够清晰。相比西文字体,中文字体结构复杂,字库庞大,网页的渲染效果会比西文字体艰难很多。
但无论是中文还是西文,我们经常需要用到的无非是字体大小、字重、字色,还有就是经常被我们忽视的行高和行宽,我们从西文字体提取三个最主要的因素,即字高、行高、行宽。基于西文字体的结构转换为中文,我们可以理解为,字高指的就是我们肉眼所能看到的字体的实际高度,而行高指的是字高+上边距+下边距,反过来说,行高减去字高除以 2 就能得到我们的上下边距,行宽指的就是整个文本的宽度。
举一个图文模块的例子,图(1)中我们肉眼所看到间距,在我们做标注时,看到的其实是图(2)中的三个色块,我们实际给到开发的标注,是色块的尺寸和色块之间的间距,以及详细的文本属性。
2. 文字行宽
关于行宽,以设计 banner 的标题及描述文字为例,定义行宽是为了让文本在极限宽度的时候进行换行,再固定好配图的尺寸,从而得到文本与配图之间的间距,定义行宽、行数、字数,能够更好地为运营人员规范输出的文案,避免因字数过多或过少所造成的视觉不平衡。
当我们处理无序列表时,四个短句文本,长短不一,同样我们需要限制一行文本宽度,定义一行能承载的最多字数,以及跟产品确认可能出现的最多字数的情况,确认模块设计的可行性,保证后续运营人员在替换文案的时候不会出错。
以上两个例子都是我们设计文字经常出错的地方,正确的定义规范,无论是交付开发或者其他下游,都能保证模块设计的可扩展性及规范化,保证最终上线质量。
3. 图标视错觉
关于图标,这里提到一个几何学错觉的概念,视觉上的大小、长度、面积、方向、角度等几何构成,和实际上测得的数字有明显差别的错觉,称为几何学错觉。人眼所接受的视觉平衡,往往不是设计软件上精准的对齐,我们总是会通过调整间距、大小或角度来补齐一些负空间,让画面保持视觉平衡。
以客户案例的卡片样式为例,客户案例在 to B 产品中是必不可少的模块,我们的客户 logo 有的圆形,有的长方形,有的纯文字,尺寸差距比较悬殊,这种情况下我们需要给他限制一个高度,在这个高度以内,再根据 logo 本身的体量来调整图形的大小,处理好 logo 的视觉平衡,最后红色区域是 logo 的实际尺寸,蓝色区域则是我们实际给到开发的尺寸,从开发的角度来看其实就是占位符,而规范的作图则是把占位符的透明度调整为 0,以占位符为实际有效作图区。
UI 设计中通常以「向右箭头」来表示当前链接可跳转,使用箭头作图时,当我们把箭头和文字右对齐,箭头其实会更加的往外突出,这时候我们会人为的往里边推 1 至 2 像素,最后实际给到开发的也应该是红框的尺寸,也就是 16×16 的占位图尺寸。
「按钮」也是 UI 设计中常用的组件,当我们在按钮里使用图标加文字时,由于文字的体量更大,整体重心会往右偏,所以我们通常会认为让图标和文字整体往左偏移,使整体的视觉更加平衡,实际给到开发的,也是两个不同等的边距。
1. 理性的设计
在 iOS 和 Android 的设计规范中,都有提到过使用「8点栅格」的概念,即建议使用 8×8 的网格系统进行设计,我们都知道 0.5px 的渲染在屏幕上会变模糊,之所以使用 8 的倍数是因为市场上主流的屏幕都能被 8 整除,使用 8 点栅格能够的让我们所设计的内容样式在屏幕上保持高清显示,而在日常的网页设计中,我其实更加倾向使用 4 点栅格系统。
我们以下图 4 组数列为例,大家可能都曾使用过上面三组蓝色数列中的数值应用到设计中,或以 5 为倍数,或以 10 为倍数、或以偶数为设计逻辑,而实际上以 5 为倍数则会包含奇数,奇数会导致控件文字对不齐,当 5 的倍数和偶数同时使用时,则会出现类似 14、15、16 这种相差为 1 的相邻数,这样会导致我们的尺寸规范不好定义规则,难以形成逻辑,而使用 4 的倍数,他们的公差为 4,不会出现奇数,也不会出现相邻数。
我们再看看一些通用的尺寸定义,例如常见的 icon 设计尺寸都是以 4 为倍数。
常见的网页栅格及其所均分的卡片和间距,也都是 4 的倍数,如果我们的控件尺寸,图标尺寸和间距都使用 4 的倍数来定义,那所有的信息模块自然都能更好的相互适应,层层递进的逻辑关系也会更加明显。
我们把 4 点栅格的设计逻辑套用到卡片设计上,第一眼我们可能比较难去评判两者的好坏,但仔细看,我们就会发现第一个卡片的按钮没有水平对齐,相互之间的间距尺寸也是没什么逻辑性。假如今天调整一个 8px 的间距,明天调一个 10px 的间距,设计师走查起来也很难发现有问题,对接的开发也难以有一个可以参考的规范标准。而相对的,以 4 为倍数,我们会发现所有的信息都会完美对齐,而且倍数为 4 的每个数值之间公差为 4,即使设计稿微调了 1px 我们都能很快发现,开发在还原设计稿时也会有一个衡量标准。
网格设计在报纸、杂志、海报等平面设计领域中也是十分常见的设计手法,通过建立网格,考究每一个信息模块在页面中的摆放位置,大小占比,颜色占比,从而使得页面信息保持秩序、均衡。
使用 4 点栅格系统,通过理性、秩序、逻辑的设计方式赋予画面秩序感以及阅读体验,而以 4 为倍数,每个数字之间都相差为 4,不会太大,也不会太小,同时保持着秩序,让设计更加理性。对于团队合作,设计师与开发也将更有默契,不必再为不清不楚的间距浪费时间。
1. 有效切图
关于切图,切图之前应跟开发确定好输出的格式和尺寸,确定应该用 SVG,一倍图或是两倍图。SVG 体量小渲染质量好,单色使用时还能替换颜色,PNG 则通常用在实景图,一倍图和二倍图则根据实际需要进行输出。
如果要做分层动画,那我们就需要分层切图,如果桌面端和手机端样式差别较大,那我们需要和开发沟通好如何实现,是否需要特殊切图,所有的特殊切图和特殊样式,我们都应该提前跟开发沟通好。
2. 交互细节
如果某个控件或信息模块交互样式较多,那我们可以有一个空白画板来清晰地标注这些状态和样式,很多开发在还原过程中都是一手视觉稿一手交互稿,但视觉设计师作为展示产品最终形态的执行层,很多情况下,视觉阶段依然会有很多需要跟交互和产品沟通修改的地方,所以为了避免遗漏修改点,视觉稿应该呈现最完整的设计细节,这样也会很大程度上节省开发的时间,减少出错的几率。
当页面内容有一定的更新频率,我们则需要标明视觉样式规范,以及后续的运营规则,完整的收尾,可以避免产品经常过来寻求上线素材和规范。有些需要隔三个月或半年才上线的需求,清晰的标注也能帮助我们快速回忆起需求背景,让我们在日常工作中保持头脑清晰,有条不紊,这其实也是在给我们自己节省时间。
3. 重构稿走查
走查还原的时候,在 Chrome 浏览器的空白处右键点击检查,找到里面的 Computed 窗口,我们可以找到具体的文字、间距、投影等属性,有时候一些比较细微的调整,我们可以双击具体的数值进行调整,调整到自己满意之后再把具体的数值给到开发,这样就不用在我们摇摆不定的情况下,造成双方的困扰。
最后,在预发布的时候,我们可以利用 SwitchHosts 的客户端来配置开发环境进行体验,保证最终上线的效果。
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务。
如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里
如何爬去爬去今日头条动态数据,
网上有很多教程,我就不在啰嗦了
第一步如何分析得到存储数据的真实url
首先打开https://www.toutiao.com/,搜索街拍,会跳转https://www.toutiao.com/search/?keyword=%E8%A1%97%E6%8B%8D
你如果用传统的方式你将的得不到任何有价值的信息
这个时候你怎么办呢?
你这个时候注意查看requests url,
Request URL: https://www.toutiao.com/api/search/content/?aid=24&app_name=web_search&offset=0&format=json&keyword=街拍&autoload=true&count=20&en_qc=1&cur_tab=1&from=search_tab&pd=synthesis×tamp=1559831008973
到这里我们就找到了数据春芳的真正url了
你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章,了解一下Markdown的基本语法知识。
后面就简单了,直接上代码
import os
import re
import json
import requests
from requests import RequestException
from requests import exceptions
from urllib.parse import urlencode
from demo01.util import buid_proxy
‘’’
抓取今日头条图片图片集
因为今天头条数据是动态,因此第一步是找到存储图片的真正url
第二步就是构造浏览器(伪浏览器),因为现在防爬网站做的很好,他会更具某项标准你是否是机器人,因此这步很重要
‘’’
proxies=buid_proxy()
def get_one_page(offset, keyword):
‘’’
获取网页html内容并返回
‘’’
params = {
‘aid’: ‘24’,
‘app_name’: ‘web_search’,
‘offset’: offset,
‘format’: ‘json’,
‘keyword’:keyword,
‘autoload’: ‘true’,
‘count’: ‘20’,
‘cur_tab’: ‘1’,
‘from’: ‘search_tab’,
‘pd’: ‘synthesis’,
‘timestamp’: ‘1559660659001’}
header = {
"User-Agen":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36",
"referer":"https://www.toutiao.com/search/?keyword=%E8%A1%97%E6%8B%8D",
"cookie":"tt_webid=6692573135994799624; UM_distinctid=16ace1c56988c-06f62adc4fd369-7a1437-144000-16ace1c5699a3; csrftoken=368635b7c1d736ff1889c2b70705afa9; tt_webid=6692573135994799624; WEATHER_CITY=%E5%8C%97%E4%BA%AC; s_v_web_id=152a5d87eb7690f9953388e50371f37b; CNZZDATA1259612802=1893030441-1558619693-https%253A%252F%252Flanding.toutiao.com%252F%7C1559662594; _ga=GA1.2.569135354.1559664708; _gid=GA1.2.419995265.1559664708; __tasessionId=wb39ej38m1559741348358",
}
url = 'https://www.toutiao.com/api/search/content/?' + urlencode(params)
#print(url)
try:
# 获取网页内容,返回json格式数据
response = requests.get(url, headers=header,proxies=proxies)
# 通过状态码判断是否获取成功
if response.status_code == 200:
#此处必须这样写不然会出现中文乱码
response=response.content.decode('utf-8')
html=response
return html
return None
except RequestException:
return None
def parse_one_page(html):
‘’’
解析出组图网址,并将网页中所有图集的标题及图片地址返回
‘’’
urls = []
data = json.loads(html,encoding=‘utf-8’)
if data and ‘data’ in data.keys():
for item in data.get(‘data’):
#print(item)
page_urls = []
title = item.get(‘title’)
#print(title)
image_list = item.get(‘image_list’)
if image_list !=None:
for i in range(len(image_list)):
# 获取large图片地址
url = image_list[i][‘url’]
# 替换URL获取高清原图
url = url.replace(‘large’, ‘origin’)
page_urls.append(url)
urls.append({‘title’: title,‘url_list’: page_urls})
return urls
def save_image_file(url, path):
‘’’
保存图像文件
‘’’
ir = requests.get(url)
if ir.status_code == 200:
with open(path, ‘wb’) as f:
f.write(ir.content)
f.close()
def main(offset, word):
html = get_one_page(offset, word)
#print(html)
urls = parse_one_page(html)
print(urls)
#图像文件夹不存在则创建
root_path = 'E:/test001/photo/TOUTIAO'
if not os.path.exists(root_path):
os.mkdir(root_path)
for i in range(len(urls)):
print('---正在下载 %s'%urls[i]['title'])
folder = root_path + '/' + urls[i]['title']
if not os.path.exists(folder):
try:
os.mkdir(folder)
except NotADirectoryError:
continue
except OSError:
continue
url_list = urls[i]['url_list']
try:
for j in range(len(url_list)):
path = folder + '/index_' + str("%02d"%j) + '.jpg'
if not os.path.exists(path):
save_image_file(urls[i]['url_list'][j], path)
except exceptions.ProxyError:
return None
if name == ‘main’:
main(0,‘街拍’)
新的改变
我们对Markdown编辑器进行了一些功能拓展与语法支持,除了标准的Markdown编辑器功能,我们增加了如下几点新功能,帮助你用它写博客:
全新的界面设计 ,将会带来全新的写作体验;
在创作中心设置你喜爱的代码高亮样式,Markdown 将代码片显示选择的高亮样式 进行展示;
增加了 图片拖拽 功能,你可以将本地的图片直接拖拽到编辑区域直接展示;
全新的 KaTeX数学公式 语法;
增加了支持甘特图的mermaid语法1 功能;
增加了 多屏幕编辑 Markdown文章功能;
增加了 焦点写作模式、预览模式、简洁写作模式、左右区域同步滚轮设置 等功能,功能按钮位于编辑区域与预览区域中间;
增加了 检查列表 功能。
功能快捷键
撤销:Ctrl/Command + Z
重做:Ctrl/Command + Y
加粗:Ctrl/Command + B
斜体:Ctrl/Command + I
标题:Ctrl/Command + Shift + H
无序列表:Ctrl/Command + Shift + U
有序列表:Ctrl/Command + Shift + O
检查列表:Ctrl/Command + Shift + C
插入代码:Ctrl/Command + Shift + K
插入链接:Ctrl/Command + Shift + L
插入图片:Ctrl/Command + Shift + G
合理的创建标题,有助于目录的生成
直接输入1次#,并按下space后,将生成1级标题。
输入2次#,并按下space后,将生成2级标题。
以此类推,我们支持6级标题。有助于使用TOC语法后生成一个完美的目录。
如何改变文本的样式
强调文本 强调文本
加粗文本 加粗文本
标记文本
删除文本
引用文本
H2O is是液体。
210 运算结果是 1024.
插入链接与图片
链接: link.
图片:
带尺寸的图片:
居中的图片:
居中并且带尺寸的图片:
当然,我们为了让用户更加便捷,我们增加了图片拖拽功能。
如何插入一段漂亮的代码片
去博客设置页面,选择一款你喜欢的代码片高亮样式,下面展示同样高亮的 代码片.
// An highlighted block
var foo = 'bar';
1
2
生成一个适合你的列表
项目
项目
项目
项目1
项目2
项目3
计划任务
完成任务
创建一个表格
一个简单的表格是这么创建的:
项目 Value
电脑 $1600
手机 $12
导管 $1
设定内容居中、居左、居右
使用:---------:居中
使用:----------居左
使用----------:居右
第一列 第二列 第三列
第一列文本居中 第二列文本居右 第三列文本居左
SmartyPants
SmartyPants将ASCII标点字符转换为“智能”印刷标点HTML实体。例如:
TYPE ASCII HTML
Single backticks 'Isn't this fun?' ‘Isn’t this fun?’
Quotes "Isn't this fun?" “Isn’t this fun?”
Dashes -- is en-dash, --- is em-dash – is en-dash, — is em-dash
创建一个自定义列表
Markdown
Text-to-HTML conversion tool
Authors
John
Luke
如何创建一个注脚
一个具有注脚的文本。2
注释也是必不可少的
Markdown将文本转换为 HTML。
KaTeX数学公式
您可以使用渲染LaTeX数学表达式 KaTeX:
Gamma公式展示 Γ(n)=(n−1)!∀n∈N \Gamma(n) = (n-1)!\quad\foralln\in\mathbb NΓ(n)=(n−1)!∀n∈N 是通过欧拉积分
Unexpected text node: ' 'Unexpected text node: ' '
Γ(z)=∫
0
∞
t
z−1
e
−t
dt.
你可以找到更多关于的信息 LaTeX 数学表达式here.
新的甘特图功能,丰富你的文章
Mon 06
Mon 13
Mon 20
已完成
进行中
计划一
计划二
现有任务
Adding GANTT diagram functionality to mermaid
关于 甘特图 语法,参考 这儿,
UML 图表
可以使用UML图表进行渲染。 Mermaid. 例如下面产生的一个序列图::
张三
李四
王五
你好!李四, 最近怎么样?
你最近怎么样,王五?
我很好,谢谢!
我很好,谢谢!
李四想了很长时间,文字太长了不适合放在一行.
打量着王五...
很好... 王五, 你怎么样?
张三
李四
王五
这将产生一个流程图。:
链接
长方形
圆
圆角长方形
菱形
关于 Mermaid 语法,参考 这儿,
FLowchart流程图
我们依旧会支持flowchart的流程图:
开始
我的操作
确认?
结束
yes
no
关于 Flowchart流程图 语法,参考 这儿.
导出与导入
导出
如果你想尝试使用此编辑器, 你可以在此篇文章任意编辑。当你完成了一篇文章的写作, 在上方工具栏找到 文章导出 ,生成一个.md文件或者.html文件进行本地保存。
导入
如果你想加载一篇你写过的.md文件或者.html文件,在上方工具栏可以选择导入功能进行对应扩展名的文件导入,
继续你的创作。
mermaid语法说明 ↩︎
注脚的解释 ↩︎
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务。
如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里
WWDC19 可能是最近几年最令人激动的苹果开发者大会了。重回高端专业领域的 Mac Pro 不仅仅是性能怪兽,在专业度、设计感甚至细节的模块化的设计上,体现出了苹果这一顶尖大厂应有的底蕴,说实话,考验民间硬件评测玩家们的资金实力和评测能力的时候到了。在发布Mac Pro 这一系列产品的环节,空耳几乎完全听不懂说的是啥,不过可以全程感知到每一个单词都是牛X的,苹果官方页面的介绍现在肯定是最有说服力的,因为最近的评测起码是要等到今年年底。
属于 iOS 13 的 Dark Mode 正正好好满足了所有人的想象,但是和简单直接的 Android Dark Mode 相比,又多出一丝优雅,非常苹果。拥有 App Store 和一连串新功能的 watchOS 终于成为了一个更加独立、功能强大的硬件设备了,而 tvOS …… 不是重点。
重点是,在 iOS 和 macOS 之间,硬生生多出了一个 iPadOS,这才是整个发布会上,最亮眼的星。
屏幕尺寸介于 iPhone 和 Mac 之间的 iPad ,一直沿用着交互机制相对比较简约的 iOS 。也正是因此,绝大多数的用户的重度需求,被电脑尤其是Mac 所分走了,而高频轻量的需求则被 iPhone 给分走了,iPad 系列产品在很多时候都是作为家庭娱乐设备而存在,你听到更多关于它的功能应用场景,是看视频追剧。
Apple Pencil 是这个系列的转折点。书写,创作,搭配键盘输入,屏幕尺寸从9.7 一路上探到 12.9,iPad 开始在触摸为王的时代,开始切入更多的使用场景。在学校里面越来越多的学生开始使用一台iPad 来作为 All in one 学习/娱乐设备,艺术家和音乐者开始使用 iPad 替代手绘板和合成器,AR和娱乐的结合也越来越紧密,从创作到专业领域,iPad 成为了越来越多轻应用场景的核心。
吃灰的 iPad 拥有了更多的可能性,而 iOS 的功能限制反倒成为了 iPad 短板,这大概也是 iPadOS 在整个生态中独立出来的最重要原因之一吧。
使用单一屏幕作为输入核心,围绕触摸来交互,以原有 iOS 作为开发核心,深入到更多的细分应用场景,连通 macOS 和 iOS ,iPadOS 的定位看似暧昧,实则在这个多元和高度垂直的时代,帮苹果趟出了第三条路。
iPadOS 的新布局看起来终于不那么 iPhone了,原有最左一屏的小组件汇集到主屏幕之后,看起来越来越有桌面的意思的。
……专为多点触摸的显示屏而设计,通过直观的手势实现多任务……它现在被称为iPadOS。
这是苹果给 iPadOS 所写的出道宣言。
比起 iOS 12 时代更强的分屏模式,发布会现场演示的时候,展示了使用托拽在多个应用之间快托拽内容和元素的操作,多屏互通效率极高。
而多任务不仅仅体现在多个应用之间的互动,同一个应用同样可以多屏存在——也就是我们常说的多任务。比如打开两个「提醒事项」应用,在两个笔记之间,来回编辑内容。点击Dock 中的特定应用图标,你就能看到它到底开了多少个页面。
仔细想想,这是不是和桌面端的系统的逻辑越来越接近了?
想成为了一个独立的设备,iPad 在用户输入端的短板需要补足,而为了解决这一问题,苹果为 iPadOS 精心定制化了一套组合拳:编辑手势,输入提速,外设支持。
快速输入是 iPad 的短板之一。不借助键盘而能快速输入的方法之一,就是单手快速输入。苹果在iPadOS 上使用了一个全局的小键盘,使用双指捏合快速呼出,全局浮动,使用QuichPath 滑动手势输入法,减少输入的难度。这就是使用输入法和键盘输入提速的方法之一。
长段落或者是其他内容,又要怎么编辑呢?苹果巧妙地将 Macbook 系列触控板的三指手势微调了一下,给迁移过来了:三指捏合是复制,三指散开是粘贴,而三指滑动是撤销。
而辅助快速编辑手势的, 是智能选取功能,光标定位比以往更加智能和精准,把编辑输入的最后一个短板也给补上了。
iPad 的多点触摸屏幕本就支持大量不同的手势,功能支持不是难点,难点在于用尽可能少、且认知度足够高的常见手势,以的认知负荷,让用户更快上手,更舒适地做到各种各样的事情。
以触摸为核心的交互,以及的指针的交互,在iPadOS 上交汇了。这种交互模式无疑是实验性的,但是这也是未来所有的移动端和数字产品的设计者都要考虑的问题,而iPadOS 就是最重要的试验田。
当然,外置键盘输入也并不是难事。iPad 本身的配套键盘套和第三方蓝牙键盘,多数有输入需求的用户都已经购置了,为此,苹果给iPadOS 搭配了丰富的快捷键,来辅助输入:
当然,输入这件事情上,Apple Pencil 也是非常重要的组成部分。苹果将系统自带的备忘录应用进行了重设计,其中很大一部分原因,就是为 Apple Pencil 提供更为强大的绘图功能:
这样一来,即使你没有购买第三方的绘图工具,同样可以用它画出足够漂亮的插画作品。除了特定APP中的手写输入和绘图这样的使用场景之外,Apple Pencil 还作为日常截图批注的主力,方便日常作笔记:
更好的输入,最终的目的,始终是为了更好地输出内容。
iPadOS 的野心很大。作为一块10英寸上下的屏幕之内的操作系统,它作为内容承载的硬件,是一个很合理的想象,不然也不会有那么多开发者一直在开发将iPad 作为外接屏幕的应用,而现在,用户只需要连上Wifi ,它就能作为 Mac的外接屏幕。
打通了这一个环节之后,后面的事情就自然而然了:Apple Pencil 可以在屏幕上画画,这样一来,它很自然而然就成了手绘板。发布会上,苹果官方所放出的图片当中,涵盖了多数设计师都在使用的设计软件,其中不乏 AI、AE、Pr、Sketch、C4D、Zbrush 这些大热设计工具。
更重要的一点在于,Apple Pencil 原本 20ms 的反应延迟,在这次的更新之后,将会达到9ms,反应速度提升了一倍以上!它已经是一个称职的手绘板了。
有意思的地方在于,并没有 PS。为什么?答案很简单啊,iPadOS平台上的原生 PS 马上就要来了啊!连上Adobe 的创意云,两个平台又呼应上了……
毕竟,想要打通细分的应用场景,iPadOS 是需要自身具备强大生产力的,这意味着大量的独立功能、服务和应用支撑。
想要 iPadOS 能够独立完成视觉创造的工作,对于多种字体的支持是肯定需要的。在iPad 上独立运行 Photoshop 也同样是需要这样的功能支撑的,所以,干脆官方提供支持了:
而值得注意的是,作为一个设计公司,苹果的想象力并不止于此。这次更新的功能当中,有一个非常引人瞩目的功能是 SF Symbols。
苹果将1000多个常见的 iOS 和 macOS 的图标和苹果官方的旧金山字体融为一体,这些图标和符号支持 iOS 13、iPadOS以及的 watchOS 6 和 tvOS 13,而且你还可以在官方的文档支持之下,自己创造!
具体可以戳这里了解:SF-symbols 使用文档
完全独立的 iPadOS 将会需要好好管理本地和云端的文件系统,官方将文件管理器进行了升级,确保它无需借助另外一台电脑来完成操作。
核心应用没有问题,和外接内容进入口也要一并升级。功能强大的 TypeC接口能够直接读取U盘和存储卡:
而作为主要的浏览器,Safari 浏览器也向着桌面端浏览器的方向进了优化和调整,比如支持下载:
此外,图片、照片和视频的本地管理和剪辑功能,也一并进行了升级,这也是为了让iPad 能够成为一个更加独立的产品而存在。
而真正改变游戏玩法的东西,在开发和设计上。
多年以前,苹果为了统一全平台的应用开发,开发语言从原本的 Obj-C 迁移到自家的 Swift 语言。随着移动端应用量的快速增长,移动端的应用数量其实早已超过 macOS 平台的开发数量和频度,这种变化也催生了 Project Catalyst。
图片来自 engatget
这个名为「催化剂」的项目的目标是希望开发者可以更加便捷地将 iOS 应用迁移到 macOS 上,比如说 Twitter 的开发者只花了几天时间,就将现有的 iOS APP 迁移到 macOS 上。紧随其后,成千上万的移动端应用将都可以逐步地反哺到 macOS 上。
但是 Project Catalyst 只是权宜之计,真正治根又治本的东西,则是这次的新的UI框架,SwiftUI。SwiftUI 是一个典型的原生应用框架,是苹果在磨合了上十年的经验之后,所创造出一个的UI开发框架,开发者仅仅只需要极少量的代码和交互式的设计,就能够调用这一框架。这一改变对于 iOS 平台的设计和开发都会有直接的影响。
在现场演示的时候,原本复杂无比的开发代码,在换用 SwiftUI 之后仅需几行代码声明就可以搞定:
新的 Xcode 11 当中,开发者可以使用托拽的方式来增删组件,而右侧的实时预览则能够呈现每一点改变。而基于 SwiftUI 的代码开发模式,可以快速复用迁移到整个苹果的产品平台上,比以往任何时候都要快:
关于SwiftUI 的相关文档:https://developer.apple.com/documentation/swiftui/
官方教程:https://developer.apple.com/tutorials/swiftui/
在新的 iPadOS 和 iOS13 中,系统的整体速度和性能得到了进一步的提升,解锁速度提升了30%,启动速度是以往的2倍,而应用的容量也比以往要小。
对,深色模式也是苹果这次 iOS 产品更新的最核心特点,甚至整个WWDC19 主题演讲环节的整体视觉设计也是完全沿用这种沉浸感极强的深色模式视觉来进行构建的。目前苹果的 HIG 当中 iOS 的章节中新增了 Dark mode 的章节,而 iPadOS 相关的系统的设计设计指南还未更新。
「在 iOS 13 及以上的版本当中,用户可以选择深色模式为默认的外观风格。在深色模式下,系统界面、视图、菜单和控件都会使用较暗的配色方案,并且让前景元素更加鲜艳,确保突出。用户可以选择选择深色模式作为默认的视觉风格,也可以通过设置,让它在光线较暗的时候,自动切换过去。需要注意的是,深色模式可以让人更加专注。在设计的时候,需要在浅色模式和深色模式中都进行测试,因为有些元素和配色在一种模式下可用,在另一种模式下并不一定适用。」
苹果目前在设计规范中所提供的设计要求相对比较简略,感兴趣的同学可以借助翻译工具看一下:Dark Mode
如果你对于深色模式感兴趣,我们还有文章提供给你:
由于目前苹果官方暂时没有更多的内容,我们可以把深色模式更多的内容留到今后来聊。
觉得社交网络帐号登录不够安全?Google 和 Facebook 两大巨头在发布会上成了反面案例,苹果适时地推出了自家的帐号登录服务。
苹果将产品和用户之间的边界划分得非常清晰,包括借助 Homekit 为用户提供基于本地存储的安全服务,在网上登录的时候使用经过加密的邮箱帐号,等等。
而被苹果点名的两家著名科技企业,Google 和 Facebook 也是在之前的 Google I/O 大会以及F8 大会上,相继针对隐私策略、安全服务进行了提升。
如果你对于这些大会感兴趣可以看看之前的文章:
和每年9月的新品发布相比,WWDC 的信息量一点都不小。尤其今年还有超赞的 Mac Pro,单开2篇文章都不一定聊得完。但是在我看来,和设计关系最紧密的产品,应该就是 iPadOS了。这个独特操作系统,巧妙地卡在一个独特的需求点上,它本身的设计和定位、用户体验的考量、服务用户的思路、牵涉到的功能和服务乃至于它对于设计的影响,都是巨大的。
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务。
如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里
Echarts数据化可视图表
开发工具与关键技术:Visual Studio 2015 使用Echarts图表
作者:郭海明
撰写时间:2019年 6月 4日
1
2
3
在创建一个网页的时候,有一些页面会有许多数据,浏览起来枯燥而乏味,而且数据之间的对比也不够明显。那么有什么方法可以让这些数据的对比明显起来,使数据看起来也没有那么枯燥呢!答案当然是有的,我们只需要引用Echarts数据可视化图表就可以了。使用Echarts数据化图表不仅可以让数据之间对比明显,还可以使数据更加生动起来,增强用户浏览页面数据的体验感。
Echarts提供了常规的折线图,柱状图,饼状图,散点图。还有用于统计的盒型图,用于地理数据可视化的地图,热力图,线图,用于关系数据可视化的关系图,多维数据可视化的平行坐标。还有用户BI的漏斗图,仪表盘,并且支持图与图之间的混搭。
Echarts图表使用起来的方法页很简单,首先将Echarts插件引用到视图里面,视图里面添加显示Echarts图表的类。给这个类显示图表的空间,并给类ID,用于后面写好图表之后将图表放到这个类里面。
然后在
将学生信息数据表格需要用到的数据表,进行多表的连接查询,连接完成之后,
获取到需要用到的数据,封装到自定义的AchievementInfor的实体类里面。
写出接收不同阶段成绩的方法。用于接收每个不同阶段的成绩.
写完之后,返回到视图里面去写调用Echarts的图表,这里我们显示的是折线图,所以首先在
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务。
蓝蓝设计的小编 http://www.lanlanwork.com