首页

用栈判断是否是回文字符串

seo达人

如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里

加粗样式
***@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界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务

Vue的响应式原理(MVVM)深入解析

seo达人

如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里

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界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务

腾讯设计师:如何让你的设计稿做到95%还原?

雪涛

如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里

视觉设计师作为展示产品最终形态的执行层,产品上线前走查视觉与交互还原是必经环节,而留给设计师走查修改的时间其实非常少,有时候为了配合产品上线时间,通常只能牺牲一些细节,在下一次迭代进行优化。为了每一次上线的产品都能够得到更好地还原,这就需要设计师去了解开发到底是根据哪些规则还原我们的设计稿,以及在每一次制作和交付设计稿的时候,我们应如何设定好每一个细节的规则。

开发:这里已经完全对齐了。

视觉:看起来还没完全对齐,我的图也没有切错吧?

开发:字体大小和间距都是按照视觉稿来的。

视觉:这里间距偏差这么大,为什么不按照视觉稿?

开发:视觉样式好多,每个设计师的间距好像都不一样。

视觉:……

我们经常会听到身边的设计师与开发小哥的一些对话,关于对齐、大小、间距等设计还原问题经常会讨论很久,有时甚至会觉得,几个像素的间距是不是没有必要这么纠结。以我较常接触的云产品官网为例,云产品官网体量庞大,单个页面或信息模块的样式复用可高达上百个子产品页面,此时第一个模块设计的规范性、扩展性、复用性则变得尤为重要,所以为了让设计方案更加合理,为了让合作更加,这里总结一些设计经验,与大家一起探讨。

本文将从以下三个方面,思考作为视觉设计师,应当如何让设计更加合理有效:

  • 视觉处理(设计)
  • 设计逻辑(方法)
  • 交付走查(合作)

视觉处理

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界面设计  包装设计  图标定制  用户体验 、交互设计、 网站建设 平面设计服务

爬去动态网站今日头条图片集

seo达人

如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里

如何爬去爬去今日头条动态数据,
网上有很多教程,我就不在啰嗦了
第一步如何分析得到存储数据的真实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&timestamp=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: '&ThinSpace;'Unexpected text node: '&ThinSpace;'
Γ(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界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务

还在用 iPad 看剧吗?苹果全新发布的 iPadOS 不止能让你做图了!

雪涛

如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里

WWDC19 可能是最近几年最令人激动的苹果开发者大会了。

重回高端专业领域的 Mac Pro 不仅仅是性能怪兽,在专业度、设计感甚至细节的模块化的设计上,体现出了苹果这一顶尖大厂应有的底蕴,说实话,考验民间硬件评测玩家们的资金实力和评测能力的时候到了。在发布Mac Pro 这一系列产品的环节,空耳几乎完全听不懂说的是啥,不过可以全程感知到每一个单词都是牛X的,苹果官方页面的介绍现在肯定是最有说服力的,因为最近的评测起码是要等到今年年底。

属于 iOS 13 的 Dark Mode 正正好好满足了所有人的想象,但是和简单直接的 Android Dark Mode 相比,又多出一丝优雅,非常苹果。拥有 App Store 和一连串新功能的 watchOS 终于成为了一个更加独立、功能强大的硬件设备了,而 tvOS …… 不是重点。

重点是,在 iOS 和 macOS 之间,硬生生多出了一个 iPadOS,这才是整个发布会上,最亮眼的星。

1、下沉:为更细分应用场景所设计的 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 的定位看似暧昧,实则在这个多元和高度垂直的时代,帮苹果趟出了第三条路。

2、分屏:向着桌面端进发的多任务交互

iPadOS 的新布局看起来终于不那么 iPhone了,原有最左一屏的小组件汇集到主屏幕之后,看起来越来越有桌面的意思的。

……专为多点触摸的显示屏而设计,通过直观的手势实现多任务……它现在被称为iPadOS。

这是苹果给 iPadOS 所写的出道宣言。

比起 iOS 12 时代更强的分屏模式,发布会现场演示的时候,展示了使用托拽在多个应用之间快托拽内容和元素的操作,多屏互通效率极高。

而多任务不仅仅体现在多个应用之间的互动,同一个应用同样可以多屏存在——也就是我们常说的多任务。比如打开两个「提醒事项」应用,在两个笔记之间,来回编辑内容。点击Dock 中的特定应用图标,你就能看到它到底开了多少个页面。

仔细想想,这是不是和桌面端的系统的逻辑越来越接近了?

3、编辑:无需键鼠一样精细化处理内容

想成为了一个独立的设备,iPad 在用户输入端的短板需要补足,而为了解决这一问题,苹果为 iPadOS 精心定制化了一套组合拳:编辑手势,输入提速,外设支持。

快速输入是 iPad 的短板之一。不借助键盘而能快速输入的方法之一,就是单手快速输入。苹果在iPadOS 上使用了一个全局的小键盘,使用双指捏合快速呼出,全局浮动,使用QuichPath 滑动手势输入法,减少输入的难度。这就是使用输入法和键盘输入提速的方法之一。

长段落或者是其他内容,又要怎么编辑呢?苹果巧妙地将 Macbook 系列触控板的三指手势微调了一下,给迁移过来了:三指捏合是复制,三指散开是粘贴,而三指滑动是撤销。

而辅助快速编辑手势的, 是智能选取功能,光标定位比以往更加智能和精准,把编辑输入的最后一个短板也给补上了。

iPad 的多点触摸屏幕本就支持大量不同的手势,功能支持不是难点,难点在于用尽可能少、且认知度足够高的常见手势,以的认知负荷,让用户更快上手,更舒适地做到各种各样的事情。

以触摸为核心的交互,以及的指针的交互,在iPadOS 上交汇了。这种交互模式无疑是实验性的,但是这也是未来所有的移动端和数字产品的设计者都要考虑的问题,而iPadOS 就是最重要的试验田。

当然,外置键盘输入也并不是难事。iPad 本身的配套键盘套和第三方蓝牙键盘,多数有输入需求的用户都已经购置了,为此,苹果给iPadOS 搭配了丰富的快捷键,来辅助输入:

当然,输入这件事情上,Apple Pencil 也是非常重要的组成部分。苹果将系统自带的备忘录应用进行了重设计,其中很大一部分原因,就是为 Apple Pencil 提供更为强大的绘图功能:

这样一来,即使你没有购买第三方的绘图工具,同样可以用它画出足够漂亮的插画作品。除了特定APP中的手写输入和绘图这样的使用场景之外,Apple Pencil 还作为日常截图批注的主力,方便日常作笔记:

更好的输入,最终的目的,始终是为了更好地输出内容。

4、输出:屏幕输出,手绘板,还有应用

iPadOS 的野心很大。作为一块10英寸上下的屏幕之内的操作系统,它作为内容承载的硬件,是一个很合理的想象,不然也不会有那么多开发者一直在开发将iPad 作为外接屏幕的应用,而现在,用户只需要连上Wifi ,它就能作为 Mac的外接屏幕。

打通了这一个环节之后,后面的事情就自然而然了:Apple Pencil 可以在屏幕上画画,这样一来,它很自然而然就成了手绘板。发布会上,苹果官方所放出的图片当中,涵盖了多数设计师都在使用的设计软件,其中不乏 AI、AE、Pr、Sketch、C4D、Zbrush 这些大热设计工具。

更重要的一点在于,Apple Pencil 原本 20ms 的反应延迟,在这次的更新之后,将会达到9ms,反应速度提升了一倍以上!它已经是一个称职的手绘板了。

有意思的地方在于,并没有 PS。为什么?答案很简单啊,iPadOS平台上的原生 PS 马上就要来了啊!连上Adobe 的创意云,两个平台又呼应上了……

毕竟,想要打通细分的应用场景,iPadOS 是需要自身具备强大生产力的,这意味着大量的独立功能、服务和应用支撑。

5、独立:一切都是为了让 iPad 独立生存

想要 iPadOS 能够独立完成视觉创造的工作,对于多种字体的支持是肯定需要的。在iPad 上独立运行 Photoshop 也同样是需要这样的功能支撑的,所以,干脆官方提供支持了:

而值得注意的是,作为一个设计公司,苹果的想象力并不止于此。这次更新的功能当中,有一个非常引人瞩目的功能是 SF Symbols。

苹果将1000多个常见的 iOS 和 macOS 的图标和苹果官方的旧金山字体融为一体,这些图标和符号支持 iOS 13、iPadOS以及的 watchOS 6 和 tvOS 13,而且你还可以在官方的文档支持之下,自己创造!

具体可以戳这里了解:SF-symbols 使用文档

完全独立的 iPadOS 将会需要好好管理本地和云端的文件系统,官方将文件管理器进行了升级,确保它无需借助另外一台电脑来完成操作。

核心应用没有问题,和外接内容进入口也要一并升级。功能强大的 TypeC接口能够直接读取U盘和存储卡:

而作为主要的浏览器,Safari 浏览器也向着桌面端浏览器的方向进了优化和调整,比如支持下载:

此外,图片、照片和视频的本地管理和剪辑功能,也一并进行了升级,这也是为了让iPad 能够成为一个更加独立的产品而存在。

而真正改变游戏玩法的东西,在开发和设计上。

6、融合:彻底打通平台的应用开发模式

多年以前,苹果为了统一全平台的应用开发,开发语言从原本的 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倍,而应用的容量也比以往要小。

7、沉浸:深色模式无处不在

对,深色模式也是苹果这次 iOS 产品更新的最核心特点,甚至整个WWDC19 主题演讲环节的整体视觉设计也是完全沿用这种沉浸感极强的深色模式视觉来进行构建的。目前苹果的 HIG 当中 iOS 的章节中新增了 Dark mode 的章节,而 iPadOS 相关的系统的设计设计指南还未更新。

「在 iOS 13 及以上的版本当中,用户可以选择深色模式为默认的外观风格。在深色模式下,系统界面、视图、菜单和控件都会使用较暗的配色方案,并且让前景元素更加鲜艳,确保突出。用户可以选择选择深色模式作为默认的视觉风格,也可以通过设置,让它在光线较暗的时候,自动切换过去。需要注意的是,深色模式可以让人更加专注。在设计的时候,需要在浅色模式和深色模式中都进行测试,因为有些元素和配色在一种模式下可用,在另一种模式下并不一定适用。」

苹果目前在设计规范中所提供的设计要求相对比较简略,感兴趣的同学可以借助翻译工具看一下:Dark Mode

如果你对于深色模式感兴趣,我们还有文章提供给你:

由于目前苹果官方暂时没有更多的内容,我们可以把深色模式更多的内容留到今后来聊。

8、安全:更私密的网络,更安全的生活

觉得社交网络帐号登录不够安全?Google 和 Facebook 两大巨头在发布会上成了反面案例,苹果适时地推出了自家的帐号登录服务。

苹果将产品和用户之间的边界划分得非常清晰,包括借助 Homekit 为用户提供基于本地存储的安全服务,在网上登录的时候使用经过加密的邮箱帐号,等等。

而被苹果点名的两家著名科技企业,Google 和 Facebook 也是在之前的 Google I/O 大会以及F8 大会上,相继针对隐私策略、安全服务进行了提升。

如果你对于这些大会感兴趣可以看看之前的文章:

结语

和每年9月的新品发布相比,WWDC 的信息量一点都不小。尤其今年还有超赞的 Mac Pro,单开2篇文章都不一定聊得完。但是在我看来,和设计关系最紧密的产品,应该就是 iPadOS了。这个独特操作系统,巧妙地卡在一个独特的需求点上,它本身的设计和定位、用户体验的考量、服务用户的思路、牵涉到的功能和服务乃至于它对于设计的影响,都是巨大的。

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计  cs界面设计  ipad界面设计  包装设计  图标定制  用户体验 、交互设计、 网站建设 平面设计服务

Echarts数据化可视图表

seo达人

如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里

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界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务

什么场景思维?顾客体验地图给你答案

蓝蓝

 如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里

今天我们就来讨论一下什么是顾客体验地图。

一、什么是顾客体验地图?

顾客体验地图( Customer Journey Map) 是一张超越时间和空间,从个体的视角得到用户与企业、服务、产品之间的关系地图。它能够视觉化地描绘用户在使用服务的整个过程中的流程、需求、痛点。它可以很好地帮助我们梳理和分析常见的场景可能存在的问题。在营销、服务、产品的场景分析中CJM都能发挥很大作用。

我们来欣赏一些著名公司做的顾客体验地图:

1. 星巴克:用户到星巴克喝完咖啡的整个体验过程

  • 图中央的横轴是用户在体验过程中步骤:准备(Anticipate)、进入(Enter)、参与(Engage)、退出(Exit)、反馈(Reflect),每一个步骤下还对用户行为做了进行一步细分,例如,“参与”步骤中包含了:排队、点单、支付、坐下、喝、工作;
  • 在图上方,标识出了用户在体验过程中心情变化,以积极和消极的进行划分,对每个触点(圆点)标记了相应的说明,例如:在工作阶段,免费的wifi就是一个积极的触点;
  • 下半部分是从用户视角描述了他在该动作下的不同用户故事,例如:8.f 我享用着免费Wi-Fi,而且信号也够用。

2. 乐高:“用户体验环(Customer Experience Wheel)”

在整个体验中找到乐高没?

  • 虽然比画成圆形,但是它本质上也是顾客体验地图;
  • 在图的中心是这个用户角色的说明;
  • 圆周是用户体验的整个旅程,体验的好坏用表情来表示体验的好坏;
  • i 标记出我们需要更多信息来帮助我们提升体验;

3. 英国政府:使用CJM解决公共服务问题

受害人报案到打官司的体验流程

  • 站在用户的视角,评估用户的满意度;
  • 寻找不同政府部门的服务边界;

4. Desonance 绘制的CJM也很有特色

这张图包含了很多便于浏览的视觉化信息:

  • 用户类型 (Customer Type):“用户类型”可以用“用户角色分析法(Persona)”或者移情图进一步细化。
  • 体验阶段及旅程 (Experience Phases & The Journey): 在不同的体验阶段以图文结合的故事化的方式来描述不同的行为活动,图中包含了痛点、触点、机会点……
  • 触点详情与交互动作 (Specific touchpoint and interactions):触点的解释说明;
  • 情绪变化 (What the service is like — nights and lows ):通过高低来视觉化用户情绪变化过程,从而体现服务效果;
  • 痛点和机会点 (Point of delight/opportunities & Point of pain/service barriers ): 通过使用图标的方式标记在旅程图中 ;
  • 要点说明( Key to explain the map);

二、如何绘制?

了解完什么是顾客体验地图后,我们开始学习如何创建它。顾客体验地图的创建需要五步:明确目标、探究、头脑风暴、绘制地图、优化迭代:

1. 确定目标

考虑好产品或服务的整体目标,以及期望顾客旅程图反应出具体目标。在做之前,最好把原有的体验流程感受一遍。并且与利益相关者沟通,探寻背后真正的动因。可以使用5W1H:

  • what:我们希望通过顾客体验地图解决什么问题?
  • why:为什么要解决这个问题?
  • where:这些问题在哪些场合发生?
  • when:时间截止期限是什么?
  • who:涉及到哪些利益相关者?
  • how:期望达到的愿景是怎么样的?

2. 探究

(1)检视所有相关的用户研究资料,其中包括定性和定量的调查结果,以便于提供洞察客户体验。也可以通过书籍资料做更多的研究。常用的研究方法包括客户访谈、人种学和情境调查、客户调查、客户支持/投诉日志、网络分析、社交媒体收听和竞争情报。

(2)移情映射,从各个方面描述一个角色在特定场景中的经历。这个练习帮助我们的团队加深对顾客体验的理解,并对顾客所需要的东西做出惊人的洞察力。移情图也为顾客体验地图的绘制提供了物质基础。我们的目标是获得一个全面的感觉,在这段经历中扮演那个角色的感觉,特别是关注他们的想法、感觉、视觉、听觉、说话和行动。

(3)先生成一个客户触点清单以及这些触点出现的场景。然后通过头脑风暴寻找被遗漏的接触点或场景。例如,触点可以是“付账单”,与触点相关的场景可以是“在线付费”、“通过邮件付费”或“亲自付费”。

3. 头脑风暴

为了收集更多的Idea,我们需要组建一个团队进行头脑风暴。头脑风暴的目的是在短时间内产生尽可能多的想法。我们可以选择品牌属性或心态的词汇。头脑风暴的时候,围绕这些词进行。我建议团队选择3-5个词(例如:可访问的,社交的,安慰的),然后每个单词使用2分钟的时间。每个人都会写下他们当时所能想到的许多想法。2分钟后切换到下一个词,直到所有的词被用作灵感。

使用亲和图进行整理。亲和图是通过视觉方式组织团队的思想,凝聚和发现概念中的的方法。亲和图解有助于我们从一个广泛的网络转移到探索许多可能性,以获得对这个观众的正确解决方案的重点。所有的团队成员都应该把他们的想法放在墙上的头脑风暴活动中。有人把这些想法分类并贴上标签。作为一个群体,开始考虑你可以在哪里组合,提炼,并删除想法,形成一个凝聚力的未来客户体验的愿景。

4. 描绘顾客的体验旅程

把所有的东西放在一起:时间线、触点、频道、情绪波动,以及为如何改进未来客户旅程所产生的所有美妙的新想法。顾客体验地图有5个关键要素:

  • 角色:这张图的主角用户是谁;
  • 触点:场景中服务与用户接触的关键点;
  • 渠道:交互行为发生的地方是网页端、App、电话、还是在线下某一个地方?
  • 时间线:从服务的前、中、后的不同阶段,可以进行细分;
  • 情绪:在体验过程中的情绪变化;

购买场景下的顾客体验地图

另外,这张图还可以提供一些额外信息:

  • 真实的瞬间: 通过照片拍摄一些能让人留下足够印象的积极的交互画面。
  • 服务提供者:对体验有影响的相关人员,如服务员、朋友、同事等;

#专栏作家#

PM熊叔,微信公众号:PM熊叔,人人都是产品经理专栏作家。教育类产品产品经理出身,学过设计,做过开发,做过运营的产品经理。

设计思维是一种解决问题的方法,运用同理心,横向思考,做原型,讲故事,

蓝蓝

编辑:蓝蓝


设计思维是一种解决问题的方法,运用同理心,横向思考,做原型,讲故事,令人信服地澄清洞见。


2004年,斯坦福大学机械工程系的教授戴维·凯利(DavidKelley)创办了D.School(斯坦福大学哈索普莱特纳设计学院),并在D.School教授关于设计方法论的课程,他也是世界最著名的创业设计与咨询公司IDEO的创始人。

什么是设计思维?

设计思维需要将人放回故事的中心。要学会将人放在首位,这就是设计思维的核心精神:以人为本的设计,也叫做以用户为中心的设计(User-Centered Design)。设计思维,就是一套以人为本的解决问题的方法论。解决问题,要从人的需求出发,多角度地寻求创新解决方案,并创造更多的可能性。

在“设计思维”在被不同的学者提出之后,IDEO是第一家将设计思维应用于商业问题的解决之中。

D.School将设计思维分成五大步骤:“Empathy同理心思考”、“Define需求定义”、“Ideate创意构思”、“Prototype原型实现”、“Test实际测试”,

接下来,就让我们了解一下如何实施设计思维的五步骤!

1同理心思考(Empathy)

同理心思考,就是要获得对你试图解决的问题的共鸣。简单来说,就是换位思考。比如你希望改善学校的教室环境,那么,你就可以像学生一样,坐在课桌后面上一整天的课。或者,你希望学生们来解决班级纪律的问题,你可以让一位学生来做一天的老师。这个步骤的目标是深入解读用户,收集大量信息。

2需求定义 (Define)

在收集到的调查信息基础上,我们需要更的定义需求。像“让学生的成绩更好”,这就不是一个的需求定义。而“提升学生在自习时间的专注力”,则是更精准的,入手点明确的需求定义。只有精准定义需求,我们才能开始入手解决问题!

3创意构思(Ideate)

这个步骤可以看做是头脑风暴的阶段。围绕上一步定义的需求,我们可以跳出局限,打破惯性思维,天马行空的提出各种各样的点子。不要一定要想到好点子,而是要在一百个点子里选出最好的。

4原型实现(Prototype)

这个步骤是要做出可以是粗糙、简单的产品或产品中的特定功能的原始模型,用于测试上一阶段提出的解决方案。原型可以是一个具体的产品的模型,也可以是一个小规模的环境或过程的简单模拟。

5实际测试 (Test)

这个阶段,我们会使用实现的产品原型,或模拟环境来严格测试问题是否得到解决,需求是否得到满足。这个阶段非常重要,一些想法可能会在这个过程中被重新定义,甚至,发现新的问题。

以上,就是实施设计思维的五大步骤。

第6步:重复以上步骤进行迭代 

反馈——原型——测试——反馈——原型.......


很多时候团队都是在缺乏对于真实目的和需求认识清楚的基础上被迫做一些彻底改造,怎么做?

蓝蓝

编辑:蓝蓝

战略设计中的一部分,是需要对自己和他人开诚布公,让大家清楚你真正想要从一项创新活动中寻求什么。很多时候,团队都是在缺乏对于真实的目的和需求认知清楚的基础上被迫使做一些彻底改造或是重新想象的事情。


需要探素的问题可能包括:


我们想要的解决方案的本质是什么?

破坏性创新还是渐进式创新?我需要很明确这点吗?

我们是昨天需要还是明天需要?

我是否为我正投入做的挑战耗费了合适的资源?


破坏性创新是一些新的、之前没有过的体验,而渐进式创新是在现有的给人们来的利益点的基础上做的一些新的、改进式创新。当然,我们每大都在连续不断地努力、改善我们提供的产品和服务。无论是哪一种创新変革,在不同的时间范時都有对它的需求。你希望哪种创新变革,以及你能花在上面的时间,都会影响到你如何实现创新。


变化的类型 :短期、中期、长期

破坏性创新、渐进式创新、持续改进



举个例子,假设一个领导者确实想要“尽快”做出破坏性创新,那么关键是就把它尽快培育起来并推向市场,与所需要的资源、人力和资金的需求展开一番对话。这个简单的对话对于构建你的战略边界是很重要的。没有它,你可能会在一些不必要的努力上浪费时间。时机很重要,不要等到太完美。

或许它不是人们想要放在首位的对话,但是从领导力的角度,确实最为重要的,也是会赢得参与挑战的团队成员的高度赞赏的。



日历

链接

blogger

蓝蓝 http://www.lanlanwork.com

存档