使用function關鍵字定義函數
函數聲明會被提升(Hoisting),將聲明移動到當前作用域頂端的默認行為。
參數:
如果函數調用的參數太多(超過聲明),則可以使用函數的內置對象arguments
arguments.length 會返回函數被調用時收到的參數數目
arguments[index]可以得到相應的參數
傳遞對象的時候是使用引用來傳遞的,如果函數修改了對象屬性,則原始對象也改變了。
調用:
以函數形式調用函數:(這種方式調用默認的是全局對象調用)
function myFunction(a, b) {
return a * b;
}
myFunction(10, 2);
作為方法來調用函數:(這種方式調用屬于函數的擁有者myObject)
var myObject = {
firstName:"Bill",
lastName: "Gates",
fullName: function () {
return this.firstName + " " + this.lastName;
}
}
myObject.fullName();
通過函數構造器來調用函數:(如果函數調用的前面是 new 關鍵字,那么這是一個構造函數調用)
function myFunction(arg1, arg2) {
this.firstName = arg1;
this.lastName = arg2;
}
var x = new myFunction("Bill", "Gates");
x.firstName;
call()和apply()方法:
var person = {
fullName: function() {
return this.firstName + " " + this.lastName;
}
}
var person1 = {
firstName:"Bill",
lastName: "Gates",
}
var person2 = {
fullName: function(city, country) {
return this.firstName + " " + this.lastName + "," + city + "," + country;
}
}
call() 方法是預定義的 JavaScript 方法。
它可以用來調用所有者對象作為參數的方法。
通過 call(),您能夠使用屬于另一個對象的方法。
如:
person.fullName.call(person1)// person1來調用person的fullName方法
call()可以帶參數,參數對應按順序的傳給方法
person2.fullName.call(person1,"Seattle", "USA")
apply()方法和call()方法類似
區別在于接收參數的方式不一樣。
call(obj,"x","y") 方法分別接受參數
apply(obj,["x","y"]) 方法接收數組形式的參數
箭頭函數:(ES6)
箭頭函數不需要function關鍵字、return關鍵字和大括號
var x = function(x, y) {
return x y;
}
var x = (x, y) => x y;
兩個的作用相同。
箭頭函數沒有自己的this、如果函數是單個語句,則只能省略 return 關鍵字和大括號
藍藍設計( www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務。
User表:
User類:
package pers.zhang.domain;
public class User {
private Long user_id;
private String user_code;
private String user_name;
private String user_password;
private String user_state;
public Long getUser_id() {
return user_id;
}
public void setUser_id(Long user_id) {
this.user_id = user_id;
}
public String getUser_code() {
return user_code;
}
public void setUser_code(String user_code) {
this.user_code = user_code;
}
public String getUser_name() {
return user_name;
}
public void setUser_name(String user_name) {
this.user_name = user_name;
}
public String getUser_password() {
return user_password;
}
public void setUser_password(String user_password) {
this.user_password = user_password;
}
public String getUser_state() {
return user_state;
}
public void setUser_state(String user_state) {
this.user_state = user_state;
}
}
ORM元數據:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
";
<hibernate-mapping package="pers.zhang.domain" >
<class name="User" table="sys_user" >
<id name="user_id" >
<generator class="identity"></generator>
</id>
<property name="user_code" column="user_code" ></property>
<property name="user_name" column="user_name" ></property>
<property name="user_password" column="user_password" ></property>
<property name="user_state" column="user_state" ></property>
</class>
</hibernate-mapping>
控制層:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
//獲得查詢參數
String userIdStr = request.getParameter("userId");
String userName = request.getParameter("userName");
//獲得離線查詢對象
DetachedCriteria detachedCriteria = DetachedCriteria.forClass(User.class);
//拼裝查詢條件
if(userIdStr != null && !"".equals(userIdStr)) {
Long userId = (long) Integer.parseInt(userIdStr);
detachedCriteria.add(Restrictions.eq("user_id", userId));
}
if(userName != null && !"".equals(userName)) {
detachedCriteria.add(Restrictions.like("user_name", userName, MatchMode.ANYWHERE));
}
//作為參數傳遞給service層
UserService userService = new UserService();
List<User> list = userService.findUserByCondition(detachedCriteria);
request.setAttribute("userList", list);
request.getRequestDispatcher("list2.jsp").forward(request, response);
}
Service層:
public List<User> findUserByCondition(DetachedCriteria detachedCriteria) {
//傳遞給Dao層
UserDao userDao = new UserDao();
return userDao.findUserByCondition(detachedCriteria);
}
1
2
3
4
5
Dao層:
public List<User> findUserByCondition(DetachedCriteria detachedCriteria) {
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
//關聯session
Criteria criteria = detachedCriteria.getExecutableCriteria(session);
//查詢
List<User> list = criteria.list();
return list;
}
前端頁面:
忘記寫查詢數據回顯了…
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<script type="text/javascript" src="js/jquery-2.1.0.js" ></script>
<script type="text/javascript" src="js/bootstrap.min.js" ></script>
<link rel="stylesheet" href="css/bootstrap.css" />
</head>
<body>
<form class="form-inline" role="form" method="post" action="${pageContext.request.contextPath }/findUserByCondition">
<div class="form-group">
<input type="text" class="form-control" id="exampleInputEmail2" placeholder="用戶ID" name="userId">
</div>
<div class="form-group">
<input type="text" class="form-control" id="exampleInputPassword2" placeholder="用戶名" name="userName">
</div>
<button type="submit" class="btn btn-default">篩選</button>
</form>
<div style="text-align: center; width: 600px;">
<table class="table table-hover">
<tr><td>編號</td><td>用戶ID</td><td>用戶名</td><td>昵稱</td><td>密碼</td></tr>
<!-- 顯示數據 -->
<c:forEach items="${userList }" var="list">
<tr><td>${list.user_id }</td><td>${list.user_code }</td><td>${list.user_name }</td><td>${list.user_password }</td><td>${list.user_state }</td></tr>
</c:forEach>
</table>
</div>
</body>
</html>
測試:
藍藍設計( www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務。
講述邊際效應對應不同線上線下產品的不同狀態以及優勢
現如今對于大多數的互聯網產品來說,其實都大致會用到“邊際效應”這個概念,在看似華麗渲染的互聯網背后,真正支撐著的是對人的深刻認識與理解。當然,現如今的產品很多都有規律可循,包括商業模式、變現方式等等,那么這次我們就來說說那些在互聯網中產品的邊際成本遞減效應的設計。
首先呢,在這里我要先為大家解釋一下何為邊際成本。
從概念性角度解釋:邊際成本指的是每一個單位新增的產品(或購買的產品)所帶來的總成本增量。
比如說現如今的共享單車,在僅生產第一輛的時候,其公司花費的成本是極大的,它包含:設計費、電話費、路程費、人工費等等等等……但是,在生產第100輛的時候,小車兒的成本就低很多了,再不創新的前提下,只要復制就可以了,而如果在生產第1000輛的時候,那成本就更低了,這就是經濟規模帶來的效應。那么,同樣的復制,為什么越復制越便宜呢?其實,這里面有一個對等的增產量對比,由于小車數量的增多,遍布區域的擴大,所以,也就導致公司的機會成本增高,也就是成本更低,所以,考慮邊際成本遞減的同時,也要考慮機會的增多。
剛才說到的其實就是邊際效應里成本遞減的模式,也是我們這次討論產品的核心,所謂的邊際效應遞減,就是指在其他條件不變的情況下,如果一種投入要素連續的等量增加,當增加到一定產值后,所提供的產品增量就會下降,同時可變要素的邊際產量就會遞減。
我在舉個例子:日常的滴滴打車,就是遞減的模式,因為滴滴大多數的供給側平臺用戶就是私家車出來接單,所以,當平臺每多接入一輛車,那么對于滴滴平臺來講邊際成本就越趨于零。
其實,類似于滴滴打車這樣的線上+線下的資源整合性平臺,更加符合互聯網的經營模式,這是因為互聯網在21世紀,就是以免費為前提的,隨著用戶的增多,邊際成本的下降,無非就是在完善經營的條件下,多開一些服務器和寬帶罷了,其他的成本幾乎已經可以忽略不計,而這也正是互聯網產品成為霸主的必要因素之一。
注(供給側:經濟學術語的一種,意思是指供給方面,國民經濟的平穩發展取決于經濟中需求和供給的相對平衡。 供給顯示了隨著價錢升降而其它因素不變的情況下,某個體在每段時間內所愿意賣出的某貨物的數量。在某一價格下,消費者愿意購買的某一貨物的總數量稱為需求量。在不同價格下,供給量會不同。供給和需求也就是說價格與需求量的關系。若以圖像表示,便稱為供給曲線。)
在我們逛街購物時,幾乎都會買一杯奶茶飲品,而這里面就運用到了邊際效應的負效應模式,他們運用第二杯半價的手段來提升消費者對產品第一次的貪婪程度,也就是“欲望值”,同時也提升了產品的銷售,但邊際成本不變,當消費者購買后,負效應可能就會產生,因為消費者不一定能喝完。這里就體現的是商品價值取決于人的欲望和欲望被滿足的程度比例。
再比如商場內大牌服裝都寫著全場8折,其實仔細想想,8折的價格真的很劃算么?他們這么做也同樣是在運用了邊際效應的同時調取了消費者心理的欲望值,在消費者第一次購買時,單純考慮的爽點而非負效應,但隨著商品購買完的數量,才真正會產生負效應。
還有一個是關于電影票的,我的一個朋友會經常去看電影,之前去看電影的時候是在現場買的票,那次售票員給他推送了一個非常超值的套餐,就是單買一張票是原價48元,但是近期有一個限量套餐,這個套餐里包含:5場電影+1桶爆米花,價格是149元,但是需要一次性消費,聽起來是不是非常超值?我的朋友考慮反正也沒事,那就多看幾場,還便宜。但是如果按照邊際成本遞減與負效應來講,這絕對是一件虧本的買賣,誰能一直做著看十幾個小時的電影不走?我想電影院也一定有這樣的數據才會推出這樣的套餐吧。但隨著消費者購買人數越多,邊際成本遞減,其他人也會紛紛模仿,這里面包含一個人類固有的“羊群效應”,也就形成了商業價值,但隨著消費者看電影時間的延長,負效應也隨之而來。
注(羊群效應:羊群效應理論,也稱羊群行為、從眾心理。經濟學里經常用“羊群效應”來描述經濟個體的從眾跟風心理。)
首當其沖的,自然是微信了,這個傳奇產品堪稱邊際成本做的最好的一個,在我們之前都是運用短信電話的時候,每發一條短信,每打一個電話都要考慮不同的費用,但由于微信的出現,極大的解決了用戶的這個痛點,微信已最核心的打字聊天、語音/視頻通話為主要支點,并賦予各種特色產品輔助。在微信最大化的邊際成本趨于零的同時,迅速擴大了用戶使用產品的范圍區,所以,作為互聯網的邊際成本,我想微信的在這方面確實做的很好。
這款產品為共享汽車類型,屬于線上+線下產品,Gofun出行的邊際成本做的比較合理是,首先是他的供給側能力較足,因為依托了首汽集團的優勢資源,極大的降低了邊際成本,并通過對用戶的日常作息將碎片打車時間、坐公交時間、出游時間等需求作為整體分析,提供了這一種出行服務,并且現在的產品里還融合了長時間租車服務,這就極大的又一次挖掘了一批潛在用戶,在邊際成本遞減并趨于零的同時,反響的用戶群體范圍也在逐漸擴大。同時這個產品還在登陸時跳出有廣告提示,“分享可得免費時長開車券等優惠”,這種手法也是除了在邊際成本遞減的同時,運用的用戶酬賞機制,目的是通過用戶引流用戶。
在文章開篇的時候我拿共享單車舉過例子,其實摩拜單車的性質與共享汽車的性質大體一致,主線路相似程度可達到80%,這里我要和大家說一個定律,關于用戶的定律。當產品開發者抓區并成功解決掉某幾種目標用戶的痛點后,其相等模式可無限制復制,并形成范圍值生產從而解決掉這幾種用戶對等的群體用戶痛點。
我給大家舉個例子應該就徹底明白了,就像醫藥行業診斷,當醫生遇到一種從未遇見過的病毒時,其第一次需要花費的成本是極其昂貴的,但只要一旦得到解決,那么當再次遇到同類型病毒時,就可以快速復制解決,其邊際成本迅速降低,反之收益增高,同時同類型病毒則可批量解決。共享汽車和單車產品正是邊際成本與復制的這一體現。
邊際成本在20世紀時是非常難得的一個概念,因為在20世紀的成本里,幾乎都是建立在“原子經濟”上的,而直到21世紀互聯網形體的出現,邊際成本將真實的成倍數下降,這是因為21世紀的成本發生了轉移,建立在了“比特經濟”上。
所謂原子經濟的本質就是需要以大規模生產取勝,它所遵從的是絕對的單一化、標準化、格式化創造。這種創造,并不能形成邊際成本的遞減,甭別說是趨于零,它需要的是逐漸遞增服務,就像和滴滴打車對抗的線下出租車,隨著消費者的增多,它能做的不是整合,而是新增出租車和司機進行匹配,如果不加入互聯網行業,他們將很難維持下去。
而比特經濟,則正好是多元化、個性化、小眾化、扁平化的。它所崇尚的就是一種主客一體、多元共生共存的理念、可以使使用者分享滿足感和快樂感。這樣的好處是在快速擴大用戶群體區值的同時還能使邊際成本下降。
文章來源:站酷
不知道從什么時候我開始 對“創新”這個詞感到些許乏力和恐懼,開始思考為什么有些人能看透問題本質?于是有了本文的探索和總結。
平時我們大部分時間都在做一些“應激反應”的事情,經常處于“被安排”的情況下,大腦逐漸懶得去思考背后的東西,通常根據自己的主觀意愿做出一些反應。慢慢依賴一些“道聽途說”而來的方法論來做一些事情,“套用”效果也不理想。
有一定履歷的產品經理多數也會迷上“經驗論”。
種種行為都是沒有通過本質思考的行為表現,都是一些脈沖式的思考。別人做什么 ,我們也跟著去做,只能在這個行業里面產生細微的迭代,無法實現真正的創新。
關于創新,埃隆馬斯克引爆了一個概念,回歸到事物本質,看透問題本源的思維叫“第一性原理”,它不是一個定律也不是真理,而是一種思維模式。
我先不解釋到底什么是第一性原理,因為本來就處于蒙圈的情況下再去看一些專業的解釋就會更加蒙圈。
下面分享一個故事,一起來了解一下本質思考這種思考方式,拋開哲學、生命、宇宙本質,圍繞“搶域名”這件事,主角蔡文勝是如何將域名搶注成功率從十萬分之一變成50%以上?他到底是怎么做到及如何思考的。
背景:fm365.com注冊于1999年10月21日,因忘記續費,到2003年10月21日過期,當時這個網站是聯想重金打造的門戶網站流量非??捎^,當時可能有10萬人要想搶注這個域名。
想搶注域名的人都知道域名釋放時間是在2003年10月21日,但很多人沒有做好基本的調研與了解,不同域名服務商釋放時間不一樣,有些是次日0點,有些是30天,所以當時大部分人都不知道這個具體域名掉落時間,實際上這個域名掉落時間是在70天之后。
那么知道了域名掉落的具體日期, 也不可能一整天都去注冊搶注, 還需要知道具體時間才能搶注成功,而事實上當時這個域名在美國一個域名商手上,所以掉落時間是在美國的中午12點,對應中國是凌晨3點,在那個時間點域名才完全掉落。
那么問題來了,知道了最后具體掉落日期和時間,怎樣才能脫穎而出,成為那個唯一一個能把域名搶到的人?
蔡文勝做了以下4件事:
第一件,首先注冊域名上所有信息、 名字、郵箱等字段事先填好 ,這個過程大概需要5秒鐘, 然后直接按f5就可以了,只要1秒不到,就能提交注冊信息。
第二件,蔡文勝當時查了一下這個網絡請求到底是怎么走的,發現這個請求是先從廈門連到上海,上海連到美國,請求的路徑非常長,當時在2003年網速還是非常的慢,所以蔡文勝索性租了一臺上海的服務器,直接從上海連到美國,這樣至少在中國理論上是最快的。
第三件,節省注冊資料字節長度,把88888@qq.com改成 1@1.com,因為這信息回頭也可以修改,壓縮后比完整的信息要少幾百個字節,這樣加快提交速度,又提高成功率。
第四件,當時據說搶注這個域名的人有10萬人,蔡文勝預估有大概前面3件事能淘汰掉90%的人,還和剩余10%的人進行競爭,所以還是不能保證能夠注冊并搶注成功。最后蔡文勝搞了一個自動點擊腳本,每秒提交1000次。最終蔡文勝從10萬人里面脫穎而出,成為唯一一個搶到域名的人。
回歸到搶域名這件事的本質上,把域名開放時間設為T0,提交信息到域名服務器的時間設為T1,使T1-T0的時間最短就能搶注成功。
看完上面的故事,回歸產品人如何訓練/培養自己的本質思維。
每個人都有一定思維慣性,看到事物會下意識的做出一些反應。
在《思考,快與慢》書中的知識叫“快系統”,人會本能直覺迅速做出一些判斷和反應,這套系統好處是大腦反應非??欤牡瓦€”省電“。
所以我們一旦意識到自己在用過往或他人、競爭對手等經驗時先打住,不是說不能用,而先思考這些“經驗”對現在是否真正能用上。
每個人都有自己對主觀意識,特別是產品經理這個崗位主觀意識真的太強了。在數據報表或調研結果上看到一批數據會帶上自己的主觀想法來解釋這一批數據原因。
擺脫原有的思維慣性應該啟動大腦的“慢系統”,慢系統需要調動我們的邏輯思維等能力,一旦啟動邏輯思維能力周期很長,啟動很慢很費力,所以我們日常那么多事情處理的時候,沒有什么時間去切換慢系統,所以會造成前面所說的應激反應。
當然我們也非常難做到每次都使用“慢系統”來解決問題,大腦處理不過來,頭發也堅持不住,但我們可以鍛煉出好的思維方式,讓自己思考時不輕易的跑到原有的思維慣性去。
蔡文勝在搶注FM365這事上就是不斷追問自己,“我還能不能更快一點?”、“我怎樣才能比別人更快搶到!”、“如何將請求路徑變短?”、“怎樣才能提升請求速度?” 從解決問題的路徑上,根據目標一層一層的不斷的對自己發問,最終這些問題都會迎刃而解。
有問題請教別人也是突破思維慣性的好方法,拋開對錯,觀點過濾,交流時可以認真聽但不要照著做,和老板給你提需求是一個道理。問題方和解決方看到的視角都是不一樣的,利于思維開闊。
“實踐”指的洞察已發生的事物做出自我思考的問題和想法、比如在“產品分析”環節重點研究下對方可能接下來會做些什么事,預估做了會產生哪些結果?當前的業務形態為什么會這樣設計?
總之產品方法論有時候并沒有那么重要,最重要的不是學習別人的方法論,而是通過自己的本質思考,不斷總結出自己的方法論,有意識的去訓練自己的思維習慣,養成思維模型,這對產品經理才是重要的事情。
文章來源:人人都是產品經理
AI被熱捧那么久,王維嘉博士的《暗知識》是第一本把它講明白的中文科普書。
這本書第一個知識框架,就是下面這張4象限圖:
(該圖來自:王維嘉的《暗知識》)
該圖將知識按“是否可表達”、“是否可感受”的兩個維度分為四類:
具體來說,暗知識是機器發現的,人類無法感受也無法表達的知識。
就像圍棋,人類2000年來保留的棋譜大概有3000萬個(8位數),但圍棋上棋子的擺放方法的可能性有2的361次方個(108位數),中間何止相差萬億倍。人類對圍棋的認知,就是基于3000萬這個8位數范圍的認知。與機器相比,相差10的100次方。這部分機器能掌握而人不能的,就是暗知識。
這是本書讓人驚嘆的第一個點,通過設立一個新的二維坐標模型,就能夠找到人類以往概念上的盲區!其次,王博士選的詞匯也是超一流的,“暗”和“默”兩個字都很有神采。
雖然是“科普書”,但書里還是不得不講到人類的“神經網絡”、計算機的“機器學習”、“卷積”等復雜概念。
我用自己的語言,以“識別一只貓”為例,為大家簡單講述一下AI吧:
(1)識別貓與計算“1+2=?”不同,前者是“默知識”—— 無法用準確的語言描述出來。在計算機歷史上,通過“尖尖的耳朵”、“長尾巴”、“圓眼睛”等信息來識別貓的程序都失敗了。
(2)我們閉上眼睛想想,如何把一只貓與一只豹子的照片區別開,需要補充很多語言描述。把一只貓與一只狗區別開,又需要補充一些描述,其實人是不能把“識別一只貓”這件事情用語言明確說清楚的 —— 既然人說不清,傳統計算機程序就做不到。但人,哪怕是三歲的孩子都能區別貓和狗,背后是什么原理呢?
(3)后來科學家通過研究人類大腦的神經網絡,發現大腦是通過分層判斷,最終在神經元中留下“歷史痕跡”的邏輯鏈條的。這是很有趣的生物學現象,一個神經元受到的刺激(生物電擊)越多,得到的營養就越多、就會成長得越強大。而每次判斷在每層神經元中留下的痕跡,就會強化今后整個人腦神經網絡的判斷能力。
(4)計算機科學家根據對人類大腦神經網絡的認識,開發了計算機“神經網絡”。這個網絡不但可以識別“貓”,而且識別貓的過程也同樣無法輸出成為人能認識的“文字描述”。
(5)這些識別算法就沉淀在“神經網絡”中(表現為數據及數據關系),無法被人類直接掌握,人只能通過安裝了神經網絡的計算機獲得這個能力。
(6)不知大家注意到沒有,為了讓計算機解決這個“默知識”的問題,我們最終是用了“暗知識”來解決。
(7)這類“暗知識”,能夠在計算機之間快速復制,但無法在人和人之間復制,人和人之間能傳遞的只能是控制AI計算機的方法。
暗知識大體說完,我再回到與我們的思考方式相關度更高的“默知識”。
《思考,快與慢》這本書大約是我2013年讀到的,我認為這是那一年我讀到最好的書。好就好在研究老對象(人類行為與注意力)的過程中,用了新思考框架,并建立了有說服力的體系。
幾年來,這本書被我放在電腦顯示器下面,意喻為“抬高了我的視野”。當然,最初是為抬高了顯示器,起到保護頸椎的作用。
書里是這樣定義人的兩種思維模式的:
當系統2學習掌握了重復使用的套路后,大腦會將重復工作轉給系統1。
我高中時,經常因為簡單的數學加減乘除四則混合運算錯誤,導致考試得不到高分。我訓練自己做了大量專項練習,后來不僅計算過程不出錯,而且感覺當時是把簡單的四則運算從“系統2”挪到“系統1”了。考試時,手上做著乘法豎式,腦子里考慮是否有更好的解題思路。
從另一個角度看,大腦的重復套路工作從“系統2”轉給“系統1”,還有一個更大的好處 —— 降低能力消耗。
系統1反應很快,對能量的消耗遠低于系統2。我查了《人類簡史》、《文明是副產品》等書籍,看到這樣的資料:晚期智人的大腦占體重的1/20,但耗能、耗氧量卻達到全身的1/5。在工業革命前的5萬年里,智人供養這樣一個大腦是極其不容易的,所以我推斷:
系統1畢竟簡化了判斷過程,是否會造成很多誤判呢?我相信是的,但因為能量的限制,人類當時應該是找到了中間最優解。
我認為:《思考,快與慢》的“系統1”,學習的其實就是前一節說的“默知識”。
還是以騎自行車為例,咱們可以教新手一些保持自行車平衡的要領,但一個新手學會騎車的過程,是實踐重于理論的。最后形成的知識,就是無法說清的“默知識”,這個默知識保存在我們每個人的“系統1”當中。
當然,系統1與系統2的關系還有很多層次,并對人類社會產生了深遠影響。
例如:遇到緊急情況時(“快撞到行人了”),系統2會從系統1接管人體控制權,多費一點腦力控制好自行車的方向,避免造成交通事故。
畢竟我的讀者都是toB企業同事,我還是講一個書中與咱們業務有關的故事。作者丹尼爾·卡尼曼是諾貝爾經濟學獎獲得者,21歲時(1955年)曾經在以色列軍隊里負責設計士兵面試流程。這之前,面試官完全根據感覺打分,結果篩選出來的新兵合格率很低??崧隽艘惶自O計,聽起來和我在《SaaS創業路線圖(六):如何擴張團隊?》中的做法類似,就是要求面試官嚴格按框架打分。
(上圖為我系列文章(六)中提供的打分表)
卡尼曼不是他的面試官們的上級,面試官們不喜歡做“打分機器人”。卡尼曼的讓步是,同意面試官根據標準格式打分后,最后“閉上眼睛給士兵打個總分”。
最后的結果是,新的測評方法大幅提高了有效率。45年后卡尼曼回到該部隊,發現他的面試方法還在延用。
而我的面試表最后也有這樣一行:“自己是否愿意帶領此人去完成一個困難的任務?”其實這是一個非常感性的問題,與表格其它部分(記錄工作年限、記錄回答情況等)非常不同。
我觀察,這就是在很多領域中,決策復雜問題的一個優選方法:
這個過程的好處是:
我們企業決策中,如果死板地使用調查前設計的“打分表”,往往會錯過發展機會。因為環境在劇烈變化,調查前很難做出完美的打分表。而“默知識”會讓我們熟悉業務的決策者更準確地做出判斷。
上面說了很多“默知識”的例子,具體怎么學習和使用“默知識”呢?最近“得到APP”的精英日課正好也推出了一篇文章“內隱學習和外顯學習”。
簡而言之,外顯學習就是學習“明知識”的過程,掌握歷史知識、化學公式……
內隱學習,則是學習“默知識”的過程,學到的是個“感”。例如:英語的語感。
1993年高考時,記得我的英語成績大約是140分(滿分150)。因為不考口語,這全都是英語語法和單詞,大多是“明知識”。
但我工作后能在外企說流利的英文,全有賴于大學時在華中理工(現在的華中科技大學)有一個教“外貿英語”的廖老師。他逼著我們每人整篇整篇地背誦外貿英語,上課經?,F場考對話,當時那個厭惡哪……沒想到堅持了一個學期,死記硬背了幾百句常用對話后,英語“語感”就形成了。大腦中可以用英文思考問題,我是一生受用。
“精英日課”引用的一個調查研究還有個有趣的結論:外顯學習明知識,注意力越集中越好;但集中注意力反而會妨礙內隱學習。
為什么?因為“默知識”是沒有明確規則的,越努力找規律越學不會,不如放松一些,讓頭腦直接沉浸在直觀信息中,這樣更容易領悟那個“感”。
在企業經營中,我們經常需要新的創意:如何設計一個擺脫俗套的新激勵方式?如何做營銷上的創新?如何設計一個全新的內容?這時候,讓注意力分散些,看看不相關的書籍、討論一些別的話題,可能靈感會來的更快。
就像我寫這篇文章,目的與路線圖系列是一樣的,還是想幫助大家提升經營管理能力。但如果不引入更多關于思考方式、關于人類發展史的文章,就會跳不出日常操作的層面,不能給大家帶來新的空氣。
這篇文字是“思考方式革命”的第一篇。我講的不是明知識、也不是默知識,我講的是一些新的思考方法。
(1)如何通過增添新的維度,讓你對研究對象(無論是客戶群、團隊或產品服務)增加新的評估方式?操作工具就是最前面的四象限圖。
(2)設計新體系時,用詞要精準。王維嘉博士用一個“暗”字,一個“默”字,把體系講的很清楚?!懊徽圆豁槨?,這是我經常說的道理。一個事兒的“名字”選錯了,要費很多口舌解釋,到頭來沒聽到解釋的人看了還是會誤解。
(3)計算機AI算法是基于人類的“神經網絡”模型的。企業管理中,一個體系的設計、一個測算模型的建立,都要基于“自然”的業務規則,基于人性的需求進行考量。我不是講抽象的“道”,我說的是可以操作的規則。
(4)例如:人的大腦將重復套路工作交給系統1,就是符合降低消耗的規則的。而“能量的限制”就是工業革命前的20萬年里控制人類發展的主要因素。
(5)我們做企業,也是同樣有很多限制,財務上有利潤要求、有任何時點現金流不得低于安全線的要求。這屬于“明知識”。
(6)在不能用“明知識”直接通過計算做出決策的復雜情況下,基于“感覺”的判斷實際上更準確。所以專業知識重要,但業務背景更重要。
(7)但如果只靠“感覺”決策,也很危險。文中舉了一個新兵打分的例子。最佳方法是:讓決策者先結構化地全面多維度打分,然后再“感性”地做出最終判斷。
(8)注意力分散些,有利于創新。所以需要新點子時,要給團隊成員新環境、新場景和一些新時間。
(9)默知識這么重要,如何得到?要反復練習,不專注(忘掉規則)地學習。
當下消費市場,年輕人是絕對的主力人群。對于品牌來講,抓住年輕人就是抓住了市場,于是品牌們紛紛開始“年輕化”。但是在這條路上,一不小心,可能就會陷入“坑”中。本文筆者對品牌年輕化進行分析解讀,總結了自己的看法,供大家學習參考。
互聯網打破了渠道與媒介的壁壘,加速了整個社會消費觀念、品味、需求的變遷。無論是消費觀念還是購買能力,顯然當下的年輕人是絕對的主力人群。
對于品牌而言,就好像牧羊一般,草在哪兒,羊群就在哪兒,不追草的羊不是已經餓死,就是在餓死的路上。
于是品牌年輕化好似成為了一切品牌問題的解藥,不幸的是,這些品牌在年輕化的道路,都走到了相似的逼仄中,年輕化僅僅達到了“形”的貼近,卻夭折在了“神”的部分。
那品牌年輕化到底該如何做呢?
木蘭姐認為,在回答這個問題之前,我們需要先弄清楚一點:
品牌年輕化≠品牌年輕人化
與人一樣,品牌也有自己的生命周期,會經歷誕生-成長-成熟-老化的過程。但與人不同的是,品牌生命周期并不單純以年齡來劃分,而是與市場環境、經濟環境、消費者行為綁定在一起。
但很多品牌往往容易陷進一個誤區:認為品牌年輕化就是年輕人化,于是先給年輕人貼幾個標簽,然后再把這些標簽貼在自己身上,試圖收獲年輕人的認同,混進他們的圈子,用看似時尚、熱門、流行的元素將自己打扮成“年輕人”,但往往最后結果卻是不被年輕人買單的無效溝通。
舉個例子:
KFC前段時間的形象風波就是大型的翻車現場,讓消費者者覺得品牌對“年輕”有誤解。
KFC為了更貼合年輕消費者對顏值的要求,完全翻轉了大家對爺爺慈祥微胖的印象,以更時尚的高顏值形象走入消費者眼簾。
但這個形象橫空出現,只給消費者帶來了短暫的視覺沖擊,并沒有讓其產生情感上的認同,甚至是嚇到了部分消費者,很多人直呼不買賬。
△圖片截取自網絡
所幸這只是KFC品牌年輕化的一次嘗試,并沒有真正投入市場,也沒有給品牌帶來太多的影響。
從KFC的案例中我們可以得到什么樣的警醒呢:或許品牌用表面的裝嫩的方式能夠獲得一時關注,但混入年輕人的圈子,走進他們的內心卻有些難度。
就像1000個讀者就有1000個哈姆雷特一樣,1000個消費者可能會有1000種需求或喜好,品牌無法對這個群體“一刀切”,也沒有一個品牌能做到被所有年輕人追捧。
要知道,這一代年輕人并不是很多品牌自以為所謂的 “狂拽炸酷吊炸天”這么簡單,品牌需要做的是真正洞察年輕人的生活態度,先在價值觀上找到和年輕人真正的契合點,強調 “我”,而不是追隨 “他”。
那正解如何呢?
就像物理學中的杠桿支點一樣,支點找得準不準,直接影響其他要素的確定。對企業而言,突破品牌桎梏,精準地找到品牌年輕化的支點,才是贏得消費群體的王道。
而這個“品牌年輕化”的支點,木蘭姐認為應該是為品牌灌注新鮮活力,延長或恢復品牌的“青春期”,讓品牌可以一直活躍在時代主力消費人群的面前,不至于被消費者和市場遺忘。
無疑,旺旺是其中的佼佼者者。
旺旺在年輕化的道路上摸索出了一條康莊大道,除了主打情懷回憶殺,還不斷嘗試將品牌時尚化,以此來滿足年輕人的潮流需求,比如六一攜手奈雪的茶推出寶藏奶茶;與自然堂聯合,打造自然堂x旺旺定制款氣墊BB霜組合裝,以及聯名款服裝等,一系列令人意外又驚喜的跨界合作,無疑賺足了眼球。
這一波國民經典IP與原創潮牌的跨界合作,不僅意味著旺旺已經洞察到現如今年輕一代的喜好,更代表了旺旺作為一個國民老品牌,有著高度的包容性,在打破以往成就、固化的品牌形象后,以有活力、年輕化、時尚潮流的品牌范兒,不斷刷新品牌的高曝光度,以及年輕人對品牌的認可度。
可以說,旺旺在嘗試年輕化營銷的同時,也能看到其要做年輕化內容、年輕化產品、年輕化品牌的決心。
還有我們的國民老品牌百雀羚,不管是提到廣告,還是產品,百雀羚都是美妝界永遠繞不開的話題,而百雀羚能在消費者心中留下如此重要的認知,都離不開其一直以來的努力和創新。
從三生花系列到現如今的故宮美什件,從《一九三一》到今天的《見微知著》、《多了一點》,通過消費者喜歡的方式,為品牌注入新鮮的血液,讓經典老品牌顯得“年輕力”十足,成功激活了消費群體,并在品牌年輕化的形象和銷售轉化量上都實現了質的突破。
可見,只有為品牌注入與時代相符的新內涵,才能積極契合消費族群的變遷,才是品牌永葆年輕的護城河。
提到這一點之前,我們先來看一個2018年最佳汽車營銷廣告案例,來自奧迪。
在這支廣告里,奧迪沒有流于表面的年輕元素,而是全程展現了一位滑雪飛人,觀眾跟著他腳下的雙板劃過幾乎地球上所有的地貌:山地,森林,沙漠,草原,火山,長城,海洋…
而整個片子中,奧迪車全程沒有入境,只在影片結尾,藍色海洋的背景里出現奧迪的廣告語:“All Conditions Are Perfect Conditions.(所有場景,都是完美場景)”。
但就是這支充滿“挑戰、無畏、前進等精神”的廣告大片最后贏得戛納社會化營銷金獎,引起熱議,深受年輕觀眾的喜愛。
這說明了什么?品牌年輕化,不應拘泥于品牌面貌的年輕,更多的是品牌內核的年輕。
再舉個極端的案例:
年過123歲的銳步(Reebok)簽下80歲“高齡青年”王順德為品牌代言人。這個加在一起超過200歲的“超高齡組合”,如果純粹按年紀來說,絕對稱不上“年輕”,而如果單從代言人王順德的外形上硬要找一點年輕元素的話,可能也就能是那一頭狂野白發中的“狂野”了。
為什么會選中王順德?銳步看中了王順德身上年輕的態度——堅持、自信、突破極限,向消費者傳遞出“任何年紀,都可以活出自己的樣子,突破極限,打破年齡的疆界”的心態。
而這跟當代年輕人釋放個性,崇尚平等,追求自由,積極進取,享受生活,不喜歡權威,不喜歡說教的價值觀是一致的,銳步升華了代言人背后的品牌精神。
所以木蘭姐認為,如果你正在為品牌年輕化發愁,不妨從品牌的核心精神和態度入手,形成年輕的品牌價值觀,去發現目標消費群的價值需求,找到一個能在你們之間產生共鳴的態度,讓他們對品牌產生認同。
此外,90后及00后的自我意識是全面覺醒的,與以往的群體不同,他們天生具有強烈的表達欲及掌控欲,這也進一步催化品牌要用“陪伴心態”去與年輕人相處,真正懂他們,幫他們發聲,彰顯自我……最終成為他們心里“陪在他們身邊的人”。
比如說江小白的文案,其實不少是用戶自己寫的文案,然后通過篩選量產出來。再比如有時間火爆的《我的說明書》H5、DIY類H5,引發了同類H5作品的爆發,背后都是用戶的自我價值表達。
還有今年五四青年節百度APP通過創意互動手繪形式,站在年輕人的角度,說出了他們的心聲,彰顯年輕人的才華和態度,也是狠狠地刷了一波存在感。
我們從不拒絕新事物
青年人,就要站在時代與潮流的風口浪尖
甭管哪年,在愛國這個原則性問題上
我們的脾氣還是有點大
在國家最需要我們的時候
青年人逆風而行,救民于水火之中
這就像安裝了八個情感按鍵,撬動用戶心中的共鳴開關,最終完成內容與用戶的深度溝通,讓用戶認同品牌價值;更重要的是設計出文案,讓用戶表達自我,從而在用戶群中分享傳播品牌價值。
由此可見,年輕化不是品牌的一廂情愿,而是品牌和消費者的合謀:“看見世界,找到自己”。
最后,木蘭姐想說,年輕化的“套路”不可能一成不變,無須刻意貼合年輕人時下的熱點,抓住深的洞察獲得年輕人共鳴,才是品牌年輕化的最好方式。
文章來源:人人都是產品經理
區分取消與關閉,可以很大程度上避免丟失用戶已操作的內容。在關閉視圖之前保存用戶的更改,使用文本標簽而不是「X」圖標,并在破壞性操作之前提供確認對話框。
很久以前,「X」這個符號是用在地圖上,標記「寶藏的藏身地」。但在今天的數字化界面中,「X」符號不再用來標記位置,而是被用來取消進程,或者關閉某個臨時頁面/彈框。但是如何確定「X」代表的是「取消」 還是「關閉」?有的時候可以確定,有時卻模糊不清難以界定。
其實,主要的問題在于「X」圖標缺少了文本標簽。當同一個圖標在不同的界面,卻代表不同的含義,該圖標的可用性就會受到影響,因為用戶判斷不了到底是什么含義。
當用戶單擊/點擊「X」按鈕來關閉模態彈框或視圖時,系統會完全取消該過程并清空之前所有操作,這讓人沮喪,甚至抓狂。因為用戶通常認為「X」圖標表示取消或者關閉,所以區分這兩種可能性對于交互的成功至關重要。
在某些情況下,區分取消 or 關閉并不重要。當一個彈窗占據你的大部分屏幕時,點擊「X」按鈕(盡可能快地),既可以關閉該模態,也可以取消它可能觸發的任何進程。
但是,如果頁面中包含正在運行的計時器,正在播放的音頻,正在選擇多個選項標簽,或其他類型未保存的內容,那就很有必要說明「X」圖標所代表的意義。因為用戶可能打算讓計時器或音頻繼續運行,或者希望立刻應用這些選好的選項標簽,或保存正在進行的工作,同時希望關閉該視圖繼續其他操作。
例如:絲芙蘭在結賬過程中,使用模態窗口來展示用戶可以添加到購物車的免費商品。在以下示例中,單擊「 ADD(添加)」按鈕選擇商品后, 該按鈕直接被變成了「 Remove(移除)」,看起來似乎商品已經被添加到購物車中了。但是,實際上當用戶單擊右上角的「X」圖標后,該商品并不在購物車中。他需要再重復這個步驟,最后點擊「Done(完成)」按鈕,商品才會被加入購物車。
Sephora:單擊右上角的「X」會取消選擇這些試用商品整個過程。用戶必須先單擊「ADD」,再單擊「Done」才能將商品添加到購物車。
要避免丟失用戶正在操作的內容,首先需要確定用戶的意圖,是取消還是關閉,并提供明確的選項。有以下幾種方法:
1. 要求確認
如果用戶在已經執行操作的模態彈框或頁面視圖中,點擊「X」圖標,app 則可以在關閉視圖之前,直接詢問用戶是否應用該操作,來確認其意圖。此解決方案非常適合會破壞用戶工作的破壞性取消操作。例如,過濾器視圖可能會被意外關閉,并且關閉會導致用戶丟失其選定的選項。
這個問題在移動端界面上很常見,因為過濾器視圖占用了很大的屏幕空間,這使用戶很難或不能判斷是否已經應用了那些選擇。為了防止這種潛在的錯誤,在關閉過濾器視圖之前,跟用戶確認是否要應用這些選擇并關閉視圖,抑或是清除這些選擇。例如:下圖中,當用戶選擇后,點擊「X」圖標時,Lowes 會出現如下確認彈框。
左 :點擊「X」圖標或返回箭頭,所有的選項都會被取消,并將用戶帶回上一個頁面。右:點擊「X」后,出現一個確認對話框,確認用戶是應用還是取消篩選,然后再返回結果列表頁。
同樣,當用戶關閉正在進行的課程時,語言學習應用Duolingo 會顯示一個確認對話框,課程進行中不能中途離開,除非確認「退出」。至少,該 APP 向用戶傳達了這一限制,同時他們也可以選擇「取消」來繼續課程。點擊「X」按鈕將結束當前課程。為了防止出錯,結束前會出現一個確認對話框。
缺點:
2. 使用文本標簽
不要完全依賴對話框來讓用戶確認模糊的「X」圖標,而是使用明確的文本標簽。文本可以消除歧義,并清楚地傳達將發生的操作:取消與關閉。
Yelp 的篩選頁面在屏幕頂部提供了標有「Cancel(取消)」和「Reset(重制)」的按鈕,在底部提供了一個大大的「Apply(應用)」按鈕。類似地,Etsy 中的 Filters 視圖提供了「Clear(清除)」和「Done(完成)」兩個按鈕。
注意:Etsy 使用「Done」而不是「Apply」,因為過濾器一經選擇就可以被應用,而這里是關于開關切換與否的建議。
(左)Yelp:Cancel、Reset 和 Apply 這三個文本標簽既直接又清晰,這樣用戶就不太可能不小心關閉視圖而丟失他們過濾器中的選擇。(右)Etsy:Clear 為用戶取消提供了一種清晰的方式,而點擊 Done 則返回到「產品列表」頁,其中的選擇已經應用。
3. 關閉并保存
如果必須使用「X」圖標而不是文本標簽(比如為了以節省空間,或者正在遵循團隊的設計語言),請謹慎使用,并在用戶完成前保存操作/內容。另外,可以提供一個單獨的「取消」按鈕,讓用戶在進程之外有一個緊急出口,并消除「X」在兩種含義之間的歧義。
例如:Gmail 會自動保存在非模態窗口中填寫的郵件信息到草稿(Drafts)。這樣的好處是,用戶在需要折疊或關閉該窗口時,仍然保存原來的內容以便于下次繼續編輯。將鼠標懸停在消息窗口右上角的「X」圖標上時,會顯示一段提示:Save & Close(保存到草稿并關閉)。此外,點擊窗口右下角的「垃圾桶」圖標可以刪除該郵件,這個圖標離頂部的「保存和關閉」選項很遠,可以防止用戶誤點。
Gmail:Hover 透露,「X」圖標是用于關閉窗口而不是刪除草稿,它允許用戶保存并關閉消息窗口而不會丟失剛剛正在編輯的郵件。
對于長進程或傾向于在后臺運行的進程(如計時器),默認自動保存也是一種很好的解決方案。
例如,Glow Baby 中,后臺運行喂食或睡眠計時器時,用戶還可以瀏覽 APP 的其他區域。因為這些計時器一般會運行很長一段時間。此功能還能讓用戶在 APP 中做其他的任務操作,例如記錄之前換尿布的時間、瀏覽文章、逛論壇等。點擊計時器視圖中的「X」圖標也只是關閉窗口并不會取消正在運行的計時器。
Glow Baby:(左)點擊運行計時器視圖中的「X」圖標,在不停止計時器的情況下取消視圖,從而允許用戶繼續使用 APP 記錄其他類型的事件、參與社區討論、閱讀文章等。(中)運行計時器的狀態顯示在屏幕頂部的狀態欄中。(右)在計時器暫停時點擊「X」圖標,彈出「放棄」或「取消」按鈕以確認用戶的真正意圖。
請注意:在關閉前保存中間工作或維護正在進行的過程是主動的,但有時可能會與用戶的意圖相反。如果用戶打算通過單擊「X」按鈕取消其選擇,那自動應用這些選擇可能會令人困惑和沮喪。
這就是為什么還必須有一個單獨的「取消」按鈕,給用戶一個出口,而不是強迫他們必須關閉時自動保存。
雖然「X」圖標會造成模棱兩可,而且經常導致可用性問題,但它不太可能馬上從所有接口中消失。設計人員應該注意「X」圖標的多重含義,消除「關閉」和「取消」之間的歧義,并提供確認對話框或自動保存等保護性措施,避免丟失任何用戶正在操作的內容。
若存在疑問,請記?。合缺4?,再退出。
為什么手機驗證碼登錄微信/淘寶時,驗證碼輸入錯誤,二者都是用的模態對話框提示用戶,而不是用 Toast 呢?
補充:Toast 這一控件,原是 Android 系統的控件。但自 Android 5.0 推出原質化設計后,Toast 就被弱化,而是將 Snackbar 作為官方推薦的控件。如今在 Material Design 中更是找不到 Toast 的蹤影。主要原因還是 Snackbar 在交互友好性方面比 Toast 要好,例如:支持手勢交互、支持與 CoordinatorLayout 聯動等。
在本篇開始之前,我們稍作回顧。目前已經完成的兩個系列包括:「iOS 13 設計新特性」,涉及深色模式、SF Symbols、卡片面板及情境菜單等話題,錯過的朋友不妨回看,畢竟新系統將會在近兩日正式推送。在「基礎設計原理」當中,演講人通過一場夏威夷之旅帶領我們了解了一系列重要的設計原理,包括一致性、可供性、心智模型、漸進呈現等等,深入淺出,老少咸宜,強烈推薦。
△ Mike Stern 老師的「基礎設計原理」
而本期開始的新話題則聚焦于如何面向 Apple 生態體系中的多種設備進行設計,包括如何選擇平臺,如何針對不同的平臺權衡功能與外觀風格,如何構建生態體驗等等;演講者是 Apple 的設計師 Cas Lemmens。
在 Apple,我們非常自豪于我們所創造的一系列設備平臺。在創造和升級這些平臺的過程中,我們都會以提升人們的日常生活品質為目標,并力圖在人與設備之間構建富有意義的關聯。這關聯未必僅存在于單一平臺當中;你所使用的 Apple 設備越多,便越發能體會到整個生態帶來的依存關系。
你可能會戴著 Apple Watch 晨跑,可能會在 MacBook 或是 iMac 上完成一天的工作;下班后,你可能會借助 iPhone 的一系列功能來使用公共交通,或是在你的車里使用 CarPlay;回到家,你可能會通過 Apple TV 看劇或電影;睡前,你可能還會在 iPad 上讀書。
無論你正在使用何種設備,Apple 的平臺生態都可以識別你、理解你,并幫助到你。
面向這樣的生態體系進行設計,你必須對其中的每一個平臺都有著深刻的理解。對于 Apple 的設計師而言,這樣的挑戰已經變得司空見慣。我們必須謹慎思考每一個 app 可能適合的平臺類型,以及如何使其針對不同的平臺進行相應的調整。
Apple 開發的 app 當中,有些是面向全平臺的,例如「照片」或「音樂」。
而有些則僅存在于特定的平臺當中,例如「備忘錄」、「郵件」等等。
有些服務可以在你擁有多種設備的情況下帶來最優體驗,例如 ApplePay;另外一些則必須基于多臺設備同時運行,例如 FaceTime。
今天,我要與各位分享的,便是 Apple 的設計師在進行跨平臺設計時所采用的典型流程。希望這些經驗可以幫助各位更加且目標明確地將你的產品和服務推向 Apple 生態圈當中的更多平臺。
我們首先會從「平臺選擇」開始,即了解每一個平臺的情境特質與能力特征,并以此為基礎選擇最恰當的目標平臺。
然后是「平臺適配」,即基于目標平臺的設備特性,對我們希望實現的功能進行權衡與管理。
接下來是「風格協調」,即在品牌風格與平臺規范之間尋求平衡,對 app 的視覺外觀及操作體驗進行定義。
然后是「平臺連接」,即探索如何在不同的設備平臺之間實現功能的連續性,打造輕松、無縫的使用體驗。
最后,我們還會嘗試「平臺擴展」,即探索如何同時基于多平臺實現最優的綜合生態體驗。
以上便是跨平臺設計的主要流程。接下來,我們將對這五個步驟逐一進行了解。
所謂「平臺選擇」,即回答「我要面向哪個平臺進行設計」這個問題。
或許你還沒有上線過任何 app,目前正在考慮以哪個平臺作為首發;或許你已經在一兩個平臺上發布過 app,正在考慮接下來應該進行怎樣的擴展。
在選擇平臺時,有兩個最為關鍵的概念需要我們重點思考:
對于「情境」的理解至關重要,因為當情境發生變化時,人們通常會切換他們所使用的設備,以不同的方式完成不同的任務。
舉個例子。譬如你正在辦公室里工作,或是在學校上著課;這些都是高度聚焦和穩定的情境。當你離開這些場所,乘上了公交車或地鐵,你便進入了高度動態和移動化的情境。這兩類情境之間的差異非常明顯,我們通常會從 Mac 切換至 iPhone 或 Watch,因為后兩者本就是面向移動化情境進行設計的。
而對于「能力」的理解則可以幫助你掌握并充分利用特定平臺的獨特功能。
接下來,讓我們從「情境」與「能力」這兩個方面,對 Apple 生態體系當中的一些典型平臺進行分析。
首先是 iPhone,因為這可能是我們多數人最為熟悉的平臺了。
從情境的角度來看,iPhone 始終保持開機,始終與我們相隨,因此它是高度移動化的;同時,iPhone 也是高度私人化的設備,我們不會輕易與他人共享使用;此外,iPhone 通常被用于高頻而短時的互動,我們每次使用不會超過幾分鐘。
iPhone 所具有的能力可以有效地支持其情境特質?!甘冀K開機,常伴于身」的特性要求 iPhone 必須具備良好的環境感知能力,其內置的陀螺儀、加速計等傳感器可以始終在背景進程當中處理環境相關的信息,即便是在我們沒有使用 iPhone 的時候;iPhone 的 Touch ID(及 Face ID 等機制)則會為我們提供私人化的保護;其高清晰度的觸屏則能確保我們在短時間的互動過程中獲得輕松與愉悅的體驗。
與 iPhone 類似,Watch 也具備「始終開機,常伴于身」的特性,且同樣是高度私人化的。但 Watch 具有更強的即刻性,所面向的是更為短暫的互動,譬如你只需一瞥便可以從表盤上獲取與當下情境最為相關的信息;而提示信息在你注視稍久時還會進一步提供詳細信息。
Watch 所具備的能力與其私人化的情境特質息息相關。Watch 可以追蹤你的運動狀態、地理位置及心率;其觸覺反饋可以通過輕觸手腕來提醒你查看信息;而表盤也是高度定制化的,你可以讓最為需要的信息始終呈現在表盤之上,便于一瞥之間快速獲取。
而 iPad 則具有較為復雜的情境特質,既可以被用于穩定的環境,同時也支持移動化場景。你可以用 iPad 完成一些而聚焦的任務,也可以將其作為放松型設備來享受影視或游戲體驗。而所有這些互動過程都比 iPhone 或 Watch 更加持久。
從能力的角度,iPad 的大屏正是對這些情境特質的有效支持。充足的屏幕尺寸可以幫助你完成高精度的操作,環境光傳感器可以使其良好適應于日夜不同的光照條件;高保真揚聲器和高精度觸屏可以為影音或游戲帶來更具沉浸感的視聽體驗;若是配合 Apple Pencil,iPad 還能幫助你完成更加、更具創意性的工作。
再來看 Mac。其情境特質具有高度的專業性,你可以進行非常而聚焦的工作,譬如設計和開發 app;MacBook 可以被作為共享設備來使用,但它同時也是個人化的,因為多數使用者都擁有獨立的個人帳戶;我們通常會長時間使用 MacBook 或 iMac,譬如每天都會有幾個小時的互動時間。
在能力方面,為了支持高度專業化的任務,Mac 具備著非常高的性能表現;鍵盤鼠標可以幫助你進行而復雜的操作;多任務能力允許你以自己所需的方式進行工作;而多帳戶體系則能使 Mac 適用于更多樣的工作場景。
最后來看 Apple TV。這是生態當中最具共享性的平臺,我們通常會與家人或朋友一起觀看;TV 最具穩定性,始終與電視機綁定在一起,不會四處移動;TV 是完完全全的放松型設備,我們用它來享受影音或游戲,每次使用時長通常在三十分鐘到幾個小時之間。
配以高清顯示屏,TV 的畫質將會鮮活得呼之欲出;TV 的遙控器輕便易用,你可以輕松地將其傳遞給朋友和家人;TV 可以與 HomeKit 良好配合,使其高度穩定的特性得以在「家庭」這個場景中充分地發揮;其界面設計特別面向 10 碼左右的距離進行優化,使你可以輕松地窩在沙發里享受娛樂體驗。
通過以上分析,你便能理解,為何了解每個平臺的「情境」與「能力」對于你的目標平臺選擇來說是如此重要的事了。
「情境」是平臺的立命之本,而「能力」則決定了其獨特性。
對于你的 app 來說也是如此。你需要問自己兩個關鍵問題:我的 app 可以在怎樣的情境里體現產品價值?要實現產品價值,需要哪些特定的技術能力作為支持?
在 Apple 內部,每當需要為 app 選擇目標平臺時,我們都會反復進行一項簡單的練習?,F在我來為各位進行演示。
首先讓我們以「健身記錄」 app 為例。
想想看「健身記錄」的產品特性,你會發現它首先必須具備移動性。它需要追蹤你全天的運動行為,以便進行的數據統計。因此它需要設備平臺具備「始終開機,常伴于身」的特質,即高度的移動性。
同時,「健身記錄」還必須是私人化的。它應該能且只能追蹤你個人的數據。
接下來,我們要通過象限圖來建立情境特質與平臺之間的映射關系。其中橫軸代表「移動性」,從左到右遞減;一系列 Apple 設備平臺按照各自的特質分布在軸線上,譬如 Watch 最具移動性,而 TV 最具穩定性。
而縱軸代表「私人性」,從上到下遞減。其中 Watch 最具私人性,TV 則最具共享性。
對于「健身記錄」而言,由于要同時具備高度的移動性與私人性,因此在象限圖當中會大致位于左上方的位置。這便解釋了為什么它會出現在 Watch 和 iPhone 當中,而非其他平臺。
接下來我們以 GarageBand 為例。
GarageBand 涉及到的人機互動是高度精準型的,因為人們需要非常準確地操作音頻內容,使它們出現在正確的時間和地點。
此外,GarageBand 必須良好地支持多任務,因為人們往往會將多種音頻器材和樂器連接進來同時進行演奏。
我們通過象限圖來建立映射關系。其中橫軸代表交互的性,左端為粗放型,最具代表性的平臺是 Watch,因為其屏幕較小,而人們的手指相對粗大,難以完成具有高精度要求的操作;右端為精準型,代表平臺為 MacBook 或 iMac,因為鍵鼠操作具備最高的度。
縱軸則代表「多任務能力」,從上到下遞減。在 Mac 上,我們可以輕松地進行多任務操作;而對于 Watch,你每次只能完成一項任務。
GarageBand 需要同時具備高度的交互能力,以及良好的多任務能力,因此在象限圖當中會大致位于右側偏上的位置,所對應的即是 Mac、iPad 和 iPhone。
這兩個例子都非常簡單,各自僅涉及到兩方面的情境特質。在實際當中,我們通常需要將更多、更復雜的特質因素考慮進去;最終,我們希望能夠為 app 找到最適合其生存的平臺。
以上便是跨平臺設計流程中的第一步,「平臺選擇」,即綜合考量不同設備的情境特質及能力特征,進而為 app 選擇最為適合的平臺。
對于同一個頁面布局,幾乎每個人的寫法都不一樣,有人喜歡Flex彈性盒子布局,有的人則喜歡Float浮動布局,有些人喜歡Margin負值布局,等等。從來就沒有一種統一的布局方案,現在大伙寫代碼也就放飛自我,只要能在規定的環境上跑起來,不會亂就行了。但是,身為腦癱正經前端,我們還是有必要分出在不同情況應使用的布局。
這一篇博客比起作為文章,不如作為工具書。當你對布局迷茫時,不妨打開看看。我們可以不求甚解,只需要先把所有布局掌握熟練。
文章目錄
CSS3 終極布局指南
正常布局(語義化布局)
正常布局,按照瀏覽器的內置CSS渲染
應用場景
帶來的問題
挫
不兼容
沒有自適應
解決方案
Float浮動布局
什么是浮動?
浮動元素的排列
浮動解決的布局問題
浮動帶來的問題
父元素高度坍縮
不希望浮動時清除浮動
總結
定位布局
定位的應用
static
relative
absolute
高度坍縮
對比float
總結
fixed
祖先未使用transform:none
使用
sticky 粘性定位
Flex布局
瀏覽器支持
Flex使用介紹
Flex容器屬性
flex-direction 排布方向
flex-wrap 控制換行
flex-flow [排布方向/控制換行]的簡稱
justify-content 子項目在主軸上的排布
align-items 子項目在交叉軸排布
align-content 定義多根軸線排布
Flex子項屬性
order 子項排布靠前排名
flex-grow 子項放大比例
flex-shrink 子項縮小比例
flex-basis
flex
align-self
Grid 布局
參考
聲明
正常布局(語義化布局)
正常布局,按照瀏覽器的內置CSS渲染
大道至簡在遠古時代,CSS還有沒被發明,瀏覽器渲染HTML的時候,只是按照規定好的如標題、段落、表格等格式渲染。且不同的瀏覽器對于相同元素的渲染也是不同的,現在這項傳統藝能保留到了今天。
不過到了今天,正常布局也稍微被W3C重視了一下。在HTML5的規定中,新增加了不少語義化的元素。所謂語義化元素就是讓大家規定它就是來做這件事的。
新增加的語義化元素。
標簽名稱 作用
hearder header 標簽定義文檔的頁面組合,通常是一些引導和導航信息。
nav nav 標簽定義顯示導航鏈接不是所有的成組的超級鏈接都需要放在nav標簽里。nav標簽里應該放入一些當前頁面的主要導航鏈接。 例如在頁腳顯示一個站點的導航鏈接(如首頁,服務信息頁面,版權信息頁面等等),就可以使用nav標簽,當然,這不是必須的。
article article標簽裝載顯示一個獨立的文章內容。例如一篇完整的論壇帖子,一則網站新聞,一篇博客文章等等,一個用戶評論等等 artilce可以嵌套,則內層的artilce對外層的article標簽有隸屬的關系。例如,一個博客文章,可以用article顯示,然后一 些評論可以以article的形式嵌入其中。
section section 標簽定義文檔中的節(section、區段)。比如章節、頁眉、頁腳或文檔中的其他部分。
aside aside 用來裝載非正文類的內容。例如廣告,成組的鏈接,側邊欄等等。
hgroup hgroup 標簽用于對網頁或區段的標題元素(h1-h6)進行組合。例如,在一個區段中你有連續的h系列的標簽元素,則可以用hgroup將他們括起來。
time time 標簽定義公歷的時間(24 小時制)或日期,時間和時區偏移是可選的。該元素能夠以機器可讀的方式對日期和時間進行編碼,這樣, 舉例說,用戶代理能夠把生日提醒或排定的事件添加到用戶日程表中,搜索引擎也能夠生成更智能的搜索結果。
mark mark 標簽定義帶有記號的文本。請在需要突出顯示文本時使用 <mark> 標簽。
figure figure標簽規定獨立的流內容(圖像、圖表、照片、代碼等等)。figure 元素的內容應該與主內容相關,但如果被刪除,則不應對文檔流產生影響。
可以看到HTML5規定中增加了不少新的標簽,但是這些標簽大部分并不是為了補充正常的文檔布局的,而是服務于搜索引擎的爬蟲。不要覺得頁面布局只是給人看的!對于布局清晰地頁面,搜索引擎的爬蟲也會給出更高的分數。
應用場景
作為布局的基石。
開發較為單一的頁面,比如電子書閱讀頁面,面向視力障礙人士的報紙頁面等。
帶來的問題
挫
使用瀏覽器默認的CSS意味著你不可定制自己的頁面,對于像<ul>、<table>這樣的標簽,你也只能忍受上世紀的設計風格了。
不兼容
先前說了,每個瀏覽器對于基礎的HTML節點的渲染都不一樣,也就是說你寫的頁面在IE上是一個風格,換到Safari上又是一種風格。
沒有自適應
有一說一,正常布局(語義化)還是用來當基石比較好,對于響應式、自適應那還得看下面伙計的發揮。
解決方案
解決挫的方法就是使用style屬性,也就是使用CSS美化我們的頁面。解決不兼容的問題則需要初始化CSS,大伙應該在不少的頁面的頭部見過一大坨css代碼吧,就像下面Google頁面。(部分)
body{color:#000;margin:0}body{background:#fff}a.gb1,a.gb2,a.gb3,.link{color:#1a0dab !important}.ts{border-collapse:collapse}.ts td{padding:0}#res,#res .j{line-height:1.2}.g{line-height:1.2;text-align:left;}.ti,.bl{display:inline}.ti{display:inline-table}#rhs_block{padding-bottom:15px}a:link,.w,#prs a:visited,#prs a:active,.q:active,.q:visited,.kl:active,.tbotu{color:#1a0dab}.mblink:visited,a:visited{color:#609}.cur,.b{font-weight:bold}.j{width:42em;font-size:82%}.s{max-width:48em}.sl{font-size:82%}
1
頁面初始化也是很重要的,它可以使我們的代碼健壯的運行在各個環境的瀏覽器上。
Float浮動布局
什么是浮動?
如果首先要認識一個物品,認識一個東西的最好方式是了解為什么會產生它,也就是要翻它的歷史。——NaoTan·Ma·Nong
看上圖,啊,報社最愛的環繞,一堆文字環繞一張圖片,這樣的布局使得頁面緊湊,并且有較好的閱讀體驗。如果我們要在HTML中實現這樣的布局應當怎么設置呢?手動設置換行?不行,缺少靈魂。如果能使文字繞過圖片排列下來就好了。
于是Float屬性出世,它不僅解決了文字環繞問題,并且帶來了新的布局方案。
如上面的布局,我們用代碼實現主要部分。
.side-bar{
float:left;
}
.main-content{
float:left;
}
1
2
3
4
5
6
浮動元素的排列
當一個元素被設置為浮動元素時,首先,它會被移除文檔流,設置float:left|right則元素會向設置方向排列,直到遇到父元素邊框(或者說最大寬度)或者另一個浮動元素時停止。
當設置父元素display:flex時,子元素的浮動值無效!
浮動解決的布局問題
使用浮動我們可以解決傳統的兩列布局、三列布局的自適應。下面代碼是用浮動實現的兩列布局。
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>兩列布局</title>
<style>
body,
html {
margin: 0;
background-color: rgb(228, 228, 228);
}
header {
margin-bottom: 20px;
}
footer {
margin-top: 20px;
}
.layout {
height: 50px;
border: 1px solid black;
}
aside {
width: 25%;
float: left;
border: solid 1px black;
height: 500px;
}
article {
width: 70%;
border: solid 1px black;
height: 500px;
float: right;
}
</style>
</head>
<body>
<header class="layout"></header>
<div style="overflow:auto;">
<aside>
</aside>
<article>
</article>
</div>
<footer class="layout"></footer>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
效果如下
浮動帶來的問題
父元素高度坍縮
一般來說新手在學習浮動布局之后,遇到的第一個問題就是父元素高度坍縮。什么是高度坍縮?
看上圖,在父元素的四個子元素均為浮動元素,由于浮動元素的特性浮動元素脫離文檔流,所以父元素不會被撐起高度。
如何解決?答案很簡單,使用BFC塊級格式上下文。當父元素為BFC的時候,內部計算高度會帶上浮動元素的高度。
不希望浮動時清除浮動
使用clear屬性可以使元素清除周圍的浮動。
如上圖,對段落文字清除浮動,導致原本環繞的文字,另起一行。順便解決了高度坍縮的問題。
總結
浮動在帶來方便的同時也引入了新的問題,如果能處理好這些問題那么浮動也可以當做布局的主力,但是都已經9102年了,我們應該追隨CSS3的布局方案,盡量少使用浮動。
定位布局
收拾房子的時候總會把物品按照相應的位置放置,這樣會讓房間看上去更加整潔。所以,我們CSS也是可以這樣做的。
使用position屬性,調整元素的位置。position一共有四種定位類型:定位元素、相對定位、絕對定位、粘性定位,五種取值:static、relative、absolute、fixed、sticky。
名稱 描述 定位類型
static 該關鍵字指定元素使用正常的布局行為,即元素在文檔常規流中當前的布局位置。此時 top, right, bottom, left 和 z-index屬性無效。 定位元素
relative 該關鍵字下,元素先放置在未添加定位時的位置,再在不改變頁面布局的前提下調整元素位置(因此會在此元素未添加定位時所在位置留下空白)。position:relative 對 table-*-group, table-row, table-column, table-cell, table-caption 元素無效。 相對定位
absolute 不為元素預留空間,通過指定元素相對于最近的非 static 定位祖先元素的偏移,來確定元素位置。絕對定位的元素可以設置外邊距(margins),且不會與其他邊距合并。 絕對定位
fixed 不為元素預留空間,而是通過指定元素相對于屏幕視口(viewport)的位置來指定元素位置。元素的位置在屏幕滾動時不會改變。打印時,元素會出現在的每頁的固定位置。fixed 屬性會創建新的層疊上下文。當元素祖先的 transform 屬性非 none 時,容器由視口改為該祖先。 絕對定位
sticky 盒位置根據正常流計算(這稱為正常流動中的位置),然后相對于該元素在流中的 flow root(BFC)和 containing block(最近的塊級祖先元素)定位。在所有情況下(即便被定位元素為 table 時),該元素定位均不對后續元素造成影響。當元素 B 被粘性定位時,后續元素的位置仍按照 B 未定位時的位置來確定。position: sticky對 table 元素的效果與 position: relative相同。 粘性定位
一般使用position屬性時,會使用其相對定位與絕對定位、粘性定位,它們都使用top、bottom、left、right來調整自身位置,但是調整的基準不一樣。
定位的應用
static
static是元素正常出現在文檔流中的定位,文檔流中的排列為自上而下,自左至右。一般來說block元素自占一行,inline元素橫向排列。
正常情況下在我們的頁面中大部分元素為static定位,對于一些特殊需求我們需要使用其他定位。比如像wiki中的關鍵詞,鼠標移動上去的時候,關鍵詞下面顯示式卡片。
relative
relative是在實現一些特殊布局的時候經常使用的一種定位方式。設置為relative的元素并不會脫離文檔流,但是可以通過top、bottom、left、right調整元素對于默認基準的位置。
.box {
display: inline-block;
width: 100px;
height: 100px;
background: red;
color: white;
}
position: relative;
top: 20px;
left: 20px;
background: blue;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
使用相對定位可以實現一些炫酷的效果。
.content{
text-align: center;
margin: 20px;
}
.card{
position: relative;
display: inline-block;
width: 200px;
height: 200px;
background-color: darkgray;
top: 210px;
right: 170px;
visibility: hidden;
}
span:hover+.card{
visibility:visible;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<div class="content">
<span>鼠標移到我身上!</span>
<div class="card">
</div>
</div>
1
2
3
4
5
6
效果
但是,使用相對定位依然會出現一些問題。relative定位并不會脫離文檔流,所以.content元素的高度為200px。
absolute
與relative定位不同的是absolute是脫離文檔流的,而且相對基準是position屬性不為static的祖先元素,如果祖先都是static則元素相對body定位。并且,對于absolute元素,如果不設置top/bottom/left/right的話依然排列在正常布局位置。
html,
body {
margin: 0;
}
.content {
position: relative;
/ top: 50px; /
margin-top: 50px;
}
.static {
position: static;
}
.relative {
position: relative;
margin: 20px 0;
}
.absolute {
display: inline-block;
width: 50px;
height: 50px;
background-color: lightcoral;
position: absolute;
}
.non-ab {
display: inline-block;
width: 50px;
height: 50px;
background-color: darkblue;
margin-left: 100px;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<div class="content">
<div style="height: 50px;"></div>
<div class="static">
<div class="non-ab">
</div>
<div class="absolute">
</div>
</div>
<div class="relative">
<div class="absolute">
</div>
<div class="non-ab">
</div>
</div>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
上面的代碼很有意思,有興趣的同學可以放在codepen上面跑一下子。這個例子驗證了absolute的排列方式。當我們知道我們在做什的時候,也就不需要墨守成規(對于absolute元素的父元素統一設置relative屬性)了。
高度坍縮
只要是脫離了文檔流的元素都會出現高度坍縮,所以在使用absolute屬性時,請確保父元素不會因此而改變。
對比float
Float與absolute都會使元素脫離文檔流,但是眾所周知對相同元素設置float與設置absolute會出現不同的效果。這是因為float與absolute本身的排列不一樣。
float:脫離文檔流,排列時以父元素為基準,并且會為占用其他浮動元素的位置。
absolute:脫離文檔流,排列時分情況:第一種情況,對于未設置left、right、top、bottom屬性的元素,排列在正常顯示位置,并不占用空間。第二種情況,設置位置屬性的元素,基于非static祖先元素排列。
上面兩者比較顯著的差異為float會影響下一個float元素,但是absolute元素不會。
總結
說absolute為絕對定位也并不貼切,它也是基于祖先元素定位的,只是脫離了文檔流。我個人還是比較推薦在處理元素相對位置問題上使用absolute屬性的,但前提是您已經深刻理解了absolute的排列方式。
fixed
不為元素預留空間,而是通過指定元素相對于屏幕視口(viewport)的位置來指定元素位置。元素的位置在屏幕滾動時不會改變。打印時,元素會出現在的每頁的固定位置。fixed 屬性會創建新的層疊上下文。當元素祖先的 transform 屬性非 none 時,容器由視口改為該祖先。
fixed元素也會脫離文檔流,并且和absolute元素一樣,當不設置任何left、top、bottom、right值的時候,元素依然按照正常定位的位置放置。
祖先未使用transform:none
當祖先元素未使用transform:none的時候,fixed元素相對于該祖先元素進行定位。
在上面的圖片中,我設置小黃塊為fiexd屬性,并讓父元素設置為 使用transform:matrix(1, 0, 0, 1, 0, 0);,這時候小黃塊并沒有相對于body進行定位,當滾動條下拉時,小黃塊定位固定在父元素左上角。
使用
fiexd元素一般用在如:to-top按鈕,或者側邊懸浮面板,或者懸浮導航欄之中。
sticky 粘性定位
盒位置根據正常流計算(這稱為正常流動中的位置),然后相對于該元素在流中的 flow root(BFC)和 containing block(最近的塊級祖先元素)定位。在所有情況下(即便被定位元素為 table 時),該元素定位均不對后續元素造成影響。當元素 B 被粘性定位時,后續元素的位置仍按照 B 未定位時的位置來確定。position: sticky對 table 元素的效果與 position: relative相同。
上面我們使用了fiexd與transform,發生了我們意想不到的效果,那就是fixed元素并未相對于body進行移動,也沒有在父元素中進行標準的fixed定位?,F在我們使用以下sticky屬性來看一下效果。
<style>
.box{
box-sizing: border-box;
height: 150px;
border:solid 3px black;
margin: 0 0 20px 0;
overflow: auto;
}
.block{
width: 50px;
height: 50px;
background-color: orange;
}
.sticky-1{
position:sticky;
top: 0px;
}
</style>
<div class="box box-1">
<p>下面這個小黃塊設置為sticky</p>
<div class="sticky-1 block">
</div>
<p>
hahah
</p>
<p>
hahah
</p>
<p>hahaha</p>
<p>hahaha</p>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
當我們向下滾動的時候神奇的事情發生了。
小黃塊固定到了父元素的top:0位置了,不僅如此,再向上滑動后,小黃塊又回復了當時的位置,而且占用了文檔本身的位置。
使用這個特性我們可以制作浮動的Header組件,當用戶向下滑動至窗口上側的時候,Header組件也跟隨窗口滑動。
Flex布局
對于前端工程師來說,最讓人頭疼的莫過于自適應布局。對于不同分辨率的設備要做到頁面統一,在CSS3出現之前,還是挺不容易的。還有就是前端工程師頭疼的一個布局問題:垂直居中。
CSS3中新出了一種布局技術:CSS彈性盒子布局,我們來看一下MDN是如何介紹的。
CSS 彈性盒子布局是 CSS 的模塊之一,定義了一種針對用戶界面設計而優化的 CSS 盒子模型。在彈性布局模型中,彈性容器的子元素可以在任何方向上排布,也可以“彈性伸縮”其尺寸,既可以增加尺寸以填滿未使用的空間,也可以收縮尺寸以避免父元素溢出。子元素的水平對齊和垂直對齊都能很方便的進行操控。通過嵌套這些框(水平框在垂直框內,或垂直框在水平框內)可以在兩個維度上構建布局。
接下來,我會使用Flex布局技術,設計一些我們常使用頁面布局,并指出優點與缺點。但是,我們首先要來看一下瀏覽器的支持程度。
瀏覽器支持
特性 Firefox (Gecko) Chrome Internet Explorer Opera Safari
基礎支持 20.0 (20.0) 21.0-webkit 29.0 10.0-ms 11.0 12.10 6.1-webkit
主流的瀏覽器全部支持Flex屬性。注:與社會脫軌的IE9并不支持Flex,如果想寫出兼容IE9的頁面,請不要使用Flex。
Flex使用介紹
使用flex務必清楚一些屬性概念。
Flex容器:對于一個基本元素(不含任何CSS屬性,如div),設置display:flex,即可創建一個Flex容器。
Flex子項:父元素為Flex容器的元素,稱之為Flex子項,其排布受到父元素影響。注:一定是父元素為Flex容器的元素,祖先不算。
排布方向:指Flex子項在Flex容器中的排布方向。排布方向有兩種:column、row。在Flex容器上使用flex-direction: column|row(默認);即可設置。
主軸:指的Flex容器中是與排列方式相同的方向的軸。如設置Flex容器direction: column;則其主軸為豎直方向。
交叉軸:指的Flex容器中是與排列方式相反的方向的軸。如設置Flex容器direction: column;則其主軸為水平方向。
我們一定要清楚上面的基礎概念,這對深入使用Flex有很大的幫助。下面我會介紹一些Flex常用的屬性,主要分為兩部分:對Flex容器、對Flex子項。
Flex容器屬性
flex-direction 排布方向
flex-direction 屬性指定了內部元素是如何在 flex 容器中布局的,定義了主軸的方向(正方向或反方向)。
flex-direction屬性接受以下值:
row:子項目在flex容器中橫向,從左至右排列。
row-reverse:表現和row相同,也是橫向,但是是從右到左。
column:子項在容器中豎向排列,從上至下。
這里不貼圖了
column-reverse:表現和column相同,子項在容器中豎向排列,從下至上。
這里不貼圖了
flex-wrap 控制換行
CSS flex-wrap 指定 flex 元素單行顯示還是多行顯示 。如果允許換行,這個屬性允許你控制行的堆疊方向。
取值:
nowrap(默認)
flex 的元素被擺放到到一行,這可能導致溢出 flex 容器。 cross-start 會根據 flex-direction 的值 相當于 start 或 before。
wrap
flex 元素 被打斷到多個行中。cross-start 會根據 flex-direction 的值選擇等于start 或before。cross-end 為確定的 cross-start 的另一端。
wrap-reverse
和 wrap 的行為一樣,但是 cross-start 和 cross-end 互換。
flex-flow [排布方向/控制換行]的簡稱
CSS flex-flow 屬性是 flex-direction 和 flex-wrap 的簡寫。
示例:flex-flow: column-reverse wrap;
justify-content 子項目在主軸上的排布
CSS justify-content 屬性定義了瀏覽器如何分配順著父容器主軸的彈性元素之間及其周圍的空間。
justify-content同時受到父容器主軸的影響。
取值:
start
從行首開始排列。每行第一個元素與行首對齊,同時所有后續的元素與前一個對齊。
flex-start(默認)
從行首開始排列。每行第一個彈性元素與行首對齊,同時所有后續的彈性元素與前一個對齊。
flex-end
從行尾開始排列。每行最后一個彈性元素與行尾對齊,其他元素將與后一個對齊。
center
伸縮元素向每行中點排列。每行第一個元素到行首的距離將與每行最后一個元素到行尾的距離相同。
left
伸縮元素一個挨一個在對齊容器得左邊緣,如果屬性的軸與內聯軸不平行,則left的行為類似于start
right
元素以容器右邊緣為基準, 一個挨著一個對齊,如果屬性軸與內聯軸不平行,則right的行為類似于start.
space-between
在每行上均勻分配彈性元素。相鄰元素間距離相同。每行第一個元素與行首對齊,每行最后一個元素與行尾對齊。
space-around
在每行上均勻分配彈性元素。相鄰元素間距離相同。每行第一個元素到行首的距離和每行最后一個元素到行尾的距離將會是相鄰元素之間距離的一半。
space-evenly
flex項都沿著主軸均勻分布在指定的對齊容器中。相鄰flex項之間的間距,主軸起始位置到第一個flex項的間距,主軸結束位置到最后一個flex項的間距,都完全一樣。
看上去與space-around的排布很相似,但其實還是有一些區別的。space-evenly會在每一行均勻分布間隙,而space-around是均勻分布項目。
借一張圖
看上去我們要學的屬性很多,但是其實我們只需要記住我們常用的幾個屬性就行:flex-start、flex-end、space-between、center、space-around、space-evenly。以上這幾個就是我們常用的屬性值,通過設置主軸方向、設置排列方式,我們可以靈活地組織我們的元素。
align-items 子項目在交叉軸排布
CSS align-items屬性將所有直接子節點上的align-self值設置為一個組。 align-self屬性設置項目在其包含塊中在交叉軸方向上的對齊方式。
取值:
normal
這個關鍵字的效果取決于我們處在什么布局模式中:在絕對定位的布局中,對于被替代的絕對定位盒子,這個效果和start的效果的一樣;對于其他所有絕對定位的盒子,這個效果和stretch的效果一樣。 在絕對定位布局的靜態位置上,效果和stretch一樣。對于那些彈性項目而言,效果和stretch一樣。對于那些網格項目而言,效果和stretch一樣,除了有部分比例或者一個固定大小的盒子的效果像start。這個屬性不適用于會計盒子和表格。
flex-start
元素向側軸起點對齊。
flex-end
元素向側軸終點對齊。
center
元素在側軸居中。如果元素在側軸上的高度高于其容器,那么在兩個方向上溢出距離相同。
因為align-items其實和justify-content我這里就不放一些圖片湊字數了。
align-content 定義多根軸線排布
該屬性對單行彈性盒子模型無效。(即:帶有flex-wrap: nowrap)。
CSS的align-content屬性設置了瀏覽器如何沿著伸縮盒子容器(flexbox container)的縱軸和網格容器(Grid Container)的主軸在內容項之間和周圍分配空間。
它的取值和align-items差不多,經常有人會把他們搞混。
align-content一般定義多行的交叉軸排列。
絕大多數情況下我們使用align-items即可實現我們的需求。
Flex子項屬性
order 子項排布靠前排名
CSS order 屬性規定了彈性容器中的可伸縮項目在布局時的順序。元素按照 order 屬性的值的增序進行布局。擁有相同 order 屬性值的元素按照它們在源代碼中出現的順序進行布局。
取值:
<integer>
表示此可伸縮項目所在的次序組。
flex-grow 子項放大比例
CSS flex-grow 屬性定義彈性盒子項(flex item)的拉伸因子
取值:
<number>
默認值0,即如果存在剩余空間,也不放大。負值無效。
flex-shrink 子項縮小比例
CSS flex-shrink 屬性指定了 flex 元素的收縮規則。flex 元素僅在默認寬度之和大于容器的時候才會發生收縮,其收縮的大小是依據 flex-shrink 的值。
總而言之,你定了這個屬性,其他項目會先壓榨你的空間,然后再均勻縮小其他項目。
flex-basis
flex-basis屬性定義了在分配多余空間之前,項目占據的主軸空間(main size)。瀏覽器根據這個屬性,計算主軸是否有多余空間。它的默認值為auto,即項目的本來大小。
注:分配多余空間之前??!
也就是說你給的flex-basis值大于當前分配空間時,依然會被壓縮。
flex
flex屬性是flex-grow, flex-shrink 和 flex-basis的簡寫,默認值為0 1 auto。后兩個屬性可選。
align-self
align-self屬性允許單個項目有與其他項目不一樣的對齊方式,可覆蓋align-items屬性。默認值為auto,表示繼承父元素的align-items屬性,如果沒有父元素,則等同于stretch。
這個屬性了不得,它也是我們經常用的子項目屬性之一。
.item {
align-self: auto | flex-start | flex-end | center | baseline | stretch;
}
1
2
3
就像上面的圖,他可以決定子項目的交叉軸單獨排列方式。
Grid 布局
未完待續…明天補上
參考
HTML5語義化標簽屬性-HTML5屬性手冊
All About Floats | CSS-Tricks
清除浮動的四種方式及其原理理解
【前端Talkking】CSS系列——CSS深入理解之absolute定位
CSS 彈性盒子布局
Flex 布局教程:語法篇
藍藍設計( www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務。
three.js 的簡單實例
三大主件: 渲染器、場景、相機
思想核心: 相機獲取到場景內顯示的內容, 然后再通過渲染器渲染到畫布上面
渲染器: 實例化渲染器的同時生成的一個 Canvas 畫布, 之后將這個畫布添加到了 DOM 當中
場景: 場景只是一個容器, 顯示的內容需要進行添加, 添加一個內容稱作一個網格, 每個網格基本上包括幾何體和材質, 網格也稱之為模型
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>three</title>
<style>
body {
margin: 0;
}
canvas {
width: 100%;
height: 100%;
display: block;
}
</style>
</head>
<body onload="init()">
<script type="text/javascript" src="js/jquery-3.4.1.min.js"></script>
<script type="text/javascript" src="js/three.min.js"></script>
<script type="text/javascript" src="js/stats.min.js"></script>
<script type="text/javascript" src="js/dat.gui.min.js"></script>
<script>
//聲明一些全局變量
var renderer, camera, scene, geometry, material, mesh, stats, rotate = true;
//初始化渲染器
function initRenderer() {
renderer = new THREE.WebGLRenderer(); //實例化渲染器
renderer.setSize(window.innerWidth, window.innerHeight); //設置寬和高
document.body.appendChild(renderer.domElement); //添加到dom
}
//初始化場景
function initScene() {
scene = new THREE.Scene(); //實例化場景
}
//初始化相機
function initCamera() {
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 200); //實例化相機
camera.position.set(0, 0, 15); //初始化的坐標
}
//創建模型
function initMesh() {
geometry = new THREE.BoxGeometry(2, 2, 2); //創建幾何體
material = new THREE.MeshNormalMaterial(); //創建材質
mesh = new THREE.Mesh(geometry, material); //創建網格
scene.add(mesh); //將網格添加到場景
}
//運行動畫
function animate() {
requestAnimationFrame(animate); //循環調用函數
//判斷是否可以旋轉
if(rotate) {
mesh.rotation.x += 0.01; //每幀網格模型的沿x軸旋轉0.01弧度
mesh.rotation.y += 0.02; //每幀網格模型的沿y軸旋轉0.02弧度
}
stats.update(); //更新性能檢測框
renderer.render(scene, camera); //渲染界面
}
//性能檢測框
function initStats() {
stats = new Stats();
document.body.appendChild(stats.dom);
}
//創建調試框
function initGui() {
//控制參數初始值
controls = {
positionX: 0,
positionY: 0,
positionZ: 0,
rotate: true
};
gui = new dat.GUI(); //實例化對象
gui.add(controls, "positionX", -10, 10).onChange(updatePosition);
gui.add(controls, "positionY", -5, 5).onChange(updatePosition);
gui.add(controls, "positionZ", -10, 10).onChange(updatePosition);
function updatePosition() {
mesh.position.set(controls.positionX, controls.positionY, controls.positionZ);
}
gui.add(controls, "rotate").name("旋轉").onChange(function(e) {
rotate = e;
});
}
//初始化函數,頁面加載完成是調用
function init() {
initRenderer();
initScene();
initCamera();
initMesh();
initStats();
initGui();
animate();
}
</script>
</body>
</html>
藍藍設計( www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務。
藍藍設計的小編 http://www.syprn.cn