為什么大爺大媽們總對(duì)排隊(duì)情有獨(dú)鐘,為什么平常不想要的東西一打折就買(mǎi)一堆……震驚!原來(lái)套路你的竟然都是自己的大腦!
如今想要成為一名合格的用戶體驗(yàn)設(shè)計(jì)師,首要就是對(duì)目標(biāo)用戶的理解和把控。而為了實(shí)現(xiàn)這一目標(biāo),掌握一些心理學(xué)知識(shí)就顯得尤為重要。當(dāng)我們能在設(shè)計(jì)中合理利用心理學(xué)的時(shí)候,就離創(chuàng)造出讓用戶感慨「深得朕心」的體驗(yàn)不遠(yuǎn)了。
這次要介紹的是設(shè)計(jì)心理學(xué)中與我們?nèi)粘I蠲芮邢嚓P(guān)的認(rèn)知偏差 (Cognitive bias) ,了解它的基本定義之后再結(jié)合相關(guān)案例探討如何在設(shè)計(jì)中利用認(rèn)知偏差來(lái)創(chuàng)造更好的用戶體驗(yàn)。
網(wǎng)絡(luò)上的定義是這樣的:人們?cè)谥X(jué)自身、他人或外部環(huán)境時(shí),常因自身或情境的原因使得知覺(jué)結(jié)果出現(xiàn)失真的現(xiàn)象。
簡(jiǎn)單來(lái)說(shuō),就是大腦創(chuàng)造了一些快捷方式,在處理信息時(shí)自然地去調(diào)用這些快捷方式,只是這種操作在快速的同時(shí),也會(huì)對(duì)我們的決策過(guò)程產(chǎn)生危害,比如我們會(huì)選擇性忽略一些信息,或是自發(fā)地對(duì)信息進(jìn)行腦補(bǔ)。這樣的認(rèn)知模式導(dǎo)致我們產(chǎn)生了非理性的偏差。
△ 圖:大腦的操作
認(rèn)知偏差種類豐富,已經(jīng)被提出的就有幾百種,有很多尚未被完全驗(yàn)證。下圖總結(jié)了現(xiàn)有的認(rèn)知偏差,它們大概可以分為四類:信息過(guò)載,信息的意義不明確,大腦來(lái)不及認(rèn)真作出反應(yīng)以及大腦存不下所有的記憶。通過(guò)這張圖,我們可以更清晰地了解不同認(rèn)知偏差背后的成因。
△ 圖:認(rèn)知偏差寶典
那我們?cè)撛趺丛谠O(shè)計(jì)中利用認(rèn)知偏差呢?我根據(jù)日常工作中經(jīng)常接觸的消費(fèi)場(chǎng)景和學(xué)習(xí)場(chǎng)景總結(jié)了以下幾個(gè)方面:
△ 圖:章節(jié)概覽,也叫懶人速讀版
作為體驗(yàn)設(shè)計(jì)師,我們需要為用戶的決策創(chuàng)造合適的環(huán)境,來(lái)引導(dǎo)其按照我們?cè)O(shè)計(jì)的方向去達(dá)成他們的目標(biāo)。
錨定效應(yīng)
錨定效應(yīng)(Anchoring)是比較常見(jiàn)的一個(gè)被利用在消費(fèi)場(chǎng)景中的認(rèn)知偏差。它指的是人在做決定的時(shí)候,會(huì)在很大程度上依賴于其接觸到的信息。
比如商場(chǎng)里原價(jià) 2000 現(xiàn)價(jià) 500 的商品,原價(jià)的存在會(huì)讓人覺(jué)得這件商品的價(jià)值就是 2000,現(xiàn)在 500 簡(jiǎn)直是撿了大便宜。
在體驗(yàn)設(shè)計(jì)中可以借鑒這種做法,通過(guò)前后對(duì)比放大來(lái)優(yōu)惠感知,進(jìn)而促進(jìn)用戶做出有利于我們的決策。
△ 圖:利用錨定效應(yīng)推薦會(huì)員套餐,對(duì)比差價(jià)確實(shí)誘人
從眾效應(yīng)
從眾效應(yīng)(Bandwagon Effect)是另外一個(gè)常見(jiàn)的用于消費(fèi)場(chǎng)景的認(rèn)知偏差,指的是人們做決定時(shí)通常會(huì)和他人保持一致。
下圖是售前頁(yè)一般的設(shè)計(jì)技巧,通過(guò)展示購(gòu)買(mǎi)人數(shù)和滾動(dòng)播放購(gòu)買(mǎi)信息來(lái)體現(xiàn)出該商品的熱門(mén),讓正在猶豫的用戶「隨大流」下單購(gòu)買(mǎi)。
基于此,我們?cè)谠O(shè)計(jì)中可以營(yíng)造出一種群體選擇的效果來(lái)吸引更多的用戶。
△ 圖:這么多人選擇,跟隨大家不會(huì)錯(cuò),買(mǎi)它
內(nèi)群體偏差
前面提到的認(rèn)知偏差之外,內(nèi)群體偏差 (ingroup bias) 也一般被用來(lái)引導(dǎo)用戶決策,它是指人們會(huì)在認(rèn)知上傾向于自己所屬的群體。
比如 Booking 在查看評(píng)論的區(qū)域加入了篩選評(píng)論語(yǔ)言這一按鈕,雖然設(shè)計(jì)的本意可能是為了方便用戶更好地理解評(píng)論內(nèi)容,但是在真實(shí)的使用過(guò)程中可以發(fā)現(xiàn),用戶更加信任自己所選標(biāo)簽內(nèi)的評(píng)論內(nèi)容,因?yàn)橥Z(yǔ)言往往意味著來(lái)自相同的國(guó)家或者相近的文化背景,用戶通過(guò)這種方式找到一個(gè)小群體,然后被影響進(jìn)而做出與群體內(nèi)人們更為相似的決策。
△ 圖:同胞的評(píng)價(jià)更可靠
因此在體驗(yàn)設(shè)計(jì)中利用內(nèi)群體偏差的關(guān)鍵點(diǎn)在于打造群體歸屬感,借由小群體的力量影響用戶的決策。
引導(dǎo)用戶做出于我們有利的決策之外,同樣,我們可以利用認(rèn)知偏差提高用戶粘性,增強(qiáng)用戶和產(chǎn)品之間的聯(lián)系,使他們對(duì)產(chǎn)品「愛(ài)不釋手」。
宜家效應(yīng)
宜家效應(yīng) (The Ikea Effect) 是指消費(fèi)者對(duì)于自己投入勞動(dòng)、情感而創(chuàng)造的物品的價(jià)值產(chǎn)生高估的價(jià)值判斷偏差的現(xiàn)象,消費(fèi)者對(duì)于一個(gè)物品付出的勞動(dòng)(情感)越多,就越容易高估該物品的價(jià)值。利用宜家效應(yīng)提高用戶粘性的核心是創(chuàng)造低投入、高回報(bào)、高貢獻(xiàn)價(jià)值的任務(wù),保證用戶能夠完成任務(wù)的基礎(chǔ)上貢獻(xiàn)自己的價(jià)值。
在學(xué)習(xí)場(chǎng)景中我們可以利用宜家效應(yīng)提高用戶粘性,將用戶留下來(lái)堅(jiān)持學(xué)習(xí)。
首先需要保證用戶能夠完成任務(wù)。懂你英語(yǔ) ®A? 產(chǎn)品中,我們會(huì)在用戶設(shè)置目標(biāo)時(shí)描述該目標(biāo)的表現(xiàn),用戶以此選擇自己的目標(biāo)。這種方式下的用戶對(duì)于任務(wù)結(jié)果的預(yù)見(jiàn)性提高,能清楚的知道如果完成任務(wù)會(huì)達(dá)到什么效果,更能被促使順利地完成任務(wù)。
△ 圖:目標(biāo)展示與貢獻(xiàn)積累
其次,用戶對(duì)產(chǎn)品粘性增強(qiáng)需要能夠感知到自己所做出的投入,學(xué)習(xí)場(chǎng)景下這種投入感知更多體現(xiàn)在知識(shí)的累積上。在懂你英語(yǔ) ®A? 課程中,我們將用戶與目標(biāo)之間的距離設(shè)計(jì)為學(xué)習(xí)路徑,用戶每完成一個(gè)階段的學(xué)習(xí)便會(huì)在路徑上明顯前進(jìn),日積月累下來(lái)用戶能看到自己前進(jìn)的印記,清晰感知到自身知識(shí)的累積,也就因此對(duì)產(chǎn)品有更高的價(jià)值感受。
負(fù)向偏見(jiàn)
由于學(xué)習(xí)的「反人性」,學(xué)習(xí)場(chǎng)景下的用戶在體驗(yàn)流程中產(chǎn)生消極情緒的概率要大于其余場(chǎng)景,比如學(xué)習(xí)效果不好,難以堅(jiān)持等。此類消極情緒對(duì)于學(xué)習(xí)產(chǎn)品影響很大,是因?yàn)樨?fù)向偏見(jiàn) (negativity bias) 的存在,人們對(duì)不好的事情的記憶比快樂(lè)的記憶更加清晰,更經(jīng)常回憶。
因此在學(xué)習(xí)場(chǎng)景下我們需要給用戶更多的正面積極的反饋來(lái)抵消掉負(fù)面體驗(yàn)的影響。在懂你英語(yǔ) ®A? 課程設(shè)計(jì)中,我們?cè)趯W(xué)習(xí)結(jié)果頁(yè)根據(jù)用戶不同的學(xué)習(xí)表現(xiàn)給出不同的反饋,即使是偏低的成績(jī),也依然會(huì)給出一個(gè)較為積極的反饋,以期鼓勵(lì)用戶堅(jiān)持學(xué)習(xí)。
△ 圖:做得不好也不要灰心
除了簡(jiǎn)單抵消掉用戶的負(fù)面偏見(jiàn),我們甚至可以通過(guò)設(shè)計(jì)去完全扭轉(zhuǎn)局面,變困境為有趣的體驗(yàn)。最經(jīng)典例子便是谷歌斷網(wǎng)時(shí)的小恐龍游戲,不知道有多少人會(huì)故意關(guān)掉網(wǎng)絡(luò)來(lái)玩這個(gè)游戲。
△ 圖:谷歌的斷網(wǎng)小恐龍
作為設(shè)計(jì)師我們可以通過(guò)了解和利用認(rèn)知偏差來(lái)創(chuàng)造既讓用戶滿意又平衡商業(yè)的雙贏體驗(yàn)。但由于設(shè)計(jì)師本身也是人類,與用戶擁有同樣的思考機(jī)制,因此在日常的調(diào)研分析和設(shè)計(jì)的過(guò)程中也要警惕認(rèn)知偏差的影響,不斷深入了解用戶以及使用科學(xué)的測(cè)試方法來(lái)完善自己的設(shè)計(jì),持續(xù)迭代反思,不因?yàn)槟硞€(gè)方案自己傾注了很多心血,就覺(jué)得它是最好的。用戶可能并不買(mǎi)賬呢。
最近設(shè)計(jì)項(xiàng)目中涉及到「瓷片區(qū)」,于是和一些設(shè)計(jì)伙伴請(qǐng)教了解了一下,在此記錄總結(jié)一下,也希望可以對(duì)大家有些小小的幫助。
聽(tīng)說(shuō):美團(tuán)內(nèi)部將首頁(yè)的運(yùn)營(yíng)廣告位模塊稱為瓷片位,其可以根據(jù)需求變動(dòng)靈活調(diào)整,就像瓷片一樣靈活適用,顧名思義,瓷片區(qū)也就被叫開(kāi)來(lái)了。
根據(jù)下圖我們可以了解到,瓷片區(qū)在產(chǎn)品中的應(yīng)用。
瓷片區(qū)作為與 Banner、金剛區(qū)并行的三大運(yùn)營(yíng)板塊,都負(fù)責(zé)著導(dǎo)流的功能。瓷片區(qū)較兩者更便于在頁(yè)面中進(jìn)行布局,可以靈活復(fù)用。
在電商產(chǎn)品中,導(dǎo)流指的是通過(guò)某種形式,增加對(duì)商品/功能的曝光,使自己的用戶群去購(gòu)買(mǎi)或了解感興趣的商品/功能。導(dǎo)流簡(jiǎn)化流程:導(dǎo)流入口 → 落地頁(yè) → 轉(zhuǎn)化率,設(shè)計(jì)師需要通過(guò)在這個(gè)流程中收集的數(shù)據(jù),進(jìn)行復(fù)盤(pán)反思優(yōu)化設(shè)計(jì)。
瓷片區(qū)屬于運(yùn)營(yíng)區(qū),在頁(yè)面中通常位于用戶容易點(diǎn)擊的區(qū)域。通常為圖文混排,常見(jiàn)的類型有:實(shí)物類、插畫(huà)類。
1. 實(shí)物類
應(yīng)用場(chǎng)景:需要對(duì)商品/服務(wù)有高曝光度的產(chǎn)品類型,如外賣(mài)、電商、旅游類等,通過(guò)對(duì)自有商品/服務(wù)的直觀展示,達(dá)到吸引用戶的目的。
優(yōu)點(diǎn):識(shí)別度高、適配千人千面、元素更換靈活;
缺點(diǎn):圖片質(zhì)量要求較高;
2. 插畫(huà)類
應(yīng)用場(chǎng)景:常見(jiàn)于金融類、虛擬類產(chǎn)品。
優(yōu)點(diǎn):高度概括主題的圖形,通過(guò)插畫(huà)增加產(chǎn)品的調(diào)性和趣味性;
缺點(diǎn):針對(duì)性比較強(qiáng),難復(fù)用,花費(fèi)時(shí)間;
1. 排版
瓷片區(qū)常見(jiàn)排版方式:左右排版、上下排版和對(duì)角線排版。設(shè)計(jì)師可以將三種排版方式組合設(shè)計(jì),使頁(yè)面更具有節(jié)奏感;
2. 圖片
對(duì)于電商或商城類產(chǎn)品來(lái)說(shuō),配圖的好壞是影響用戶點(diǎn)擊率最直觀的元素;設(shè)計(jì)瓷片區(qū)時(shí)需要考慮全局配圖和局部配圖的情況:
3. 文字
4. 背景
瓷片區(qū)背景常見(jiàn)類型:白色/淺色背景、漸變色背景;設(shè)計(jì)師根據(jù)產(chǎn)品調(diào)性及業(yè)務(wù)需求對(duì)背景進(jìn)行靈活使用,但要遵守以下原則:
文中從四點(diǎn)對(duì)瓷片區(qū)進(jìn)行了一個(gè)概括性的了解總結(jié),設(shè)計(jì)要點(diǎn)的話在排版設(shè)計(jì)中都是需要注意的基礎(chǔ)知識(shí)所以未多加贅述,以此為自己在項(xiàng)目中遇到的知識(shí)點(diǎn)做一次沉淀。
文章來(lái)源:優(yōu)設(shè) 作者:木子的小千世界
一轉(zhuǎn)眼,夏天就來(lái)了,設(shè)計(jì)中需要清新又抓人眼球的圖片,老板又要求使用各年齡段都喜歡的插畫(huà)風(fēng)格,應(yīng)用場(chǎng)景要廣,但是預(yù)算又沒(méi)有那么多,該怎么辦呢?這也不是熬夜就能熬出來(lái)的,不要煩惱,下面這個(gè)網(wǎng)站立馬解決你上面所有需求的同時(shí),還能幫助提升你的工作效率,延緩你禿頭的時(shí)間。
這個(gè)創(chuàng)造性超強(qiáng)的插畫(huà)制作網(wǎng)站就是 BLUSH ,你可以根據(jù)自己的想法進(jìn)行元素的替換,也可以直接使用 8 位網(wǎng)站合作設(shè)計(jì)師的現(xiàn)有作品,超清新的顏色和多樣的搭配空間,絕對(duì)會(huì)讓你十分滿意的,無(wú)論是做 Banner、海報(bào)還是用作文章中的插圖都十分合適。最重要的是,可以免費(fèi)商用!接下來(lái)就跟著我一起,走進(jìn)這個(gè)網(wǎng)站吧。
網(wǎng)站鏈接:https://blush.design/
網(wǎng)站內(nèi)擁有 12 大種類的插畫(huà)圖庫(kù),包含人物、城市風(fēng)景、植物、甜點(diǎn)、涂鴉等等。選擇你喜歡或者需要的一類,就可以開(kāi)始你的創(chuàng)作。操作類似于換裝游戲,在各個(gè)你需要改變的地方更換你喜歡的元素就可以。如果你要摸清整個(gè)網(wǎng)站可以產(chǎn)生多少種搭配的話,可能需要花上你不止一天的時(shí)間哦。
從上圖可以看出,單在人物上,網(wǎng)站就提供了不同的風(fēng)格,有像兒童形象的「Friendly ones」,也有極簡(jiǎn)線條的「Big Shoes」,還有夸張超炫的「Power Moves」等等。接下來(lái),為了更好的理解網(wǎng)站提供的服務(wù)和操作的方式,我選取實(shí)用多變的「Croods」來(lái)演示。
首先在欄目左側(cè)選擇「Croods」,就會(huì)看到下面這樣的界面。最上面是設(shè)計(jì)師的作品,下面則是可以由你自由創(chuàng)造作品的入口,造型可以選擇站著或者坐著,場(chǎng)景可以選擇談話、聚會(huì)、公園等等,整體的背景也有五大類供你選擇。
這里我選擇點(diǎn)擊「Peaceful Place」。網(wǎng)站出現(xiàn)的作品很符合現(xiàn)在多數(shù)人在家辦公的狀態(tài),如果你不想自己動(dòng)手,那直接選擇這張圖片或者點(diǎn)擊「Randomiza」再隨機(jī)生成一張圖片,自己滿意之后,點(diǎn)擊「Download」便可以獲取 PNG 格式的圖片,不過(guò),高品質(zhì) PNG 和 SVG 格式則需要付費(fèi)。
當(dāng)然,你也可以通過(guò)改變圖片上的各個(gè)元素,生成你所需要的場(chǎng)景插畫(huà)。例如想要一個(gè)盤(pán)著腿坐在沙發(fā)上發(fā)消息,和朋友聊天聊的很開(kāi)心的一個(gè)形象,就可以通過(guò)下方給予的元素進(jìn)行個(gè)性化定制,把表情改成開(kāi)心,電腦換成手機(jī),右上方替換成聊天框,最后導(dǎo)出為下圖的樣子。如果想要多人的場(chǎng)景,在上一步選擇多人的場(chǎng)景進(jìn)入就可以了。
同時(shí),網(wǎng)站也支持下載插件,方便眾位設(shè)計(jì)師在 Figma 中更好的運(yùn)用。在首頁(yè)點(diǎn)擊右上角的「Get Plugin」進(jìn)入頁(yè)面,注冊(cè)賬號(hào)就可以順利安裝插件。大家可以根據(jù)自己的需要選擇下載插件或者直接在網(wǎng)站上在線制作。
最后,不得不提的一點(diǎn)是,網(wǎng)站圖庫(kù)在兼顧多樣性和平等性上做了很大的努力,人物的膚色可以隨你改變,殘疾人也有一席之地,可以選擇為人物匹配輪椅,或者給人物戴上假肢,涵蓋盡可能多的人物情況和場(chǎng)景。相信這樣的網(wǎng)站一定能滿足你豐富的設(shè)計(jì)需求,快去使用吧!
文字來(lái)源:優(yōu)設(shè) 作者:山楂
在教程開(kāi)始之前,我先說(shuō)一下今天的教程我們會(huì)講哪些部分。首先我們會(huì)分析兒童風(fēng)格的特點(diǎn)、然后在這些特點(diǎn)之上給大家演示繪制一些插畫(huà)小元素。
我們先來(lái)看一下這些海報(bào)里,是不是很容易就能分辨出,哪一個(gè)是關(guān)于兒童主題的畫(huà)面?
可能剛剛的會(huì)比較明顯,那這組是不是也同樣可以分辨出哪一個(gè)兒童感比較強(qiáng)的畫(huà)面??jī)和兴热荒軌蛟谶@些風(fēng)格里凸顯,它一定有一些特點(diǎn)。那么接下來(lái)我會(huì)通過(guò)幾個(gè)方面去分析這些特點(diǎn)。
我們要選用一些符合兒童風(fēng)格的元素。植物是兒童畫(huà)里出現(xiàn)最常用的元素,動(dòng)物作為自然界的一份子,當(dāng)然也非常適合。一些兒童屬性的物品。比如書(shū)本、棒棒糖等。還有天空的云朵、房子這些兒童畫(huà)畫(huà)的時(shí)候經(jīng)常出現(xiàn)的元素,都非常適合兒童畫(huà)面。
但是一些明顯不屬于兒童用品的元素就不合適了。比如說(shuō)口紅,口紅不會(huì)讓人聯(lián)想到兒童,更多是成年女性。骷髏頭這種恐怖的物體也不能出現(xiàn)。
那我問(wèn)一下,眼鏡適合嗎?如果是這種尖銳的眼鏡的話可能不太適合。
但是一旦它的外形變得圓潤(rùn)可愛(ài),就很合適。很多物品也像眼鏡一樣,只要把外形改變得更符合兒童的氣質(zhì),就不會(huì)顯得突兀。
假如某一些物體兒童化特征不明顯,而又想讓它有兒童感,那應(yīng)該怎么做呢?加入表情,表情簡(jiǎn)單可愛(ài),就能表現(xiàn)兒童感的情緒。
每個(gè)物體加上表情就會(huì)變得可愛(ài)。但也正因?yàn)檫@些表情加在了本身沒(méi)有表情的物體上,所以風(fēng)格里有一種搞怪感。
我把隨機(jī)下載的兒童海報(bào)拼接在一起,整體分析它們的特點(diǎn)。
兒童插畫(huà)的海報(bào)元素使用的色相比較多,這里隨機(jī)抽取的海報(bào)里,畫(huà)面都是使用了比較多的顏色,紅、黃、藍(lán)、綠基本都用上了。
在飽和度上都偏高,一般保持在 70% 以上。
明度方面,把畫(huà)面模糊再變黑白,我們可以看到整體畫(huà)面給我們的感覺(jué)是比較亮的,就連中間用了大色塊的海報(bào)的明度也在 50% 以上。而存在的一些深色也是作為畫(huà)面的點(diǎn)綴。
那么總結(jié)起來(lái),一般是色相選取的顏色比較多、飽和度比較高、明度比較高。我們以這張圖為例。
當(dāng)它的顏色種類變少的時(shí)候,畫(huà)面的活潑程度就會(huì)降低。
而飽和度變低后,不僅活潑度降低,這種顏色的風(fēng)格會(huì)趨向于成人化。
畫(huà)面的顏色變深之后,畫(huà)面就沒(méi)有透氣感。有一個(gè)很合適的成語(yǔ)形容,叫「老氣橫秋」。就是缺乏朝氣的感覺(jué)。
那么兒童插畫(huà)的形體有什么特點(diǎn)?總結(jié)起來(lái)有兩個(gè)特點(diǎn),簡(jiǎn)單和隨意。首先兒童對(duì)世界的理解還不夠深,能力也不足,往往畫(huà)岀來(lái)的東西都是以概括的形式。
比如兒童畫(huà)一顆真實(shí)的樹(shù)的時(shí)候,去掉很多細(xì)節(jié),把一個(gè)物體比較有特征的外形表現(xiàn)出來(lái)。比如兒童畫(huà)一顆樹(shù)可能是這樣畫(huà)的。
其次兒童的能力和經(jīng)驗(yàn)不夠,畫(huà)畫(huà)的時(shí)候邊緣都是比較不平滑的,看起來(lái)比較隨意。
而且就算本來(lái)在他眼中是對(duì)稱的物體,因?yàn)槭掷L的感覺(jué)而看起來(lái)歪歪扭扭。
當(dāng)一個(gè)物體簡(jiǎn)單成平滑的幾何形的時(shí)候,它是偏向于設(shè)計(jì)感和現(xiàn)代感的。當(dāng)它越來(lái)越接近于隨意感覺(jué)的時(shí)候,它的兒童特征會(huì)更強(qiáng),同時(shí)更親切。
就像這些作品,雖然是插畫(huà)師畫(huà)的,但是卻有很強(qiáng)的兒童感,就是這種簡(jiǎn)單和隨意再加上插畫(huà)師的審美形成的畫(huà)面。
要注意的是簡(jiǎn)單和隨意的把握,太過(guò)隨意,商業(yè)化的價(jià)值就不高了。
兒童海報(bào)里的插畫(huà)雖然每個(gè)元素比較簡(jiǎn)單隨意,但是要保持畫(huà)面比較完整,是需要很多元素的拼湊的。
就像這個(gè)幼兒園品牌的元素都特別隨意,但是最后呈現(xiàn)的效果卻也不錯(cuò),除了在延伸上花了很多心思之外,還因?yàn)樗脑乇容^多,看起來(lái)不至于太單薄。
而這些元素的擺放可以不遵循嚴(yán)格的透視和邏輯,這種方式體現(xiàn)了兒童繪畫(huà)和成年人嚴(yán)格的繪畫(huà)原理的不同。
能滿足上面的特點(diǎn)的兒童風(fēng)格有很多,在這里我打算用一種比較簡(jiǎn)單的繪制風(fēng)格,來(lái)進(jìn)行操作的演示。
首先我們畫(huà)一顆簡(jiǎn)單的樹(shù),來(lái)看一下這個(gè)風(fēng)格。外形不會(huì)追求非常的對(duì)稱。
就連樹(shù)干我也是用「畫(huà)筆工具」和鼠標(biāo)畫(huà)的。營(yíng)造一種隨意感。
在這里調(diào)整一下最后整體的外形后,我們會(huì)發(fā)現(xiàn)它的邊緣和線條都太順了。沒(méi)有手繪的自然感。
所以我們要用到「變形工具」,對(duì)邊緣進(jìn)行推拉,這樣它的邊緣就不會(huì)特別光滑了。
最后調(diào)整一下尖銳的錨點(diǎn),樹(shù)就這么簡(jiǎn)單地完成了。
大家可能會(huì)覺(jué)得這個(gè)風(fēng)格過(guò)于簡(jiǎn)單了,我用畫(huà)動(dòng)物,去講解一下其中的細(xì)節(jié)。首先還是用「鋼筆工具」,把形體輪廓和主要部位畫(huà)出來(lái)。 大家是不是覺(jué)得畫(huà)到這里就完成了?其實(shí)這個(gè)風(fēng)格比較簡(jiǎn)單,如果沒(méi)有一些裝飾感的細(xì)節(jié)的話就會(huì)顯得太過(guò)隨意了。所以在這只鳥(niǎo)里,要去想怎么添加一些細(xì)節(jié)。
首先可以加個(gè)腮紅。腮紅的顏色不一定是紅的。像鳥(niǎo)的身體色塊面積太大了,需要有裝飾,所以畫(huà)幾條羽毛。羽毛的形狀太過(guò)規(guī)矩了,還是需要轉(zhuǎn)曲用「變形工具」調(diào)整。
還有尾巴的部分也是需要用線的形式讓整體更有細(xì)節(jié)感。最后都是要用「變形工具」讓它的線條有種隨意感。
最后的細(xì)節(jié)在嘴巴上添加,直接畫(huà)一條直線。其實(shí)添加細(xì)節(jié)就是不要出現(xiàn)一整大塊的純色色塊。
對(duì)于物體的簡(jiǎn)化不用太過(guò)于死板,比如我們現(xiàn)在看到的這個(gè)植物,它可以直接簡(jiǎn)化成圓形和密集的點(diǎn)的組合。
一開(kāi)始我是直接用「剪切蒙板」的,但是這樣邊緣過(guò)于光滑了,而且里面的點(diǎn)也被框住,不夠美觀。于是就把點(diǎn)的分布超出圓形一點(diǎn)。這樣看起來(lái)就比較有細(xì)節(jié)了。
而我們通過(guò)改變形體,就可以演變出很多種不一樣的形態(tài)。比如這個(gè)物體,我在做的時(shí)候想能不能把中間的圓縮小一點(diǎn) 。黑色的點(diǎn)占比再大一點(diǎn)。這樣就產(chǎn)生了另外一種植物。
甚至還可以直接去掉中間的圓,把點(diǎn)再放大作為主體。原本的點(diǎn)放大會(huì)變得太過(guò)隨意。所以只能通過(guò)畫(huà)圓形和「變形工具」調(diào)整。
這樣又可以得到不一樣的一顆植物了。這樣的演變可以根據(jù)畫(huà)面的需求選取不一樣的植物。
所以在這里我已經(jīng)畫(huà)好一套常用元素的素材了。以植物動(dòng)物為主,基本能滿足日常設(shè)計(jì)中的需求了。這套素材會(huì)分享給大家,在我們的訂閱號(hào)后臺(tái)回復(fù)「兒童節(jié)素材」就可以下載。這套素材是允許大家商用的。有了素材后,怎么用呢,接下來(lái)我將用這套素材演示它能怎么使用。
這些素材可以在畫(huà)面作為點(diǎn)綴營(yíng)造氣氛。
直接使用這些素材,堆疊成完整的畫(huà)面。
也可以和圖片中的人物或者產(chǎn)品做穿插。
接下來(lái)用一個(gè)案例演示一下,我是怎么用素材的。這個(gè)是學(xué)而思的手機(jī)端海報(bào)的文案,主要有標(biāo)題部分、課程內(nèi)容、和二維碼等。
首先建立一個(gè)手機(jī)端尺寸。設(shè)置好版心的大小。在這里我做的是下方卡片式的結(jié)構(gòu)。(白色色塊部分是海報(bào))
可以先把文案編排進(jìn)來(lái)。首先安排好大的元素,二維碼和活動(dòng)價(jià)格。主講老師和上課時(shí)間的小標(biāo)題,字號(hào)大小要保持一致??ㄆ锏男畔⒕途幣磐炅?。
標(biāo)題是畫(huà)面最大的字號(hào)放在上方,副標(biāo)題和補(bǔ)充信息和大標(biāo)題居中。接下來(lái)就是要在畫(huà)面中添加我們的素材了。那么怎么選擇呢?首先要定好你要選擇的元素范圍,不要同時(shí)出現(xiàn)太多種類的元素。以植物為主、再加上幾個(gè)元素點(diǎn)綴是一般不會(huì)出錯(cuò)的選擇。
首先添加的是面積比較大、塊面化比較明顯的元素。這里就加了三棵簡(jiǎn)單的樹(shù)。
接下來(lái)就是添加一些更有裝飾感的花花草草。
在添加元素的時(shí)候也要注意畫(huà)面點(diǎn)、線、面的結(jié)合。就比如現(xiàn)在我們添加的元素主要是以面和點(diǎn)為主。
雖然樹(shù)的樹(shù)干也有線,但是輪廓的線條太「順」了。
所以要添加「線」的特征更明顯一點(diǎn)的元素。
在畫(huà)面的上方加上適合存在畫(huà)面上方的元素、比如長(zhǎng)頸鹿因?yàn)楸旧肀容^高,所以沒(méi)問(wèn)題。把標(biāo)題移到適合的位置,加蒲公英作為點(diǎn)綴。最后只剩下中間的部分怎么做出和主題相關(guān)聯(lián)的畫(huà)面了。
我們還有一個(gè)信息可以放在人物的手上。最后一個(gè)元素就從海報(bào)的主題出發(fā)。既然是學(xué)習(xí)的內(nèi)容,可以畫(huà)一本書(shū),放在背影上。元素的拼湊完成了,最后就是細(xì)節(jié)的添加。
現(xiàn)在畫(huà)面下方的信息不夠突出,是因?yàn)榭ㄆ捅尘岸际前咨?,所以下方加上一個(gè)深色的色塊,讓信息更顯眼。
突出的信息可以變顏色。
背景變成黃白色,最后加上 logo?,F(xiàn)在畫(huà)面好像完成了,但是我最后還發(fā)現(xiàn)了一個(gè)問(wèn)題,畫(huà)面上的顏色飽和度都很高,各種顏色之間碰撞,看起來(lái)有點(diǎn)透不過(guò)氣的感覺(jué)。
是因?yàn)楫?huà)面缺少淺色。所以我選了兩個(gè)花把它變成白色。
現(xiàn)在這個(gè)素材使用的案例就完成了。
最后要說(shuō)明,這一套素材它只是一種風(fēng)格,我們教程前面有說(shuō)到的任何一個(gè)因素的改變都可以演變成無(wú)數(shù)的風(fēng)格。
比如它的顏色搭配也可以變,變成一種更亮眼的顏色。或者說(shuō)它變得更隨意,有筆觸的自然感。甚至還可以是畫(huà)畫(huà)技法風(fēng)格變化。也可以為每一個(gè)元素都加上眼睛,一種搞怪感就出現(xiàn)了。所以是有無(wú)限的可能性的,最重要的是要學(xué)以致用。
做好畫(huà)面還不夠,我們畫(huà)面選擇的字體也是很重要的,那么我覺(jué)得這幾款字體做得都不錯(cuò)。
文章來(lái)源:優(yōu)設(shè) 作者:研習(xí)設(shè)
什么是圖片懶加載
當(dāng)我們向下滾動(dòng)的時(shí)候圖片資源才被請(qǐng)求到,這也就是我們本次要實(shí)現(xiàn)的效果,進(jìn)入頁(yè)面的時(shí)候,只請(qǐng)求可視區(qū)域的圖片資源這也就是懶加載。
比如我們加載一個(gè)頁(yè)面,這個(gè)頁(yè)面很長(zhǎng)很長(zhǎng),長(zhǎng)到我們的瀏覽器可視區(qū)域裝不下,那么懶加載就是優(yōu)先加載可視區(qū)域的內(nèi)容,其他部分等進(jìn)入了可視區(qū)域在加載。
這個(gè)功能非常常見(jiàn),你打開(kāi)淘寶的首頁(yè),向下滾動(dòng),就會(huì)看到會(huì)有圖片不斷的加載;你在百度中搜索圖片,結(jié)果肯定成千上萬(wàn)條,不可能所有的都一下子加載出來(lái)的,很重要的原因就是會(huì)有性能問(wèn)題。你可以在Network中查看,在頁(yè)面滾動(dòng)的時(shí)候,會(huì)看到圖片一張張加載出來(lái)。
lazyLoad
為什么要做圖片懶加載
懶加載是一種網(wǎng)頁(yè)性能優(yōu)化的方式,它能極大的提升用戶體驗(yàn)。就比如說(shuō)圖片,圖片一直是影響網(wǎng)頁(yè)性能的主要元兇,現(xiàn)在一張圖片超過(guò)幾兆已經(jīng)是很經(jīng)常的事了。如果每次進(jìn)入頁(yè)面就請(qǐng)求所有的圖片資源,那么可能等圖片加載出來(lái)用戶也早就走了。所以,我們需要懶加載,進(jìn)入頁(yè)面的時(shí)候,只請(qǐng)求可視區(qū)域的圖片資源。
總結(jié)出來(lái)就兩個(gè)點(diǎn):
1.全部加載的話會(huì)影響用戶體驗(yàn)
2.浪費(fèi)用戶的流量,有些用戶并不像全部看完,全部加載會(huì)耗費(fèi)大量流量。
懶加載原理
圖片的標(biāo)簽是 img標(biāo)簽,圖片的來(lái)源主要是 src屬性,瀏覽器是否發(fā)起加載圖片的請(qǐng)求是根據(jù)是否有src屬性決定的。
所以可以從 img標(biāo)簽的 src屬性入手,在沒(méi)進(jìn)到可視區(qū)域的時(shí)候,就先不給 img 標(biāo)簽的 src屬性賦值。
懶加載實(shí)現(xiàn)
實(shí)現(xiàn)效果圖:
imgLazyLoad
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
div {
display: flex;
flex-direction: column;
}
img {
width: 100%;
height: 300px;
}
</style>
</head>
<body>
<div>
<img data-src="https://cdn.suisuijiang.com/ImageMessage/5adad39555703565e79040fa_1590657907683.jpeg">
<img data-src="https://cdn.suisuijiang.com/ImageMessage/5adad39555703565e79040fa_1590657913523.jpeg">
<img data-src="https://cdn.suisuijiang.com/ImageMessage/5adad39555703565e79040fa_1590657925550.jpeg">
<img data-src="https://cdn.suisuijiang.com/ImageMessage/5adad39555703565e79040fa_1590657930289.jpeg">
<img data-src="https://cdn.suisuijiang.com/ImageMessage/5adad39555703565e79040fa_1590657934750.jpeg">
<img data-src="https://cdn.suisuijiang.com/ImageMessage/5adad39555703565e79040fa_1590657918315.jpeg">
</div>
</body>
</html>
監(jiān)聽(tīng) scroll 事件判斷元素是否進(jìn)入視口
const imgs = [...document.getElementsByTagName('img')];
let n = 0;
lazyload();
function throttle(fn, wait) {
let timer = null;
return function(...args) {
if(!timer) {
timer = setTimeout(() => {
timer = null;
fn.apply(this, args)
}, wait)
}
}
}
function lazyload() {
var innerHeight = window.innerHeight;
var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
for(let i = n; i < imgs.length; i++) {
if(imgs[i].offsetTop < innerHeight + scrollTop) {
imgs[i].src = imgs[i].getAttribute("data-src");
n = i + 1;
}
}
}
window.addEventListener('scroll', throttle(lazyload, 200));
可能會(huì)存在下面幾個(gè)問(wèn)題:
每次滑動(dòng)都要執(zhí)行一次循環(huán),如果有1000多個(gè)圖片,性能會(huì)很差
每次讀取 scrollTop 都會(huì)引起回流
scrollTop跟DOM的嵌套關(guān)系有關(guān),應(yīng)該根據(jù)getboundingclientrect獲取
滑到最后的時(shí)候刷新,會(huì)看到所有的圖片都加載了
IntersectionObserver
Intersection Observer API提供了一種異步觀察目標(biāo)元素與祖先元素或文檔viewport的交集中的變化的方法。
創(chuàng)建一個(gè) IntersectionObserver對(duì)象,并傳入相應(yīng)參數(shù)和回調(diào)用函數(shù),該回調(diào)函數(shù)將會(huì)在目標(biāo)(target)元素和根(root)元素的交集大小超過(guò)閾值(threshold)規(guī)定的大小時(shí)候被執(zhí)行。
var observer = new IntersectionObserver(callback, options);
IntersectionObserver是瀏覽器原生提供的構(gòu)造函數(shù),接受兩個(gè)參數(shù):callback是可見(jiàn)性變化時(shí)的回調(diào)函數(shù)(即目標(biāo)元素出現(xiàn)在root選項(xiàng)指定的元素中可見(jiàn)時(shí),回調(diào)函數(shù)將會(huì)被執(zhí)行),option是配置對(duì)象(該參數(shù)可選)。
返回的 observer是一個(gè)觀察器實(shí)例。實(shí)例的 observe 方法可以指定觀察哪個(gè)DOM節(jié)點(diǎn)。
具體的用法可以 查看 MDN文檔
const imgs = [...document.getElementsByTagName('img')];
// 當(dāng)監(jiān)聽(tīng)的元素進(jìn)入可視范圍內(nèi)的會(huì)觸發(fā)回調(diào)
if(IntersectionObserver) {
// 創(chuàng)建一個(gè) intersection observer
let lazyImageObserver = new IntersectionObserver((entries, observer) => {
entries.forEach((entry, index) => {
let lazyImage = entry.target;
// 相交率,默認(rèn)是相對(duì)于瀏覽器視窗
if(entry.intersectionRatio > 0) {
lazyImage.src = lazyImage.getAttribute('data-src');
// 當(dāng)前圖片加載完之后需要去掉監(jiān)聽(tīng)
lazyImageObserver.unobserve(lazyImage);
}
})
})
for(let i = 0; i < imgs.length; i++) {
lazyImageObserver.observe(imgs[i]);
}
}
源碼地址-codePen點(diǎn)擊預(yù)覽
vue自定義指令-懶加載
Vue自定義指令
下面的api來(lái)自官網(wǎng)自定義指令:
鉤子函數(shù)
bind: 只調(diào)用一次,指令第一次綁定到元素時(shí)調(diào)用。在這里可以進(jìn)行一次性的初始化設(shè)置。
inserted: 被綁定元素插入父節(jié)點(diǎn)時(shí)調(diào)用 (僅保證父節(jié)點(diǎn)存在,但不一定已被插入文檔中)。
update: 所在組件的 VNode 更新時(shí)調(diào)用,但是可能發(fā)生在其子 VNode 更新之前。指令的值可能發(fā)生了改變,也可能沒(méi)有。但是你可以通過(guò)比較更新前后的值來(lái)忽略不必要的模板更新
componentUpdated: 指令所在組件的 VNode 及其子 VNode 全部更新后調(diào)用。
unbind: 只調(diào)用一次,指令與元素解綁時(shí)調(diào)用。
鉤子函數(shù)參數(shù)
指令鉤子函數(shù)會(huì)被傳入以下參數(shù):
el:指令所綁定的元素,可以用來(lái)直接操作 DOM。
binding:一個(gè)對(duì)象,包含以下 property:
name:指令名,不包括 v- 前綴。
value:指令的綁定值,例如:v-my-directive="1 + 1" 中,綁定值為 2。
oldValue:指令綁定的前一個(gè)值,僅在 update 和 componentUpdated 鉤子中可用。無(wú)論值是否改變都可用。
expression:字符串形式的指令表達(dá)式。例如 v-my-directive="1 + 1" 中,表達(dá)式為 "1 + 1"。
arg:傳給指令的參數(shù),可選。例如 v-my-directive:foo 中,參數(shù)為 "foo"。
modifiers:一個(gè)包含修飾符的對(duì)象。例如:v-my-directive.foo.bar 中,修飾符對(duì)象為 { foo: true, bar: true }。
vnode:Vue 編譯生成的虛擬節(jié)點(diǎn)。
oldVnode:上一個(gè)虛擬節(jié)點(diǎn),僅在 update 和 componentUpdated 鉤子中可用。
實(shí)現(xiàn) v-lazyload 指令
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
img {
width: 100%;
height: 300px;
}
</style>
</head>
<body>
<div id="app">
<p v-for="item in imgs" :key="item">
<img v-lazyload="item">
</p>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
Vue.directive("lazyload", {
// 指令的定義
bind: function(el, binding) {
可視化是利用計(jì)算機(jī)圖形學(xué)和圖像處理技術(shù),將數(shù)據(jù)轉(zhuǎn)換成圖形或圖像在屏幕上顯示出來(lái),再進(jìn)行交互處理的理論、方法和技術(shù)。面對(duì)醫(yī)療行業(yè),如何將行業(yè)數(shù)據(jù),轉(zhuǎn)化為視覺(jué)可視化中的點(diǎn)線面,是在這個(gè)項(xiàng)目中需要思考的問(wèn)題。
本文將帶來(lái)設(shè)計(jì)師在醫(yī)療院感可視化項(xiàng)目中的設(shè)計(jì)過(guò)程及思考,講述如何在業(yè)務(wù)場(chǎng)景下對(duì)數(shù)據(jù)進(jìn)行抽取表達(dá)。通過(guò)可視化打破傳統(tǒng)院感系統(tǒng)的表單呈現(xiàn),使院感場(chǎng)景具備互動(dòng)性、觀賞性,滿足不同角色的使用需求。同時(shí)院感醫(yī)生通過(guò)可視化的解決方案能清晰直觀的了解到院感發(fā)生分布、病例分析,從而控制院感發(fā)生和預(yù)防。
本項(xiàng)目以浙江省建德市第一人民醫(yī)院為案例,地理數(shù)據(jù)以建德醫(yī)院坐標(biāo)為準(zhǔn)。
項(xiàng)目背景
院感是什么?院感為醫(yī)院感染,入院48小時(shí)內(nèi)都有可能感染到院感細(xì)菌。在醫(yī)院里有專門(mén)的院感醫(yī)生職位,對(duì)醫(yī)院感染進(jìn)行有效的預(yù)防與控制。而傳統(tǒng)院感管理的工作流:醫(yī)護(hù)人員及院感醫(yī)生 > 院感系統(tǒng)分析疑似病例 > 得出結(jié)論預(yù)防或治療。這種偏人工的方式數(shù)據(jù)獲取方式,無(wú)法更的獲取院感發(fā)生的原因、定位、以及未來(lái)的院感預(yù)測(cè)。
P1 因此我們通過(guò)對(duì)醫(yī)院數(shù)據(jù)的整理,抽離出影響院感的數(shù)據(jù),將院感發(fā)生、發(fā)展、管控、治療、預(yù)測(cè)全流程進(jìn)行整合。
P2 通過(guò)醫(yī)院>樓層>人員三個(gè)層面,空間和時(shí)間兩個(gè)維度對(duì)院感展示。打破傳統(tǒng)院感系統(tǒng)的表單呈現(xiàn),使院感場(chǎng)景具備互動(dòng)性、觀賞性,滿足不同角色的使用需求:如院長(zhǎng)的展示性需求。院感醫(yī)生通過(guò)可視化的解決方案能清晰直觀的了解到院感發(fā)生分布、病例分析,從而控制院感發(fā)生和預(yù)防。
P3 同時(shí)在這樣的設(shè)計(jì)場(chǎng)景下,可以覆蓋的醫(yī)療業(yè)務(wù)場(chǎng)景和數(shù)據(jù)單位也會(huì)更多元,具有一定的商業(yè)化價(jià)值。
P4 設(shè)計(jì)流程
整個(gè)項(xiàng)目的設(shè)計(jì)流程可以分為4個(gè)階段:信息收集、可視化、線上搭建、效果調(diào)試。在此項(xiàng)目實(shí)踐中,重點(diǎn)投入在前三大部分。
P5 Part1信息收集
我們基于項(xiàng)目背景,梳理要展現(xiàn)的數(shù)據(jù)指標(biāo),對(duì)整體業(yè)務(wù)場(chǎng)景進(jìn)行故事腳本的規(guī)劃(即如何展現(xiàn)前期的數(shù)據(jù)收集,并把其串聯(lián)在整體業(yè)務(wù)場(chǎng)景中),設(shè)定動(dòng)作攝像機(jī)語(yǔ)言,同時(shí)也需要了解最終呈現(xiàn)的硬件設(shè)備與使用環(huán)境。
P6 Part2可視化
1.交互信息框架
首先梳理院感的信息框架和交互方式。
整個(gè)大屏分為院樓層,呈現(xiàn)整體院感數(shù)據(jù)的統(tǒng)計(jì);樓層屏,作為重點(diǎn)病區(qū)的監(jiān)測(cè)預(yù)測(cè);個(gè)人屏,分析病例回溯病程,從而預(yù)測(cè)院感。三屏之間相互跳轉(zhuǎn), 交互演示方式從醫(yī)院的外部跳轉(zhuǎn)內(nèi)部結(jié)構(gòu)、再到患者的個(gè)人維度,三屏都分別展示相關(guān)的數(shù)據(jù)指標(biāo)。
P7 2.視覺(jué)風(fēng)格
在大屏視效風(fēng)格探索上,期初的目標(biāo)是希望可以打造不一樣行業(yè)視覺(jué)語(yǔ)言,所以選擇不同于以往的設(shè)計(jì)大屏風(fēng)格,選擇白色的風(fēng)格,符合大家對(duì)醫(yī)護(hù)行業(yè)的認(rèn)知。但到中期發(fā)現(xiàn),在硬件設(shè)備上展示發(fā)是過(guò)曝的。因此對(duì)設(shè)計(jì)風(fēng)格進(jìn)行調(diào)整改為X光片的風(fēng)格,色系上偏冷綠的感覺(jué)。這是在這個(gè)項(xiàng)目中的試錯(cuò)經(jīng)驗(yàn)之一。
P8 3.建模設(shè)計(jì)
在可視化部分中遇到的難點(diǎn):建筑模型的高還原。下圖為建德第一人民醫(yī)院實(shí)拍圖。在大屏項(xiàng)目中,必須真實(shí)還原地理位置。而在此醫(yī)院沒(méi)有清晰的CAD圖紙?zhí)峁┑?;在Google的衛(wèi)星地圖下也沒(méi)有的建筑結(jié)構(gòu)的,所以我在建模的過(guò)程中,是踩了坑的,先盲畫(huà)了一版,但是精細(xì)度不夠,過(guò)于粗糙。
P9 因此我反復(fù)看得到的資料,通過(guò)在確定地理氛圍內(nèi),去豐富場(chǎng)景。這樣的好處是使業(yè)務(wù)場(chǎng)景更加豐富,包括擴(kuò)展到院外的車(chē)流數(shù)據(jù),為業(yè)務(wù)場(chǎng)景提供更多可能性 當(dāng)然后期也搖到了建筑內(nèi)部的消防圖,根據(jù)消防圖繪制內(nèi)部結(jié)構(gòu)。
P10 4.數(shù)據(jù)面板
對(duì)可視化組件的組件進(jìn)行設(shè)計(jì):時(shí)間篩選、數(shù)據(jù)統(tǒng)計(jì)、占比關(guān)系、趨勢(shì)分析。設(shè)計(jì)之前也參考了很多概念版的可視化設(shè)計(jì),希望在院感屏上可以呈現(xiàn)一種科技概念的感覺(jué)。
P11 Part3線上搭建
1.獲取地理數(shù)據(jù)
這部分是非常耗時(shí)的,datav是數(shù)據(jù)驅(qū)動(dòng)的可視化產(chǎn)品,在搭建部分,是全程依靠datav平臺(tái)的。
首先需要明確地理數(shù)據(jù),通過(guò)高德數(shù)據(jù)通過(guò)點(diǎn)線成面,可以作為場(chǎng)景定位,也就是物理模型的經(jīng)緯度數(shù)據(jù) 后面還原數(shù)據(jù)效果,造虛擬數(shù)據(jù),是非常依賴于這個(gè)坐標(biāo)數(shù)據(jù)的。
119.291724 , 29.472365
這是建德醫(yī)院的坐標(biāo),醫(yī)院在地圖上的數(shù)據(jù)是很簡(jiǎn)化的,顆粒度很大,具體位置無(wú)法顯示。
P12 因此我們需要建立與地理數(shù)據(jù)綁定的建模,先對(duì)位置。
P13 在這個(gè)過(guò)程中我發(fā)現(xiàn),如果最開(kāi)始沒(méi)有對(duì)準(zhǔn)位置,也不用緊張,可以在DATAV平臺(tái)增加hook數(shù)據(jù)過(guò)濾器,解決地理數(shù)據(jù)與世界坐標(biāo)無(wú)法對(duì)齊的問(wèn)題。
2.線上場(chǎng)景還原
根據(jù)對(duì)確定過(guò)位置模型進(jìn)行烘焙還原。這個(gè)過(guò)程中遇到了一些不知名的原因烘焙失敗,原因可能是命名有中文/位置數(shù)據(jù)錯(cuò)誤/模型塊面復(fù)雜等,遇到這樣的問(wèn)題就需要重新從頭檢查烘焙流程每一步。
P14 3.數(shù)據(jù)維度展示還原
這一步我們需要把前期做好的數(shù)據(jù)可視化效果,還原到線上模型中。在這一步我遇到的問(wèn)題是因建德醫(yī)院內(nèi)部具體結(jié)構(gòu)的缺失,使一些可視化效果無(wú)法精準(zhǔn)匹配到模型上。所以設(shè)計(jì)過(guò)程中只能依賴于在對(duì)的地理位置上豐富的場(chǎng)景內(nèi)造數(shù)據(jù),這個(gè)過(guò)程是比較吃力的。
P15 這個(gè)問(wèn)題的解決辦法是通過(guò)開(kāi)發(fā)工具和導(dǎo)出的結(jié)構(gòu)俯視圖,對(duì)位置,然后轉(zhuǎn)化出LEGO的數(shù)據(jù)
P16 在數(shù)據(jù)效果還原的過(guò)程中,也發(fā)現(xiàn)我在前期設(shè)計(jì)的數(shù)據(jù)效果,不能全部實(shí)現(xiàn),有些是依賴于開(kāi)發(fā)的 。這時(shí)可以通過(guò)其他組件效果代替嘗試,比如熱力的效果用粒子放大,通過(guò)參數(shù)調(diào)節(jié)得到熱力 再比如局部房間的掃管,通過(guò)設(shè)計(jì)部分多次烘焙模型,不斷疊加掃光層,得到房間監(jiān)測(cè)的效果
P17 設(shè)計(jì)小結(jié)
綜合以上的經(jīng)驗(yàn),院感可視化從設(shè)計(jì)到落地,整體結(jié)構(gòu)應(yīng)該是這樣從物理基礎(chǔ)坐標(biāo)的獲取、到場(chǎng)景搭建、再到數(shù)據(jù)展示的過(guò)程。在這個(gè)過(guò)程中會(huì)用到DATAV、C4D、數(shù)據(jù)庫(kù)、簡(jiǎn)單的代碼等技術(shù)來(lái)實(shí)現(xiàn)。
P18 這個(gè)項(xiàng)目雖然這只是醫(yī)療行業(yè)中一個(gè)小的業(yè)務(wù)場(chǎng)景,但我們的業(yè)務(wù)數(shù)據(jù)提取及可視化設(shè)計(jì)思路,他不僅限于醫(yī)療行業(yè),同時(shí)也可以成為場(chǎng)館類大屏解決方案的一部分,是具有一定商業(yè)化價(jià)值的。同時(shí)在這過(guò)程中沉淀下來(lái)的人體結(jié)構(gòu)模型,和一些設(shè)計(jì)經(jīng)驗(yàn),是可以復(fù)用到對(duì)應(yīng)行業(yè)解決方案中,達(dá)到提效。
轉(zhuǎn)自:
火車(chē)車(chē)次
/^[GCDZTSPKXLY1-9]\d{1,4}$/
手機(jī)機(jī)身碼(IMEI)
/^\d{15,17}$/
必須帶端口號(hào)的網(wǎng)址(或ip)
/^((ht|f)tps?:\/\/)?[\w-]+(\.[\w-]+)+:\d{1,5}\/?$/
網(wǎng)址(url,支持端口和"?+參數(shù)"和"#+參數(shù))
/^(((ht|f)tps?):\/\/)?[\w-]+(\.[\w-]+)+([\w.,@?^=%&:\/~+#-]*[\w@?^=%&\/~+#-])?$/
統(tǒng)一社會(huì)信用代碼
/^[0-9A-HJ-NPQRTUWXY]{2}\d{6}[0-9A-HJ-NPQRTUWXY]{10}$/
迅雷鏈接
/^thunderx?:\/\/[a-zA-Z\d]+=$/
ed2k鏈接(寬松匹配)
/^ed2k:\/\/\|file\|.+\|\/$/
磁力鏈接(寬松匹配)
/^magnet:\?xt=urn:btih:[0-9a-fA-F]{40,}.*$/
子網(wǎng)掩碼
/^(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])(?:\.(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])){3}$/
linux"隱藏文件"路徑
/^\/(?:[^\/]+\/)*\.[^\/]*/
linux文件夾路徑
/^\/(?:[^\/]+\/)*$/
linux文件路徑
/^\/(?:[^\/]+\/)*[^\/]+$/
window"文件夾"路徑
/^[a-zA-Z]:\\(?:\w+\\?)*$/
window下"文件"路徑
/^[a-zA-Z]:\\(?:\w+\\)*\w+\.\w+$/
股票代碼(A股)
/^(s[hz]|S[HZ])(000[\d]{3}|002[\d]{3}|300[\d]{3}|600[\d]{3}|60[\d]{4})$/
大于等于0, 小于等于150, 支持小數(shù)位出現(xiàn)5, 如145.5, 用于判斷考卷分?jǐn)?shù)
/^150$|^(?:\d|[1-9]\d|1[0-4]\d)(?:.5)?$/
html注釋
/^<!--[\s\S]*?-->$/
md5格式(32位)
/^([a-f\d]{32}|[A-F\d]{32})$/
版本號(hào)(version)格式必須為X.Y.Z
/^\d+(?:\.\d+){2}$/
視頻(video)鏈接地址(視頻格式可按需增刪)
/^https?:\/\/(.+\/)+.+(\.(swf|avi|flv|mpg|rm|mov|wav|asf|3gp|mkv|rmvb|mp4))$/i
圖片(image)鏈接地址(圖片格式可按需增刪)
/^https?:\/\/(.+\/)+.+(\.(gif|png|jpg|jpeg|webp|svg|psd|bmp|tif))$/i
24小時(shí)制時(shí)間(HH:mm:ss)
/^(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d$/
12小時(shí)制時(shí)間(hh:mm:ss)
/^(?:1[0-2]|0?[1-9]):[0-5]\d:[0-5]\d$/
base64格式
/^\s*data:(?:[a-z]+\/[a-z0-9-+.]+(?:;[a-z-]+=[a-z0-9-]+)?)?(?:;base64)?,([a-z0-9!$&',()*+;=\-._~:@\/?%\s]*?)\s*$/i
數(shù)字/貨幣金額(支持負(fù)數(shù)、千分位分隔符)
/^-?\d+(,\d{3})*(\.\d{1,2})?$/
數(shù)字/貨幣金額 (只支持正數(shù)、不支持校驗(yàn)千分位分隔符)
/(?:^[1-9]([0-9]+)?(?:\.[0-9]{1,2})?$)|(?:^(?:0){1}$)|(?:^[0-9]\.[0-9](?:[0-9])?$)/
銀行卡號(hào)(10到30位, 覆蓋對(duì)公/私賬戶, 參考微信支付)
/^[1-9]\d{9,29}$/
中文姓名
/^(?:[\u4e00-\u9fa5·]{2,16})$/
英文姓名
/(^[a-zA-Z]{1}[a-zA-Z\s]{0,20}[a-zA-Z]{1}$)/
車(chē)牌號(hào)(新能源)
/[京津滬渝冀豫云遼黑湘皖魯新蘇浙贛鄂桂甘晉蒙陜吉閩貴粵青藏川寧瓊使領(lǐng) A-Z]{1}[A-HJ-NP-Z]{1}(([0-9]{5}[DF])|([DF][A-HJ-NP-Z0-9][0-9]{4}))$/
車(chē)牌號(hào)(非新能源)
/^[京津滬渝冀豫云遼黑湘皖魯新蘇浙贛鄂桂甘晉蒙陜吉閩貴粵青藏川寧瓊使領(lǐng) A-Z]{1}[A-HJ-NP-Z]{1}[A-Z0-9]{4}[A-Z0-9掛學(xué)警港澳]{1}$/
車(chē)牌號(hào)(新能源+非新能源)
/^(?:[京津滬渝冀豫云遼黑湘皖魯新蘇浙贛鄂桂甘晉蒙陜吉閩貴粵青藏川寧瓊使領(lǐng) A-Z]{1}[A-HJ-NP-Z]{1}(?:(?:[0-9]{5}[DF])|(?:[DF](?:[A-HJ-NP-Z0-9])[0-9]{4})))|(?:[京津滬渝冀豫云遼黑湘皖魯新蘇浙贛鄂桂甘晉蒙陜吉閩貴粵青藏川寧瓊使領(lǐng) A-Z]{1}[A-Z]{1}[A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9 掛學(xué)警港澳]{1})$/
手機(jī)號(hào)(mobile phone)中國(guó)(嚴(yán)謹(jǐn)), 根據(jù)工信部2019年公布的手機(jī)號(hào)段
/^(?:(?:\+|00)86)?1(?:(?:3[\d])|(?:4[5-7|9])|(?:5[0-3|5-9])|(?:6[5-7])|(?:7[0-8])|(?:8[\d])|(?:9[1|8|9]))\d{8}$/
手機(jī)號(hào)(mobile phone)中國(guó)(寬松), 只要是13,14,15,16,17,18,19開(kāi)頭即可
/^(?:(?:\+|00)86)?1[3-9]\d{9}$/
手機(jī)號(hào)(mobile phone)中國(guó)(最寬松), 只要是1開(kāi)頭即可, 如果你的手機(jī)號(hào)是用來(lái)接收短信, 優(yōu)先建議選擇這一條
/^(?:(?:\+|00)86)?1\d{10}$/
date(日期)
/^\d{4}(-)(1[0-2]|0?\d)\1([0-2]\d|\d|30|31)$/
email(郵箱)
/^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/
座機(jī)(tel phone)電話(國(guó)內(nèi)),如: 0341-86091234
/^\d{3}-\d{8}$|^\d{4}-\d{7}$/
身份證號(hào)(1代,15位數(shù)字)
/^[1-9]\d{7}(?:0\d|10|11|12)(?:0[1-9]|[1-2][\d]|30|31)\d{3}$/
身份證號(hào)(2代,18位數(shù)字),最后一位是校驗(yàn)位,可能為數(shù)字或字符X
/^[1-9]\d{5}(?:18|19|20)\d{2}(?:0\d|10|11|12)(?:0[1-9]|[1-2]\d|30|31)\d{3}[\dXx]$/
身份證號(hào), 支持1/2代(15位/18位數(shù)字)
/(^\d{8}(0\d|10|11|12)([0-2]\d|30|31)\d{3}$)|(^\d{6}(18|19|20)\d{2}(0\d|10|11|12)([0-2]\d|30|31)\d{3}(\d|X|x)$)/
護(hù)照(包含香港、澳門(mén))
/(^[EeKkGgDdSsPpHh]\d{8}$)|(^(([Ee][a-fA-F])|([DdSsPp][Ee])|([Kk][Jj])|([Mm][Aa])|(1[45]))\d{7}$)/
帳號(hào)是否合法(字母開(kāi)頭,允許5-16字節(jié),允許字母數(shù)字下劃線組合
/^[a-zA-Z]\w{4,15}$/
中文/漢字
/^(?:[\u3400-\u4DB5\u4E00-\u9FEA\uFA0E\uFA0F\uFA11\uFA13\uFA14\uFA1F\uFA21\uFA23\uFA24\uFA27-\uFA29]|[\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0])+$/
小數(shù)
/^\d+\.\d+$/
數(shù)字
/^\d{1,}$/
html標(biāo)簽(寬松匹配)
/<(\w+)[^>]*>(.*?<\/\1>)?/
qq號(hào)格式正確
/^[1-9][0-9]{4,10}$/
數(shù)字和字母組成
/^[A-Za-z0-9]+$/
英文字母
/^[a-zA-Z]+$/
小寫(xiě)英文字母組成
/^[a-z]+$/
大寫(xiě)英文字母
/^[A-Z]+$/
密碼強(qiáng)度校驗(yàn),最少6位,包括至少1個(gè)大寫(xiě)字母,1個(gè)小寫(xiě)字母,1個(gè)數(shù)字,1個(gè)特殊字符
/^\S*(?=\S{6,})(?=\S*\d)(?=\S*[A-Z])(?=\S*[a-z])(?=\S*[!@#$%^&*? ])\S*$/
用戶名校驗(yàn),4到16位(字母,數(shù)字,下劃線,減號(hào))
/^[a-zA-Z0-9_-]{4,16}$/
ip-v4
/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/
ip-v6
/^((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(([0-9A-Fa-f]{1,4}:){0,5}:((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(::([0-9A-Fa-f]{1,4}:){0,5}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:))$/i
16進(jìn)制顏色
/^#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/
微信號(hào)(wx),6至20位,以字母開(kāi)頭,字母,數(shù)字,減號(hào),下劃線
/^[a-zA-Z][-_a-zA-Z0-9]{5,19}$/
郵政編碼(中國(guó))
/^(0[1-7]|1[0-356]|2[0-7]|3[0-6]|4[0-7]|5[1-7]|6[1-7]|7[0-5]|8[013-6])\d{4}$/
中文和數(shù)字
/^((?:[\u3400-\u4DB5\u4E00-\u9FEA\uFA0E\uFA0F\uFA11\uFA13\uFA14\uFA1F\uFA21\uFA23\uFA24\uFA27-\uFA29]|[\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0])|(\d))+$/
不能包含字母
/^[^A-Za-z]*$/
java包名
/^([a-zA-Z_][a-zA-Z0-9_]*)+([.][a-zA-Z_][a-zA-Z0-9_]*)+$/
mac地址
/^((([a-f0-9]{2}:){5})|(([a-f0-9]{2}-){5}))[a-f0-9]{2}$/i
使用 vue-router 的導(dǎo)航守衛(wèi)鉤子函數(shù),某些鉤子函數(shù)可以讓開(kāi)發(fā)者根據(jù)業(yè)務(wù)邏輯,控制是否進(jìn)行下一步,或者進(jìn)入到指定的路由。
例如,后臺(tái)管理頁(yè)面,會(huì)在進(jìn)入路由前,進(jìn)行必要登錄、權(quán)限判斷,來(lái)決定去往哪個(gè)路由,以下是偽代碼:
// 全局導(dǎo)航守衛(wèi)
router.beforEach((to, from, next) => {
if('no login'){
next('/login')
}else if('admin') {
next('/admin')
}else {
next()
}
})
// 路由配置鉤子函數(shù)
{
path: '',
component: component,
beforeEnter: (to, from, next) => {
next()
}
}
// 組件中配置鉤子函數(shù)
{
template: '',
beforeRouteEnter(to, from, next) {
next()
}
}
調(diào)用 next,意味著繼續(xù)進(jìn)行下面的流程;不調(diào)用,則直接終止,導(dǎo)致路由中設(shè)置的組件無(wú)法渲染,會(huì)出現(xiàn)頁(yè)面一片空白的現(xiàn)象。
鉤子函數(shù)有不同的作用,例如 beforEach,afterEach,beforeEnter,beforeRouteEnter,beforeRouteUpdate,beforeRouteLeave,針對(duì)這些注冊(cè)的鉤子函數(shù),要依次進(jìn)行執(zhí)行,并且在必要環(huán)節(jié)有控制權(quán)決定是否繼續(xù)進(jìn)入到下一個(gè)鉤子函數(shù)中。
以下分析下源碼中實(shí)現(xiàn)的方式,而源碼中處理的邊界情況比較多,需要抓住核心點(diǎn),去掉冗余代碼,精簡(jiǎn)出便于理解的實(shí)現(xiàn)。
精簡(jiǎn)源碼核心功能
總結(jié)下核心點(diǎn):鉤子函數(shù)注冊(cè)的回調(diào)函數(shù),能順序執(zhí)行,同時(shí)會(huì)將控制權(quán)交給開(kāi)發(fā)者。
先來(lái)一個(gè)能夠注冊(cè)回調(diào)函數(shù)的類:
class VueRouter {
constructor(){
this.beforeHooks = []
this.beforeEnterHooks = []
this.afterHooks = []
}
beforEach(callback){
return registerHook(this.beforeHooks, callback)
}
beforeEnter(callback){
return registerHook(this.beforeEnterHooks, callback)
}
afterEach(callback){
return registerHook(this.afterHooks, callback)
}
}
function registerHook (list, fn) {
list.push(fn)
return () => {
const i = list.indexOf(fn)
if (i > -1) list.splice(i, 1)
}
}
聲明的類,提供了 beforEach 、beforeEnter 和 afterEach 來(lái)注冊(cè)必要的回調(diào)函數(shù)。
抽象出一個(gè) registerHook 公共方法,作用:
注冊(cè)回調(diào)函數(shù)
返回的函數(shù),可以取消注冊(cè)的回調(diào)函數(shù)
使用一下:
const router = new VueRouter()
const beforEach = router.beforEach((to, from, next) => {
console.log('beforEach');
next()
})
// 取消注冊(cè)的函數(shù)
beforEach()
以上的回調(diào)函數(shù)會(huì)被取消,意味著不會(huì)執(zhí)行了。
router.beforEach((to, from, next) => {
console.log('beforEach');
next()
})
router.beforeEnter((to, from, next) => {
console.log('beforeEnter');
next()
})
router.afterEach(() => {
console.log('afterEach');
})
以上注冊(cè)的鉤子函數(shù)會(huì)依次執(zhí)行。beforEach 和 beforeEnter 的回調(diào)接收內(nèi)部傳來(lái)的參數(shù),同時(shí)通過(guò)調(diào)用 next 可繼續(xù)走下面的回調(diào)函數(shù),如果不調(diào)用,則直接被終止了。
最后一個(gè) afterEach 在上面的回調(diào)函數(shù)都執(zhí)行后,才被執(zhí)行,且不接收任何參數(shù)。
先來(lái)實(shí)現(xiàn)依次執(zhí)行,這是最簡(jiǎn)單的方式,在類中增加 run 方法,手動(dòng)調(diào)用:
class VueRouter {
// ... 其他省略,增加 run 函數(shù)
run(){
// 把需要依次執(zhí)行的回調(diào)存放在一個(gè)隊(duì)列中
let queue = [].concat(
this.beforeHooks,
this.afterHooks
)
for(let i = 0; i < queue.length; i++){
if(queue(i)) {
queue(i)('to', 'from', () => {})
}
}
}
}
// 手動(dòng)調(diào)用
router.run()
打印:
'beforEach'
'beforeEnter'
上面把要依次執(zhí)行的回調(diào)函數(shù)聚合在一個(gè)隊(duì)列中執(zhí)行,并傳入必要的參數(shù),但這樣開(kāi)發(fā)者不能控制是否進(jìn)行下一步,即便不執(zhí)行 next 函數(shù),依然會(huì)依次執(zhí)行完隊(duì)列的函數(shù)。
改進(jìn)一下:
class VueRouter {
// ... 其他省略,增加 run 函數(shù)
run(){
// 把需要依次執(zhí)行的回調(diào)存放在一個(gè)隊(duì)列中
let queue = [].concat(
this.beforeHooks,
this.afterHooks
)
queue[0]('to', 'from', () => {
queue[1]('to', 'from', () => {
console.log('調(diào)用結(jié)束');
})
})
}
}
router.beforEach((to, from, next) => {
console.log('beforEach');
// next()
})
router.beforeEnter((to, from, next) => {
console.log('beforeEnter');
next()
})
傳入的 next 函數(shù)會(huì)有調(diào)用下一個(gè)回調(diào)函數(shù)的行為,把控制權(quán)交給了開(kāi)發(fā)者,調(diào)用了 next 函數(shù)會(huì)繼續(xù)執(zhí)行下一個(gè)回調(diào)函數(shù);不調(diào)用 next 函數(shù),則終止了隊(duì)列的執(zhí)行,所以打印結(jié)果是:
'beforEach'
上面實(shí)現(xiàn)有個(gè)弊端,代碼不夠靈活,手動(dòng)一個(gè)個(gè)調(diào)用,在真實(shí)場(chǎng)景中無(wú)法確定注冊(cè)了多少個(gè)回調(diào)函數(shù),所以需要繼續(xù)抽象成一個(gè)功能更強(qiáng)的方法:
function runQueue (queue, fn, cb) {
const step = index => {
// 隊(duì)列執(zhí)行結(jié)束了
if (index >= queue.length) {
cb()
} else {
// 隊(duì)列有值
if (queue[index]) {
// 傳入隊(duì)列中回調(diào),做一些必要的操作,第二個(gè)參數(shù)是為了進(jìn)行下一個(gè)回調(diào)函數(shù)
fn(queue[index], () => {
step(index + 1)
})
} else {
step(index + 1)
}
}
}
// 初次調(diào)用,從第一個(gè)開(kāi)始
step(0)
}
runQueue 就是執(zhí)行隊(duì)列的通用方法。
第一個(gè)參數(shù)為回調(diào)函數(shù)隊(duì)列, 會(huì)依次取出來(lái);
第二個(gè)參數(shù)是函數(shù),它接受隊(duì)列中的函數(shù),進(jìn)行一些其他處理;并能進(jìn)行下個(gè)回調(diào)函數(shù)的執(zhí)行;
第三個(gè)參數(shù)是隊(duì)列執(zhí)行結(jié)束后調(diào)用。
知道了這個(gè)函數(shù)的含義,來(lái)使用一下:
class VueRouter {
// ... 其他省略,增加 run 函數(shù)
run(){
// 把需要依次執(zhí)行的回調(diào)存放在一個(gè)隊(duì)列中
let queue = [].concat(
this.beforeHooks,
this.beforeEnterHooks
)
// 接收回到函數(shù),和進(jìn)行下一個(gè)的執(zhí)行函數(shù)
const iterator = (hook, next) => {
// 傳給回調(diào)函數(shù)的參數(shù),第三個(gè)參數(shù)是函數(shù),交給開(kāi)發(fā)者調(diào)用,調(diào)用后進(jìn)行下一個(gè)
hook('to', 'from', () => {
console.log('執(zhí)行下一個(gè)回調(diào)時(shí),處理一些相關(guān)信息');
next()
})
}
runQueue(queue, iterator, () => {
console.log('執(zhí)行結(jié)束');
// 執(zhí)行 afterEach 中的回調(diào)函數(shù)
this.afterHooks.forEach((fn) => {
fn()
})
})
}
}
// 注冊(cè)
router.beforEach((to, from, next) => {
console.log('beforEach');
next()
})
router.beforeEnter((to, from, next) => {
console.log('beforeEnter');
next()
})
router.afterEach(() => {
console.log('afterEach');
})
router.run();
從上面代碼可以看出來(lái),每次把隊(duì)列 queue 中的回調(diào)函數(shù)傳給 iterator , 用 hook 接收,并調(diào)用。
傳給 hook 必要的參數(shù),尤其是第三個(gè)參數(shù),開(kāi)發(fā)者在注冊(cè)的回調(diào)函數(shù)中調(diào)用,來(lái)控制進(jìn)行下一步。
在隊(duì)列執(zhí)行完畢后,依次執(zhí)行 afterHooks 的回調(diào)函數(shù),不傳入任何參數(shù)。
所以打印結(jié)果為:
beforEach
執(zhí)行下一個(gè)回調(diào)時(shí),處理一些相關(guān)信息
beforeEnter
執(zhí)行下一個(gè)回調(diào)時(shí),處理一些相關(guān)信息
執(zhí)行結(jié)束
afterEach
以上實(shí)現(xiàn)的非常巧妙,再看 Vue-router 源碼這塊的實(shí)現(xiàn)方式,相信你會(huì)豁然開(kāi)朗。
文章目錄
小白學(xué)VUE——快速入門(mén)
前言:什么是VUE?
環(huán)境準(zhǔn)備:
vue的js文件
vscode
Vue入門(mén)程序
抽取代碼片段
vue標(biāo)準(zhǔn)語(yǔ)法:
什么是vue指令?
v-bind指令
事件單向綁定
v-model:事件雙向綁定
v-on事件監(jiān)聽(tīng)指令
v: on:submit.prevent指令
v-if 判斷指令
v-for 循環(huán)渲染指令
Vue.js(讀音 /vju?/, 類似于 view) 是一套構(gòu)建用戶界面的漸進(jìn)式框架。 Vue 只關(guān)注視圖層, 采用自底向上增量開(kāi)發(fā)的設(shè)計(jì)。 Vue 的目標(biāo)是通過(guò)盡可能簡(jiǎn)單的 API 實(shí)現(xiàn)響應(yīng)的數(shù)據(jù)綁定和組合的視圖組件。
環(huán)境準(zhǔn)備:
vue的js文件
使用CDN外部導(dǎo)入方法
以下推薦國(guó)外比較穩(wěn)定的兩個(gè) CDN,把這些網(wǎng)址放進(jìn)script標(biāo)簽的src屬性下即可,國(guó)內(nèi)還沒(méi)發(fā)現(xiàn)哪一家比較好,目前還是建議下載到本地。
Staticfile CDN(國(guó)內(nèi)) : https://cdn.staticfile.org/vue/2.2.2/vue.min.js
unpkg:https://unpkg.com/vue/dist/vue.js, 會(huì)保持和 npm 發(fā)布的的版本一致。
cdnjs : https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.8/vue.min.js
2.VSCODE軟件
(2).使用內(nèi)部導(dǎo)入方法(自行下載js文件放進(jìn)工作區(qū)js文件夾即可)
前往vscode官網(wǎng)下載對(duì)應(yīng)版本的vscode
Vue入門(mén)程序
首先了解一下什么是插值
插值:數(shù)據(jù)綁定最常見(jiàn)的形式就是使用 **{{…}}(雙大括號(hào))**的文本插值:
單獨(dú)抽出這段來(lái)看一下:
Vue即是vue內(nèi)置的對(duì)象,el(element)指的是綁定的元素,可以用#id綁定元素,data指的是定義頁(yè)面中顯示的模型數(shù)據(jù),還有未展示的methods,指的是方法
var app = new Vue({
el: "#app",//綁定VUE作用的范圍
data: {//定義頁(yè)面中顯示的模型數(shù)據(jù)
message: 'hello vue'
}
});
代碼如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="js/vue.min.js"></script>
</head>
<body>
<!-- 插值表達(dá)式 獲取data里面定義的值 {{message}} -->
<div id="app">{{ message }}</div>
<script>
//創(chuàng)建一個(gè)VUE對(duì)象
var app = new Vue({
el: "#app",//綁定VUE作用的范圍
data: {//定義頁(yè)面中顯示的模型數(shù)據(jù)
message: 'hello vue'
}
});
</script>
</body>
</html>
步驟:文件-首選項(xiàng)-用戶片段
輸入片段名稱回車(chē)
{
"vh": {
"prefix": "vh", // 觸發(fā)的關(guān)鍵字 輸入vh按下tab鍵
"body": [
"<!DOCTYPE html>",
"<html lang=\"en\">",
"",
"<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>Document</title>",
" <script src=\"js/vue.min.js\"></script>",
"</head>",
"",
"<body>",
" <div id=\"app\"></div>",
" <script>",
" var vm=new Vue({",
" el:'#app',",
" data:{},",
" methods:{}",
" });",
" </script>",
"</body>",
"",
"</html>",
],
"description": "vh components"
}
}
此時(shí),新建一個(gè)html文件,輸入vh在按下tab鍵即可快速填充內(nèi)容
vue標(biāo)準(zhǔn)語(yǔ)法:
什么是vue指令?
在vue中提供了一些對(duì)于頁(yè)面 + 數(shù)據(jù)的更為方便的輸出,這些操作就叫做指令, 以v-xxx表示
類似于html頁(yè)面中的屬性 `
比如在angular中 以ng-xxx開(kāi)頭的就叫做指令
在vue中 以v-xxx開(kāi)頭的就叫做指令
指令中封裝了一些DOM行為, 結(jié)合屬性作為一個(gè)暗號(hào), 暗號(hào)有對(duì)應(yīng)的值,根據(jù)不同的值,框架會(huì)進(jìn)行相關(guān)DOM操作的綁定
下面簡(jiǎn)單介紹一下vue的幾個(gè)基礎(chǔ)指令: v-bind v-if v-for v-on等
v-bind指令
作用:
給元素的屬性賦值
可以給已經(jīng)存在的屬性賦值 input value
也可以給自定義屬性賦值 mydata
語(yǔ)法
在元素上 v-bind:屬性名="常量||變量名"
簡(jiǎn)寫(xiě)形式 :屬性名="變量名"
例:
<div v-bind:原屬性名="變量"></div> <div :屬性名="變量"></div>
事件單向綁定,可以用 v-bind:屬性名="常量||變量名,綁定事件,用插值表達(dá)式取出值
<body>
————————————————
版權(quán)聲明:本文為CSDN博主「熱愛(ài)旅行的小李同學(xué)」的原創(chuàng)文章,遵循CC 4.0 BY-SA版權(quán)協(xié)議,轉(zhuǎn)載請(qǐng)附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/m0_46275020/java/article/details/106055312
1. 訪問(wèn)內(nèi)部屬性
JavaScript 對(duì)象無(wú)法以常規(guī)方式訪問(wèn)的內(nèi)部屬性。內(nèi)部屬性名由雙方括號(hào)[[]]包圍,在創(chuàng)建對(duì)象時(shí)可用。
內(nèi)部屬性不能動(dòng)態(tài)地添加到現(xiàn)有對(duì)象。
內(nèi)部屬性可以在某些內(nèi)置 JavaScript 對(duì)象中使用,它們存儲(chǔ)ECMAScript規(guī)范指定的內(nèi)部狀態(tài)。
有兩種內(nèi)部屬性,一種操作對(duì)象的方法,另一種是存儲(chǔ)數(shù)據(jù)的方法。例如:
[[Prototype]] — 對(duì)象的原型,可以為null或?qū)ο?
[[Extensible]] — 表示是否允許在對(duì)象中動(dòng)態(tài)添加新的屬性
[[PrivateFieldValues]] — 用于管理私有類字段
2. 屬性描述符對(duì)象
數(shù)據(jù)屬性包含了一個(gè)數(shù)據(jù)值的位置,在這個(gè)位置可以讀取和寫(xiě)入值。也就是說(shuō),數(shù)據(jù)屬性可以通過(guò) 對(duì)象.屬性 訪問(wèn),就是我么平常接觸的用戶賦什么值,它們就返回什么,不會(huì)做額外的事情。
數(shù)據(jù)屬性有4個(gè)描述其行為的特性(為了表示內(nèi)部值,把屬性放在兩對(duì)方括號(hào)中),稱為描述符對(duì)象。
屬性 解釋 默認(rèn)值
[[Configurable]] 能否通過(guò)delete刪除屬性從而重新定義屬性;
能否修改屬性的特性;
能否把屬性修改為訪問(wèn)器屬性 true
[[Enumerable]] 能否通過(guò)for-in循環(huán)返回屬性 true
[[Writable]] 能否修改屬性的值 true
[[Value]] 包含這個(gè)屬性的數(shù)據(jù)值 undefined
value 描述符是屬性的數(shù)據(jù)值,例如,我們有以下對(duì)象 :
let foo = {
a: 1
}
那么,a 的value屬性描述符為1。
writable是指該屬性的值是否可以更改。 默認(rèn)值為true,表示屬性是可寫(xiě)的。 但是,我們可以通過(guò)多種方式將其設(shè)置為不可寫(xiě)。
configurable 的意思是可以刪除對(duì)象的屬性還是可以更改其屬性描述符。 默認(rèn)值為true,這意味著它是可配置的。
enumerable 意味著它可以被for ... in循環(huán)遍歷。 默認(rèn)值為true,說(shuō)明能通過(guò)for-in循環(huán)返回屬性
將屬性鍵添加到返回的數(shù)組之前,Object.keys方法還檢查enumerable 描述符。 但是,Reflect.ownKeys方法不會(huì)檢查此屬性描述符,而是返回所有自己的屬性鍵。
Prototype描述符有其他方法,get和set分別用于獲取和設(shè)置值。
在創(chuàng)建新對(duì)象, 我們可以使用Object.defineProperty方法設(shè)置的描述符,如下所示:
let foo = {
a: 1
}
Object.defineProperty(foo, 'b', {
value: 2,
writable: true,
enumerable: true,
configurable: true,
});
這樣得到foo的新值是{a: 1, b: 2}。
我們還可以使用defineProperty更改現(xiàn)有屬性的描述符。 例如:
let foo = {
a: 1
}
Object.defineProperty(foo, 'a', {
value: 2,
writable: false,
enumerable: true,
configurable: true,
});
這樣當(dāng)我們嘗試給 foo.a 賦值時(shí),如:
foo.a = 2;
如果關(guān)閉了嚴(yán)格模式,瀏覽器將忽略,否則將拋出一個(gè)錯(cuò)誤,因?yàn)槲覀儗?writable 設(shè)置為 false, 表示該屬性不可寫(xiě)。
我們還可以使用defineProperty將屬性轉(zhuǎn)換為getter,如下所示:
'use strict'
let foo = {
a: 1
}
Object.defineProperty(foo, 'b', {
get() {
return 1;
}
})
當(dāng)我們這樣寫(xiě)的時(shí)候:
foo.b = 2;
因?yàn)閎屬性是getter屬性,所以當(dāng)使用嚴(yán)格模式時(shí),我們會(huì)得到一個(gè)錯(cuò)誤:Getter 屬性不能重新賦值。
3.無(wú)法分配繼承的只讀屬性
繼承的只讀屬性不能再賦值。這是有道理的,因?yàn)槲覀冞@樣設(shè)置它,它是繼承的,所以它應(yīng)該傳播到繼承屬性的對(duì)象。
我們可以使用Object.create創(chuàng)建一個(gè)從原型對(duì)象繼承屬性的對(duì)象,如下所示:
const proto = Object.defineProperties({}, {
a: {
value: 1,
writable: false
}
})
const foo = Object.create(proto)
在上面的代碼中,我們將proto.a的 writable 描述符設(shè)置為false,因此我們無(wú)法為其分配其他值。
如果我們這樣寫(xiě):
foo.a = 2;
在嚴(yán)格模式下,我們會(huì)收到錯(cuò)誤消息。
總結(jié)
我們可以用 JavaScript 對(duì)象做很多我們可能不知道的事情。
首先,某些 JavaScript 對(duì)象(例如內(nèi)置瀏覽器對(duì)象)具有內(nèi)部屬性,這些屬性由雙方括號(hào)包圍,它們具有內(nèi)部狀態(tài),對(duì)象創(chuàng)建無(wú)法動(dòng)態(tài)添加。
JavaScript對(duì)象屬性還具有屬性描述符,該屬性描述符使我們可以控制其值以及可以設(shè)置它們的值,還是可以更改其屬性描述符等。
我們可以使用defineProperty更改屬性的屬性描述符,它還用于添加新屬性及其屬性描述符。
最后,繼承的只讀屬性保持只讀狀態(tài),這是有道理的,因?yàn)樗菑母冈蛯?duì)象繼承而來(lái)的。
藍(lán)藍(lán)設(shè)計(jì)的小編 http://www.yvirxh.cn