接下來的訪談翻譯自微軟官方博客,微軟的 Office 設計部門的兩位主管 Jon Friedman 和 Deepak Menon 在訪談中聊了一下 Surface Duo 背后的設計故事:
在過去的幾十年當中,數碼產品制造商經常會為了適應用戶的習慣和需求,來不斷創造產品。我們傾向于讓事物變的更小、更輕、響應更快、更具包容性。我們將不同感官融入程序,創造而優雅的產品。
隨著日常生活節奏和生產力的觀念變化,我們經常需要反思一個問題:如何賦予人們在創作和消費、專業和個人之間流暢切換的可能性?
即將發售的 Surface Duo 是一款獨特的雙屏移動設備,它有著一套專門為它的硬件所定制化的產品體驗,而它的設計也折射出我們探索問題的方式。
對于設計師來說,創造這樣的獨特產品的機會是難得的,就像你在一個住了十幾年的房子里面,發現新的房間一樣。會打開的是哪扇門?會通向哪個區域?會延伸出哪些創意?
對于 Surface Duo ,我們想知道,它的兩塊屏幕會延伸出哪些全新的工作流程,它的接縫要如何處理,怎樣減輕用戶的認知負荷?
受多年來我們在用戶研究上的成果所啟發,我們通過軟硬件結合的方式來進行 Surface Duo 的研發,讓它能適合你日常的需求,還可以帶來獨特的體驗,比如在雙屏上并排打開文檔。
Surface Duo 仍然處于起步階段,我們知道,它還有很多待解決的問題,這也是為什么微軟會引入更多的用戶和設計師,來不斷地完善它。
為了讓大家更好地了解 Surface Duo 的設計歷程,我們請來了 Deepak Menon ,他不僅參與了 Surface Duo 的研發和設計,還是 Office 設計團隊的負責人,讓他來告訴大家,Surface Duo 背后的創意、研究和設計決策。
Jon:謝謝你能來,Deepak,在過去的2個月時間里,我們一直在非常密集地使用和測試 Surface Duo~
Deepak:實際上,我干脆是拿它單主力機,現在我都覺得我已經不需要其他的任何設備了。
Jon:我們當然會這么說,畢竟是我們設計了它。但是,我想這也證明了一件事情,就是這種拓展式的雙屏,已經具備應對日常工作的能力,并且貼合大家的需求了。
Deepak:對。這不僅僅是「2塊屏幕智能手機」所帶來的體驗,它更接近于是一款「折疊式的平板電腦」的感覺。它是新事物,盡管是通過鉸鏈和轉軸來實現這種可能性。
Jon:我們接觸 Surface Duo 的時候,我們首先想到的一問題是:人類還有哪些需求是未曾被實現的?人們在達成目標過程中,有哪些問題是需要工具來彌合的?我們要如何來幫助用戶達成這個目標?雙屏的這種形態,讓我們有重新思考生產力的切入點。
Deepak:對,尤其是在移動端的生產力上。
在雙屏界面下,使用 Office 在 PDF 文檔上簽名,然后使用 Outlook 發送出去,簽合同的便捷操作。
Jon:確實,你的團隊在中國和印度這樣移動端優先的國家做了非常深入的調研。
Deepak:我們注意到很多用戶在同一設備上執行并完成一系列的任務,他們需要更快地切換。同時,企業也正在倚靠我們過去認為非常「娛樂化」的媒介來進行必要的經營。
Jon:在過去,生產力有這非常清晰的定量標準,比如一秒生產多少零件。但是如今,生產力和創意息息相關,你的情緒狀態和輸出的內容是一樣重要的。我們在不斷消費又不斷創造,反思和行動來回切換。其實這都涉及到一種傾向或者流程,你會按照一定的方式來處理信息,或者當你腦中突然劃過一個想法的時候,你會想立刻構建或者制作某個東西,而這也需要一系列的操作和任務來支撐。
從整個數字設備的發展歷程來看,雙屏的設備可能是最適合處理這種帶有步驟的「流程」。Surface Duo 最精巧地的地方,就在于它可以按照你的各種需求來折疊翻轉和交互,可大可小,同時也是一款貼合你的口袋尺寸的設備。
在橫屏模式之下,你可以像翻書一樣瀏覽 Word 文檔
Deepak:當然,它將內容消費提升到一個全新的層次,對于豐富內容的處理,Surface Duo 更加適合和專業。在 Outlook 當中,你可以快速瀏覽整個星期的工作安排,在 Word 中,你可以像翻書一樣閱讀內容。屏幕 折疊所賦予的空間讓更多的信息有了自然的展現空間。
借助 Surface Duo ,創造性的工作也得到了增強。當我使用 PowerPoint 來制作幻燈片的時候,我喜歡在一個屏幕上編輯,在另外一塊屏幕上預覽,兩塊屏幕當中,一塊幫我保持專注內容制作,另一塊幫我統領全局。另外,我也會在屏幕上開啟多個不同的應用。
將團隊的視頻通話和 PowerPoint 并列擺放,讓你一邊溝通一邊查看內容
Jon:使用它來進行遠程會議可能是我最喜歡的場景之一。我喜歡在開會的時候使用雙橫屏模式,將視頻置于頂端,在下面的屏幕瀏覽文檔。
Deepak:或者用另外一塊屏幕來調用嬰兒監視器!哈哈,疫情讓我們和家庭的關系更加密切,Surface Duo 讓我可以更多兼顧到家庭這邊。
Jon:對,很多人認為在疫情期間,家里有這么多人,移動設備的使用量可能會降低,但是很多數據表明,情況恰恰相反(僅2月初到3月下旬,微軟的 Team 移動端的用戶數量就增加了超過300%)。就我個人而言,我不想一直待在一個房間里面,盯著一塊屏幕,其他人也都反映,需要四處走動,或者在外面工作。當我開始使用Surface Duo 的時候,開始從中獲得更為強大的支撐,獲得更加有效的體驗。
當然,它最優雅的還是在窗口的管理上。打開多個窗口是一種非常常見的 PC 體驗,但是在單屏的移動端設備上其實還不算太普遍和舒適,但是在 Surface Duo 上則很自然。
Outlook 中雙屏帶來的額外空間讓你可以更快查看相關的收件箱和日歷
Deepak:關于用戶如何使用窗口來提高生產力,有過很多研究,并且兩塊屏幕之間的天然接縫,或者說轉軸,其實很自然地造就了「兩塊屏幕」和「多窗口」的認知。在某些情況下,因為接縫的存在,在兩塊屏幕上打開完全不同的兩個應用,其實是非常自然的事情。
在很多其他的情況下,用戶可能會在一個屏幕中打開一個新的程序,打開新的界面,執行單獨的操作,或者通過一個程序,在另外一個屏幕中打開下一步操作,然后再在兩個界面之間來回操作,這都是非常平穩的。這種被分割開的兩塊屏幕,創造了一種全新的交互契機,而不是制造約束。
Jon:對于 Surface 的軟硬件團隊,我最為欣賞的一點,就是這種共生和互相促進的模式。使用 Surface Duo,你可以擁有更大的屏幕空間,而且擁有眾多不同的使用應用的新方法,而 Surface Duo 也正好可以適應各種各樣不同的使用場景。而我們在創建這個產品的過程中,想要兼顧到如此之多的場景和需求,其實是需要兩個團隊親密無間地協作,才能做好。
對了,你剛剛說道關于照片、視頻、語音等內容——這些輸入方式的協作,對于創造性的工作到底有多重要?
Deepak:的確,在移動端設備上,攝像頭和麥克風是必不可少的。我們希望最大限度地讓 Office 最大限度地利用這些傳感器,在移動地使用過程中進行協同。用戶在通勤過程中如何參與到線上課程的互動?老師如何更快地給孩子批閱作業,家長要如何協助孩子?其實,Surface Duo 在研發探索的過程中,就有意識地在兼顧這些場景和問題。
從媒體庫當中,將媒體拖放到 PowerPoint 當中
Jon:我喜歡這些富有包容性的解決方案。人們的學習方式和工作方式通常是截然不同的,這些自適應性良好的輸入模型,能夠幫助能力各異的用戶完成他們所需的工作。
Deepak:當我們將新的輸入模型和智能化的功能結合到一起的時候,有趣的事情就開始發生了。我們幾乎還沒有涉及到創作方面的內容,用戶就已經擁有很多契機自由發揮,他們可以輕松、清晰地借用這種交互模式來表達自己。比如可以更加順暢地利用模板來制作精美的 Word 文檔和 PowerPoint 。
Jon:物理世界中有太多東西,我們可以將其逐漸的數字化。
Deepak:的確,將智能化的程序和多樣的傳感器耦合到一起,提高生產力的方式有很多——無論是提升工作效率、家庭安全性還是讓內心更加平靜。其實第三方開發者身上,我看到了更多思維和想法的延展,以及可能性。
Jon:對,我們已經看到很多非常有趣智能的東西了!在 Microsoft Hackathon 大會上,有人為 Surface Duo 設計了一款雙人游戲,兩個玩家各占一塊屏幕,隔著轉軸來來操作,彼此面對面,非常有趣!
Deepak:確實如此!
Jon:我們很高興 Surface Duo 最終能夠面向普通用戶,我很期待它最終會在普通用戶手中會迸發出怎樣的創意和靈思,他們能夠構建出什么樣的創新軟件。
Deepak:有太多值得期待的東西了 !
譯者按:
微軟在硬件產品上,有著豐富的翻車歷史。90年代的事情太過久遠姑且不說,最近十幾年,出過很多比較失敗的產品,比如上架僅 6 天就全線下架的時尚社交手機 Kin One 和 Kin Two,比如被支付寶團隊戲稱為「1%」的 Windows Phone 系統和手機,比如幾乎不存在兼容性的 Surface RT 系列的平板電腦。這些硬件我全都買過,可以說全是坑。
這些產品單獨來看是失敗的,但是放在更長的時間跨度上來看,卻又是微軟整個生態和產品鏈條的構成和發展上,不可或缺的部分。Kin One 是整個 Metro 設計美學真正成型并走入移動端智能設備的里程碑(之前僅用于Zune系列播放器上),Windows Phone 則是 Windows 系統向小屏幕探索的必經之路,而 Surface RT 固然失敗,但是它是帶著桌面端 Windows 系統從傳統 X86 架構走上 ARM 的一次大膽嘗試。
失敗總是難免的,而微軟這種大廠更是有著試錯買單的底氣。從內部設計和產品團隊各自為戰,到統一到一個部門來統一管理,Surface 系列產品的誕生就是分水嶺,而這件事情是在 10 年發生的。
當然,在此之后翻車的產品依然會有,但是成功的概率比起更早的階段(比如應對 iPad 誕生時,倉促推出的觸摸屏PC),已經提升很多了。
如今只剩下拼硬件參數數字產品的世界簡直是太無聊了。我很期待 Surface Duo 這類雙屏折疊硬件能帶來改變。
文章來源:優設 作者:Jon Friedman
藍藍設計( www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務
v-cloak
: 使用 v-cloak 指令可以有效解決屏幕閃動。
有時候,頁面沒渲染之前就會出現vue代碼塊,例如下圖。使用v-cloak可以很好解決這種問題。
![]()
<template> <div class="hello"> <span v-cloak>{{ content }}</span> </div> </template> <script> export default { name: "hello", data() { return { content: "測試" }; } }; </script> <style scoped> /* v-cloak這個屬性會在頁面渲染前作用于對應dom 在渲染完畢這個里面的樣式將被移除 */ [v-cloak] { display: none; } </style>
keep-alive
官網是這么解釋的:
![]()
例如:可以實現頁面緩存,比如從編輯頁切出去再切進來,頁面還是處于編輯狀態.
需要在router.js
中設置meta
屬性,meta
下的keepAlive
屬性設置為true,代表這個頁面需要進行緩存。
import Vue from 'vue' import Router from 'vue-router' import HelloWorld from '@/components/HelloWorld' import is from '@/view/is' import list from '@/view/list' import detail from '@/view/detail' Vue.use(Router) export default new Router({ routes: [ { path: '/', name: 'HelloWorld', component: HelloWorld, meta: { keepAlive: false, title: 'HelloWorld' } }, { path: '/is', name: 'is', component: is, meta: { keepAlive: false, title: 'is' } }, { path: '/list', name: 'list', component: list, meta: { keepAlive: true, title: 'list' } }, { path: '/detail', name: 'detail', component: detail, meta: { keepAlive: true, title: 'detail' } } ] })
在app.vue
中修改一下代碼<router-view />
<template> <div id="app"> <keep-alive> <!--緩存組件--> <router-view v-if="$route.meta.keepAlive" /> </keep-alive> <!--非緩存組件--> <router-view v-if="!$route.meta.keepAlive" /> </div> </template> <script> export default { name: "App" }; </script> <style> #app { font-family: "Avenir", Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } </style>
在詳情頁detail.vue
中,注意beforeRouteEnter
和beforeRouteLeave
兩個方法。
<template> <div class="detail"> <!-- form表單,用于測試是否緩存 --> <Form ref="formCustom" :model="formItem" :label-width="80"> <FormItem label="Input"> <Input v-model="formItem.input" placeholder="Enter something..."></Input> </FormItem> <FormItem label="Select"> <Select v-model="formItem.select"> <Option value="beijing">New York</Option> <Option value="shanghai">London</Option> <Option value="shenzhen">Sydney</Option> </Select> </FormItem> <FormItem label="DatePicker"> <Row> <Col span="11"> <DatePicker type="date" placeholder="Select date" v-model="formItem.date"></DatePicker> </Col> <Col span="2" style="text-align: center">-</Col> <Col span="11"> <TimePicker type="time" placeholder="Select time" v-model="formItem.time"></TimePicker> </Col> </Row> </FormItem> <FormItem label="Radio"> <RadioGroup v-model="formItem.radio"> <Radio label="male">Male</Radio> <Radio label="female">Female</Radio> </RadioGroup> </FormItem> <FormItem label="Checkbox"> <CheckboxGroup v-model="formItem.checkbox"> <Checkbox label="Eat"></Checkbox> <Checkbox label="Sleep"></Checkbox> <Checkbox label="Run"></Checkbox> <Checkbox label="Movie"></Checkbox> </CheckboxGroup> </FormItem> <FormItem label="Switch"> <i-switch v-model="formItem.switch" size="large"> <span slot="open">On</span> <span slot="close">Off</span> </i-switch> </FormItem> <FormItem label="Slider"> <Slider v-model="formItem.slider" range></Slider> </FormItem> <FormItem label="Text"> <Input
v-model="formItem.textarea" type="textarea" :autosize="{minRows: 2,maxRows: 5}" placeholder="Enter something..." ></Input> </FormItem> <FormItem> <Button type="primary">Submit</Button> <Button style="margin-left: 8px">Cancel</Button> </FormItem> <FormItem> <router-link :to="{name:'list'}"> <Button size="small" type="primary">跳轉到列表頁</Button> </router-link> <router-link :to="{name:'is'}"> <Button size="small" type="primary">跳轉到is頁</Button> </router-link> </FormItem> </Form> </div> </template> <script> export default { name: "detail", mixins: [], components: {}, filters: {}, props: [], computed: {}, data() { return { formItem: { input: "", select: "", radio: "male", checkbox: [], switch: true, date: "", time: "", slider: [20, 50], textarea: "" } }; }, watch: {}, created() { }, mounted() { }, methods: { // 重置表單 init() { this.$refs[formCustom].resetFields(); } }, // 路由進來之前,判斷是從哪個頁面過來的,設置不同的keepAlive屬性 beforeRouteEnter(to, from, next) { if (from.name === "list") { to.meta.keepAlive = true; } else { to.meta.keepAlive = false; } next(); // beforeRouteEnter不能通過this訪問組件實例,但是可以通過 vm 訪問組件實例(剛開始錯誤寫法) // next(vm => { // if (from.name === "list") { // // 在這里修改keepAlive值,是不能緩存數據的,因為在next()里面的代碼,是在vue掛載之后執行,處于activated之后,此時activated中keepAlive還是false // vm.$route.meta.keepAlive = true; // } else { // vm.$route.meta.keepAlive = false; // } // }); }, // 路由離開之前,判斷去往哪個頁面,設置不同的keepAlive屬性 beforeRouteLeave(to, from, next) { if (to.name === "list") { this.$route.meta.keepAlive = true; } else { this.$route.meta.keepAlive = false; } next(); }, activated() { // 此方法在頁面緩存時會被調用(this.$route.meta.keepAlive為true時),根據路由元信息決定是否重新加載數據。不加載則是上次填寫完的數據 // console.log(this.$route.meta.keepAlive); } }; </script> <style scoped lang="less"> .detail { position: relative; height: 100%; width: 100%; } </style>
插槽slot
解構插槽 Prop:可以傳遞子組件的變量
// 子組件 <template> <div class="isComponent"> <slot name='one' :childStr='childStr'></slot> <slot name='two'></slot> <slot></slot> </div> </template> <script> export default { name: "isComponent", data() { return { childStr: 'i am a child', }; } }; </script> <style scoped> </style> // 父組件 <is-component> <template #one="{childStr}">{{childStr}}</template> <template v-slot:two> two </template> <template> default </template> </is-component>
效果:// i am a child two default
強制刷新某個div
修飾符
事件修飾符:
.stop
:相當于原生JS中event.stopPropagation()
,阻止事件冒泡。
.prevent
:相當于原生JS中event.preventDefault()
,阻止默認事件的發生。
.capture
:事件冒泡的方向相反,事件捕獲由外到內。即有冒泡發生時,有該修飾符的dom元素會先執行,如果有多個,從外到內依次執行。
.self
:只會觸發自己范圍內的事件,不包含子元素。
.once
:事件只能觸發一次。
.passive
:事件會執行默認方法。
注:
- 每次事件產生,瀏覽器都會去查詢一下是否有preventDefault阻止該次事件的默認動作。我們加上passive就是為了告訴瀏覽器,不用查詢了,我們沒用preventDefault阻止默認動作。
passive
和prevent
沖突,不能同時綁定在一個監聽器上
按鍵修飾符: 去官網查看即可,這里不過多解釋。Vue.js-修飾符
:is
: 動態組件
優點:使代碼更符合HTML語法驗證
官網是這么解釋的:
![]()
// 父組件: <template> <div class="is"> <table> <tr :is='is'></tr> </table> </div> </template> <script> import isComponent from '../components/isComponent' export default { name: "is", components: { isComponent }, data() { return { is: 'isComponent' }; } }; </script> <style scoped> </style> // 子組件: <template> <div class="isComponent"> <span>我是tr</span> </div> </template> <script> export default { name: "isComponent", data() { return {}; } }; </script> <style scoped> </style>
@click.native
: 在封裝好的組件上使用,要加上.native才能click。
- router-link 加上@click事件,綁定的事件會無效因為:router-link的作用是單純的路由跳轉,會阻止click事件,你可以試試只用click不用native,事件是不會觸發的。此時加上.native,才會觸發事件。
- 根據Vue2.0官方文檔關于父子組件通訊的原則,父組件通過prop傳遞數據給子組件,子組件觸發事件給父組件。但父組件想在子組件上監聽自己的click的話,需要加上native修飾符。
// router-link <router-link :to="{name:'detail'}" @click.native="handleNative"> <Button size="small" type="primary">測試native</Button> </router-link> // 自己封裝的組件 <is-component @click.native="handleNative"></is-component>
作者:小城聽風雨
了解拷貝背后的過程,避免不必要的錯誤,Js專題系列之深淺拷貝,我們一起加油~
當我們在操作數據之前,可能會遇到這樣的情況:
當我們遇到類似需要場景時,首先想到的就是拷貝它,殊不知拷貝也大有學問哦~
下面簡單的例子,你是否覺得熟悉?
var str = 'How are you'; var newStr = str; newStr = 10 console.log(str); // How are you console.log(newStr); // 10
大家都能想到,字符串是基本類型,它的值保存在棧中,在對它進行拷貝時,其實是為新變量開辟了新的空間。 str
和newStr
就好比兩個一模一樣的房間,布局一致卻毫無關聯。
var data = [1, 2, 3, 4, 5]; var newData = data; newData[0] = 100; console.log(data[0]); // 100 console.log(newData[0]); // 100
類似的代碼段,但這次我們使用數組這個引用類型舉例,你會發現修改賦值后的數據,原始數據也跟著改變了,這顯然不滿足我們的需要。本篇文章就來聊一聊引用數據拷貝的學問。
如果大家對Js的數據類型存在著疑問,不妨看看《JavaScript中的基本數據類型》
拷貝的劃分都是針對引用類型來討論的,淺拷貝——顧名思義,淺拷貝就是“淺層拷貝”,實際上只做了表面功夫:
var arr = [1, 2, 3, 4]; var newArr = arr; console.log(arr, newArr); // [1,2,3,4] [1,2,3,4] newArr[0] = 100; console.log(arr, newArr) // [100,2,3,4] [100,2,3,4]
不發生事情(操作)還好,一旦對新數組進行了操作,兩個變量中所保存的數據都會發生改變。
發生這類情況的原因也是因為引用類型
的基本特性:
數組中的slice和concat都會返回一個新數組,我們一起來試一下:
var arr = [1,2,3,4]; var res = arr.slice(); // 或者 res = arr.concat() res[0] = 100; console.log(arr); // [1,2,3,4]
這個問題這么快就解決了?雖然對這一層數據進行了這樣的的處理后,確實解決了問題,但!
var arr = [ { age: 23 }, [1,2,3,4] ]; var newArr = arr.concat(); arr[0].age = 18; arr[1][0] = 100; console.log(arr) // [ {age: 18}, [100,2,3,4] ] console.log(newArr) // [ {age: 18}, [100,2,3,4] ]
果然事情沒有那么簡單,這也是因為數據類型的不同。
S 不允許我們直接操作內存中的地址,也就是說不能操作對象的內存空間,所以,我們對對象的操作都只是在操作它的引用而已。
既然淺拷貝
達不到我們的要求,本著效率的原則,我們找找有沒有幫助我們實現深拷貝
的方法。
數據的方法失敗了,還有沒有其他辦法?我們需要實現真正意義上的拷貝出獨立的數據。
這里我們利用JSON的兩個方法,JSON.stringify()
,JSON.parse()
來實現最簡潔的深拷貝
var arr = ['str', 1, true, [1, 2], {age: 23}] var newArr = JSON.parse( JSON.stringify(arr) ); newArr[3][0] = 100; console.log(arr); // ['str', 1, true, [1, 2], {age: 23}] console.log(newArr); // ['str', 1, true, [100, 2], {age: 23}]
這個方法應該是實現深拷貝最簡潔的方法,但是,它仍然存在問題,我們先來看看剛才都做了些什么:
arr
JSON 字符串
值或對象
理解:
我們可以理解為,將原始數據轉換為新字符串
,再通過新字符串
還原為一個新對象
,這中改變數據類型的方式,間接的繞過了拷貝對象引用的過程,也就談不上影響原始數據。
限制:
這種方式成立的根本就是保證數據在“中轉”時的完整性,而JSON.stringify()
將值轉換為相應的JSON格式
時也有缺陷:
所以當我們拷貝函數、undefined等stringify
轉換有問題的數據時,就會出錯,我們在實際開發中也要結合實際情況使用。
舉一反三:
既然是通過改變數據類型來繞過拷貝引用這一過程,那么單純的數組深拷貝是不是可以通過現有的幾個API來實現呢?
var arr = [1,2,3]; var newArr = arr.toString().split(',').map(item => Number(item)) newArr[0] = 100; console.log(arr); // [1,2,3] console.log(newArr); // [100,2,3]
注意,此時僅能對包含純數字的數組進行深拷貝,因為:
但我愿稱它為純數字數組深拷貝!
有的人會認為Object.assign()
,可以做到深拷貝,我們來看一下
var obj = {a: 1, b: { c: 2 } } var newObj = Object.assign({}, obj) newObj.a = 100; newObj.b.c = 200; console.log(obj); // {a: 1, b: { c: 200 } } console.log(newObj) // {a: 100, b: { c: 200 } }
神奇,第一層屬性沒有改變,但第二層卻同步改變了,這是為什么呢?
因為 Object.assign()拷貝的是(可枚舉)屬性值。
假如源值是一個對象的引用,它僅僅會復制其引用值。MDN傳送門
既然現有的方法無法實現深拷貝,不妨我們自己來實現一個吧~
我們只需要將所有屬性即其嵌套屬性原封不動的復制給新變量一份即可,拋開現有的方法,我們應該怎么做呢?
var shallowCopy = function(obj) { if (typeof obj !== 'object') return; // 根據obj的類型判斷是新建一個數組還是對象 var newObj = obj instanceof Array ? [] : {}; // 遍歷obj,并且判斷是obj的屬性才拷貝 for (var key in obj) { if (obj.hasOwnProperty(key)) { newObj[key] = obj[key]; } } return newObj; }
我們只需要將所有屬性的引用拷貝一份即可~
相信大家在實現深拷貝的時候都會想到遞歸,同樣是判斷屬性值,但如果當前類型為object
則證明需要繼續遞歸,直到最后
var deepCopy = function(obj) { if (typeof obj !== 'object') return; var newObj = obj instanceof Array ? [] : {}; for (var key in obj) { if (obj.hasOwnProperty(key)) { newObj[key] = typeof obj[key] === 'object' ? deepCopy(obj[key]) : obj[key]; } } return newObj; }
我們用白話來解釋一下deepCopy
都做了什么
const obj = [1, { a: 1, b: { name: '余光'} } ]; const resObj = deepCopy(obj);
obj
,創建 第一個newObj
[]
0
(for in
以任意順序遍歷,我們假定按正常循序遍歷)
1
obj[1]
另外請注意遞歸的方式雖然可以深拷貝,但是在性能上肯定不如淺拷貝,大家還是需要結合實際情況來選擇。
作者: 余光
在學習彈性布局之前首先就要明白其概念
flex 就是flexible box的縮寫,意為彈性布局,用來為盒裝模型提供最大的靈活性
任何一個容器都可以指定為flex布局
.box{ display: flex; }
行內元素當然也可以使用flex布局
.box{ display: inline-flex; }
Webkit 內核的瀏覽器,必須加上-webkit前綴。
.box{ display: -webkit-flex; /* Safari */ display: flex; }
注意:設為 Flex 布局以后,子元素的float、clear和vertical-align屬性將失效。
采用 Flex 布局的元素,稱為 Flex 容器(flex container),簡稱"容器"。它的所有子元素自動成為容器成員,稱為 Flex 項目(flex item),簡稱"項目"。
容器默認存在兩根軸:水平的主軸(main axis)和垂直的交叉軸(cross axis)。主軸的開始位置(與邊框的交叉點)叫做main start,結束位置叫做main end;交叉軸的開始位置叫做cross start,結束位置叫做cross end。
項目默認沿主軸排列。單個項目占據的主軸空間叫做main size,占據的交叉軸空間叫做cross size。
以上這些基礎概念,請務必牢記,下面說屬性時,不再重復說明!
- flex-direction
- justify-content
- align-items
- flex-wrap
- align-content
- flex-flow
flex items默認都是沿著main axis(主軸)從main start 開始往main end方向排布
flex-direction決定了main axis的方向,有四個取值row(默認值)、row-reverse、column、column-reverse
.box { flex-direction: row | row-reverse | column | column-reverse; }
row(默認值):主軸為水平方向,起點在左端。
row-reverse:主軸為水平方向,起點在右端。
column:主軸為垂直方向,起點在上沿。
column-reverse:主軸為垂直方向,起點在下沿。
justify-content決定了flex item在main axis上的對齊方式
flex-start(默認值):與main start對齊
flex-end:與main end對齊
center:居中
space-between:flex items 之間的距離相等,與main start、main end兩端對齊
space-evently: flex items 之間的距離相等,flex items與main start 、main end 之間的距離等于flex items之間的距離
space-around :flex items 之間的距離相等,flex items與main start 、main end 之間的距離等于flex items之間的距離的一半
這個屬性的目的主要就是為了排列main axis的item位置
當然,這些屬性你可以自己嘗試一下,這里就不再一一嘗試了,但是注意,這些都是容器的屬性,要寫在容器的css中!
決定flex items在cross axis上的對齊方式
normal:在彈性布局中,效果和stretch一樣
stretch:前提是items不設置高度,當flex items 在cross axis 方向的size為auto時,會自動拉伸至填充flex container(或者換句話說:如果項目未設置高度或設為auto,將占滿整個容器的高度。)
flex-satrt:與cross start 對齊
flex-end:與cross end 對齊
center:居中對齊
baseline:與基準線對齊
決定了flex container 是單行還是多行
nowrap(默認):單行
warp:多行
//這個比較少用
wrap-reverse:多行(對比wrap,cross start 與cross end相反)
默認情況下,項目都排在一條線(又稱"軸線")上。flex-wrap屬性定義,如果一條軸線排不下,如何換行。
決定了多行flex items 在cross axis的對齊方式 用法與justify-content相似 一個是橫軸。一個控制豎軸
stretch(默認值):與align-items的stretch類似,當items有高度的時候,無效果
flex-start:與cross start 對齊
flex-end :與cross end 對齊
center:居中對齊
space-between:flex items 之間的距離相等,與cross start、cross end兩端對齊
space-evently: flex items 之間的距離相等,flex items與cross start 、cross end 之間的距離等于flex items之間的距離
space-around :flex items 之間的距離相等,flex items與cross start 、cross end 之間的距離等于flex items之間的距離的一半
也就是說,當你使用這個屬性的時候,你可以使用上述兩個的屬性值,例如:flex-flow: row wrap;(水平排列,多行顯示)
- order
- flex-grow
- flex-shrink
- flex-basis
- align-self
- flex
order 決定flex items的排布順序 (用的不多)
可以設置為任意整數(正整數、負整數、0),值越小越排在前面
默認值為0
這個屬性了解即可,說實話沒怎么用過
可以通過align-self 覆蓋flex container 設置的align-items
auto(默認值):遵從flex container的align-items設置
stretch、flex-start、flex-end、center、baseline效果與align-items一致
相當于繼承父元素的align-items屬性,如果沒有父元素,則等同于stretch。
決定了flex items如何擴展
可以設置為任意非父數字(小數,整數 0),默認為0
當flex container 在main axis方向上有剩余得size時,flex-grow屬性才會有效
如果所有flex items 的flex-grow 綜合sum不超過1,這直接乘以剩余size就是擴展大小、
如果超過1 擴展size=剩余size*flex-grow/sum
flex-grow屬性定義項目的放大比例,默認為0,即如果存在剩余空間,也不放大。
flex-shrink (shrink 縮小,收縮)與flex-grow相似,一個擴展,一個伸縮
可以設置為任意非父數字(小數,整數 0),默認為1
當flex items在main axis 方向上超過了flex container 的size flex-shrink屬性才會生效、
如果所有flex items 的flex-shrink 總和sum超過1,每個flex item 收縮的size為:
flex item 超出flex container 的size*收縮比例/每個flex items 的收縮比例之和
如果sum不超過1,每個flex item 收縮的size為:
size = 超出的size * flex-shrink值
flex items收縮后的最終size不能小于min-width\min-height
有擴大自然就會有縮小,flex-shrink屬性定義了項目的縮小比例,默認為1,即如果空間不足,該項目將縮小。
如果所有項目的flex-shrink屬性都為1,當空間不足時,都將等比例縮小。如果一個項目的flex-shrink屬性為0,其他項目都為1,則空間不足時,前者不縮小。具體的可以自己動手嘗試一下哦,最后將會給出一個骰子布局的案例!
用來設置flex items 在 main axis方向上的base size
默認為auto,可以設置具體的寬度數值
決定flex items最終base size 的因素,優先級從高到低
max-width\max-height\min-width\min-height
flex-basis
width\height
內容本身的size
flex-basis屬性定義了在分配多余空間之前,項目占據的主軸空間(main size)。瀏覽器根據這個屬性,計算主軸是否有多余空間。它的默認值為auto,即項目(item)的本來大小。也可以設置跟width,height一樣的寬高,表示item將占據固定的空間!
flex 是flex-grow || flex-shink||flex-basis的簡寫
可以指定1 2 3個值 依次按照上述順序!默認值為 0 1 auto
.item { flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ] }
注意:
- 該屬性的默認值為 0 1 auto(注意順序),后兩個屬性可選
- 該屬性有兩個快捷值:auto (1 1 auto) 和 none (0 0 auto)。
- 如果需要這三個屬性的時候,建議使用flex,而不是單獨的三個分離的屬性,因為瀏覽器會推算相關值
光說不練假把式,手撕代碼真功夫!
下面利用flex寫了幾個骰子布局,可以參考一下!
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <style type="text/css"> #container{ background-color: #CCCCCC; height: 600px; width: 500px; /* flex */ display: flex; justify-content: space-evenly; align-items: center; } .item{ background-color: yellow; width: 100px; height: 100px; } /* 單點 */ .one{ /* 對點使用flex布局 */ display: flex; justify-content: center; align-items: center; } /* 點 */ .item-one{ display: block; height: 20px; width: 20px; background-color: #1890FF; border-radius: 50%; } /* 三點 */ .two{ display: flex; justify-content: space-between; } .two span{ margin: 2px; display: block; height: 20px; width: 20px; border-radius: 50%; background-color: #1890FF; } .two2{ align-self: center; } .two3{ align-self: flex-end; } /* 五點 */ .three{ display: flex; justify-content: space-around; } .three span{ display: block; height: 20px; width: 20px; border-radius: 50%; background-color: #1890FF; } #three_one, #three_three{ padding: 2px; display: flex; flex-direction: column; justify-content: space-between; } #three_two{ display: flex; flex-direction: column; justify-content: center; } /* 六點 */ .four{ display: flex; justify-content: space-around; } .four span{ display: block; height: 20px; width: 20px; border-radius: 50%; background-color: #1890FF; } #four1,#four2{ padding: 2px; display: flex; flex-direction: column; justify-content: space-between; } </style> </head> <body> <div id="container"> <!-- 一個點居中 --> <div class="item one"> <span class="item-one"></span> </div> <!-- 三點 --> <div class="item two"> <span class="two1"></span> <span class="two2"></span> <span class="two3"></span> </div> <!-- 五點 --> <div class="item three"> <div id="three_one"> <span></span> <span></span> </div> <div id="three_two"> <span></span> </div> <div id="three_three"> <span></span> <span></span> </div> </div> <!-- 六點 --> <div class="item four"> <div id="four1"> <span></span> <span></span> <span></span> </div> <div id="four2"> <span></span> <span></span> <span></span> </div> </div> </div> </body> </html>
手機UI中的交互是保持產品鮮活生命力的源動力。好的交互可以幫助用戶快速地獲得反饋,認知布局,增強體驗感和沉浸感。
手機UI中的交互是保持產品鮮活生命力的源動力。好的交互可以幫助用戶快速地獲得反饋,認知布局,增強體驗感和沉浸感。這里為大家整理了12款優秀并富有創意的交互作品,為你的產品設計注入靈感。
--手機appUI設計--
--手機appUI設計--
--手機appUI設計--
--手機appUI設計--
--手機appUI設計--
--手機appUI設計--
--手機appUI設計--
--手機appUI設計--
--手機appUI設計--
--手機appUI設計--
--手機appUI設計--
--手機appUI設計--
--手機appUI設計--
--手機appUI設計--
--手機appUI設計--
--手機appUI設計--
--手機appUI設計--
--手機appUI設計--
--手機appUI設計--
(以上圖片均來源于網絡)
藍藍設計( www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務
更多精彩文章:
這并不是一篇關于設計趨勢的文章,而是一篇關于基礎的設計準則的文章。如果你是一名 UI 設計師,無論你經驗是否豐富,有些設計的基準是需要保證的,有些容易遺忘的細節,需要借助速查清單來進行走查優化。
這份優化 UI 界面的速查清單,就是幫你搞定這件事情的。
首先聲明,一個項目中最好不要使用超過2種主要字體。不過這種原則已經廣為流傳,就不多說了,下面說說更細節的事情:
純大寫的字母文本,要額外拉開字母之間的字間距,提升可讀性。
字重超細的字體要謹慎使用。可以使用淺色,但是要根據字體情況進行選擇。如果你設計的文本是裝飾性也就算的,如果是需要用戶能清晰閱讀的,就要特別慎重,能不用就不用,否則在部分手機屏幕上看起來會非常糟糕。
先說說網頁排版。標題通常分 H1 到 H6 總計6個不同層級,但是通常不會全部用到,你需要確保層級最多不超過 4 個,并且控制它們整體的邏輯和一致性。網頁的首屏和登錄頁面上的大標題,可以用最大的那一級,畢竟,富有表現力的視覺排版是當下趨勢。
但是其他的文本不要和這個標題文本差距太大。英文文本以Chrome 瀏覽器為例,正文使用 16px 和 17px 這種大小,并且保留 12px 文本作為最小文本。
另外,同一個段落中,不要同時使用 16px 和 17px 這樣相近又不同的文本尺寸,會讓用戶感到迷惑。
盡量不要在行高上采用自動行高。通常,現在比較流行的做法,是將行高拉高一些,確保整體版面的透氣性和可讀性,尤其是涉及到大量文本的時候。
在需要突出顯示的部分使用粗體。標題、鏈接、按鈕都在這個范疇內。如果將粗體樣式應用到全部文本,這樣重點就不突出了。
請特別注意文本的色彩??刂坪脤Ρ榷?,確保任何類型的顯示器上都可以清晰閱讀。在設計占位符文本的時候,這個問題特別突出。
留白對于整體設計的重要性是毋庸置疑的。留白的變化有助于設計師理清元素之間的關系,提供節奏感,增加平衡感。
將一個語義塊和另外一個語義塊分開,最簡單的方法就是在兩者之間增加一條 1px 的線。但是這并不是最好的方法。
我見過不少設計作品中,界面中一個又一個線條繪制的盒子相互嵌套,復雜無比,每個盒子都是用 1px 粗細的線繪制的。但是,如今的UI界面上基本不用這種手法了,大量的卡片替代了以往的各種「盒子」,通過投影和間距來控制卡片之間的關系。
邊距有助于從視覺上來判斷元素之間的親疏關系。當我們考慮一個新聞資訊卡片的布局的時候,它包含有一張圖片、一個標題,還有3~4行預覽文本和發布日期,那么應該如何分組和間隔?標題和文本應該是一組,這一組和圖片、日期的距離更遠一些。聽起來很令人困惑?看下面的圖片你就理解了:
總會有客戶或者產品會想把所有的功能和元素都懟到同一個頁面或者 APP 當中。這個時候,要你讓標題、菜單、文本、特價優惠、社交帳號和電話號碼都齊齊整整地塞到一起,同時還要給每個組件搭配上圖標。
說真的,這種問題總不能避免。這個時候可以使用這個理由來試圖進行溝通:用戶一次接收的信息越少,進行有效操作的可能性就越大。循序漸進地呈現信息,能夠讓人更加愉悅,用戶對于信息的接受性也更強。
用戶永遠都不會費力巴拉地去拆解和分析你的頁面布局,緊密局促的布局也早已不符合主流審美和日常需求了。
如果你設計的是海報、Banner 或者是 卡片 等我們所熟知的視覺元素,那么請注意邊緣留白的設計。如果按照經典的方式來布置(從左上到右下),那么盡量讓上方的留白更大,這看起來會讓視覺更加穩當,并且更加具有視覺吸引力。
Logo、圖像、圖標、背景這些元素決定了整個設計給人的情緒。所以在設計的時候,需要有針對性地挑選和優化。
我并不經常做 LOGO,但是在我的職業生涯中也起碼做過 20 個LOGO。我的經驗是:好 LOGO 很難制作。但是設計師只要遵循基本的原則,就能創建出像樣的 LOGO。
比如仔細選擇配色。我有一次看到一家名為 「VIP catch」 的釣魚用品店,他們使用了紫色的 LOGO,從名字、配色到色彩的選擇都和釣魚這個場景沒有一點關系。如果選對配色,有針對性地加入一些和釣魚相關的元素,其實也就好了。
另外就是,如果你時間有限,就不要試圖給品牌 LOGO 設計一個特定的符號或者圖形了,因為真的很難做好。最好制作成文本 LOGO,通過微調字體來制作。
元素下方的陰影一定不要用黑色。始終基于表層的、前景的元素來選取陰影的顏色和明暗。通常,一個看起來舒適的陰影是通過多個陰影疊加造就的,一個小且明確的陰影,位于正下方,另外一個陰影模糊且彌散,透明度更高。
任何可以矢量化的元素,都盡量制作成為矢量的。從符號、箭頭到 LOGO ,現在都最好制作成為矢量 SVG 格式,方便開發人員嵌入到設計系統當中。PNG 圖標的邊緣模糊,在清晰度越來越高的視網膜屏幕上,矢量圖形元素不僅更加銳利,而且消耗更少的系統資源。
如果你正在為網站處理一組圖標,請盡量確保這些圖標在視覺風格和細節處理上是統一的,看起來是同屬一個「家族」的。這意味著圖標的筆觸寬度、邊框半徑、視覺重量都應該是一樣的。
除了上面的幾個常見的要點之外,我還要額外補充幾點,它們很難直接歸結為一類,但是同樣重要。
很多 UI 界面元素在過去多年的發展過程中,已經形成了認知廣泛的「最佳實踐」。如果在設計這些 UI 組件的時候,采用打破甚至徹底違背「最佳實踐」的做法,比如將圖片+標題+ 文本 的順序打亂,可能會讓人感到迷惑。
熟悉的設計并不意味著無聊,你總能夠在 UI 界面的一些地方找到發揮創造力的地方,而不是在這些有著清晰規則的地方搞創新。設計師和藝術家是截然不同的職業,在設計過程中,創意沖動應該在不干擾用戶體驗的前提下,進行發揮。
在設計移動端 UI 界面之前,應該和開發人員進行充分的溝通,這一點很重要。iOS 和 Android 端的 APP 的尺寸還相對固定,但是如果你設計的是移動端的網頁,那么可能涉及到的頁面尺寸就非常多了,這個時候就要用到斷點非常多的網格系統來進行響應式的設計了。
Lorem Ipsum 在中文中叫亂數假文,它是自動生成的一種占位符。在如今的設計領域當中,直接使用亂數假文看起來非常不專業,因為無論是 Sketch 還是 Figma 當中都有太多的插件,可以幫你生成符合語境的占位符內容。在此基礎上還有另外一個要點,就是展示性的組件內容也不要簡單地復制,盡量使用不同的圖片和配色,讓它們看起來更加真實。
這份UI快速檢查清單目前是比較符合當下 UI 設計行業的需求的,但是它并非是教條,在特定的情況下,你可能不用遵循它。當然,在多數時候,這份清單能夠幫你讓設計更加優秀。
1、字體版式
1.1、注意大寫
1.2、注意超細體的字體
1.3、標題和正文字體尺寸
1.4、行高
1.5、文本和標題的層次結構
1.6、文字對比
2、間距和邊距
2.1、去掉多余的框架和線條
2.2、梳理從屬關系
2.3、少即是多
2.4、屏幕邊緣留白不均勻
3、配色和圖像
3.1、關于 LOGO
3.2、陰影
3.3、圖標和圖像
4、其他設計常識
4.1、避免使用怪異的布局
4.2、布局尺寸和參數
4.3、亂數假文
結語
藍藍設計( www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務
不管是平面設計、品牌設計,還是UI設計,配色都是一個基礎,決定著作品的視覺效果。這篇文章就從色相、純度、明度(色彩的三大屬性)三個角度,展開談談色彩的搭配。
之前我也無意中看到餓了么把「超級會員」改成了「吃貨卡」,感覺還不錯。雖然并不了解餓了么的會員業務,但這次改版體現了一些有趣的設計思路,正好對應了我們在設計上的疑惑點。于是就著該讀者的問題,一起來聊聊其中有意思的點。
比如,如何在同質化的功能上做出一些創新且有價值的改變;如何降低營銷感,把商業需求統一到用戶需求上;如何不需要再糾結今天到底吃什么了……
我們「以為」的,就是真實的嗎?
今天的文章,從一張圖開始。
在《認知與設計》的第一章里,作者提到了關于感知的話題,在影響感知的幾種方式里,第一種就是「感知的啟動」,其中很典型的案例是下面的一張素描,你能看出畫面中是什么嗎?
一條斑點狗。
或者你沒看出來?如果你看到了這只狗,就很難再回頭把這張素描看做隨機無序的點了。就像書里說的那樣,我們看到的很多東西取決于別人告訴我們它是什么。
產品功能也是如此,它告訴了我們這是什么,我們就會這么認為。如果一開始設計的就是吃貨卡,也許很多人不會想到它是會員的變體,而是僅僅當做一個福利卡來看了。對于超級會員和吃貨卡的感知差別僅僅在于定義上的不同,而非本質的改變,這是很有意思的一個點。
拿生活中的一個例子去看,相同的杯子,我們可以叫它咖啡杯,同樣也可以叫它養生杯,當面對不同的叫法時,我們是不是就會產生不同的代入感?
而產品大多數時候都是通過渲染場景、營造氛圍來達到這個目的,我們通常將其稱之為產品定位。
所以產品需要定位,需要一個鮮明的形象,然后讓產品中的所有信息、功能、風格、色彩都去表現它,才能樹立起用戶的認知,帶來深入人心的記憶點。于是,相同的功能在不同產品中的差異除了內容的填充、使用的方法、規則的定義外,還可以改變的就是 —— 包裝。
就餓了么這次改版的「吃貨卡」而言,它本身并非一個新功能,只是「超級會員」的一個變體,會員的本質就是產品根據用戶的投入而給予的特權。所以產品只是集合了這一部分有投入有特權的群體罷了,至于怎么稱呼,會員也好、吃貨也罷,在產品層面都是一樣的。
會員,官方的解釋是:通過正式手續加入某個會社或專業組織的人。
在任何地方,我們都可以成為會員,但不是任何地方,我們都能變成吃貨。所以吃貨卡這個定義,一下子就把強烈的產品屬性透傳了出來,并聯結了我們的目標用戶,會員的「積分」也自然地轉化成了「吃貨豆」,這種概念上的改變,就是一種包裝。
這是我在這篇文章中要聊的第一個點,就是通過品牌塑造來重新包裝一個功能,而包裝的形式要依附于產品定位。
第二大點,我們來聊營銷廣告與產品功能的碰撞。
在廣告濫用和形式多變的今天,我們已經逐漸習慣至無感那些具有豐富色彩和設計元素的廣告內容,以至于可以自動篩選出它們,打上標簽,從我們的視覺中過濾出去。
但總有一些廣告似乎天生具有一種隱秘的商人氣質,帶著精明的窺探,去誘導大家瀏覽、點擊、分享、消費。
廣告是產品的一種營銷語言,而營銷有時就是讓利,以廣告的形式,通過優惠與福利來抓住用戶的心,而用戶往往會認為這是欺騙。那么當商業目標和用戶目標無法趨于一致的時候,我們又該如何讓用戶為產品站臺呢?
首先,對于廣告的刻板印象常源自我們接觸廣告的失敗經驗,其大致可分為三類。
第一類「虛假利益」??浯蠛锰帲蚰梅亲罱K的利益引誘,直到我們了解了詳情才發現自己是個被騙的傻瓜。
于是,產品通過弱化營銷性的信息流廣告,并加上清晰的廣告標簽,公開透明的讓用戶感受到自己被平等地尊重,即滿足商業利益,又解決了用戶的訴求問題,將兩者利益統一。
但這一類并不是我們今天要聊的重點,我們繼續往下看。
第二類「難度操作」,比如那些假的關閉圖標、廣告背景中極小的跳過按鈕、或者在領取福利時的層層步驟,都是用戶在接觸廣告時難度操作的體現。
前兩種對用戶來說無法原諒,而最后一種往往會作為一種營銷策略,去增加用戶獲得獎勵前對產品的投入,比如瀏覽、轉發、消費等,這是沒有問題的,關鍵是用戶是否提前獲知了我們得到獎勵的所有條件。我們厭惡的,是超出我們預期的那些負擔任務。
吃貨卡的任務模塊在優化后就直接展示了任務詳情。但是首頁領任務的提示卻隱藏了任務的重要條件,比如「下 2 單,賺 400 吃貨豆」,實際是兩筆超 20 元的訂單。那是否會存在一類用戶,沒有點擊查看詳情而直接下單,下單之后,發現并沒有完成進度?因為外賣費用沒有超過 20 元。
如果產品是擔心用戶因為 20 元的門檻而不做任務,那么在點擊查看后的任務詳情不是把這一類用戶推向進一步的否定嗎?我們因這樣的手段能夠額外獲得多少增長,同時,又有多少用戶因此對所有的任務失去信任,我們無法準確計算,因為得到是顯性的,而失去是隱性的。比如一些音樂產品的會員機制,用戶辦理好之后想聽某首歌,發現還需要另外再付費,于是卸載了軟件。
另外,改版后吃貨豆的領取方式也對應發生了改變,不是直接的發放,而是轉為點擊領取。
雖然趣味的動效消解了部分用戶對冗余操作的厭惡感,但還是能從反饋渠道中看到用戶對這種強制限時去領取獎勵做法的反感。這種領取模式也可說是一種變相簽到,只不過這種簽到的獎勵不是你通過額外行為主動賺取的,而是在已經得到的情況下被迫操作領取,和支付寶領取積分的方式一樣。限定時間內不領取,還會消失。
游戲積分的領取,之所以有領取操作,是因為積分積攢的寶箱獎勵,是額外的收獲。玩家玩游戲的目的是體驗游戲而不是為了積分與寶箱,這兩者之間是有差異的。
多余的操作看起來增加了頁面的曝光度,帶來了更多的轉化可能,卻「實在」地提高了用戶獲得獎勵的成本,從而間接降低了獎勵的價值,因為投入產出比太低,所以用戶常常寧愿放棄這樣的獎勵。
產品想要讓用戶感覺到方便和實惠,體驗滿意,但又通過這種點擊才能領取的方式,強制綁定用戶與頁面,來觸發用戶的下一步行動。表面上可玩性增強了,實則是體驗感的缺失。
第三類是關于「過度選擇」。交互設計有一本經典的入門書籍叫《Don’t make me think》,描述了如何通過設計幫助用戶理解與操作,來提高產品的易用性。同理,當我們思考營銷在產品中的表現時,難道就不需要考慮用戶了么?
過去的營銷就像過去的產品一樣,以產品實現而非用戶為中心,表現產品的實現方式而不去考慮用戶的心理模型。
比如軟件需要我們命名才能保存,特別是系統自帶的記事本軟件,不僅需要自己輸入文件名,還用 *txt 占了命名位,使用星號讓我們無法直接保存。相比之下,很多軟件已不再需要用戶命名,會直接提供默認命名,還有像 Typora 這類產品,可以自動將我們的第一段文本內容作為默認文件名。
對營銷而言,以實現為中心的設計想法體現在制造了盡可能多的活動類型和規則上,希望觸達不同的用戶。而事實是,在過度選擇的壓力下,很多用戶直接選擇了忽視。
如果去看餓了么會員舊版的設計,我們會發現它有紅包、獎勵金和折扣商品三類福利,三者的關系是相對分離的。
其中的規則是,當我們成為了會員:
所以我們有三種獲得紅包的途徑:領取、購買、兌換。
再看新版吃貨卡的設計,在直接領取與購買紅包不變之外,新版強調以用戶的消費去獲得獎勵,不管是直接兌換紅包或者兌換店鋪的專屬紅包,都是以吃貨豆兌換為核心。相比舊版,將商鋪折扣商品,替換為吃貨豆兌換專項紅包,其實本質是一樣的,無非就是為了提高吃貨豆與吃貨卡的利用率罷了。
在這樣一個前提下,產品增加了紅包類別,給予了用戶更多選擇的自由。雖然隨著紅包的分類維度變多(專享和吃貨聯盟的紅包、特定品牌和分類的紅包、具體店鋪的紅包),產品的規則趨向復雜,但是理解變簡單了,我們也只需要做好兌換這一件事就可以。
復雜的規則仍然可以呈現出簡明的設計,我們不需要用戶來負責過濾這些復雜信息,而應當要求產品,站在用戶這邊,去降低理解成本。自然地,產品與用戶就能并軌而走,商業需求與用戶需求也可統一。
當然,或許也會有用戶反感這樣的功能被活動化,但不得不說,這確實是一個品牌的升級。
這篇文章從幾個角度聊了「吃貨卡」好與不好的地方。
當然它不僅僅是一個會員功能的改版,在概念玩法上也是一種升級。從設計角度看,確實有創意的表現,雖然也有不可取之處,但是它背后的設計思考是值得學習的。
我們知道,設計雖然會受到許多框架和規則的限制,但從問題出發,思考方案的過程才是設計本身最有意思的地方。好比游戲,也是因為規則與框架的限制,以至于才有了如今豐富多彩的游戲形態。
所以即使看向那些常規的功能和成熟的設計,我們也可以融入一些不一樣的東西,站在過去到現在的經驗上,再做出一點改變,使其更具可玩性。
文章來源:優設 作者:呆呆U理
藍藍設計( www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務
2020年已經過去一大半,這些時間以來,我一直在關注數字設計領域未來的設計趨勢。從年初就開始收集,到今8月份了,我想是時候將發現的一些趨勢風格分享出來,這些風格很有可能繼續延續到2021的產品設計上。
對于UI界面視覺趨勢,同樣需要我們高度重視。畢竟每年改版方向,視覺風格研究是必不可少的一個環節,下面正式開始。
今年在各網站上看到大面積的漸變色設計,相對前兩年來說越來越少,設計上有所克制。大面積的漸變色雖然視覺沖擊力強,但大部分停留在概念中。
從今年設計中我們可以看到設計更加理性與克制,將漸變色彩運用到關鍵功能上,突出強調重要信息。
機票選購界面,將漸變色運用到頭部位置去強調功能。
運用在功能卡片上,突出重點信息。
如上圖,設計上同樣只將漸變色運用在背景上,其他卡片上基本沒有漸變色。
幾何圖形設計是目前運用最多一個設計手法,今年發現一些比較抽象藝術化包豪斯風格幾何圖形,在UI設計中大量運用,且效果還不錯。
這種圖形帶來好處就是記憶性強,應用廣,它不僅可以拓展在品牌包裝,品牌圖形延展,還可以運用在UI設計中。
卡片設計采用一些具有意向符號的圖形,來表達功能的設計,形成記憶點。
品牌設計上,也是重復這種極簡包豪斯風格幾何圖形。將logo元素提取,進行包豪斯風格化,重復運用在設計中。
今年這樣的設計屢見不鮮,大量3D運用在界面設計中,二維的界面已經不再滿足當前設計需要。設計師去探索更多維度學科與UI界面融合,形成一種全新的視覺感官。
uber的概念官網就通過3D來呈現,表達功能亮點。
將二維世界三維化,將是2021年重要的趨勢。目前國內外線上有一些產品,開始在部分功能模塊使用這樣設計手法,如Naver,支付寶等。
可以說是趨勢輪回,毛玻璃的效果又回來了。這也是今年在各網站設計上出現頻次多一些的設計。
新的毛玻璃效果更加去注重功能說明,用在視覺強調的地方。
如上圖設計,毛玻璃運用在頂部關鍵信息上。這樣設計即可減少其他色彩運用,還可以對功能信息進行強調。
毛玻璃效果運用在個人中心,人物頭像位置,進行設計強調。
運用毛玻璃去包裝UI界面,可以提升品質感與神秘感。
將功能與場景融合設計,用戶在使用產品過程中,能產生更多情景體驗感觸。這也是最近今年喊的比較火的一種設計思路。在各網站上,這樣設計出現次數越來越多,設計效果沖擊力強,得到很多設計師的認可。
場景中關鍵人物元素與設計進行巧妙集合。
運用超現實設計手法,將人物與酒店場景進行排版布局。
將制作材料與產品集合。
擬真植物元素與土地進行巧妙集合,在視覺上傳達逼真效果。
雜志化設計風格鮮明,可以有助產品去打造強化記憶點。雜志化設計的優勢可以不受到網格約束,排版使用大字體,同時設計排版上更加個性。我們在做產品概念探索前期,可以多去嘗試這樣的風格。
擬物圖標又回來了,Apple新版本的Big Sur系統,就采用擬態圖標,這也是一個新的嘗試,當然也是一個開始。我們很有必要時刻關注這個趨勢,未來將會在更多設計中看到擬物化圖標的出現。
不過這種風格也不能大面積運用在界面中,我們可以運用在一些關鍵功能入口設計上。
在天氣上的運用,相對之前扁平化設計,目前具有空間的擬物化設計,增加了真實感。
圓形趨勢,我想大家也許會忽略的點,最近幾年設計中,圓形的設計無處不在。它的好處不言而喻,親和力強、場景覆蓋廣,幾乎任何設計都能去用圓形。因此我們有必要去注意圓形運用技巧。
星巴克的web UI概念設計,采用圓形與產品進行集合設計排版。
新擬態趨勢是2020年受到廣泛關注的趨勢之一,這種趨勢大量使用了柔和的陰影和微弱漸變,使設計既具有未來感又具有現實感,并且為熟悉的界面帶來了新的感覺。相對之前大面積濃厚陰影而言,目前新的簡化擬態界面,會克制使用這些元素。
2021年擬態界面,更注重功能與體驗。擬態效果會使用在關鍵功能上,如儀表、按鈕,又或者需要重點強調的地方,避免了大面積使用這種設計手法。
2021年的趨勢相對來說,有繼續延續2020年一些設計風格,這些風格將會在繼續加強,同時我們也有發現,目前越來越多3D元素與二維界面進行集合設計,能更生動傳達功能與將故事,2021年大家務必要注意這種趨勢的延續。
作為設計師,我們對設計的思考不能只停留在表象層面,而更多的需要圍繞信息傳達這一設計的本質功能,以充滿自省的精神深化和反思自己的設計意識,同時要時刻保持對趨勢的敏感度。將新趨勢合理的運用在產品設計中,以產生最大化收益。
文章來源:優設 作者:功夫UX
藍藍設計( www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務
藍藍設計的小編 http://www.syprn.cn