首页

2020年越来越火的车载交互该怎么设计?来看前辈的经验总结!

雪涛

这次我们不聊视觉,也不畅想未来,只说说当下 HMI 产品设计与交互体验。

本文内容会涉及一些专业的汽车知识名词,因为篇幅有限,如有些知识名词不太明白可以百度一下。

别看错了,不是HDMI!

说到 HMI 大多数设计师应该是既熟悉又陌生,HMI 是 Human Machine Interface 的缩写,「人机接口」,也叫人机界面,人机界面(又称用户界面或使用者界面)是系统和用户之间进行交互和信息交换的媒介, 它实现信息的内部形式与人类可以接受形式之间的转换,凡参与人机信息交流的领域都存在着人机界面。

听起来是不是觉得这不就是 UI 吗?有什么区别吗?似乎差不多,几乎是没有区别的,只不过是在某些场合和设备上管他叫 UI,比如移动端设备,而在另外某些场所和设备上管他就叫 HMI,比如汽车车机和数控机床。所以这个概念也不用去特别较真,HMI 就权当作是汽车上的 UI 界面吧。毕竟汽车是高科技与工业结合的完美产物,「HMI」念出这个词时候就感觉是蛮专业的!很般配!

HMI前世与今生?

刚才说 HMI 最早更应用于工业上,比如常见的各种机床、制造装备。

或者说让时间再向前推进一点!

而这里通常意义的 HMI 则更加聚焦点,基本特指汽车车机或者车载多媒体设备。

说到这里还是要从车载仪表盘说起,从德国人卡尔·本茨发明世界第一辆汽车,距今已经 100 多年的时间了,在那些还没有 HMI 这个名词的年代,那么他是以什么形态出现的?那就不得不提「仪表盘」了。

当然写这篇文章并不是去评测谁家 HMI 更优秀,而是希望通过一些假设、实验和推断,和大家一起来探讨一下如何更有效地设计 HMI。

屏幕越大越好?车内到底需要几块屏幕?

我们先从屏幕开始。

说到屏幕,设计师都是比较敏感的,因为我们最终的设计交互创意都是需要都是在屏幕上显示展示出来的,HMI 当然也不例外。现在在车载屏幕上你能看到最大尺寸多大?

拿特斯拉为例,Model S 和 Model X 车型都是 17英寸,Model 3 为 15 英尺。

当然他肯定不是最大的,熟悉汽车朋友你应该知道我想说谁了,没错就是他!拥有 48 寸可多段升降屏幕的 BYTON 新能源概念车 M-Byte!48 寸的确很夸张,难道屏幕越来越大就是未来 HMI 的方向吗?

当然这个问题肯定是否定的,为什么?那就要从车载屏幕的作用来说起。

首先我是作为一个曾经就职于汽车公司的设计师,并且是一名地道的汽车发烧友,凭借对汽车还算熟悉和热爱做出一些产品交互分析,以下如有不妥之处还望海涵。

汽车内屏幕的作用

按照功能场景总体可分为三类:主行驶状态信息、附设备状态信息、多媒体 & 外设

不可缺少还需要与使用者、场景结合,我们先来做一个大概的用户画像。

对应这些需求,汽车需要有仪表台(屏)控制和显示的区域有五个。

五个区域分别是:

  • 主驾驶仪表屏
  • 中控台控制(屏)
  • 后排娱乐屏
  • 副驾驶信息屏
  • 扶手控制台(屏)

其中前三个是主流配置,后两个比较少见。

关于汽车设备这块我们不做深入展开了,毕竟这篇文章主要讨论的还是设计,直接看结果!

题外音:屏幕安全性的考量

汽车是比较特殊的设备,基于安全性考虑,汽车内屏幕尺寸不宜太大与太多。

屏幕总体为玻璃材质,但与车窗挡风玻璃的材质不同,当汽车遭遇碰撞的时候,车内屏幕极易破损并形成尖锐物,极大可能会乘坐人员造成二次伤害,所以车内屏幕不易太多,更不易太大。虽然车载屏幕变大变多已不可逆转,而且随着屏幕技术的提升,柔性 OLED 的应用也将会在一定范围解决安全问题。但也需要汽车相关设计者多在安全方面进行考虑,任何产品体验应该建立在安全基础之上的,特别是交通工具。

物理实体按钮过时了?

为什么大屏幕操控成为了当前的 HMI 主流了呢?那不得不去提一下另外一个我们熟悉的设备——手机!

同样一个有限的区域,如果用物理按键那么这个区域只能是固定的功能,而屏幕就可以无限扩展。特别是在汽车中控屏上集成内容会很多,体现就更加突出。

但是在汽车上的全部使用屏幕真的是最佳选择吗?显然这是有待商榷的。

不可否认屏幕的确有很强的扩展性,但是缺点也是明显的:1.触控反馈缺乏 2.交互效率不高

对于这样的判断,我们可以通过两个实验来进行验证。

将类似于 Surface Dial 这种智能按钮交互装置引入汽车的屏幕控制中,每个按钮可以根据情景进行自定义,并且吸附到汽车屏幕的任何位置进行交互操作,相信这一定是一种全新的使用体验。当然这一定是需要解决比如吸附力、安全性等一系列问题。

屏幕触控反馈

虽然目前的屏幕还无法做到完美触控反馈,但已经出现了一些新的硬件技术来试图解决这些问题,比如 Tanvas Touch,其定义为 「手指与触摸界面之间的电子压力控制」。简单来说他们的产品就 「皮肤的磁铁」 一样,能够更加精准地感应手指的动作,最后结果就是比 Apple 的 3D Touch 更加具有压感的触摸操作表现。

原理是利用手指尖触摸显示屏时产生的静电引力来模拟触感,通过电磁脉冲把更的反馈发送到用户的指尖。

Tanvas 也正在与汽车制造商们合作把这项技术嵌入到汽车或屏幕上,让人们更容易感触受到不同物体的表面。

也许在未来我们真的会遇到他。

文章来源:优设    作者:残酷de乐章

数据可视化指南:那些高手才懂的坐标轴设计细节

雪涛

坐标系是能够使每个数组在维度空间内找到映射关系的定位系统,更偏向数学/物理概念。在数据可视化中,最常用的坐标系分为笛卡尔坐标系和极坐标系,本文介绍的坐标轴设计主要也是围绕直角坐标系展开。

什么是坐标轴

在说坐标轴之前先来介绍下什么是坐标系。坐标系是能够使每个数组在维度空间内找到映射关系的定位系统,更偏向数学/物理概念。

维基百科对坐标系的定义是:对于一个 n 维系统,能够使每一个点和一组 n 个标量构成一一对应的系统,它可以用一个有序多元组表示一个点的位置。

数据可视化中,最常用的坐标系有两种:笛卡尔坐标系和极坐标系,均为二维坐标系。

  • 笛卡尔坐标系即直角坐标系,是由相互垂直的两条轴线构成。
  • 极坐标系由极点、极轴组成,坐标系内任何一个点都可以用极径和夹角(逆时针)表示。用到直角坐标系的常见图表有柱状图、折线图、面积图、条形图等。

下文介绍的坐标轴设计主要也是围绕直角坐标系展开,用到极坐标系的图表有饼图、圆环图、雷达图等。

坐标轴是坐标系的构成部分,是定义域轴和值域轴的统称。系的范围更大,而轴包含在系的概念里。由于可视化图表绘制的数据大部分都有一定的现实意义,因此我们可以根据坐标轴对应的变量是连续数据还是离散数据,将坐标轴分成连续轴、时间轴、分类轴三大类。轴的类型不同在设计处理上也有差异。

坐标轴的构成要素

介绍坐标轴设计前,我们先将坐标轴拆分成「原子」要素,具体分为轴线、轴刻度、轴标签、轴标题/单位、网格线。

坐标轴易被忽视的设计细节

根据坐标轴的构成,分类讨论下每个构成要素容易被忽视的设计细节。

轴线一般只考虑是否显示,例如柱状图、折线图等,在有背景网格线的情况下,会隐藏 y 轴线,条形图则是隐藏 x 轴线,以达到信息降噪,突出视觉重点的目的。

轴刻度通常不显示,只有在肉眼无法定位到某个标签对应的数据点时,会显示刻度线,辅助用户定位,比如折线图,或抽样显示的柱状图。

网格线用于定位数据点的值域范围,跟随值域轴的位置单向显示,柱状图采用水平网格,条形图采用垂直网格。样式为虚实线的最多,斑马线由于感知过强,一般不用。

轴标题/单位主要用于说明定义域轴、值域轴的数据含义。当可视化图表标题、图例、轴标签已经能充分表达数据含义,无需单独显示标题/单位,「如无必要,勿增实体」。

轴标签的设计就比较复杂,涉及到的细节点很多,而且对于定义域轴和值域轴上的标签和单位设计要考虑的细节点还有差异。下文将定义域轴和值域轴看成 x 轴和 y 轴,便于说明。

1. x轴标签设计

x 轴标签的设计重点在显示规则上,不同的坐标轴类型有不同的处理方式。

连续轴/时间轴的标签显示

连续轴/时间轴,是由一组前后包含同等差值的等差数列组成,缺少几个数值也能明显看出中间的对应关系。当多个标签在容器内全显示发生重叠,我们可以利用抽样显示的手段来避免这种情况。这里不推荐使用旋转,一方面从美观度上,旋转可能会破坏界面整体协调,另一方面,连续/时间轴非必须显示所有轴标签,抽样标签已经能满足用户对当前数组定义域的理解。

介绍一种常见的抽样方式:等分抽样

当多个标签在 x 轴无法完全显示,优先保留首尾标签,其余标签按同等步长间隔显示。间隔等分的前提是间隔数是合数,能被 1 和其本身以外的数整除。如果间隔数为质数,就需要「-1」转成合数。

举个例子:11 个标签,间隔数是 10,能被 2 和 5 整除,即分成 2 等分和 5 等分。12 个标签,间隔数是 11,无法等分,需要在间隔数基础上再「-1」,转成合数 10 后再等分,此时最后一个标签显示在倒数第二个数据点上。

有人会问了,能被那么多数等分,到底该选哪个呢?这就要根据标签长度来定,选择能放下最多标签的等分值。由于连续轴/时间轴,一般是数值、日期、时间等,字符长度有限,即使抽样后也能保证显示出一定数量的标签。

等分抽样不太适用于表达某个时间周期内的走势折线图,因为最后一个标签不一定对应最后一个数据点。对于这类折线图,能清楚表明起始时间和末尾时间,相比显示更多时间标签重要性来的更高。设计上可以只显示首尾标签,或首尾 + 中间值。

分类轴的标签显示

分类轴是由几组离散数据组成,相互之间独立存在,无紧密逻辑关联。若采用抽样规则,隐藏一些标签,用户对图表认知就会有困难,违背了数据可视化清晰、有效的设计原则。分类轴最佳处理方式是标签旋转 45 度,若 45 度仍显示不下,继续旋转 90 度。如果 90 度还是放不下就要考虑结合图表交互或反转图表。

标签旋转方向也有讲究,因为人的视觉习惯是从左到右,从上到下,标签顺时针旋转 45 度更符合用户的浏览动线。

分类轴标签字段有长有短,长文本标签直接旋转不仅影响美观,而且也不利于用户阅读。如果数据量比较少只有 2~4 个,长文本标签更适合水平展示,显示不下省略即可;如果数据量比较多,就限定字符数后旋转。

2. y轴标签设计

y 轴标签的设计重点在标签数量、取值范围和数据格式上。标签显示区域一般根据最长标签宽度自适应缩放。如果数组是固定的,就写成固定宽度,节省图表计算量,提高渲染速度。

y轴标签数量

标签数量不建议过多,太多的标签必定导致横向网格线变多,造成元素冗余,干扰图形信息表达。根据 7±2 设计原则,y 轴标签数量最多不超过这个范围。

y轴标签取值范围

y 轴标签的取值范围决定了图形在整个绘图区域的显示高度。

折线图 y 轴标签取值一般保证图形约占绘图区域的 2/3,以更有效的传达数据波动幅度,避免掩盖和夸大变化趋势。2/3 即斐波那契数列第二位起,相邻两数之比,也是黄金分割最简单的计算方法。

柱状图的 y 轴标签取值应从 0 基线开始,以恰当反映数值。如果展示被截断的柱状图,可能会误导观众做出错误的判断。

y轴标签数据格式

y 轴标签的数据格式在 ant.vision 写的比较详细,重复内容不在此说明,重点讲下一些特殊的设计细节。标签保留的小数位数保持统一,不要因为某些轴标签是整数值,就略去小数点。

正负向的 y 轴标签,由于负值带「-」符号,整个 y 轴看起来会有视觉偏差,特别是双轴图的右 y 轴更明显。这里建议正负向 y 轴给正值标签带上「+」,以达到视觉平衡的效果。

总结

写了那么多关于坐标轴的设计,你是不是恍然大悟,原来小小的坐标轴还有如此之多的细节。往常我们做图表设计,可能只是用网上自动生成的图表简单调整下,或者按照通用样式来设计。然而,通用样式虽然能表达数据意义,但也缺少了对图表细节的把控,失了精致优雅的感觉。

作为数据可视化设计的一小部分,就是这些设计细节,决定了图表最终的传达效果。

文章来源:优设    作者:米粒的DesignNote

手机appUI界面设计赏析(一)

前端达人

与传统PC桌面不同,手机屏幕的尺寸更加小巧操作,方式也已触控为主,APP界面设计不但要保证APP功能的完整性和合理性,又要保证APP的功能性和实用性,在保证其拥有流畅的操作感受的同时,满足人们的审美需求。

接下来为大家介绍几款手机appui界面设计

点击查看原图

--手机appUI设计--

点击查看原图

--手机appUI设计--

点击查看原图

--手机appUI设计--

点击查看原图

--手机appUI设计--

点击查看原图

--手机appUI设计--

点击查看原图


--手机appUI设计--



微信图片_20200529093951.jpg

--手机appUI设计--


微信图片_20200529093948.png

--手机appUI设计--


微信图片_20200529093946.png


--手机appUI设计--


点击查看原图

--专业又贴心医疗App页面设计--


微信图片_20200529093941.jpg

--专业又贴心医疗App页面设计--微信图片_20200529093938.jpg

--专业又贴心医疗App页面设计--微信图片_20200529093936.jpg

--专业又贴心医疗App页面设计--微信图片_20200529093933.jpg

--专业又贴心医疗App页面设计--微信图片_20200529093930.jpg

--手机appUI设计--


微信图片_20200529093928.jpg

--手机appUI设计--


微信图片_20200529093925.jpg

--手机appUI设计--


微信图片_20200529093921.jpg

--手机appUI设计--


点击查看原图

--手机appUI设计--


点击查看原图

--手机appUI设计--


点击查看原图

--手机appUI设计--


点击查看原图

--手机appUI设计--


点击查看原图

--手机appUI设计--


点击查看原图


--手机appUI设计--


点击查看原图

--手机appUI设计--


点击查看原图


--手机appUI设计--


--手机appUI设计--


点击查看原图



--手机appUI设计--

(以上图片均来源于网络)



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



   更多精彩文章:

       手机appUI界面设计赏析(二)




JavaScript版数据结构与算法——基础篇(一)

前端达人

数组

数组——最简单的内存数据结构

数组存储一系列同一种数据类型的值。( Javascript 中不存在这种限制)

对数据的随机访问,数组是更好的选择,否则几乎可以完全用 「链表」 来代替

在很多编程语言中,数组的长度是固定的,当数组被填满时,再要加入新元素就很困难。Javascript 中数组不存在这个问题。

但是 Javascript 中的数组被实现成了对象,与其他语言相比,效率低下。

数组的一些核心方法

方法 描述
push 方法将一个或多个元素添加到数组的末尾,并返回该数组的新长度。(改变原数组)
pop 方法从数组中删除最后一个元素,并返回该元素的值。(改变原数组)
shift 方法从数组中删除第一个元素,并返回该元素的值,如果数组为空则返回 undefined 。(改变原数组)
unshift 将一个或多个元素添加到数组的开头,并返回该数组的新长度(改变原数组)
concat 连接两个或多个数组,并返回结果(返回一个新数组,不影响原有的数组。)
every 对数组中的每个元素运行给定函数,如果该函数对每个元素都返回 true,则返回 true。若为一个空数组,,始终返回 true。 (不会改变原数组,[].every(callback)始终返回 true)
some 对数组中的每个元素运行给定函数,如果任一元素返回 true,则返回 true。若为一个空数组,,始终返回 false。(不会改变原数组,)
forEach 对数组中的每个元素运行给定函数。这个方法没有返回值,没有办法中止或者跳出 forEach() 循环,除了抛出一个异常(foreach不直接改变原数组,但原数组可能会被 callback 函数该改变。)
map 对数组中的每个元素运行给定函数,返回每次函数调用的结果组成的数组(map不直接改变原数组,但原数组可能会被 callback 函数该改变。)
sort 按照Unicode位点对数组排序,支持传入指定排序方法的函数作为参数(改变原数组)
reverse 方法将数组中元素的位置颠倒,并返回该数组(改变原数组)
join 将所有的数组元素连接成一个字符串
indexOf 返回第一个与给定参数相等的数组元素的索引,没有找到则返回 -1
lastIndexOf 返回在数组中搜索到的与给定参数相等的元素的索引里最大的值,没有找到则返回 -1
slice 传入索引值,将数组里对应索引范围内的元素(浅复制原数组中的元素)作为新数组返回(原始数组不会被改变)
splice 删除或替换现有元素或者原地添加新的元素来修改数组,并以数组形式返回被修改的内容(改变原数组)
toString 将数组作为字符串返回
valueOf 和 toString 类似,将数组作为字符串返回

是一种遵循后进先出(LIFO)原则的有序集合,新添加或待删除的元素都保存在栈的同一端,称作栈顶,另一端就叫栈底。在栈里,新元素都靠近栈顶,旧元素都接近栈底。

通俗来讲,就是你向一个桶里放书本或者盘子,你要想取出最下面的书或者盘子,你必须要先把上面的都先取出来。

栈也被用在编程语言的编译器和内存中保存变量、方法调用等,也被用于浏览器历史记录 (浏览器的返回按钮)。

代码实现

// 封装栈
    function Stack() {
        // 栈的属性
        this.items = []

        // 栈的操作
        // 1.将元素压入栈
        Stack.prototype.push = function (element) {
            this.items.push(element)
        }
        // 2.从栈中取出元素
        Stack.prototype.pop = function () {
            return this.items.pop()
        }
        // 3.查看栈顶元素
        Stack.prototype.peek = function () {
            return this.items[this.items.length - 1]
        }
        // 4.判断是否为空
        Stack.prototype.isEmpty = function () {
            return this.items.length === 0
        }
        // 5.获取栈中元素的个数
        Stack.prototype.size = function () {
            return this.items.length
        }
        // 6.toString()方法
        Stack.prototype.toString = function () {
            let str = ''
            for (let i = 0; i< this.items.length; i++) {
                str += this.items[i] + ' '
            }
            return str
        }

    }

    // 栈的使用
    let s = new Stack()

队列

队列是遵循先进先出(FIFO,也称为先来先服务)原则的一组有序的项。队列在尾部添加新
元素,并从顶部移除元素。添加的元素必须排在队列的末尾。

生活中常见的就是排队

代码实现

function Queue() {
        this.items = []
        // 1.将元素加入队列
        Queue.prototype.enqueue = function (element) {
            this.items.push(element)
        }
        // 2.从队列前端删除元素
        Queue.prototype.dequeue = function () {
            return this.items.shift()
        }
        // 3.查看队列前端元素
        Queue.prototype.front = function () {
            return this.items[0]
        }
        // 4.判断是否为空
        Queue.prototype.isEmpty = function () {
            return this.items.length === 0
        }
        // 5.获取队列中元素的个数
        Queue.prototype.size = function () {
            return this.items.length
        }
        // 6.toString()方法
        Queue.prototype.toString = function () {
            let str = ''
            for (let i = 0; i< this.items.length; i++) {
                str += this.items[i] + ' '
            }
            return str
        }
    }
    
    // 队列使用
    let Q = new Queue()

优先级队列:

代码实现


function PriorityQueue() {
        function QueueElement(element, priority) {
            this.element = element
            this.priority = priority
        }
        this.items = []

        PriorityQueue.prototype.enqueue = function (element, priority) {
            let queueElement = new QueueElement(element,priority)

            // 判断队列是否为空
            if (this.isEmpty()) {
                this.items.push(queueElement)
            } else {
                let added = false // 如果在队列已有的元素中找到满足条件的,则设为true,否则为false,直接插入队列尾部
                for (let i = 0; i< this.items.length; i++) {
                    // 假设priority值越小,优先级越高,排序越靠前
                    if (queueElement.priority < this.items[i].priority) {
                        this.items.splice(i, 0, queueElement)
                        added = true
                        break
                    }
                }
                if (!added) {
                    this.items.push(queueElement)
                }
            }

        }
        
    }
    

链表

链表——存储有序的元素集合,但在内存中不是连续放置的。


链表(单向链表)中的元素由存放元素本身「data」 的节点和一个指向下一个「next」 元素的指针组成。牢记这个特点

相比数组,链表添加或者移除元素不需要移动其他元素,但是需要使用指针。访问元素每次都需要从表头开始查找。

代码实现:
单向链表


function LinkedList() {
        function Node(data) {
            this.data = data
            this.next = null

        }
        this.head = null // 表头
        this.length = 0
        // 插入链表
        LinkedList.prototype.append = function (data) {
            // 判断是否是添加的第一个节点
            let newNode = new Node(data)
            if (this.length == 0) {
                this.head = newNode
            } else {
                let current = this.head
                while (current.next) { 
                // 如果next存在,
                // 则当前节点不是链表最后一个
                // 所以继续向后查找
                    current = current.next
                }
                // 如果next不存在
                 // 则当前节点是链表最后一个
                // 所以让next指向新节点即可
                current.next = newNode
            }
            this.length++
        }
        // toString方法
        LinkedList.prototype.toString = function () {
            let current = this.head
            let listString = ''
            while (current) {
                listString += current.data + ' '
                current = current.next
            }
            return listString
        }
         // insert 方法
        LinkedList.prototype.insert = function (position, data) {
            if (position < 0 || position > this.length) return false
            let newNode = new Node(data)
            if (position == 0) {
                newNode.next = this.head
                this.head = newNode
            } else {
                let index = 0
                let current = this.head
                let prev = null
                while (index++ < position) {
                    prev = current
                    current = current.next
                }
                newNode.next = current
                prev.next = newNode
            }
            this.length++
            return true
        }
        // get方法
        LinkedList.prototype.get = function (position) {
            if (position < 0 || position >= this.length) return null
            let index = 0
            let current = this.head
            while (index++ < position){
                current = current.next
            }
            return current.data
        }
        LinkedList.prototype.indexOf = function (data) {
            let index = 0
            let current = this.head
            while (current) {
                if (current.data == data) {
                    return index
                } else {
                    current = current.next
                    index++
                }
            }

            return  -1
        }
        LinkedList.prototype.update = function (position, data) {
            if (position < 0 || position >= this.length) return false
            let index = 0
            let current = this.head
            while (index++ < position) {
                current = current.next
            }
            current.data = data
            return  true
        }
        LinkedList.prototype.removeAt = function (position) {
            if (position < 0 || position >= this.length) return null
            if (position == 0) {
                this.head = this.head.next
            } else {
                let index = 0
                let current = this.head
                let prev = null
                while (index++ < position) {
                    prev = current
                    current = current.next
                }
                prev.next = current.next
            }
            this.length--
            return  true


        }
        LinkedList.prototype.remove = function (data) {
            let postions = this.indexOf(data)

            return this.removeAt(postions)
        }
        
    }

    let list = new LinkedList()
双向链表:包含表头表尾 和 存储数据的 节点,其中节点包含三部分:一个链向下一个元素的next, 另一个链向前一个元素的prev 和存储数据的 data牢记这个特点

function doublyLinkedList() {
        this.head = null // 表头:始终指向第一个节点,默认为 null
        this.tail = null // 表尾:始终指向最后一个节点,默认为 null
        this.length = 0 // 链表长度

        function Node(data) {
            this.data = data
            this.prev = null
            this.next = null
        }

        doublyLinkedList.prototype.append = function (data) {
            let newNode = new Node(data)

            if (this.length === 0) {
            // 当插入的节点为链表的第一个节点时
            // 表头和表尾都指向这个节点
                this.head = newNode
                this.tail = newNode
            } else {
            // 当链表中已经有节点存在时
            // 注意tail指向的始终是最后一个节点
            // 注意head指向的始终是第一个节点
            // 因为是双向链表,可以从头部插入新节点,也可以从尾部插入
            // 这里以从尾部插入为例,将新节点插入到链表最后
            // 首先将新节点的 prev 指向上一个节点,即之前tail指向的位置
                newNode.prev = this.tail
            // 然后前一个节点的next(及之前tail指向的节点)指向新的节点
            // 此时新的节点变成了链表的最后一个节点
                this.tail.next = newNode
            // 因为 tail 始终指向的是最后一个节点,所以最后修改tail的指向
                this.tail = newNode
            }
            this.length++
        }
        doublyLinkedList.prototype.toString = function () {
            return this.backwardString()
        }
        doublyLinkedList.prototype.forwardString = function () {
            let current = this.tail
            let str = ''

            while (current) {
                str += current.data + ''
                current = current.prev
            }

            return str
        }
        doublyLinkedList.prototype.backwardString = function () {
            let current = this.head
            let str = ''

            while (current) {
                str += current.data + ''
                current = current.next
            }

            return str
        }

        doublyLinkedList.prototype.insert = function (position, data) {
            if (position < 0 || position > this.length) return false
            let newNode = new Node(data)
            if (this.length === 0) {
                this.head = newNode
                this.tail = newNode
            } else {
                if (position == 0) {
                    this.head.prev = newNode
                    newNode.next = this.head
                    this.head = newNode
                } else if (position == this.length) {
                    newNode.prev = this.tail
                    this.tail.next = newNode
                    this.tail = newNode
                } else {
                    let current = this.head
                    let index = 0
                    while( index++ < position){
                        current = current.next
                    }
                    newNode.next = current
                    newNode.prev = current.prev
                    current.prev.next = newNode
                    current.prev = newNode

                }

            }

            this.length++
            return true
        }
        doublyLinkedList.prototype.get = function (position) {
            if (position < 0 || position >= this.length) return null
            let current = this.head
            let index = 0
            while (index++) {
                current = current.next
            }

            return current.data
        }
        doublyLinkedList.prototype.indexOf = function (data) {
            let current = this.head
            let index = 0
            while (current) {
                if (current.data === data) {
                    return index
                }
                current = current.next
                index++
            }
            return  -1
        }
        doublyLinkedList.prototype.update = function (position, newData) {
            if (position < 0 || position >= this.length) return false
            let current = this.head
            let index = 0
            while(index++ < position){
                current = current.next
            }
            current.data = newData
            return true
        }
        doublyLinkedList.prototype.removeAt = function (position) {
            if (position < 0 || position >= this.length) return null
            let current = this.head
            if (this.length === 1) {
                this.head = null
                this.tail = null
            } else {
                if (position === 0) { // 删除第一个节点
                    this.head.next.prev = null
                    this.head = this.head.next
                } else if (position === this.length - 1) { // 删除最后一个节点
                    this.tail.prev.next = null
                    this.tail = this.tail.prev
                } else {
                    let index = 0
                    while (index++ < position) {
                        current = current.next
                    }
                    current.prev.next = current.next
                    current.next.prev = current.prev
                }
            }
            this.length--
            return current.data
        }
        doublyLinkedList.prototype.remove = function (data) {
            let index = this.indexOf(data)
            return this.removeAt(index)
        }
    }


感谢你的阅读~
————————————————
版权声明:本文为CSDN博主「重庆崽儿Brand」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/brand2014/java/article/details/106134844



大数据可视化设计赏析(三)

前端达人

     如今大数据产业正在超出我们的想象悄然发展,而随着大数据时代的到来,越来越多的公司开始意识到数据资源的管理和运用。今天就给大家介绍一些可视化大屏的UI设计。


点击查看原图

    --大屏UI设计--

点击查看原图

 --大屏UI设计--

点击查看原图

 --大屏UI设计--

点击查看原图

 --大屏UI设计--

点击查看原图

 --大屏UI设计--

点击查看原图

 --大屏UI设计--

点击查看原图

 --大屏UI设计--

点击查看原图

 --大屏UI设计--

点击查看原图

 --大屏UI设计--

点击查看原图

 --大屏UI设计--

点击查看原图

 --大屏UI设计--

点击查看原图

 --大屏UI设计--

点击查看原图

 --大屏UI设计--

c24b7efe812270eb555c5ab24b8a5fa2626973621ab956-4LUO4k_fw658.gif

 --大屏UI设计--

eebdcf2ab80ccf28a832b463b5efb8d390baa8401fbcda-58EU2O_fw658.jpg


eee7b0bd72a92d26ef0ea8b65921a2fcacf49ae934f18-ScQnAI_fw658.png

f0ab44b8e812af72209891521cbff1fe6ff656b863d09-JxGZiR_fw658.jpg



f5c7bedb9779f20ca239e235a98ef8eae839a5f980e8a-gkXvyM_fw658.png

 --大屏UI设计--


点击查看原图

 --大屏UI设计--

TB2XULnmC0mpuFjSZPiXXbssVXa-680650857的副本.jpg

 --大屏UI设计--点击查看原图

 --大屏UI设计--点击查看原图

 --大屏UI设计--点击查看原图

 --大屏UI设计--点击查看原图

 --大屏UI设计--点击查看原图

 --大屏UI设计--点击查看原图

 --大屏UI设计--点击查看原图

 --大屏UI设计--WechatIMG166.jpeg

 --大屏UI设计--点击查看原图

 --大屏UI设计--点击查看原图

 --大屏UI设计--点击查看原图

 --大屏UI设计--点击查看原图

 --大屏UI设计--

点击查看原图

 --大屏UI设计--

点击查看原图

 --大屏UI设计--

WechatIMG174.jpeg

 --大屏UI设计--

WechatIMG175.jpeg

 --大屏UI设计--

WechatIMG164.jpeg

 --大屏UI设计--

WechatIMG176.jpeg

 --大屏UI设计--

点击查看原图

 --大屏UI设计--

点击查看原图

 --大屏UI设计--

(以上图片均来自于网络)


其实可视化大屏的UI设计并不只是一个简单的设计,其核心就是要以展示数据为核心,不管在多么炫目的情况下都不会影响数据的展示。


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





    更多精彩文章:

       

 大数据可视化设计赏析(一)

  大数据可视化设计赏析(二)

  大数据可视化设计赏析(三)

  大数据可视化设计赏析(四)

  大数据可视化设计赏析(五)

  大数据可视化设计赏析(六)

  大数据可视化设计赏析(七)




认识 ESLint 和 Prettier

seo达人

ESLint

先说是什么:ESLint 是一个检查代码质量与风格的工具,配置一套规则,他就能检查出你代码中不符合规则的地方,部分问题支持自动修复。


使用这么一套规则有什么用呢?如果单人开发的话倒是没什么了,但是一个团队若是存在两种风格,那格式化之后处理代码冲突就真的要命了,统一的代码风格真的很重要!


(其实以前自己做一个项目的时候,公司电脑和家庭电脑的代码风格配置不一样,在家加班的时候也经常顺手格式化了,这么循环了几次不同的风格,导致 diff 极其混乱

想提高设计转化率,按钮应该放在左边还是右边?

雪涛

任何一名设计师应该都会接触到运营活动页,产品落地页此类需求。而这些落地页设计需求的业务目标衡量标准都相当明确——即转化率。再进一步,与我们的设计输出直接相关的就是首页转化率/点击率。这些数据通过埋点能很轻易地获得,一般情况下,产品经理会提前在需求文档中标明需要埋点的地方(埋点简单说就是测量某个位置或者交互节点的具体数据,例如发生了多少次点击),获得数据用于验证产品最终是否符合预期,是否达到了理想的转化效果。

叮~ 讲到这我们应该明确了一件事,整个落地的设计其实最终都是为那个关键数据服务,无论是点击率还是转化率,达到预期甚至超出预期,那你的设计就完美地完成了任务,这也是验证设计有效性的主要方法,将设计与数据关联,用可量化的数据指标来验证偏感性的视觉工作。

就这样,设计与产品/运营的世纪大战开始了。因为我们都有了一个共同的目标,因此在产品的最终收益、期望效果方面互相都很明确。但在实现手段上,我们很轻易地产生了分歧。主要分歧点就是「按钮在左还是按钮在右」这个问题上。我们需要理解,这不是一个简单的交互问题,因为它其中掺杂了商业内容。如果这是一个交互问题,那我们很容易判断,例如弹窗的主次按钮应该主右副左,这既符合平台规范,也符合用户认知和操作习惯。

然而作为一个强商业属性的落地页,按钮在左或者按钮在右都有其合理性。我选择左,而运营同学代表他们团队要求右。 于是我败下阵来,当然,虽然表面上设计师输了,但我们怎么能服输,于是我想尽办法来验证左侧放置按钮才是更有利于转化的形式。下面我们来看看不同的倾向对应的设计原理。

左与右的矛盾

产生左与右的争执其实主要源于设计与需求方的两个判断方向。首先说一下我的判断逻辑,按照已知经过验证的理论,即 F 阅读顺序(尼尔森的用户阅读视线模型),用户浏览落地页的顺序应当是从左往右自上而下,因此左上角的信息最早触达用户。在当前主流的首图式落地页样式下,首图 banner 中的内容应当置于左侧,以使用户更快地获知产品的关键信息。

在落地页首图的体验文案本身就是一个设计的覆盖范围,因为它直接关系到首页的视觉传达效率,即用户需要花费多长时间、多少精力才能理解你的产品。我们往往在首页体验文案中采用主标题加副标题的形式,着重解释这个产品是个什么东西、用户能从这获得什么,往往通过主副文案搭配的形式,来完成整个大意的阐述。

基于此,核心内容置于左侧,用户在快速扫视时能够第一时间获知产品信息,了解产品利益点,这与我们精心准备整个网站,以及精心准备诱导力文案的方法相契合。这是我做出内容置于左侧的设计决策的主要思路。可以看出,我这里主要参考的是 F 阅读模型这一理论,根据这个经验我得到的结论是 重要的信息应当摆放在左侧以使用户立即触达核心信息,这将有利于接下来的引导或者转化。

另一方面,运营同学又是基于什么考虑决定将核心内容放在右侧的呢?答案是操作习惯,理论化的话可以用费茨定律概括,(目标距离用户距离越短,用户触达的效率越高)。考虑到大部分用户使用右手操作,鼠标也大都悬停在屏幕右侧,因此,按钮置于右侧,用户点击的路径变得更短,也就更容易触达和转化(纯体验角度或者说效率角度)。

你仔细阅读这部分内容,从分歧点到各自的理论支撑实际上都没有太大的漏洞,为什么没有漏洞?因为确实都没有错误,也都存在其合理性。例如我们常用的购物 APP 会把按钮置于右下角,用户操作起来必然比左上角的按钮更加容易。那么在这两种分析都合理的背景下,我们要对比或争论的其实不是哪个判断是错误的,而是哪个判断更有利,更合理,能够带来更多的数据转化。因此,这个问题最终由对错问题,转化为一个优劣问题。

左与右的妥协(一种结论)

有些人很机智,这个时候肯定会想,既然左边最容易触达信息,右边最容易触达按钮操作,那左边放置内容,右侧放置操作不就完美解决了吗?哎呀,读者真聪明。

由于 F 阅读的逻辑,将展示性质的「内容」放置于左侧,使用户更快触达关键信息,由于费茨定律,以及多年来养成的用户习惯(操作组件在右侧,当然现在很多放在中间的情况)将需要执行的操作置于右侧,使用户快速交互并完成任务。有一定道理,甚至在实际落地产品中我们也能看到一些类似的设计,例如豆瓣。 这是一种左与右的妥协

但需要注意的是,豆瓣产品的右侧放置的是较为复杂的交互模块,例如完整的登录注册模块。在该场景下,用户在交互路径更短的右侧区域执行交互效率要明显高于左侧区域。

那么下面开始论述按钮置于左侧的观点

论点一:排版的限制

豆瓣的形式对于落地页产品,可能并不适用。主要有两方面原因。我们都知道,产品落地页首屏的组成为体验文案,主 CTA,插画配图三部分。常规做法是插画作为一组信息置于一侧,文案加按钮作为一组信息置于一侧。因为,体验文案与按钮具有强关联性,同时按钮与文案作为一组信息,才能与另一侧的插画搭配构建平衡的布局,呈现比较优美的视觉效果。

请登录后查看原图,因此,豆瓣那种妥协方式并不适用于商业类落地页。因为内容和操作本身是一体的,这源于排版的规整性的限制,按钮和文案只能同时存在于一侧,如果刻意去追求左侧内容,右侧操作,效果就像下面这样。一方面,只靠文案和按钮无法撑起左右两个区域,一方面文案和按钮被割裂开,用户的视线由文案转到按钮的路径过长,体验较差。(文案与按钮成组后,用户可以在阅读内容产生动机后立即触达交互按钮并完成转化)

论点二:文案与配图孰轻孰重

如果你亲自体验这两种区别的落地页(左图右文/左文右图),你会发现有一个共同点,就是在某个区域的停留时长,没错就是内容区域。以下图的顶部卡片区域为例,在阅读时我的浏览情况是,大致地扫视左侧的插画,然后注视右侧文字区,了解文章的具体内容,并在此区域停留较长时间,毕竟仔细阅读需要花费时间。

这就涉及到一个问题,插画与内容哪个更重要?其实答案很明显,我们只需要舍弃掉其中一项来测试下,看看哪个内容的缺失会对用户理解设计传达的语义产生较大影响。OK,我觉得没必要测试了(虚晃一枪)。很明显,删除插画后,我们仍然可以通过文章的标题来获知文章概要等关键信息,就像落地页首屏的体验文案,即便没有插画我们也能通过首页文案来获知这个产品是什么,能够为我带来什么。

然而如果去掉关键信息,去掉标题与按钮,仅凭插画我们无法分辨当前页面到底在讲述什么东西。设计本身就像是人与人的交流,产品就是我们,而用户则是我们的交流对象,去掉核心的文案,相当于把我们自己变成了哑巴,而去掉插画,最多相当于我们交流时面无表情罢了。

因此,在商业落地页中,我们以转化为核心目标,而能够更快地触达最重要的信息显然是明智之举,因此我们希望将核心的文案内容置于左侧。

(另外,一图胜千言的原理只适用于个别场景,例如数据可视化。设计人员通过将数值数据转化为易于理解的柱状图扇形图,来传达数据结论。而视觉修饰性质的插画则无法做到准确表意,我们通常在产品设计中见到的插画更多的是在情感上和审美上给予我们一定的愉悦,但想要准确描述关键信息,还是需要文字作为核心角色)

论点三:用户会因为便于操作而产生动机?

另一点同样值得我们思考,即用户真的会因为某个按钮更容易点击而被转化吗?或者我们换个形式问,假设你是一名男性,你会因为按钮在鼠标附近而选择点击购买女士内衣吗?你会在自己财务状况较差的时候因为按钮在鼠标附近而点击购买品吗?在大多数理性场景下,我相信你不会这样做。

所以这时候要引入福格模型,用来阐述产生转化的整个路径。福格模型简单来讲就是一个公式:B=MAT。B(behavior) 代表行为,M(motivation) 代表动机也就是用户需求,A(ability) 代表用户使用的门槛,T(trigger) 代表触发。也就是用户行为的产生需要用户需求为基础,需要保证产品的易用性,但是这还不够,在这个基础上我们还需要在产品中通过设计触发用户。完成转化的三个关键要素是,动机、能力、触发,缺一不可。

福格模型帮助我们解决了这个疑问。用户的购买或者转化始于动机,就像我上面举的例子,如果一个用户根本对产品没有需求(男性对女性内衣),那就不会产生动机,在没有动机的情况下,后面两项内容,能力或者触发都没有意义,无法发挥作用。整个转化的流程可以参考下方的示意图。

实际上对于那些有强烈动机购买或使用产品的用户,你的一切设计都没有太大意义,因为用户有强烈诉求的情况下,他会发挥主观能动性去找到转化的入口,主动完成转化。同理,有些用户是完全不会产生动机的,不是目标用户群。

设计策略主要针对的是有动机但不强烈(某种程度上有需求或者被吸引),以及暂时没有动机的两类用户。通过我们的首屏及详细内容,痛点利益点的介绍,来放大用户动机,制造共鸣点,创造美好的想象空间,使用户涌现强烈动机。然后转化就自然而然的产生。

因此,在首屏我们的核心要义是通过内容设计来触发用户动机,而不是想方设法触发操作。走捷径的误触方案设计能保证百分百的触发率,但那种触发没有任何意义。到这里我们应该明确了,用户会因为好的内容所触发的动机而买单,但不会因为你把按钮放在我手边而产生购买冲动。

因此,我的结论是,用户更有可能因为左侧展示的强洞察力的文案而产生动机,而动机是整个转化的起始,也是最关键的一点,有了动机,触发(按钮位置)的效率即便低一点,但转化仍然很有可能继续(就像动机产生了惯性,有了强烈的动机会自发地去寻找触发器,去寻找按钮以自主完成转化,但触发器不会有惯性)

这个观点论述下来,主要涉及到 F 阅读模型,费茨定律以及福格模型,算是很基本的设计原则,也顺便帮大家重温一下。最后,我们再拿一些其他实证来进一步论述,例如国内一线公司的落地页设计。

1. 一线公司落地页布局

2. 全球独角兽企业落地页

文章来源:优设    作者:南山可

B端系统,筛选控件总结

分享达人

写在前面


首先我们先从筛选本身讲起吧~

 

筛选可以说是我使用比较频繁的一种交互形式,比如我点外卖,会选择满减优惠力度大,同时我也可以选择在哪一个价格区间内的产品,这就会用到筛选,而到了B端产品上来,一个CRM系统当中,筛选的逻辑也会比移动端的复杂,伴随着:且关系、或关系、大于、小于等等这样复杂的逻辑,也为设计本身增加了很多难度。因此,今天我们就来讨论讨论筛选控件

 


1、筛选存在的意义


筛选存在的对于整个表单来说是非常重要的,它可以帮助用户,在表单茫茫多的数据当中进行快速的定位;可以对表单进行快速划分,缩短用户对于数据的寻找时间;能够满足用户在工作中,实际业务场景的筛选。

对于实际B端场景来说,筛选是日常数据分类的一个重要途径,我们先来看看实际场景到底有哪些?

 

用几个我们CRM用户日常使用的场景来说:

 

比如今天作为一个电话销售人员,想要联系最近注册的用户时,通常会通过筛选来选出最近几天注册过,同时又没有销售更进的客户,进行一个优先级的排布;

 

再比如说,在销售周报当中,销售主管可以通过筛选得到每个人这周完成的状态,也可以通过筛选得出每个人对于线索的更进情况和对客户的流失状态等等,这些都可以通过各种各样的筛选形式来满足用户对于特定情况下的使用



筛选和搜索、导航的区别?

 

筛选可以通过多个筛选条件进行多维度的寻找,而导航、搜索只能通过单一条件进行指定筛选。

虽然在现在很多搜索都可以支持多维度用空格去进行多字段的关键词搜索,但本质上区别不大

所以在B端项目当中,如果你有表单,那你就需要筛选



2、筛选的类型


我们将筛选分为基础筛选和高级筛选两种,两种筛选会根据业务场景不同,在不同的页面去使用

 

2.1、基础筛选


基础筛选一般为系统预设好的筛选字段,具有很强的业务和场景的需求。基础筛选一般分为四个部分:


筛选条件:是指用户可以筛选的范围

筛选项:是指用户可以选择的筛选项目

已选项:是指用户已经选中的筛选项

备选项:是指用户还没有选择的筛选选项



基础筛选更多作为用户快捷筛选的一种方式,因为一般使用场景当中用户几个筛选逻辑为“且”

同时筛选的逻辑也为简单筛选,所以在使用场景上只适合在对筛选要求不高的场景下使用。


2.2、高级筛选


高级筛选一般为筛选中含有运算符,同时筛选当中包含条件关系,比如且关系或者否关系。一般高级筛选包含以下几类关键词

 

筛选关系:是指几个筛选条件之间的关系,一般为 且、或关系,即 且 关系为几个条件之间的并集;或 关系为几个条件之间的联集

筛选字段:是指在筛选当中,所要的筛选项,一般为表单当中的所有可筛选的字段

筛选操作:是指筛选字段和筛选值之间的关系,常见的筛选操作有:大于、小于、是、否、包含、不包含、为空、不为空等等。

筛选值:你所需要筛选的数值



高级筛选一般满足更多的用户场景,为用户多条件多字段、多个筛选关系、多个筛选操作 提供有利保障。




3、筛选的布局


3.1、上下布局


当在筛选器条件少于5个的情况下,最常使用的就是上下布局,这样筛选能与网站保持统一的情况下,上下布局也更方便用户进行阅读

 

当筛选器过多的情况下(一般在5-15个之间),筛选器过多,需要滚屏才能看到筛选结果,用户使用起来会很别扭。所以在5-15个的情况下,一般会将筛选项进行收折,这样保证筛选整体面积不会太大,同时将用户常用的筛选放在前面,可以满足用户基本的业务需求和使用场景



3.2、左右布局


左右布局在PC端一般是以字段选择进行筛选,通俗来讲就是将用户可以筛选的所有字段全部罗列出来,然后通过勾选选,择出你需要筛选的字段,进行筛选器的使用

 

左右布局的好处是能够将筛选的所有条件都直接的展示出来,可以适应很多场景,在筛选器用15个以上时。通过左右布局的方式,能够让筛选条件进行滚动,在最大限度保持用户使用体验




4、筛选的形式


在日常的B端产品中,筛选的形式有哪些?筛选到底应该怎么设计?接下来为大家总结梳理一些在 B端产品 中的筛选玩法,希望为你开启新大陆。


4.1、平铺型



平铺型一般为用户搜索结果数据量过大,使用户搜索出来的结果与其预期差距过大,用户然后可以通过筛选对数据的再一次分类,使用户能够精准寻找其想要的结果。

平铺型一般为筛选条件少于6个,这样能够通过1行或者2行去展示筛选项的结果

 

多用于信息量大的产品,比如电商、视频网站等等。常见的淘宝、京东、腾讯视频PC端 都采取用这样的方式,将所有的筛选条件列出来。

 

平铺型的好处是将筛选项的结果全部或者部分放出,能够帮助用户快速理解筛选项以及快读找到自己想要的结果。

缺点也是很明显,平铺型的控件占比大,需要占据大量面积展示平铺出的筛选结果。

 

比如淘宝PC端,搜索一个产品后花去40%的面积去展示所有的筛选条件,其实就是想引导用户,淘宝搜索过后spu的数量仍然过大,想通过进一步的筛选,让用户明确自己对想要东西。同时因为面积占比大,通常平铺型都是以收折的状态,只有在搜索触发后才会完全展开


4.2、收折型



收折型筛选是一种简单直接的筛选形式,将用户常用的筛选形式通过下拉框的形式进行筛选。每一个筛选条件就是一个下拉框,这种形式看上去很简单,但是在B端场景中,下拉框对于用户来说认知成本低,操作性也较强,同时在用户重度使用时,又能给用户很好的使用体验的一种方式

 

优点:

用户可以直接对其常用的字段筛选进行一步操作,并且没有复杂的筛选关系,全部都是“且”的筛选逻辑,能够保证用户进行快速的筛选选择

 

缺点:

将所有信息全部平铺展开,信息量过于冗杂繁多,同时在做通用性产品时,这种方式很难做到通用性


 

4.3、单侧筛选



单侧筛选是一种更通用的筛选形式,通过对于你想筛选的字段进行勾选,勾选完成后就会出现筛选条件,然后选择筛选字段、筛选操作、筛选值,一般选择完成所有筛选后,还需要点击查询,筛选操作才算完成。

 

整个单侧筛选,大量的筛选条件可以放置在表单的左侧或者右侧,通过表单纵向空间,去承载大量筛选条件。

 

优点:

节省空间、通用性强。因为在很多Saas系统、Paas系统当中,无法针对每一个客户进行设计,就要考虑到系统通用型高,做一些大而全的功能。在每个表单也所需要定制化修改的地方很少,同时能容纳的信息量可以很大。

 

缺点:

就是在后台系统当中只有这一种筛选形式会面临在我常用的几种筛选的字段中,要通过不断寻找,来满足我的筛选需求,操作麻烦。

 

 

我们产品在某一次改版就将筛选由收折式修改为单侧式,因为我们用户使用筛选的场景非常的多,用户每次筛选都要多进行2、3步操作,导致用户进行了大量的吐槽,后来进行修改,将筛选顺序支持手动调整顺序,用户吐槽的次数才慢慢减少。



4.4、表头筛选

 


表头筛选是一种复杂筛选的形式,其最开始是来源于Excel的筛选形式。点击表单的筛选按钮,可以将表头的筛选字段直接带入,方便用户。之后在后台产品的发展中,得以借鉴过来。

 

优点:

可以通过表头的点击,使用户更快捷进入到自己的筛选条件,在通常情况下,在表单越左的数据显然是越重要的,也是使用筛选去筛频率最高的,因此高频的筛选场景基本还是得到满足。


缺点:

用户第一次进入系统很难理解这种交互形式,且在每个表头都会有一个icon,影响用户对于表头的识别。

 

 

4.5、弹窗式



通过点击筛选按钮,展现出筛选弹窗,进行筛选。这种筛选适合在筛选功能在系统中不是很重要的层级。最常见的就是Tapd,在其中筛选不是很强的一个功能,同时也是系统中十分有必要的。

 

优点:

是能够在节省面积的情况下,可以进行很复杂的筛选,同时可以支持复杂情况下的筛选

 

缺点:

弹窗会遮挡一部分表单数据,会影响筛选人的判断,其次筛选条件的添加也相对更加繁琐。

 

 


5、选择更合适的筛选

在我们一系列筛选的调整过后,我们团队也总结了对于我们来说更重要的条件和形式,来和大家分享探讨一下。

 

5.1、使用频率

我们认为影响筛选控件最重要的是用户的使用频率,因为用户的使用频率和使用方式,直接影响到我们筛选是用普通筛选or高级筛选,也会影响到筛选的形式。

 

5.2、满足实际业务所需

筛选功能的做法,取决于我们产品未来是想往哪一个方向发展,如果想把功能做的强大,就得考虑到筛选的后续扩展性。因此满足实际业务也是十分重要。

 

5.3、用户认知成本

在B端系统当中,最可能遇见的就是你给用户设计的路径但是其实用户根本没有往你想的方向去操作。我们系统最开始给用户设计好了很多功能点,但是用户对于这个点的认知成本实在过低,也导致了后面系统功能点很多都被埋没。因为在你设计好了一个功能点后,要适当引导用户,解释这个功能的使用场景才不会让你设计的功能被淹没。

 

 


其实在B端产品中,易用本身就是难且长的过程,在每一个功能的设计都需要你去思考很多方面:用户易用、信息层级、未来扩展,你都要做出取舍,而对于每个模块都需要你思考、结合用户场景,B端web的设计一直都是摸黑前进,我也只是将自己的一段时间的工作进行总结,说的不正确,欢迎大家指正。

 转自:站酷-Cengg 


Mac 视觉史 vol.1:从 Macintosh 到 Mac OS

雪涛

2009 年,买不起 Macbook 的我在 PC 上装上了黑苹果。在此之前,我用虚拟机体验了 Apple II 、Mac OS 8.1、Mac OS 9.2.2 、Mac OS X 10.6 ,在不断的折腾过程中,我开始对苹果、对GUI 的整个历史发生了兴趣。

此后,我在Jeff Johnson 的《认知与设计》当中,在 Steve Krug 的《Don’t Make Me Think》当中,在一本又一本和UI、交互、体验相关的经典书籍当中, 发现 Mac 系统的界面一直被作为范例来展示。

Mac 确实是优秀设计的典范,是 GUI 设计史当中绕不过去的最重要的操作系统家族。所以,视觉史系列文章的第一篇,我决定从 Mac 系统下手。

两大系列,四个名字

简单来说,我们泛指的 Mac 系统,通常是分为2个大的系列的。

1982 年随 Macintosh 发布的系统,一直到 1999年发布的 Mac OS 9 为第一个系列,一般被统称为「Classic Mac OS」。

而 2001 年之后所诞生的 Mac OS X 系列的操作系统,包括现在所说的 macOS ,则被视作为第二个系列的 Mac 系统,其中 X 是罗马数字 10 的意思。

苹果公司最初只有 Macintosh 电脑,系统并无名称,直到第5个大版本的时候,操作系统才拥有 Macintosh 这个名字。而 Mac OS 这一系统名称,则是在系统更新到第7个大版本的时候才被提出,而自此开始,Mac OS 的称谓正式出现。

而 macOS 则相当于是 Mac OS X 品牌的一次重启。它始于 10.12 Sierra 这一版本,并且为了和 iOS、tvOS、watchOS 这几个系统品牌保持一致,而从 Mac OS X 更名为 macOS。

在很长一段时间,国外很多老用户会将它简称为「OS8」、「OS9」,而在2001年之后直到今天,依然有很多人将它简称为「OSX」,这也是在了在讨论 Mac 系统这个前提下所用到的、带有版本的简略称谓。

注释:国内有不少人会将 Mac 称为「OS系统」,但是 OS 本就是 Operation System 的缩写,意为操作系统,Windows 是 OS,Linux 也是 OS,「OS系统」是一个错误且尴尬的表述。

如果不深究细节的话,Macintosh,MacOS,Mac OS X , macOS 这四个都简称为 Mac 系统。

图形化界面:向施乐偷师

Macintosh 并非最早的图形化界面,但却是真正推动图形化界面操作系统发展的里程碑。

Xerox Alto

对于图形化用户界面的起源,一个相对统一的共识是,它来源于施乐的帕罗奥托研究中心,而最早使用图形化界面的电脑,是当时正出于研发中的 Xerox Alto。在之前的文章当中,我曾经专门聊过最早图形化界面的诞生和设计细节:

比尔盖茨曾经指责乔布斯从施乐这里「偷」走了图形化界面(GUI)的设计,实际上,为了换得机会去施乐的帕罗奥托研究中心去观摩学习研发中的Xerox Alto 和开发工具 Smalltalk,乔布斯是拿股权交换得来的。

这是 Xerox Alto 当时所采用的图形化界面。界面的确图形化了,只不过,从今天的视角来看,整体的界面逻辑并不清晰。

而在GUI的设计细节、实现方式上,Macintosh 则截然不同,可以说是后来居上。

规避纠纷: Macintosh 的名字来源

说回 Mac。

回溯到 1979年,Jef Raskin 是Macintosh 电脑和操作系统项目的发起者和监督者,他想用自己最喜欢的一种苹果(McIntosh)来给这个操作系统命名。

这种名为 McIntosh 的苹果不仅被誉为加拿大国家级苹果,但是更重要的原因在于,当时纽约还有一家名为 McIntosh Laboratory 并且提供高端定制音响服务的公司,为了避免商业品牌上的冲突,Raskin 将系统的名称改为 Macintosh,故意错开了一个字母。当然随后 Macintosh 的名字逐渐超过了前者,在世界范围内,甚至慢慢超过了加拿大最著名的水果。

当然,1984年,最初版本的 Macintosh 系统随着同名的苹果电脑的发布而面向大众,这个并非最早的图形化界面操作系统开始了它的历程,如今它是最著名、最具有影响力的图形化界面的操作系统之一。

Macintosh 电脑的主板由 Burrell Smith 所设计,结合当时的硬件技术,让最终上市的 Macintosh 电脑拥有了一块分辨率为 512×342 的单色显示屏。

在这块寸土寸金的单色屏幕上,Macintosh 系统需要将图形化界面的价值尽可能发挥出来。

Macintosh 系统:正式拥有姓名

Macintosh 电脑开始出现在各大杂志媒体上,蜚声世界,但是此刻,这一操作系统并没有官方的名称。 1.x系列的只有一个非正式的 System 1 的名字,而随后的大版本也被称为 System 2,System 3,等等。

直到 System 5 的时候,这一操作系统才算是正式有了 Macintosh 的名称,而它正式的完整名称是 Macintosh System Software 。

System 1 ~ System 5:功能迭代

最早的 System 1 当中,开机之后有一个非常可爱的欢迎界面:

菜单和窗口的概念清晰,比起 Xerox Alto 的设计更加成熟:

左上角的苹果图标打开之后,本质上是一个程序列表:

在 System 1 当中,文件夹是一个虚拟概念,在文件系统当中其实是根本不存在文件夹的,它是模拟现实文件夹的概念而存在的一个图形化界面概念:

在系统出错之后,系统报错界面中会使用炸弹图标来进行提示:

1984年的 Macintosh 的系统崩溃界面都比 2000 年之后的的 Windows 蓝屏界面来得更加有趣:

当然,用一个带有图形化界面的电脑玩游戏,难道不是一件天经地义的事情吗:

特别值得一提的是,Macintosh 自打一开始就为自己设计了一系列的字体:

其中风格独特的 San Francisco 在多年以后还拥有一个同名的字体,作为系统默认的字体而存在。

随后,在随后的 System 3 当中,垃圾桶的 APP 图标增加了「有垃圾文件」和「已清空」两种状态的区分,并且给系统新增了一个欢迎界面:

文件夹也不再只是一个虚拟的概念了:

同样的,在 System 3 当中游戏的精美程度也有了一定程度的提升:

当然,从 System 1 到 System 4,系统的功能在一代代地增加,但是受限于屏幕和基本的性能,其界面在整体观感上差别并不大:

不过在图标和界面细节的处理上,越来越丰富,越来越细致,比如系统的控制面板,功能和细节比 System 1 时代丰富了许多:

在 System 5 当中,Macintosh 还加入了多任务的功能,也就是 MultiFinder,使得用户终于可以同时运行多个任务,不过因为性能限制,跑多任务的时候,会比单任务慢不少。

System 6 :集大成的版本

对于 Macintosh 系统而言, System 6 是一个阶段性集大成的版本。系统的版本和软件的版本在 System 6 当中进行了统一,并且功能也有了相当程度的完善。

性能更强劲的 Macintosh SE/30 和 笔记本电脑 Macintosh Portable 也是在 System 6 更新期间发售的。

Macintosh Portable

Macintosh SE/30

System 7:拥有色彩的新世代

终于,黑白用户界面的时代在 1991 年终结,Macintosh 系统从 System 7 开始拥有了彩色的用户界面:

色彩的加入,系统图标的拟真度也再一次提升,比如垃圾桶的图标,光影已经相当逼真了。

而为了更好地利用彩色界面的功能,用户可以根据自己的偏好进行全局色彩设置:

软件安装的进度指示方式,比起同时代的系统乃至于后面的很多系统,都要清晰明确:

关键信息的说明和引导上,Macintosh 系统在30年前就已经有明确的范式了,比如重要信息标红强调:

由于这个阶段系统分辨率的限制,在按钮的视觉层次构建上,阴影和按钮凸起的效果,都做的比较简单,但是总体上始终上是在模拟现实存在的元素,通过尽可能贴近现实的视觉设计,来减轻用户的认知负荷,计算器和键盘的设计就非常的典型:

System 7 当中,还内置了交互式的用户帮助系统:

在控制面板当中,图标的统一性再一次得到了提升,风格上明显有着当时的特征,只不过在信息的传达上,还不够优秀,如果没有文本标签,你很难判断每个按钮对应的功能是什么:

值得一提的是,System 7 所处的阶段,大量的兼容机和包括 Windows 在内的操作系统开始出现,激烈的市场竞争之下,苹果也发布了一系列的新款的 Macintosh 电脑:

为了应对激烈的竞争,苹果还想出了新的策略,而这一策略也促成 Macintosh 系统后续逐渐成为一个独立的品牌。

Mac OS :第一次品牌重构

1996年,乔布斯重回苹果。同时在这个阶段,Macintosh 系统也随之进行了品牌重设计,Macintosh 系统更名为 Mac OS。

为了应对激烈的市场竞争,这一阶段的 Macintosh 电脑开始逐步切换到 PowerPC 架构的 CPU 芯片,同时,苹果公司也开始授权一些第三方厂商,使用同样架构的芯片和主板,并且安装System 7 的系统。

可以直接安装 System 7 的 StarMax 兼容机

这样一来,就开始出现问题了:非苹果产的电脑上,也会显示 「Macintosh 」的字样,那这个怎么和原厂的 Macintosh 电脑进行区分呢?

很简单,在原装的 Macintosh 上,依然还是 Macintosh,但是在兼容机上,它就是「黑苹果」——Mac OS:

在当时,很多人认为这种区分,仅仅只是用来进行差异化的临时解决方案。此时乔布斯即将重掌苹果,并且打算把前 CEO 的系统第三方授权策略给干掉。将 Macintosh 更名为 Mac OS 就是解决方案,只不过这个解决方案并后面还有其他的深意。

因为后面还有新系统。

Mac OS 8:一石二鸟的更新

Mac OS 8 是在 1997年7月26日发布的,同一个月另外一件大事,就是乔布斯正式任命为 CEO,执掌大权。

其实,此处的 Mac OS 8 并非真正意义上的大版本更新——它原本应该是 Mac OS 7.7 。但是,前 CEO 同第三方厂商签订的系统授权协议,是基于Macintosh System 7 的,而直接发布 8.0 版本等同于是巧妙地利用命名,直接把后续的服务和协议一起给断掉了,同时新的 Mac OS 系统从名字上也直接区分于原本的 Macintosh,可以说是釜底抽薪的一招绝杀。

同时,新名字,新世代,也是开创新局面的好预兆,一举多得。新的 Mac OS 8 系统在更加优秀的硬件基础上,在显示效果上也一下子进入了高清的时代。

虽然 Mac OS 8 在底层上,依然继承自 System 7 ,但是因为几年前开始的 Copland 项目有不少遗产,身为继承者的 Mac OS 8 在视觉和体验上,提升了相当明显:

Mac OS 8 当中加入了主题选择的功能,虽然比较简单,但是也至少有着跟 Windows 95 相互匹敌:

和同时代的很多操作系统一样,在多媒体软件上, Mac OS 8 有了颇为炫酷的视觉效果:

界面左上角的 Apple LOGO 继续作为程序列表的菜单按钮而存在:

类似 2.5 D 的图标设计,是这个时代的用户界面设计的流行风尚:

而这种变化,在 Mac OS 8.5 这一版本上,有了更为明显的提升——比如文本抗锯齿效果,让文本更加易于阅读:

更加柔和自然的的光影变化,更复杂的交互和界面元素,Mac OS 8.5 所呈现出来的视觉效果乃至于体验,不会弱于同时代的任何系统:

但是也仅仅只是不弱于对手而已。

Mac OS 9:争取时间的权宜之计

Mac OS 9 是 Mac 系统第一个系列的最后一个大版本。

和 Mac OS 8 类似,原本的 Mac OS 9 原本应该作为 Mac OS 8.7 来发布的。

其实早在乔布斯回归并发布 Mac OS 8 之后,Mac OS 9 的发展路径和命运就已经注定了:为老硬件和老用户更新,并且继续为真正的新系统争取时间。

Mac OS 9 是在 1999 年 10 月 23 日发布的。这个面向新世纪而发布的操作系统,苹果是以「有史以来网络功能最好的操作系统」来进行宣传。

此时,乔布斯重组的设计团队,已经为新的操作系统挑选好了新的设计语言,而此时发布的 Mac OS 9 当中,也适当地加入了一些为真正的下一代系统所准备的视觉元素,比如播放器软件中的不锈钢拉丝效果:

窗口界面中的元素有着细腻微妙的光影起伏:

搜索应用中的内阴影、高度拟物化的小图标:

特别要说的是,此时的 Mac OS 9 中已经可以找到很多贴合现代 UI 设计中的诸多原则了,比如富有逻辑的分组:

容纳多个并列分组的标签页交互:

在诸如帮助页面和安装界面中,使用了层级丰富的排版视觉设计:

也许现在你对于字体的这种投影深恶痛绝,但是在20年前,这样的视觉效果是令人惊艳的:

Mac 系统第一系列自此收官

Mac 系统的第一个操作系统系列,在明面上有着相对清晰的脉络:自家电脑,用自家系统。通过这一系列的界面设计,可以总结出下面的几点:

  • 第一个系列的 Mac 系统在交互和整体框架上,保持了高度了延续性;
  • 模拟现实世界中元素的设计理念,从 Xerox Alto 一直延续下来没变过;
  • 在已有屏幕分辨率基础上,最大化地提供优质的视觉体验,是它的宗旨;
  • Mac 系统确实在很早的阶段,就已经开始注意体验和「不言自明」的交互逻辑;

Mac 的图形化界面,始于施乐,成于乔布斯,在迭代中一步步完善。

不过,从 System 7 开始,它的危机就已经出现了。从 1991 年到 1999 年这 8 年时间当中,暗地里发生了一系列的事情,这些事情是 Mac 系统视觉史当中,不可或缺的组成部分。

下一篇,依然是 Mac 系统的视觉史,其中包括 WIndows、NeXTstep、BeOS,当然,还有 Mac OS X。

参考:
https://history-computer.com/ModernComputer/Personal/Macintosh.html
https://en.wikipedia.org/wiki/Xerox_Alto
https://web.archive.org/web/20001109004000/http://www.apple.com:80/macos/
https://apple.fandom.com/wiki/Mac_OS_8.5
https://en.wikipedia.org/wiki/System_7
https://www.versionmuseum.com/history-of/classic-mac-os
https://en.wikipedia.org/wiki/Macintosh_clone
https://en.wikipedia.org/wiki/Classic_Mac_OS

https://guidebookgallery.org/guis/macos/macos10


文章来源:优设    作者:陈子木

Mac 视觉史 vol.2:90年代失败操作系统大赏

雪涛

在第一篇 Mac 视觉史当中,我梳理过了整个 Mac 系统第一阶段的明线,而这一篇,我们来聊一下它的「暗线」。

这一章所涉及到的项目,几乎可以组成一个 大型的「90年代失败操作系统大赏」,在主要由成功者们所构成的故事、新闻乃至与传说当中,这些失败的故事和项目,被提及的次数很少。

但是对于 Mac OS X 而言,这里的每一次作死和失败都充满了意义。

对于绝大多数的用户而言,Mac OS X 是21世纪初顶尖设计的范式,在今天,它是最优秀操作系统的当中的典型。

但是仔细想想看:从 System 1.0 到 Mac OS 9.2.2,长达15年时间的挤牙膏渐进式升级的Classic Mac OS,怎么可能突然一下子就变成了充满现代感的 Mac OS X?这种翻天覆地式的变化的确充满了戏剧感,但那是在今天的视角之下。

在这场「90年代失败操作系统大赏」当中,无疾而终者多不胜数,你所看到的不仅有粉墨登场,还有各式各样的粉末谢场。在 Mac 的视觉史当中,这一篇应该是一个大型的「处刑现场」。

失败的尝试,同样是 Mac 整个视觉演变史当中,绕不过去的部分——没有这些失败,就没有今天我们所熟知的 macOS 的视觉风格,没有后面 iOS 、iPadOS、watchOS 等等一系列交互界面和视觉。

来自内部的压力

虽然我们此刻所谈及的是操作系统的视觉史,但是操作系统背后最重要的始终是推动它的「人」。谈 Windows 必然会涉及 比尔·盖茨,而谈到 Mac ,也不得不说乔布斯。

和当年很多操作系统不一样的地方在于,乔布斯一直坚持硬件和软件(操作系统)理应是一体的。这也是为什么在很长的一段时间以内,Macintosh 指的既是硬件(电脑),也是软件(操作系统),而因为这台电脑是更容易被指代的对象,当用户在指代系统的时候,使用的是诸如 System 1 ,System 2 这样的词汇。

原本的 Maciontsh 是有内部竞争对手的——Lisa,这个以乔布斯女儿命名的电脑研发项目被夺走之后,乔布斯在 Macintosh 上投注了300% 的精力,亲手操刀了不少设计。拥有大量资源倾斜的 Lisa 在当时那个阶段,看起来也并不差:

在这个 1983年的 UI 界面上,细节处理其实也算得上非常用心了,比如顶部菜单上的「阴影渐变效果」:

当然,Lisa 的定位也非常明确,它就是一台办公电脑,所以它的系统名称也非常简单直接地使用了 Lisa Office System 这样的名字:

也正是在这样的对比之下,有着丰富字体、多样的媒体功能、能够玩游戏的 Macintosh 在这场内部竞赛中,得以胜出。

当然,如同我们都知道的,乔布斯在发布 Macintosh 的 2年后被迫离开自己创立的公司。当然,更重要的是,硅谷的巨头们更加清楚计算机的发展方向。这使得 Macintosh 面对的外部压力骤增。

激烈的外部竞争

图形化界面(GUI)的概念和交互模式——这个点子本身可能比实现技术来得更重要。

在高手云集的硅谷,虽然绝大多数的企业和开发者都是后期入局者,但是他们只要投入足够多的技术人员和时间,类似的图形化交互界面总归是能做出来的。

比如 Visi Corp 给 IBM 提供了 Visi On 这样的图形化程序:

微软也在 1985 年为 IBM 的 PC 提供了 Windows 软件:

Commodore 的图形化界面也差不多同期问世:

而 GEOS 甚至为更老的 Apple ][ 提供了图形化界面的操作系统:

这些系统都是在 Macintosh 发布那一两年内相继问世的。

从 System 6 开始新尝试

操作系统领域的竞争,刺激着苹果寻求突破。

多数企业都不会把鸡蛋放在一个篮子里,这样孤注一掷的决策确实有太大的风险。其他的商用操作系统,都开始拥有日渐完善的桌面端图形界面,使得苹果在差异性和独特性上不足。除了在硬件性能和产品线上增加投入,他们也开始尝试开发更优秀的图形化界面和下一代操作系统。

在上一篇当中,我提到过,在 80 年代末所发售的 System 6 是一个集大成的版本,在硬件性能和黑白显示器之下,这个操作系统本身的核心功能已经颇为完善了。这个时候,苹果开始有意识地进行一些探索性的项目。

「Pink」和「Blue」项目

某种意义上来说,「Blue」 和「Pink」 两个项目几乎是同时开始的。

虽然 1988 年的时候,乔布斯早已离开,但是他所塑造的 Macintosh 是当之无愧的传奇,那种「内部创业」和「改变世界」、「创造传奇」的硅谷精神对于此刻的苹果员工依然有着极大的影响。

当时苹果内部 5 名躁动不安的中层开发工程师想拜托日渐僵化的内部管理,想改变当时 System 6 表现欠佳的局面,想打造一个次世代的旗舰操作系统——某种意义上重现 1984 Macintosh 的传奇。

他们在这次私底下的会议上重新梳理并规划未来的操作系统。他们将System 6 基础上的可以增量更新的特性、可以很快实现的功能,写在蓝色的卡片上,将技术上更加先进、符合长期价值的功能(比如当时 Macintosh 所缺乏的抢先式多任务处理和组件化程序设计)写在粉色的卡片上,将更加激进的特性写在红色的卡片上。

这次会议基本上就塑造了后面的「Blue」和「Pink」两个项目,而红色卡片上的特性由于过于激进,仅仅只是备案而没有成立项目。

数百名工程师继续在 System 6 的基础上按部就班地更新功能、维护代码库,继续「Blue」项目,而它的最终产物,就是后面我们看到的 System 7:

而另外一边的「Pink」项目,一开始并不是公开的。当时 Erich Ringewald 领导这发起这次会议的核心 5人组,想像 Macintosh 项目开始那样,找一个隐秘的房间开始这次「内部创业」。

他们看上了 位于 Bubb Road 的一间仓库,当他们进去的时候,才发现这个仓库已经被另外一个正在秘密进行 Newton 项目的团队给占了。

当然这款同样极为传奇的(失败)掌上设备我们回头再说。

一路膨胀的「Pink」项目

「Pink 」项目开局的时候,有 6个人,但是考虑到要彻底放弃 System 6 的遗产,重新开始全新的操作系统,程序要是面向对象的,要有内存保护,要抢先式多任务处理,要支持多语言足够国际化,还要有全新的图形库,这个团队开始一路膨胀。

先是苹果的先进技术小组(ATG)加入团队,人数变为11人。 2个月后,「Pink」项目增加到 25 人。7个月后,原始的5人组几乎都因为「人员多到失控」而离开「Pink」项目。1年后,「Pink」项目的开发组多达100人。

原本计划在2年后发布的「Pink」操作系统在原计划的2年之期到期之时,拥有了 150 人的超大规模,高级副总裁和市场营销部门的首脑领导着这个庞大的开发团队。

「Pink 什么时候上市?答案永远都是2年后。」

这是当时流传的一个内部笑话。

但是这个笑话只是刚刚开始。因为它才刚刚开始膨胀。

系统开发需要时间,而随着时间推移,市场变化需要「Pink」 更有竞争力,然后原本位于红色卡片上的「激进功能」开始不断的加入到「Pink」当中,然后项目就需要更多时间来开发——恶性循环开始了。

在「Pink」上,苹果投入了太多,放弃是不可能放弃了,唯一的办法就是拉更多人入局。当时的 CEO John Sculley 对外宣称「Pink」操作系统代码已经多达 150 万行,并去 IBM 做了内部演示。

然后,这个看起来像是被移植到 PC 上的 System 7 成功地引起了 IBM 的注意。让比尔·盖茨最不想看到的事情发生了:苹果、IBM 和 摩托罗拉成立 AIM 联盟。

从未发布的「Taligent」系统

AIM 联盟成立于 1991年10月2日,此时距离「Pink」项目开始已经过去了3年半。半年之后,苹果和 IBM 正式组建了合资公司 Taligent .inc ,而其中苹果占股较小。

原本被拿来吹嘘的「Pink」操作系统,此时也更名为 Taligent 。

Taligent OS 的确有着很多超越 Macintosh 的功能,比如更的程序机制,3D功能等等等等。在整个 UI 界面上,Taligent OS 使用了继承自「Pink」项目的一些设计:等轴测的图标,伪3D风格的图标,还有非矩形的窗口(注意看窗口的顶部菜单栏)。

当然,Taligent OS 从「PInk」项目继承过来的最大特性是:一直在开发,从未正式发布。

1994年,HP 入局,加入 Taligent 公司并且持股 15%,Taligent OS 的一部分技术开始运用到 HP 家的 NewWave 桌面环境中了:

与此同时,Windows 95 的关注度越来越高,而媒体吐槽苹果久未发布的新系统,并嘲讽难产多年的 Taligent OS(还有 Pink),已经成了一件政治正确的事情。

虽然 1994 年的时候,Taligent OS 在 SFA 展会上使用 Macintosh IIcI 展示了运行速度和崩溃速度同样快的 3D 应用,但是它最终还是没有发布。

1995年,苹果出售股权退出 Taligent 公司,「Pink」 项目的最终产品也并非 Taligent OS,而是 IBM 公司的 AIX 系统中的 Common Point 应用。

「Pink」到此终结。失败。

最终迷航的「StarTrek」计划

在 Taligent OS 研发期间,苹果将鸡蛋还放到了另外一个篮子里面,这个项目的代号借用了著名的科幻电影《星际迷航》,项目的 Slogan 是「大胆地探索 Mac 之前从未去到过的地方」。

这个地方就是使用英特尔芯片的 X86 架构的电脑上。

「StarTret」项目中,苹果是和当时的服务器供应商 Novell 共同构思的,这个项目最终因为内部斗争、人事纠纷、市场问题而关闭。值得一提的是,同样的尝试在 1985年的时候就有过,不过那次尝试很快就被中止了,以至于至今没有一个正式的代号留下来。

这算是2次失败。

「Copland」 操作系统

作为 「Blue」项目产物的 System 7 最终并没有彻底解决苹果在操作系统上的困顿处境,系统依然问题很多,内存保护机制、抢先式多任务处理依然还没有。而 1994年3月开始的「Copland」项目,就是为此做准备的,它的代号来源于美国作曲家 Aaron Copland 。

除了在内存分配和多任务处理等核心功能上进行开发提升,它在 GUI 的视觉层面上的优化,也花费了相当多的心思。在视觉层面上,Copland 新设计的一套主题名为 Platinum ,所有的元素都有着颇为细腻的阴影,窗口元素则有着明显的突起,原本「Pink」项目中的等轴测图标也加入了进来。

除了 Platinum 之外,Copland 还加入了面向儿童的主题P,以及更加具有未来派风格的主题Z。

除了主题本身之外,Copland 还支持窗口最小化到底部为标签,多用户登录(Windows 98 之后才有这个功能),这种功能类似于现在的家长管理——管理员帐号可以决定其他用户可以使用哪些应用。可以说,非常超前了。

当你在 Copland 中拖动文件到不同文件夹的时候,这些文件夹可以自动打开,这一功能在当时也是非常先进的。

不过,Copland 极具前瞻性的另外一面,就是它本质上是一个「要你命3000」。各种新的功能和特性出于市场需求和项目需求毫无节制地被加入进来,所有的功能相互之间都存在冲突和影响,所有人都很清晰地知道,Copland 是不可能被作为正式产品所发布出来的。

「它只是一个不同团队开发产品的合集……并且期望它们能够神奇地组合到一起。」

这是当时的 CEO Amelio 自己说的。

当然,Copland 的阵亡不可避免,只不过它的界面管理器和 Platinum 主题最终留到了 Mac OS 8 当中,为苹果公司的自救大业添砖加瓦。

Copland 失败了。自家开发团队搞不定,只能从外部想办法了。

4个外部备选方案

当时,CEO Amelio 个人比较倾向于 Windows NT,并且为此专门同盖茨通了电话,而盖茨也表示如果愿意使用 Windows,他可以组建团队将苹果的拳头产品 QuickDraw 移植过来。此时,WIndows 95 已经发布一年了,而 Windows NT 也刚刚发布,市场反响极好,份额节节攀升。

当然,苹果和微软的命运纠缠并不是此时才开始的。Windows 1.0 时代,图形化界面的专利授权是苹果授权给微软的。

而 Windows 2.0 继续沿用 1.0 时代的设计,但是苹果没有给 2.0 授权,最终引起了纠纷,盖茨借用不维护 Word 和 Excel 软件和当时的 CEO 达成了庭外的和解。这些事情回头有机会细说。

和CEO的想法不同,当时苹果的 CTO Ellen Hancock 其实是想选择 Solaris 来着,不过它还没有一套友好的用户界面,赢面不大。

最终摆在苹果CEO 和董事会桌面上的,就剩下两个备选了,一个是 BeOS,另一个是乔布斯的 NeXTSTEP。

然而这毫无疑问是一次极具戏剧化的选择,因为这两个操作系统背后的两个人,有着极深的纠葛。

让-路易·加西 和乔布斯的纠葛

Be 公司的 CEO 是法国人 让·路易·加西,他是 1981 年加入苹果公司并负责当时欧洲业务。

1985年,他在得知乔布斯计划在阵亡将士纪念日罢免 CEO 约翰·斯卡利(John Sculley)的计划后,抢先告知董事会,最终导致乔布斯从苹果辞职。

1987年,加西启动了 「Skunkworks」项目,而这个项目的产物就是后来的掌上电脑 Newton MessagePad,而最终这条产品线也是乔布斯关停的。当年的「Pink 」五人组在仓库里撞见的,就是加西的团队。

1990年,加西和CEO交恶,并且董事会对于他所推出的 Macintosh 产品不满意,最终导致他离开了苹果,并于次年创立了自己的 Be 公司。

彼时正在艰难推进 NeXT 电脑业务的乔布斯,在媒体那边的口碑并不好。而加西反而在这个时候,对 NeXT 不吝溢美之词。

当然,最终乔布斯的 NeXT 和 加西的 Be 最终还是摆在了同一张桌子上,被选择。

极具潜力的 BeOS

BeOS 是一个在当时来看极为激进的操作系统。它并不是为当时更为流行的办公场景而构建,而是一款旨在为多媒体处理而生的操作系统。

它并没有采用当时所流行的 Unix 的架构,有着一套相对更加独特的系统逻辑和设计规则。

它同样延续了当时最为流行的等轴测图标设计,在配色上更为鲜亮,在视觉化设计上,一点都不弱于同时期的任何操作系统,包括 Macintosh 和 NeXTSTEP。

在交互逻辑上,BeOS 沿用了当时很多 Unix 操作系统的右侧交互工具工具栏,正在运行的程序可以清晰地在此预览,而右上角的 BeOS LOGO 则类似开始菜单,可以呼出程序列表:

BeOS 的图标设计在统一性和规范性上极高,即使在今天看来,很多设计都不落俗套:

BeOS 能进入苹果的备选,一个很重要原因是这套操作系统兼容当时 Macintosh 所用的 PowerPC 的架构。尽管它一直都未曾推进到 1.0 正式版,但是并不影响它在电脑领域收割一大波粉丝。

但是作为一个操作系统而言,在消费市场上依然是一个失败的产品。

定位高端的 NeXTSTEP

另外一边,乔布斯 的 NeXT 电脑并没有复制 Macintosh 消费市场上的成功。不过,NeXT 作为定位高端的工作站,倒是吸引了不少科学家和计算机领域的研究人员以及顶尖的数字创意从业者的注意。

在接近被收购的当口,NeXTSTEP 系统已经推进到了4.0 的大版本。由于它本身在硬件性能上的突出表现,在操作系统的各种细节上,一点都不吝惜,竭尽全力地刻画细节。而这其中,有很多概念和想法是从 Macintosh 时代继承并发扬出来,并惠及后面的 MacOSX 乃至于 macOS。

精巧的 3D 小插件,全彩高清大尺寸拟物化图标,底部程序坞组件,以及可以购买软件的软件商店,甚至于著名的游戏 Doom 和 Quake 都是在 NeXTSTEP 上首发的。

无论是内部的功能,还是外部的 UI 元素的细节控制,NeXTSTEP 都在当时条件允许的前提下,做到了尽善尽美。比如登录和关闭窗口中的光影细节:

(注:NeXTSTEP 是操作系统,而OpenStep 是一套 API。)

当然,NeXT 本身并不算成功,被苹果收购是最好的结局之一,这不仅是市场的选择,也是苹果的选择,是乔布斯的选择。

结语:自此重启

终极对决发生在 1996年10月12日,地点是帕罗奥托的花园庭院酒店。

CEO Amelio、CTO Hancock ,以及另外 的 6 位董事会成员是最终决策者。加西志得意满,没有作任何演示,而乔布斯不仅使用了他的天赋技能「现实扭曲力场」,而且如同魔术师一般演示了 NeXTSTEP 的各种功能和特性。

苹果公司,乔布斯,加西 三方的命运在此汇聚碰撞,然后再次扭转。当然,这个扭转的过程并非一帆风顺,此时,距离苹果的命运彻底改变,还有4年时间。

在离开苹果、创立 NeXT 的阶段,乔布斯和苹果曾数度交恶,其中所产生的纠纷与诉讼在此刻依然是障碍。

NeXT公司同意了种种限制条款:其产品将作为高端智能终端直接销售给高校,而且NeXT公司不能在1987年3月之前推出产品。苹果公司还坚持,NeXT的机器「不能使用与Mac兼容的操作系统」。后来的情况表明,如果当时苹果公司的要求刚好相反,会对自身更为有利。

——《史蒂夫·乔布斯传》

看完了这些失败的产品的产品,我们终于要说一下成功的产品了。

下一篇,我们将从「水」聊起。

引用来源:

https://en.wikipedia.org/wiki/Jean-Louis_Gass%C3%A9e
https://guidebookgallery.org/articles/sortingoutfactfromfiction
http://toastytech.com/guis/guitimeline2.html
https://lowendmac.com/2005/apples-copland-project/
https://en.wikipedia.org/wiki/Appearance_Manager
https://en.wikipedia.org/wiki/Star_Trek_project
https://dl.acm.org/doi/book/10.5555/582997
https://en.wikipedia.org/wiki/System_7
https://web.archive.org/web/20070120202050/http://robinnet.net/resume/Robin_portfolio_Taligent.htm
https://web.archive.org/web/20070106224709/http://www.wildcrest.com/Potel/Portfolio/InsideTaligentTechnology/WW87.htm
https://www.operating-system.org/betriebssystem/_english/bs-aix.htm

https://www.wired.com/1993/02/taligent/


文章来源:优设    作者:陈子木

日历

链接

blogger

蓝蓝 http://www.lanlanwork.com

存档