你知道嗎?視力,聽力和行動能力完全健康的人,可以輕松地讀寫,可以有效執(zhí)行多任務(wù),并且始終可以正常工作的人約占總?cè)丝诘?0%?其余的人都是戴著眼鏡或有色盲,手腕或耳朵受傷,生活在嘈雜的環(huán)境中或網(wǎng)絡(luò)信號質(zhì)量差,忙碌或忙碌中,閱讀障礙或有注意力障礙等。
這意味著大約一半的用戶可能很難使用我們的產(chǎn)品或瀏覽我們的網(wǎng)站。因此,我們可能錯過了提高用戶滿意度并擴大受眾范圍的機會。
不過在設(shè)計階段實施一些簡單的原則就可以改善交互和整體用戶體驗,極限設(shè)計可以為所有人帶來價值,我們稱之為“包容性設(shè)計”。
什么是包容性設(shè)計?包容性設(shè)計考慮了盡可能多的人的需求和能力,而不僅僅是針對殘疾人。它認識到我們的需求會隨著時間和環(huán)境的變化而變化,因此它會預(yù)測錯誤,掙扎和不同的交互方式。它的目的是在問題發(fā)生之前解決問題,提高標準并改變良好產(chǎn)品設(shè)計的標準。
包容的用戶界面是善解人意,有意識且可訪問的。年齡,性別,教育程度,財富和能力等不同特征,在不同環(huán)境中生活或工作,獲得技術(shù)水平不同的不同人群可以舒適地使用它。
我們將使用POUR作為在用戶與界面之間創(chuàng)建簡單,輕松,快速交互的參考。
POUR代表
可以理解:數(shù)字內(nèi)容可以輕松地以不同方式進行解釋或處理嗎?
可操作:數(shù)字產(chǎn)品能否輕松自如地進行功能和控制?
可以理解:用戶可以理解界面的功能和內(nèi)部信息嗎?
健壯性:數(shù)字產(chǎn)品是否與不同的輔助技術(shù)和設(shè)備兼容?
設(shè)計師如何提供幫助
作為設(shè)計師,我們當然不能控制以上所有要求都能做到。但是我們應(yīng)該承認,人們遇到的許多可訪問性問題是由設(shè)計階段未做過的決定引起的。因此,設(shè)計師有很多機會可以有所作為。僅通過做出更明智的設(shè)計決策,我們就可以影響(改進或協(xié)助)四種經(jīng)驗。
視覺體驗:這包括形狀,顏色,對比,文本樣式-產(chǎn)品界面的所有圖形元素。
聽覺體驗:這是指與產(chǎn)品互動時產(chǎn)生的聲音,音量和清晰度。
認知經(jīng)驗:這描述了用戶花費在解釋界面上的時間,以及使用界面需要多少注意力和精力。
運動體驗:這包括執(zhí)行任務(wù)或與產(chǎn)品交互所需的所有動作和動作。
通常,可訪問性被認為是對創(chuàng)造力的挑戰(zhàn);但是,如果我們認為這是一個創(chuàng)造性的挑戰(zhàn),那么我們會開辟全新的可能性領(lǐng)域。真正好的可訪問性的訣竅不是在功能或功能上進行折衷,也不是在美學上取舍,而是使功能和創(chuàng)意體驗也可以訪問。
改善視覺體驗
1.顏色
對比度對比度是亮度或顏色的差異,使物體從周圍環(huán)境中脫穎而出,并可能對清晰度產(chǎn)生顯著影響。高對比度使視覺元素從背景中脫穎而出,更加引人注目。
專家提示:純粹的#000000黑白色會給眼睛帶來強烈的對比度,甚至會影響閱讀障礙者。這就是為什么我們傾向于避免使用它,而是選擇深灰色的原因。
亮度
亮度描述從光源發(fā)出的照明水平或從表面反射的光量。明亮的顏色反射更多的光線,并會干擾我們閱讀和處理信息的能力。
避免在背景或較大表面上使用鮮艷的顏色。請勿在文本上或文本附近使用鮮艷的顏色,以免干擾文本。如果品牌要求特定的高亮度顏色,請嘗試建議使用飽和或較深的顏色。如果你絕對必須使用明亮的顏色,則應(yīng)將其用于突出顯示動作的方法最小化,并將其與較深的色相搭配以達到平衡和高對比度。
專家提示:任何含有超過50%黃色的顏色都會自然反射更多的光。這意味著黃色,橙色,綠色和藍綠色是高風險顏色,應(yīng)謹慎使用。
色盲
色盲是無法區(qū)分特定顏色(通常是紅色和綠色,偶爾是藍色)的一種,它比你想象的要常見。
專家提示:不要僅僅依靠顏色;顏色不應(yīng)該是傳達重要信息的唯一方法。您可以執(zhí)行以下操作:
使用下劃線表示鏈接和斜體,或使用粗體突出顯示文本
將圖標與文本一起使用可傳達成功或失敗的信息
使用紋理或圖案作為圖表
為按鈕或明顯的通知使用清晰的視覺樣式,針對焦點或活動狀態(tài)使用不同的字體樣式
2.版式
字體選擇
通信是每個數(shù)字產(chǎn)品的首要目標,可以借助印刷術(shù)及其正確應(yīng)用來實現(xiàn)。內(nèi)容應(yīng)清晰易讀,這意味著易于識別和解釋,輕松閱讀和處理。
簡潔明了對于快速閱讀和解釋至關(guān)重要,請避免使用復雜的字體,因為它們只會增加視覺干擾。選擇正確的字體家族,針對那些具有清晰定義和獨特形狀的字符,因為視力障礙或閱讀障礙的人可能會因某些字符或其組合而感到困惑。
字體樣式
字體樣式還會影響弱視或閱讀障礙者的閱讀性能。我們應(yīng)該注意并謹慎使用字體樣式(如斜體,下劃線和大寫)的頻率和位置。
根據(jù)“英國閱讀障礙協(xié)會”的規(guī)定,應(yīng)避免使用斜體,特別是對于較大的副本塊或較小的字體。這是因為它們使字母傾斜,顯得更加尖銳,因此更難以閱讀。
正文也應(yīng)避免使用帶下劃線的字體樣式。給長的段落加下劃線會增加視覺噪音,從而降低閱讀性能,而給短的句子或單詞加下劃線會與活動鏈接相關(guān)聯(lián),并可能引起混亂。粗體是添加對比度和強調(diào)的更好選擇。
盡管沒有確鑿的研究,但有一些證據(jù)支持也應(yīng)避免主要針對正文使用大寫字母。似乎所有大寫字母的統(tǒng)一外觀會降低單詞形狀的對比度,從而使掃描變得不那么容易。此外,大寫看起來有點緊張,可能感覺好像有人在向您大喊大叫。
專家提示:平衡是關(guān)鍵。謹慎使用每個樣式并賦予其含義甚至可以提高可讀性。
字體大小
您知道絕大多數(shù)人戴眼鏡或隱形眼鏡嗎?實際上,十分之六以上!此外,約有62%的人通過手機訪問互聯(lián)網(wǎng),這還不包括應(yīng)用程序的使用情況。當視力不佳的人在旅途中在小屏幕上使用技術(shù)時,可能會出什么問題?
使用較大的字體。通常,16px被認為是最具有包容性的,但是請注意,字體可以以不同的比例站立,并且字體的大小可以相差很大。切勿低于14px,事實上,大多數(shù)現(xiàn)代網(wǎng)站的正文都使用18px字體,而標簽,標題或工具提示僅使用14px或16px。
專家提示:此外,避免使用薄而輕的字體,因為對于較小的字體或在明亮的光線下可能難以閱讀。
段落格式
幫助人們輕松瀏覽內(nèi)容應(yīng)該是我們的首要目標,因為只有20%的人可以閱讀內(nèi)容,其中55%的人可以快速瀏覽內(nèi)容。我們的工作是通過使用舒適的段落格式來盡可能地支持人們。
研究表明,用于支持可讀性的平均在線行長(包括空格)約為70個字符。標題,字幕和項目符號點將有助于掃描,而左段對齊將使文本更易于閱讀。
較長的文字墻使人們參與的機會大大減少。成功的段落長度不超過5到6個句子。
空格將幫助患有認知和注意力障礙的人,保持閱讀重點。對于其余的內(nèi)容,它只會使閱讀更加愉快和流暢。根據(jù)WCAG,最佳做法是將行高(行之間的間距)設(shè)置為相對于該類型大小的1.5相對值。段落之間的間距也至少應(yīng)比行間距大1.5倍,因此必須明確定義。
提示:行距不應(yīng)超過2.0,因為它可能產(chǎn)生相反的效果并分散讀者注意力。
復制版面
作為設(shè)計師,我們經(jīng)常陷入過度設(shè)計布局的陷阱,以使它們看起來引人注目或獨特,從而將可用性放在一邊。這就是為什么我們看到諸如文本的一部分之類的趨勢在彩色或帶紋理的背景上重疊圖像或文本的趨勢。只要我們知道如何以及何時使用它們,我們?nèi)匀豢梢韵硎芷渲械囊恍┶厔荨?/span>
當在彩色或帶紋理的背景上使用文本時,我們需要確保它們之間的色彩對比度足夠高,同時在整個重疊區(qū)域都保持一致-意味著在副本下沒有較淺和較暗的區(qū)域,也沒有過多的細節(jié)干擾。較大的字體大小和較重的字體粗細也會提高對比度。
專家提示:一如既往地“了解您的用戶”。時髦的布局并不適合所有人。
改善聽覺體驗
您可能在想,視覺設(shè)計如何影響聽覺體驗?因此,想象一下您正在與一個俱樂部的朋友交談。我敢打賭,您只能聽見她說的話的一半,但是您可以通過看著她的嘴唇移動,肢體語言和面部表情來保持對話的進行。由于視覺效果的支持增強了模棱兩可的聲音,因此您最終可以理解它們。
在用戶界面中,聲音對于不同的人可能意味著各種各樣的事情。它們也很容易在嘈雜的背景中丟失,因此最好以視覺提示來支持它們。
我們的目標應(yīng)該是提供聽覺和視覺提示的反饋,支持錯誤,通知以及與相關(guān)和鄰近圖形元素的重大交互。我們還必須確保視覺線索保持足夠長的活動時間,以使人們能夠看到和閱讀,同時又不隱藏任何重要的內(nèi)容。
一個好的做法-不限于支持聲音輔助技術(shù),是在UI元素中添加描述性標簽,并在圖像中添加標題,以便于在屏幕閱讀器中輕松導航。為視頻使用字幕是改善聽力體驗的另一種方法,對非母語人士也有幫助。
最后,我們不應(yīng)該忽略聲音是問題的情況,這就是為什么我們需要視覺替代的原因。有些人可能對特定的聲音敏感,或者處于聲音可能引起干擾的情況下。然后,這是一個好習慣,讓人們可以選擇關(guān)閉聲音而不必調(diào)低揚聲器音量,從而使此功能清晰可見。
專家提示:避免使用不必要的自動播放聲音和音樂,因為它們會打擾甚至驚嚇別人。
改善認知體驗
1.知覺
視覺清晰度
清晰度是用戶界面中的第一個也是最重要的屬性。成功的用戶界面使用戶能夠識別和解釋他們所看到的內(nèi)容,了解產(chǎn)品的價值和所要采取的行動,預(yù)測使用產(chǎn)品時會發(fā)生什么以及與產(chǎn)品成功交互。
形式跟隨功能是一項原則,指出對象應(yīng)反映其預(yù)期的功能或目的。為了在用戶界面中實現(xiàn)此目的,我們使用了附加功能,附加到UI的視覺提示/屬性,以顯示用戶與其交互的可能方式。
支付能力取決于用戶的身體能力,目標,過去的經(jīng)驗,當然還取決于他們認為可能的情況。按鈕應(yīng)該看起來像按鈕,就像鏈接,菜單標簽,表單等一樣。使用清晰的符號/功能可以幫助用戶識別或解釋界面,并輕松進行交互。
在用戶界面中使用熟悉的和已建立的設(shè)計解決方案將幫助用戶預(yù)測結(jié)果并自信地采取行動。因此,使用設(shè)計模式來解決常見問題是一個好習慣,該設(shè)計模式是經(jīng)過測試,優(yōu)化和可重用的解決方案。
設(shè)計模式建立在過去的經(jīng)驗和可能性的基礎(chǔ)上,并附加到特定的目標上。為避免眼前的問題,選擇正確的設(shè)計模式應(yīng)該是我們避免混淆或壓力大的交互的第一要務(wù)。
建立一致的視覺語言是獲得更全面界面的關(guān)鍵。具有相同功能和/或重要性的重復交互式UI組件應(yīng)始終以相同的方式外觀和操作。因此,導航,按鈕,鏈接,標簽,錯誤等元素應(yīng)在整個產(chǎn)品中具有一致的樣式,顏色和動畫。
值得注意的是,一致的視覺語言不僅可以通過附加含義和減少視覺噪音來幫助互動,而且還可以增強產(chǎn)品的個性,提升品牌知名度,建立情感聯(lián)系和信任。
層次結(jié)構(gòu)
視覺層次結(jié)構(gòu)是指圖形元素的視覺重量及其排列方式,使用戶可以輕松地探索和發(fā)現(xiàn)內(nèi)容。通過為頁面元素分配不同的視覺權(quán)重,我們可以對內(nèi)容進行分組并影響人們感知信息和瀏覽產(chǎn)品的順序。
顏色是第一大關(guān)注焦點。彩色元素將脫穎而出,因此在層次結(jié)構(gòu)中位于較高位置。明亮的顏色會更加突出,因此,考慮到這一點,我們應(yīng)該仔細安排和分配顏色,以將眼睛引導至正確的位置。
視覺元素的大?。ɡ缬∷?,按鈕,圖標和圖像)在確定重要性方面幾乎與顏色一樣強大。較大的圖形吸引了用戶的注意,并且顯得很重要。對于排版,明顯不同的尺寸縮放比例可以幫助建立內(nèi)容層次結(jié)構(gòu),并使內(nèi)容掃描變得輕松而輕松。
輔助視覺層次結(jié)構(gòu)的另一種方法是通過設(shè)計一致性和例外。一致對齊,外觀相似,重復或相鄰的元素給人的印象是它們是相關(guān)且同等重要的,而偏離元素以及不尋常的形狀和有趣的紋理或樣式將更加顯著。太多的設(shè)計例外會引起人們的關(guān)注,并會增加復雜性,因此,謹慎使用它們是一個好習慣。
專家提示:研究格式塔原理及其在UI設(shè)計中的應(yīng)用將有助于我們理解視覺感知和分組以改善視覺層次。
色彩應(yīng)用
顏色不應(yīng)該是傳達信息或增加意義的唯一方法,但它仍然有用且很有影響力,因此不應(yīng)將其視為裝飾性元素。顏色具有含義,盡管沒有硬性規(guī)定,但是太多的顏色會導致信息疲勞,并且不一致地使用顏色會導致混亂。
避免使用太多顏色。通常,三種顏色足以描述頁面的所有重要視覺元素。60–30–10規(guī)則可以幫助我們建立完美的和諧。其中60%的彩色項目由原色組成,以創(chuàng)建統(tǒng)一的產(chǎn)品主題,具有30%的輔助顏色增強含義和/或創(chuàng)建引人注目的效果,以及10%的強調(diào)色,以補充和輔助主顏色和輔助顏色。
此外,我們需要確保為消息使用正確的色調(diào)。除了美學,顏色還可以創(chuàng)造情感和無意識的聯(lián)系。特定陰影的含義會因我們所處的文化和環(huán)境而異,并且顏色通常具有不同的含義-在西方世界,錯誤是紅色,成功是綠色,信息是藍色等。
專家提示:可以將我們自己的含義分配給顏色,只要它們不與既定規(guī)范重疊,并且我們在整個產(chǎn)品中使它們保持一致。
符號學
符號學是對符號/圖標及其含義的研究。它著重于人們?nèi)绾涡纬珊徒忉屵@些含義,這取決于人們所看到的上下文。在用戶界面中,圖標是可視語言的一部分,用于表示功能,功能或內(nèi)容。符號學可以幫助我們設(shè)計立即被識別和理解的圖像。
盡管這些年來,我們已經(jīng)開發(fā)出具有大多數(shù)人接受和理解的含義的圖標。用戶還習慣于使用特定于平臺的圖標,并且可以輕松地進行解釋。在可能的情況下,最好遵循這些既定的解決方案,以獲得熟悉和流暢的體驗。
當然,在某些情況下,我們需要設(shè)計具有特定功能的自定義產(chǎn)品特定圖標。這些圖標必須盡可能簡單明了,以確保清晰度。它們還應(yīng)該具有一致的視覺樣式,以傳達其功能或與其他非功能性元素區(qū)分開。
最后,我們不應(yīng)該僅僅依靠視覺隱喻來傳達含義,因為某些關(guān)聯(lián)可能并不那么明顯。如果圖標需要標題來描述其含義,則可能不合適。如果不確定,請與實際用戶一起測試我們的設(shè)計會有所幫助。
專家提示:圖標不僅易于解釋,而且還可以具有多種含義。因此,將標記與功能圖標結(jié)合使用是一種很好的做法。
2.互動
記憶
許多心理學實驗表明,健康個體的處理能力非常有限。在我們的短期記憶中,我們大多數(shù)人平均可以保留7項,具體取決于個人。我們的大腦并未針對數(shù)字產(chǎn)品所需的抽象思維和數(shù)據(jù)記憶進行優(yōu)化,因此良好的設(shè)計會有所作為。
減少頁面上可用選項和信息的數(shù)量,以及使用清晰的標題,面包屑和“后退”選項來訪問以前的內(nèi)容,將幫助用戶記住或提醒自己他們在哪里,打算做什么或要做什么。是必需的。
交互元素上或附近的清晰可見副本將幫助用戶在整個交互過程中保持知情和自信。例如,表單標簽應(yīng)始終可見,動作不應(yīng)隱藏在懸停后面,按鈕應(yīng)提供目標位置的上下文,并且各節(jié)的標題應(yīng)明確。
專家提示:通過稱為“塊”的過程可以增加我們的短期記憶和處理能力。這是我們在視覺上將項目分組以形成更容易記住的較大項目的地方。
改善運動體驗
菲茨法
菲茨法則為人類的運動和互動提供了一個模型。它指出,將指針(光標或手指)快速移動到目標區(qū)域所需的時間是其距目標的距離除以目標大小的函數(shù)。意味著較小的目標會增加互動時間。
根據(jù)Fitts法則,我們旨在減小用戶與目標之間的距離,同時增加其尺寸。該法律主要適用于導航和按鈕。菜單和子菜單元素應(yīng)在附近,而按鈕,鏈接和分頁應(yīng)在較大區(qū)域上單擊,以實現(xiàn)更快更準確的交互。
專家提示:根據(jù)可用性最佳實踐,按鈕/鏈接的最小尺寸為42x42像素(重擊尺寸)。
獎勵:提高績效
到目前為止,我們已經(jīng)建立了包容性設(shè)計,旨在讓盡可能多的人訪問并實現(xiàn)他們的目標或解決他們的問題,盡管他們有自己的情況。我們可能很幸運,可以使用進的設(shè)備或超高速互聯(lián)網(wǎng),但是當我們的信號不太好時,我們會感到掙扎。對于大多數(shù)人來說,老式設(shè)備和糟糕的互聯(lián)網(wǎng)已成為常態(tài),因此,為獲得最佳性能而設(shè)計是一件大事。
極簡主義是關(guān)鍵。如果我們打算創(chuàng)造一種可以被盡可能多的人使用的產(chǎn)品,那么我們就應(yīng)該擺脫不必要的一切。圖形,圖像或動畫是有價值的,還是增加了視覺噪音和加載時間?如果是的話,那就必須走了。
圖像優(yōu)化是幫助提高數(shù)字產(chǎn)品性能的另一個標準。通過將圖像調(diào)整為合適的大小,然后通過諸如ImageOptim和TinyPNG之類的工具運行它們,可以節(jié)省寶貴的千字節(jié)和實際的加載時間。
開發(fā)人員通常使用的一種提高性能的技術(shù)是“延遲加載”模式,其中圖像的加載是異步的,并延遲到需要時才加載。例如,如果您快速滾動到頁面底部,則在網(wǎng)站完全加載之前,您可能會看到類似網(wǎng)站線框的內(nèi)容?!皾u進圖像加載”的一種替代方法是“漸進圖像加載”,其中我們顯示一個空的占位符框<div>,然后用小的低質(zhì)量模糊圖像填充它,最后用所需的高質(zhì)量圖像替換它。
在每個數(shù)字產(chǎn)品中都遵循上述最佳實踐,這是高可訪問性標準的良好起點。但是總會有改進的余地,并且更好地了解我們的用戶可以揭示提高無障礙標準的新方法。因此,有必要花費一些時間和金錢來更多地了解我們的不同類型的用戶,因為他們可以教會我們很多有關(guān)使包容性體驗成為現(xiàn)實的知識。
了解我們的用戶將幫助我們練習同理心?!百x權(quán)”不是偶然的設(shè)計思維過程的第一步。在移情階段,我們的目標是加深對我們正在設(shè)計的人員及其獨特視角的了解,因此我們可以在進行任何設(shè)計決策時與他們認同并代表他們。
zhuanz
this
this是我們在書寫代碼時最常用的關(guān)鍵詞之一,即使如此,它也是JavaScript最容易被最頭疼的關(guān)鍵詞。那么this到底是什么呢?
如果你了解執(zhí)行上下文,那么你就會知道,其實this是執(zhí)行上下文對象的一個屬性:
executionContext = {
scopeChain:[ ... ],
VO:{
...
},
this: ?
}
執(zhí)行上下文中有三個重要的屬性,作用域鏈(scopeChain)、變量對象(VO)和this。
this是在進入執(zhí)行上下文時確定的,也就是在函數(shù)執(zhí)行時才確定,并且在運行期間不允許修改并且是永久不變的
在全局代碼中的this
在全局代碼中this 是不變的,this始終是全局對象本身。
var a = 10;
this.b = 20;
window.c = 30;
console.log(this.a);
console.log(b);
console.log(this.c);
console.log(this === window) // true
// 由于this就是全局對象window,所以上述 a ,b ,c 都相當于在全局對象上添加相應(yīng)的屬性
如果我們在代碼運行期嘗試修改this的值,就會拋出錯誤:
this = { a : 1 } ; // Uncaught SyntaxError: Invalid left-hand side in assignment
console.log(this === window) // true
函數(shù)代碼中的this
在函數(shù)代碼中使用this,才是令我們最容易困惑的,這里我們主要是對函數(shù)代碼中的this進行分析。
我們在上面說過this的值是,進入當前執(zhí)行上下文時確定的,也就是在函數(shù)執(zhí)行時并且是執(zhí)行前確定的。但是同一個函數(shù),作用域中的this指向可能完全不同,但是不管怎樣,函數(shù)在運行時的this的指向是不變的,而且不能被賦值。
function foo() {
console.log(this);
}
foo(); // window
var obj={
a: 1,
bar: foo,
}
obj.bar(); // obj
函數(shù)中this的指向豐富的多,它可以是全局對象、當前對象、或者是任意對象,當然這取決于函數(shù)的調(diào)用方式。在JavaScript中函數(shù)的調(diào)用方式有一下幾種方式:作為函數(shù)調(diào)用、作為對象屬性調(diào)用、作為構(gòu)造函數(shù)調(diào)用、使用apply或call調(diào)用。下面我們將按照這幾種調(diào)用方式一一討論this的含義。
作為函數(shù)調(diào)用
什么是作為函數(shù)調(diào)用:就是獨立的函數(shù)調(diào)用,不加任何修飾符。
function foo(){
console.log(this === window); // true
this.a = 1;
console.log(b); // 2
}
var b = 2;
foo();
console.log(a); // 1
上述代碼中this綁定到了全局對象window。this.a相當于在全局對象上添加一個屬性 a 。
在嚴格模式下,獨立函數(shù)調(diào)用,this的綁定不再是window,而是undefined。
function foo() {
"use strict";
console.log(this===window); // false
console.log(this===undefined); // true
}
foo();
這里要注意,如果函數(shù)調(diào)用在嚴格模式下,而內(nèi)部代碼執(zhí)行在非嚴格模式下,this 還是會默認綁定為 window。
function foo() {
console.log(this===window); // true
}
(function() {
"use strict";
foo();
})()
對于在函數(shù)內(nèi)部的函數(shù)獨立調(diào)用 this 又指向了誰呢?
function foo() {
function bar() {
this.a=1;
console.log(this===window); // true
}
bar()
}
foo();
console.log(a); // 1
上述代碼中,在函數(shù)內(nèi)部的函數(shù)獨立調(diào)用,此時this還是被綁定到了window。
總結(jié):當函數(shù)作為獨立函數(shù)被調(diào)用時,內(nèi)部this被默認綁定為(指向)全局對象window,但是在嚴格模式下會有區(qū)別,在嚴格模式下this被綁定為undefined。
作為對象屬性調(diào)用
var a=1;
var obj={
a: 2,
foo: function() {
console.log(this===obj); // true
console.log(this.a); // 2
}
}
obj.foo();
上述代碼中 foo屬性的值為一個函數(shù)。這里稱 foo 為 對象obj 的方法。foo的調(diào)用方式為 對象 . 方法 調(diào)用。此時 this 被綁定到當前調(diào)用方法的對象。在這里為 obj 對象。
再看一個例子:
var a=1;
var obj={
a: 2,
bar: {
a: 3,
foo: function() {
console.log(this===bar); // true
console.log(this.a); // 3
}
}
}
obj.bar.foo();
遵循上面說的規(guī)則 對象 . 屬性 。這里的對象為 obj.bar 。此時 foo 內(nèi)部this被綁定到了 obj.bar 。 因此 this.a 即為 obj.bar.a 。
再來看一個例子:
var a=1;
var obj={
a: 2,
foo: function() {
console.log(this===obj); // false
console.log(this===window); // true
console.log(this.a); // 1
}
}
var baz=obj.foo;
baz();
這里 foo 函數(shù)雖然作為對象obj 的方法。但是它被賦值給變量 baz 。當baz調(diào)用時,相當于 foo 函數(shù)獨立調(diào)用,因此內(nèi)部 this被綁定到 window。
使用apply或call調(diào)用
apply和call為函數(shù)原型上的方法。它可以更改函數(shù)內(nèi)部this的指向。
var a=1;
function foo() {
console.log(this.a);
}
var obj1={
a: 2
}
var obj2={
a: 3
}
var obj3={
a: 4
}
var bar=foo.bind(obj1);
bar();// 2 this => obj1
foo(); // 1 this => window
foo.call(obj2); // 3 this => obj2
foo.call(obj3); // 4 this => obj3
當函數(shù)foo 作為獨立函數(shù)調(diào)用時,this被綁定到了全局對象window,當使用bind、call或者apply方法調(diào)用時,this 被分別綁定到了不同的對象。
作為構(gòu)造函數(shù)調(diào)用
var a=1;
function Person() {
this.a=2; // this => p;
}
var p=new Person();
console.log(p.a); // 2
上述代碼中,構(gòu)造函數(shù) Person 內(nèi)部的 this 被綁定為 Person的一個實例。
總結(jié):
當我們要判斷當前函數(shù)內(nèi)部的this綁定,可以依照下面的原則:
函數(shù)是否在是通過 new 操作符調(diào)用?如果是,this 綁定為新創(chuàng)建的對象
var bar = new foo(); // this => bar;
函數(shù)是否通過call或者apply調(diào)用?如果是,this 綁定為指定的對象
foo.call(obj1); // this => obj1;
foo.apply(obj2); // this => obj2;
函數(shù)是否通過 對象 . 方法調(diào)用?如果是,this 綁定為當前對象
obj.foo(); // this => obj;
函數(shù)是否獨立調(diào)用?如果是,this 綁定為全局對象。
foo(); // this => window
DOM事件處理函數(shù)中的this
1). 事件綁定
<button id="btn">點擊我</button>
// 事件綁定
function handleClick(e) {
console.log(this); // <button id="btn">點擊我</button>
}
document.getElementById('btn').addEventListener('click',handleClick,false); // <button id="btn">點擊我</button>
document.getElementById('btn').onclick= handleClick; // <button id="btn">點擊我</button>
根據(jù)上述代碼我們可以得出:當通過事件綁定來給DOM元素添加事件,事件將被綁定為當前DOM對象。
2).內(nèi)聯(lián)事件
<button onclick="handleClick()" id="btn1">點擊我</button>
<button onclick="console.log(this)" id="btn2">點擊我</button>
function handleClick(e) {
console.log(this); // window
}
//第二個 button 打印的是 <button id="btn">點擊我</button>
我認為內(nèi)聯(lián)事件可以這樣理解:
//偽代碼
<button onclick=function(){ handleClick() } id="btn1">點擊我</button>
<button onclick=function() { console.log(this) } id="btn2">點擊我</button>
這樣我們就能理解上述代碼中為什么內(nèi)聯(lián)事件一個指向window,一個指向當前DOM元素。(當然瀏覽器處理內(nèi)聯(lián)事件時并不是這樣的)
定時器中的this
定時器中的 this 指向哪里呢?
function foo() {
setTimeout(function() {
console.log(this); // window
},1000)
}
foo();
再來看一個例子
var name="chen";
var obj={
name: "erdong",
foo: function() {
console.log(this.name); // erdong
setTimeout(function() {
console.log(this.name); // chen
},1000)
}
}
obj.foo();
到這里我們可以看到,函數(shù) foo 內(nèi)部this指向為調(diào)用它的對象,即:obj 。定時器中的this指向為 window。那么有什么辦法讓定時器中的this跟包裹它的函數(shù)綁定為同一個對象呢?
1). 利用閉包:
var name="chen";
var obj={
name: "erdong",
foo: function() {
console.log(this.name) // erdong
var that=this;
setTimeout(function() {
// that => obj
console.log(that.name); // erdong
},1000)
}
}
obj.foo();
利用閉包的特性,函數(shù)內(nèi)部的函數(shù)可以訪問含義訪問當前詞法作用域中的變量,此時定時器中的 that 即為包裹它的函數(shù)中的 this 綁定的對象。在下面我們會介紹利用 ES6的箭頭函數(shù)實現(xiàn)這一功能。
當然這里也可以適用bind來實現(xiàn):
var name="chen";
var obj={
name: "erdong",
foo: function() {
console.log(this.name); // erdong
setTimeout(function() {
// this => obj
console.log(this.name); // erdong
}.bind(this),1000)
}
}
obj.foo();
被忽略的this
如果你把 null 或者 undefined 作為 this 的綁定對象傳入 call 、apply或者bind,這些值在調(diào)用時會被忽略,實例 this 被綁定為對應(yīng)上述規(guī)則。
var a=1;
function foo() {
console.log(this.a); // 1 this => window
}
var obj={
a: 2
}
foo.call(null);
var a=1;
function foo() {
console.log(this.a); // 1 this => window
}
var obj={
a: 2
}
foo.apply(null);
var a=1;
function foo() {
console.log(this.a); // 1 this => window
}
var obj={
a: 2
}
var bar = foo.bind(null);
bar();
bind 也可以實現(xiàn)函數(shù)柯里化:
function foo(a,b) {
console.log(a,b); // 2 3
}
var bar=foo.bind(null,2);
bar(3);
更復雜的例子:
var foo={
bar: function() {
console.log(this);
}
};
foo.bar(); // foo
(foo.bar)(); // foo
(foo.bar=foo.bar)(); // window
(false||foo.bar)(); // window
(foo.bar,foo.bar)(); // window
上述代碼中:
foo.bar()為對象的方法調(diào)用,因此 this 綁定為 foo 對象。
(foo.bar)() 前一個() 中的內(nèi)容不計算,因此還是 foo.bar()
(foo.bar=foo.bar)() 前一個 () 中的內(nèi)容計算后為 function() { console.log(this); } 所以這里為匿名函數(shù)自執(zhí)行,因此 this 綁定為 全局對象 window
后面兩個實例同上。
這樣理解會比較好:
(foo.bar=foo.bar) 括號中的表達式執(zhí)行為 先計算,再賦值,再返回值。
(false||foo.bar)() 括號中的表達式執(zhí)行為 判斷前者是否為 true ,若為true,不計算后者,若為false,計算后者并返回后者的值。
(foo.bar,foo.bar) 括號中的表達式之行為分別計算 “,” 操作符兩邊,然后返回 “,” 操作符后面的值。
箭頭函數(shù)中的this
箭頭函數(shù)時ES6新增的語法。
有兩個作用:
更簡潔的函數(shù)
本身不綁定this
代碼格式為:
// 普通函數(shù)
function foo(a){
// ......
}
//箭頭函數(shù)
var foo = a => {
// ......
}
//如果沒有參數(shù)或者參數(shù)為多個
var foo = (a,b,c,d) => {
// ......
}
我們在使用普通函數(shù)之前對于函數(shù)的this綁定,需要根據(jù)這個函數(shù)如何被調(diào)用來確定其內(nèi)部this的綁定對象。而且常常因為調(diào)用鏈的數(shù)量或者是找不到其真正的調(diào)用者對 this 的指向模糊不清。在箭頭函數(shù)出現(xiàn)后其內(nèi)部的 this 指向不需要再依靠調(diào)用的方式來確定。
箭頭函數(shù)有幾個特點(與普通函數(shù)的區(qū)別)
箭頭函數(shù)不綁定 this 。它只會從作用域鏈的上一層繼承 this。
箭頭函數(shù)不綁定arguments,使用reset參數(shù)來獲取實參的數(shù)量。
箭頭函數(shù)是匿名函數(shù),不能作為構(gòu)造函數(shù)。
箭頭函數(shù)沒有prototype屬性。
不能使用 yield 關(guān)鍵字,因此箭頭函數(shù)不能作為函數(shù)生成器。
這里我們只討論箭頭函數(shù)中的this綁定。
用一個例子來對比普通函數(shù)與箭頭函數(shù)中的this綁定:
var obj={
foo: function() {
console.log(this); // obj
},
bar: () => {
console.log(this); // window
}
}
obj.foo();
obj.bar();
上述代碼中,同樣是通過對象 . 方法調(diào)用一個函數(shù),但是函數(shù)內(nèi)部this綁定確是不同,只因一個數(shù)普通函數(shù)一個是箭頭函數(shù)。
用一句話來總結(jié)箭頭函數(shù)中的this綁定:
個人上面說的它會從作用域鏈的上一層繼承 this ,說法并不是很正確。作用域中存放的是這個函數(shù)當前執(zhí)行上下文與所有父級執(zhí)行上下文的變量對象的集合。因此在作用域鏈中并不存在 this 。應(yīng)該說是作用域鏈上一層對應(yīng)的執(zhí)行上下文中繼承 this 。
箭頭函數(shù)中的this繼承于作用域鏈上一層對應(yīng)的執(zhí)行上下文中的this
var obj={
foo: function() {
console.log(this); // obj
},
bar: () => {
console.log(this); // window
}
}
obj.bar();
上述代碼中obj.bar執(zhí)行時的作用域鏈為:
scopeChain = [
obj.bar.AO,
global.VO
]
根據(jù)上面的規(guī)則,此時bar函數(shù)中的this指向為全局執(zhí)行上下文中的this,即:window。
再來看一個例子:
var obj={
foo: function() {
console.log(this); // obj
var bar=() => {
console.log(this); // obj
}
bar();
}
}
obj.foo();
在普通函數(shù)中,bar 執(zhí)行時內(nèi)部this被綁定為全局對象,因為它是作為獨立函數(shù)調(diào)用。但是在箭頭函數(shù)中呢,它卻綁定為 obj 。跟父級函數(shù)中的 this 綁定為同一對象。
此時它的作用域鏈為:
scopeChain = [
bar.AO,
obj.foo.AO,
global.VO
]
這個時候我們就差不多知道了箭頭函數(shù)中的this綁定。
繼續(xù)看例子:
var obj={
foo: () => {
console.log(this); // window
var bar=() => {
console.log(this); // window
}
bar();
}
}
obj.foo();
這個時候怎么又指向了window了呢?
我們還看當 bar 執(zhí)行時的作用域鏈:
scopeChain = [
bar.AO,
obj.foo.AO,
global.VO
]
當我們找bar函數(shù)中的this綁定時,就會去找foo函數(shù)中的this綁定。因為它是繼承于它的。這時 foo 函數(shù)也是箭頭函數(shù),此時foo中的this綁定為window而不是調(diào)用它的obj對象。因此 bar函數(shù)中的this綁定也為全局對象window。
我們在回頭看上面關(guān)于定時器中的this的例子:
var name="chen";
var obj={
name: "erdong",
foo: function() {
console.log(this.name); // erdong
setTimeout(function() {
console.log(this); // chen
},1000)
}
}
obj.foo();
這時我們就可以很簡單的讓定時器中的this與foo中的this綁定為同一對象:
var name="chen";
var obj={
name: "erdong",
foo: function() {
// this => obj
console.log(this.name); // erdong
setTimeout(() => {
// this => foo中的this => obj
console.log(this.name); // erdong
},1000)
}
}
obj.foo();
5G以其更快的速度、連接和云訪問,將大數(shù)據(jù)引進車內(nèi)
在MWC上,華為、小米、三星等通訊企業(yè)紛紛發(fā)布了5G手機,而吉利也在2月26日的MWC上,宣布了與高通和高新興合作發(fā)布吉利全球首批支持5G和C-V2X的量產(chǎn)車型計劃??梢?G時代對于各大車企來說有著巨大的影響,尤其是車聯(lián)網(wǎng)產(chǎn)業(yè)。那么,在5G環(huán)境下,汽車行業(yè)究竟有什么變化呢?
5G是一代的移動網(wǎng)絡(luò),憑借高帶寬和低延遲,提供了更快的速度、連接和云訪問。5G的最大速度可達到每秒20GB,比4G要快100倍。它可以應(yīng)用于手機、無人駕駛、VR、電影、充電樁、醫(yī)療、農(nóng)業(yè)等多個領(lǐng)域。而基于5G通訊技術(shù)推出的C-V2X,是實現(xiàn)無人駕駛和車內(nèi)技術(shù)的重要前提。
萬物互聯(lián)
萬物互聯(lián)是自動駕駛汽車發(fā)展的關(guān)鍵,基于5G通訊技術(shù)推出的C-V2X能讓聯(lián)網(wǎng)車輛與交通基礎(chǔ)設(shè)施進行通信。通過5G可以實現(xiàn)自動駕駛汽車彼此之間所有數(shù)據(jù)的溝通與互聯(lián)。并與交通燈、道路、傳感器、停車場等基礎(chǔ)設(shè)施之間的信息互聯(lián),最終實現(xiàn)車路協(xié)同、萬物互聯(lián)。
車車互聯(lián)提升駕駛輔助
在5G環(huán)境下的汽車,可以通過云計算來計算車與車之間的距離、車輛的下一步動作、隱藏車輛可視化、零誤差高清導航等信息。同時,也可以與其他車輛實現(xiàn)共享數(shù)據(jù),提升ADAS和AEB等駕駛輔助功能,來避免車輛之間發(fā)生碰撞。
智慧交通引領(lǐng)場景化設(shè)計
5G環(huán)境下,大量的數(shù)據(jù)將被引入車內(nèi),來提供更準確的數(shù)據(jù)信息。如,高速收費、紅綠燈、RTTI、實時車位情況、消費支付、行人檢測等情況。眾多的交互有助于車輛更好的了解環(huán)境信息,并作出反饋,從而提供更好的場景化設(shè)計。如,自動超車、協(xié)作式避讓、自動播報前方道路擁擠程度并重新規(guī)劃路線功能等場景化設(shè)計。
再比如,哈曼正在研發(fā)的交通信號燈速度優(yōu)化建議技術(shù),幫助司機根據(jù)紅綠燈信息調(diào)整時速;西亞特測試了在交通信號燈中安裝熱像儀,以檢測行人的動作并將數(shù)據(jù)反饋給汽車。
車、商業(yè)、家居互聯(lián)改善駕駛體驗
當車輛與酒店、商場、影院、餐廳、健身房、加油站、家居、充電樁等場所相連接,就需要以5g結(jié)合C-V2X技術(shù)的部署為基準。從而根據(jù)車主的需求,更快地預(yù)定房間、訂餐、定電影票、充電樁、商場優(yōu)惠等活動,實現(xiàn)終端之間更的通信。
比如,我們要去看電影,那么車輛會根據(jù)實時路況(是否擁堵、有幾個紅綠燈、是否有車禍)為您選擇最佳的路線方案,并通知停車場到達時間,以方便確定是否有符合您時間的停車位,從而得到及時的反饋。
車載娛樂
可以說,如今我們所說的無人駕駛、車載觸屏、全息投影、AR(增強現(xiàn)實)、VR游戲、AR-HUD、實時電影、車輛之間影片共享、移動辦公、多模態(tài)交互等車載信息娛樂,都是需要在5G環(huán)境下來完成的。在未來,你可以在車內(nèi)利用幾秒的時間下載一部電影,也可以在車內(nèi)與其他車輛之間建立網(wǎng)絡(luò)游戲通信,實現(xiàn)虛擬內(nèi)容與車輛運動的實時對接。
奔馳與哈曼合作開發(fā)的MBUX信息娛樂平臺也引入了增強現(xiàn)實(AR)的車載導航系統(tǒng)。
MBUX信息AR車載導航系統(tǒng)
BMW Vision Next 100 AR-HUD
奧迪發(fā)布的“沉浸式車內(nèi)娛樂系統(tǒng)”,讓乘客在車內(nèi)佩戴VR眼鏡,然后車輛會根據(jù)行駛路線路況,實時匹配逼真的電競類影片。
奧迪發(fā)布的“沉浸式車內(nèi)娛樂系統(tǒng)”
手勢交互
車載機器人
全息投影
移動辦公
安全駕駛
未來的汽車將變得更加安全和,因為5G憑借其更高的帶寬、最小的延遲和零誤差高清導航,能夠預(yù)防事故和觀察到車身周圍的各個角落。再結(jié)合C-V2X技術(shù)將極大地促進車輛之間、車輛與行人、道路基礎(chǔ)設(shè)施之間的信息流動和監(jiān)控車輛異常情況。從而做到提前預(yù)知危險,并迅速作出響應(yīng)來提高道路安全性。另外,5G對于阻止黑客攻擊和數(shù)據(jù)攔截能夠得到更快響應(yīng),從而保障通訊安全。
想象一下,如果你的車可以在1毫秒內(nèi)做出反應(yīng)并將反饋傳達給數(shù)百人,那么,危險系數(shù)就會降低很多。5G時代,端到端的時長為1毫秒,同時1平方公里內(nèi)可同時連接100萬個網(wǎng)絡(luò),足以滿足智能交通和自動駕駛的要求。
無人駕駛
5G是實現(xiàn)無人駕駛最為關(guān)鍵的因素,如今,5G的成功研發(fā)有助于車輛之間大量的數(shù)據(jù)傳輸和存儲,實現(xiàn)車聯(lián)網(wǎng)的同時,也保障了車輛行駛的安全性;另一方面,5G可實現(xiàn)數(shù)據(jù)更快速的云訪問,從而更有效地減少傳感器技術(shù)的成本,最終實現(xiàn)無人駕駛。
總結(jié)
5G以其更快的速度、連接和云訪問,將大數(shù)據(jù)引進車內(nèi)。從而,在提升駕駛體驗的同時,實現(xiàn)了汽車與萬物的互聯(lián),保障了汽車駕駛中的安全性,從而為無人駕駛汽車提供了技術(shù)支撐和更便捷和的信息娛樂系統(tǒng)。
5G將成為未來十年全球主導的移動通信標準;
基于5G的C-V2X技術(shù),會加快無人駕駛技術(shù)的落地;
5G環(huán)境下的車載信息娛樂系統(tǒng)將改善用戶駕駛體驗,同時催生大量的市場新機會;
共享平臺下,5G將根據(jù)實時路況作出更準確的判斷,從而減少時間成本和停車成本;
5G遠不止應(yīng)用于汽車、手機,它將應(yīng)用于醫(yī)療、機器人、農(nóng)作業(yè)、航空等更多方面;
5G技術(shù)為無人駕駛的實現(xiàn)提供了技術(shù)支撐和安全保障,同時也降低了安裝傳感器技術(shù)的成本;
5G實現(xiàn)了車與車、道路、家居、商業(yè)之間真正意義上的“車聯(lián)網(wǎng)”,為交通提供更準確的交通信息和通信信息;
5G將會提供更多的場景,從而加快市場社會變革和新的商機,但需要大量的資金投入,能否將技術(shù)化為盈利是一大問題;
5G以毫秒的速度,提供更精細的地圖數(shù)據(jù)和更高級的駕駛輔助,并作出快速的反饋,提高了駕駛的安全性,對于減少交通擁堵,提高交通效率和道路安全有著積極的作用。
轉(zhuǎn)自-站酷
藍藍設(shè)計( m.yvirxh.cn )是一家專注而深入的界面設(shè)計公司,為期望卓越的國內(nèi)外企業(yè)提供卓越的UI界面設(shè)計、BS界面設(shè)計 、 cs界面設(shè)計 、 ipad界面設(shè)計 、 包裝設(shè)計 、 圖標定制 、 用戶體驗 、交互設(shè)計、 網(wǎng)站建設(shè) 、平面設(shè)計服務(wù)。
課程介紹
近些年,瀏覽器的功能越來越強大,漸漸得成為了復雜應(yīng)用和圖形的平臺。同時,現(xiàn)有大多數(shù)瀏覽器實現(xiàn)了對 WebGL 的支持,但要直接使用 WebGL 相關(guān)接口進行開發(fā),則需要學習復雜的著色器語言,且開發(fā)周期長,不利于項目的快速開發(fā)。
面對這種情況,Three.js 應(yīng)運而生,它不但對 WebGL 進行了封裝,將復雜的接口簡單化,而且基于面向?qū)ο笏季S,將數(shù)據(jù)結(jié)構(gòu)對象化,非常方便我們開發(fā)。Three.js 的發(fā)展十分迅速,然而配套的學習材料卻比較匱乏,于是便有了當前的這個課程。
本課程作為入門課程,不會深入做源碼解析,主要協(xié)助初學者了解 Three.js 的數(shù)據(jù)結(jié)構(gòu),基礎(chǔ) API 以及相關(guān)輔助插件的使用。幫助初學者達到快速入門的目的。
本課程共包含四大部分。
第一部分(第01-02課),入門前概述,帶你初步認識 Three.js、框架選擇標準、開發(fā)工具,源碼獲取,實現(xiàn)一個“Hello World”輔助工具。
第二部分(第03-08課),基礎(chǔ)功能篇,主要包括 Object3D、Scene、Mesh、Group、Geometry、Materials、Lights、Cameras、粒子等相關(guān)功能的介紹。
第三部分(第09-15課),進階篇,主要包括 Controls、Loaders、Animation、Tween、核心對象,與場景之間的交互以及性能優(yōu)化介紹。
第四部分(第16課),實戰(zhàn)篇,帶大家利用所學知識實現(xiàn)一個 3D 小案例。
鄭世強,現(xiàn)就職于上海某網(wǎng)絡(luò)公司擔任前端工程師,CSDN 博客作者,長期活躍于各大論壇,擅長前端開發(fā)、WEBGL 開發(fā)。
WebGL(Web 圖形庫)是一種 JavaScript API,用于在任何兼容的 Web 瀏覽器中呈現(xiàn)交互式 3D 和 2D 圖形,而無需使用插件。WebGL 通過引入一個與 OpenGL ES 2.0 緊密相符合的 API,可以在 HTML5 <canvas> 元素中使用(簡介引自 MDN)。
以我的理解,WebGL 給我們提供了一系列的圖形接口,能夠讓我們通過 JavaScript 去使用 GPU 來進行瀏覽器圖形渲染的工具。
Three.js 是一款 webGL 框架,由于其易用性被廣泛應(yīng)用。Three.js 在 WebGL 的 API 接口基礎(chǔ)上,又進行的一層封裝。它是由居住在西班牙巴塞羅那的程序員 Ricardo Cabbello Miguel 所開發(fā),他更為人知的網(wǎng)名是 Mr.doob。
Three.js 以簡單、直觀的方式封裝了 3D 圖形編程中常用的對象。Three.js 在開發(fā)中使用了很多圖形引擎的高級技巧,極大地提高了性能。另外,由于內(nèi)置了很多常用對象和極易上手的工具,Three.js 的功能也非常強大。最后,Three.js 還是完全開源的,你可以在 GitHub 上找到它的源代碼,并且有很多人貢獻代碼,幫助 Mr.doob 一起維護這個框架。
WebGL 原生 API 是一種非常低級的接口,而且還需要一些數(shù)學和圖形學的相關(guān)技術(shù)。對于沒有相關(guān)基礎(chǔ)的人來說,入門真的很難,Three.js 將入門的門檻降低了一大截,對 WebGL 進行封裝,簡化我們創(chuàng)建三維動畫場景的過程。只要你有一定的 JavaScript 基礎(chǔ),有一定的前端經(jīng)驗,我堅信,用不了多長時間,三維制作會變得很簡單。
用最簡單的一句話概括:WebGL 和 Three.js 的關(guān)系,相當于 JavaScript 和 jQuery 的關(guān)系。
Three.js 作為 WebGL 框架中的佼佼者,由于它的易用性和擴展性,使得它能夠滿足大部分的開發(fā)需求,Three.js 的具體功能如下:
Three.js 掩蓋了 3D 渲染的細節(jié):Three.js 將 WebGL 原生 API 的細節(jié)抽象化,將 3D 場景拆解為網(wǎng)格、材質(zhì)和光源(即它內(nèi)置了圖形編程常用的一些對象種類)。
面向?qū)ο螅洪_發(fā)者可以使用上層的 JavaScript 對象,而不是僅僅調(diào)用 JavaScript 函數(shù)。
功能非常豐富:Three.js 除封裝了 WebGL 原始 API 之外,Three.js 還包含了許多實用的內(nèi)置對象,可以方便地應(yīng)用于游戲開發(fā)、動畫制作、幻燈片制作、髙分辨率模型和一些特殊的視覺效果制作。
速度很快:Three.js 采用了 3D 圖形最佳實踐來保證在不失可用性的前提下,保持極高的性能。
支持交互:WebGL 本身并不提供拾?。≒icking)功能(即是否知道鼠標正處于某個物體上)。而 Three.js 則固化了拾取支持,這就使得你可以輕松為你的應(yīng)用添加交互功能。
包含數(shù)學庫:Three.js 擁有一個強大易用的數(shù)學庫,你可以在其中進行矩陣、投影和矢量運算。
內(nèi)置文件格式支持:你可以使用流行的 3D 建模軟件導出文本格式的文件,然后使用 Three.js 加載,也可以使用 Three.js 自己的 JSON 格式或二進制格式。
擴展性很強:為 Three.js 添加新的特性或進行自定義優(yōu)化是很容易的事情。如果你需要某個特殊的數(shù)據(jù)結(jié)構(gòu),那么只需要封裝到 Three.js 即可。
支持HTML5 Canvas:Three.js 不但支持 WebGL,而且還支持使用 Canvas2D、Css3D 和 SVG 進行渲染。在未兼容 WebGL 的環(huán)境中可以回退到其它的解決方案。
雖然 Three.js 的優(yōu)勢很大,但是它也有它的不足之處:
官網(wǎng)文檔非常粗糙,對于新手極度不友好。
國內(nèi)的相關(guān)資源匱乏。
Three.js 所有的資料都是以英文格式存在,對國內(nèi)的朋友來說又提高了門檻。
Three.js 不是游戲引擎,一些游戲相關(guān)的功能沒有封裝在里面,如果需要相關(guān)的功能需要進行二次開發(fā)。
隨著 WebGL 的迅速發(fā)展,相關(guān)的 WebGL 庫也豐富起來,接下來介紹幾個比較火的 WebGL 庫。
Babylon.JS 是最好的 JavaScript 3D 游戲引擎,它能創(chuàng)建專業(yè)級三維游戲。主要以游戲開發(fā)和易用性為主。與 Three.js 之間的對比:
Three.js 比較全面,而 Babylon.js 專注于游戲方面。
Babylon.js 提供了對碰撞檢測、場景重力、面向游戲的照相機,Three.js 本身不自帶,需要依靠引入插件實現(xiàn)。
對于 WebGL 的封裝,雙方做得各有千秋,Three.js 淺一些,好處是易于擴展,易于向更底層學習;Babylon.js 深一些,好處是易用擴展難度大一些。
Three.js 的發(fā)展依靠社區(qū)推動,出來的比較早,發(fā)展比較成熟,Babylon.js 由微軟公司在2013推出,文檔和社區(qū)都比較健全,國內(nèi)還不怎么火。
PlayCanvas 是一個基于 WebGL 游戲引擎的企業(yè)級開源 JavaScript 框架,它有許多的開發(fā)工具能幫你快速創(chuàng)建 3D 游戲。與 Three.js 之間的對比:
PlayCanvas 的優(yōu)勢在于它有云端的在線可視化編輯工具。
PlayCanvas 的擴展性不如 Three.js。
最主要是 PlayCanvas 不完全開源,還商業(yè)付費。
Cesium 是國外一個基于 JavaScript 編寫的使用 WebGL 的地圖引擎,支持 3D、2D、2.5D 形式的地圖展示,可以自行繪制圖形,高亮區(qū)域。與 Three.js 對比:
Cesium 是一個地圖引擎,專注于 Gis,相關(guān)項目推薦使用它,其它項目還是算了。
至于庫的擴展,其它的配套插件,以及周邊的資源都不及Three.js。
通過以上信息我們發(fā)現(xiàn),Three.js 在其庫的擴展性,易用性以及功能方面有很好的優(yōu)勢。學習 Three.js 入門 3D 開發(fā)不但門檻低,而且學習曲線不會太陡,即使以后轉(zhuǎn)向 WebGL 原生開發(fā),也能通過 Three.js 學習到很多有用的知識。
現(xiàn)在最火的微信小游戲跳一跳也是在 Three.js 的基礎(chǔ)上開發(fā)出來的。所以,Three.js 是我們必須要學的 WebGL 框架。
Three.js 可以使用 WebGL 在所有現(xiàn)代瀏覽器上渲染場景。對于舊版瀏覽器,尤其是 Internet Explorer 10 及更低版本,您可能需要回退到其他渲染器(CSS2DRenderer、CSS3DRenderer、SVGRenderer、CanvasRenderer)。
注意:如果您不需要支持這些舊版瀏覽器,則不推薦使用其他渲染器,因為它們速度較慢并且支持的功能比 WebGLRenderer 更少。
即可下載當前版本的代碼及相關(guān)案例,文件下載解壓后是這樣的:
其中相關(guān)文件夾的內(nèi)容是:
build:里面含有 Three.js 構(gòu)建出來的 JavaScript 文件,可以直接引入使用,并有壓縮版;
docs:Three.js 的官方文檔;
editor:Three.js 的一個網(wǎng)頁版的模型編輯器;
examples:Three.js 的官方案例,如果全都學會,必將成為大神;
src:這里面放置的全是編譯 Three.js 的源文件;
test:一些官方測試代碼,我們一般用不到;
utils:一些相關(guān)插件;
其他:開發(fā)環(huán)境搭建、開發(fā)所需要的文件,如果不對 Three.js 進行二次開發(fā),用不到。
還有第三種,就是直接去 GitHub 上下載源碼,和在官網(wǎng)上下載的代碼一樣。
<!DOCTYPE html><html><head> <meta charset=utf-8> <title>我的第一個Three.js案例</title> <style> body { margin: 0; } canvas { width: 100%; height: 100%; display: block; } </style></head><body onload="init()"><script src="https://cdn.bootcss.com/three.js/92/three.js"></script><script> //聲明一些全局變量 var renderer, camera, scene, geometry, material, mesh; //初始化渲染器 function initRenderer() { renderer = new THREE.WebGLRenderer(); //實例化渲染器 renderer.setSize(window.innerWidth, window.innerHeight); //設(shè)置寬和高 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); } //創(chuàng)建模型 function initMesh() { geometry = new THREE.BoxGeometry( 2, 2, 2 ); //創(chuàng)建幾何體 material = new THREE.MeshNormalMaterial(); //創(chuàng)建材質(zhì) mesh = new THREE.Mesh( geometry, material ); //創(chuàng)建網(wǎng)格 scene.add( mesh ); //將網(wǎng)格添加到場景 } //運行動畫 function animate() { requestAnimationFrame(animate); //循環(huán)調(diào)用函數(shù) mesh.rotation.x += 0.01; //每幀網(wǎng)格模型的沿x軸旋轉(zhuǎn)0.01弧度 mesh.rotation.y += 0.02; //每幀網(wǎng)格模型的沿y軸旋轉(zhuǎn)0.02弧度 renderer.render( scene, camera ); //渲染界面 } //初始化函數(shù),頁面加載完成是調(diào)用 function init() { initRenderer(); initScene(); initCamera(); initMesh(); animate(); }</script></body></html>
請將上面的代碼復制到 HTML 文件中,然后使用瀏覽器打開,我們就會發(fā)現(xiàn)下面的效果:
————————————————
版權(quán)聲明:本文為CSDN博主「GitChat的博客」的原創(chuàng)文章,遵循CC 4.0 BY-SA版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/valada/java/article/details/80871701
用例
讓我們從介紹幾種不同的填充用例開始。
標簽和值
假設(shè)你在同一行上有標簽和值,例如 name:zhangsan 和 Phone Number:(555)-555-1234。如果把他們放在一起看起來會有點奇怪,會是這樣:
Name: zhangsan
Phone Number: (555)-555-1234
你可能想要這個。
Name: zhangsan
Phone Number: (555)555-1234
或這個...
Name: zhangsan
Phone Number: (555)555-1234
金額
在中國,顯示價格時通常顯示兩位數(shù)的角、分。所以代替這個...
¥10.1
你會想要這個。
¥10.01
日期
對于日期,日期和月份都需要2位數(shù)字。所以代替這個...
2020-5-4
你會想要這個。
2020-05-04
時間
與上面的日期類似,對于計時器,你需要2位數(shù)字表示秒,3位數(shù)字表示毫秒。所以代替這個...
1:1
你會想要這個。
01:001
padstart()
讓我們從 padStart() 以及標簽和值示例開始。假設(shè)我們希望標簽彼此正確對齊,以使值在同一位置開始。
Name: zhangsan
Phone Number: (555)555-1234
由于 Phone Number 是兩個標簽中較長的一個,因此我們要在 Name 標簽的開頭加上空格。為了將來的需要,我們不要把它專門填充到電話號碼的長度,我們把它填充到長一點,比如說20個字符。這樣一來,如果你在未來使用較長的標簽,這一招仍然有效。
在填充之前,這是用于顯示此信息的入門代碼。
const label1 = "Name";
const label2 = "Phone Number";
const name = "zhangsan"
const phoneNumber = "(555)-555-1234";
console.log(label1 + ": " + name);
console.log(label2 + ": " + phoneNumber);
//Name: zhangsan
//Phone Number: (555)-555-1234
現(xiàn)在,讓我們填充第一個標簽。要調(diào)用 padStart(),你需要傳遞兩個參數(shù):一個用于填充字符串的目標長度,另一個用于你希望填充的字符。在這種情況下,我們希望長度為20,而填充字符為空格。
const label1 = "Name";
const label2 = "Phone Number";
const name = "zhangsan"
const phoneNumber = "(555)-555-1234";
console.log(label1.padStart(20, " ") + ": " + name);
console.log(label2 + ": " + phoneNumber);
// Name: zhangsan
////Phone Number: (555)-555-1234
現(xiàn)在填充第二行。
const label1 = "Name";
const label2 = "Phone Number";
const name = "zhangsan"
const phoneNumber = "(555)-555-1234";
console.log(label1.padStart(20, " ") + ": " + name);
console.log(label2.padStart(20, " ") + ": " + phoneNumber);
// Name: zhangsan
//// Phone Number: (555)-555-1234
padEnd()
對于相同的標簽和值示例,讓我們更改填充標簽的方式。讓我們將標簽向左對齊,以便在末尾添加填充。
初始代碼
const label1 = "Name";
const label2 = "Phone Number";
const name = "zhangsan"
const phoneNumber = "(555)-555-1234";
console.log(label1 + ": " + name);
console.log(label2 + ": " + phoneNumber);
//Name: zhangsan
//Phone Number: (555)-555-1234
現(xiàn)在,讓我們填充第一個標簽,與我們之前所做的類似,但有兩個小區(qū)別?,F(xiàn)在,我們使用 padEnd() 而不是padStart(),并且需要在填充之前將冒號與標簽連接起來,這樣我們就能確保冒號在正確的位置。
const label1 = "Name";
const label2 = "Phone Number";
const name = "zhangsan"
const phoneNumber = "(555)-555-1234";
console.log((label1 + ': ').padEnd(20, ' ') + name);
console.log(label2 + ": " + phoneNumber);
//Name: zhangsan
//Phone Number: (555)-555-1234
現(xiàn)在兩行都已填充。
const label1 = "Name";
const label2 = "Phone Number";
const name = "zhangsan"
const phoneNumber = "(555)-555-1234";
console.log((label1 + ': ').padEnd(20, ' ') + name);
console.log((label2 + ': ').padEnd(20, ' ') + phoneNumber);
//Name: zhangsan
//Phone Number: (555)-555-1234
數(shù)字(價格、日期、計時器等)呢?
padding函數(shù)是專門針對字符串而不是數(shù)字的,所以,我們需要先將數(shù)字轉(zhuǎn)換為字符串。
價格
讓我們看一下顯示價格的初始代碼。
const rmb = 10;
const cents = 1;
console.log("¥" + rmb + "." + cents); //¥10.1
要填充分,我們需要先將其轉(zhuǎn)換為字符串,然后調(diào)用 padStart() 函數(shù),指定長度為1且填充字符為'0';
const rmb = 10;
const cents = 1;
console.log("¥" + rmb + "." + cents.toString().padStart(2,0)); //¥10.01
日期
這是顯示日期的初始代碼。
const month = 2;
const year = 2020;
console.log(year + "-" + month); //2020-2
現(xiàn)在,讓我們填充月份以確保它是兩位數(shù)。
const month = 2;
const year = 2020;
console.log(year + "-" + month.toString().padStart(2,"0")); // 2020-02
計時器
最后是我們的計時器,我們要格式化兩個不同的數(shù)字,即秒和毫秒。盡管有相同的原則。這是初始代碼。
const seconds = 1;
const ms = 1;
console.log(seconds + ":" + ms); //1:1
現(xiàn)在要填充,我將在單獨的行上進行填充,以便于閱讀。
const seconds = 1;
const formattedSeconds = seconds.toString().padStart(2,0);
const ms = 1;
const formattedMs = ms.toString().padStart(3,0);
console.log(formattedSeconds + ":" + formattedMs); // 01:001
最后
雖然編寫自己的padding函數(shù)并不難,但既然已經(jīng)內(nèi)置在JavaScript中,為什么還要自己去做呢?有很多有趣的函數(shù)已經(jīng)內(nèi)置了。在你自己構(gòu)建一些東西之前,可能值得先快速搜索一下。
這次我們不聊視覺,也不暢想未來,只說說當下 HMI 產(chǎn)品設(shè)計與交互體驗。
本文內(nèi)容會涉及一些專業(yè)的汽車知識名詞,因為篇幅有限,如有些知識名詞不太明白可以百度一下。
說到 HMI 大多數(shù)設(shè)計師應(yīng)該是既熟悉又陌生,HMI 是 Human Machine Interface 的縮寫,「人機接口」,也叫人機界面,人機界面(又稱用戶界面或使用者界面)是系統(tǒng)和用戶之間進行交互和信息交換的媒介, 它實現(xiàn)信息的內(nèi)部形式與人類可以接受形式之間的轉(zhuǎn)換,凡參與人機信息交流的領(lǐng)域都存在著人機界面。
聽起來是不是覺得這不就是 UI 嗎?有什么區(qū)別嗎?似乎差不多,幾乎是沒有區(qū)別的,只不過是在某些場合和設(shè)備上管他叫 UI,比如移動端設(shè)備,而在另外某些場所和設(shè)備上管他就叫 HMI,比如汽車車機和數(shù)控機床。所以這個概念也不用去特別較真,HMI 就權(quán)當作是汽車上的 UI 界面吧。畢竟汽車是高科技與工業(yè)結(jié)合的完美產(chǎn)物,「HMI」念出這個詞時候就感覺是蠻專業(yè)的!很般配!
剛才說 HMI 最早更應(yīng)用于工業(yè)上,比如常見的各種機床、制造裝備。
或者說讓時間再向前推進一點!
而這里通常意義的 HMI 則更加聚焦點,基本特指汽車車機或者車載多媒體設(shè)備。
說到這里還是要從車載儀表盤說起,從德國人卡爾·本茨發(fā)明世界第一輛汽車,距今已經(jīng) 100 多年的時間了,在那些還沒有 HMI 這個名詞的年代,那么他是以什么形態(tài)出現(xiàn)的?那就不得不提「儀表盤」了。
當然寫這篇文章并不是去評測誰家 HMI 更優(yōu)秀,而是希望通過一些假設(shè)、實驗和推斷,和大家一起來探討一下如何更有效地設(shè)計 HMI。
屏幕越大越好?車內(nèi)到底需要幾塊屏幕?
我們先從屏幕開始。
說到屏幕,設(shè)計師都是比較敏感的,因為我們最終的設(shè)計交互創(chuàng)意都是需要都是在屏幕上顯示展示出來的,HMI 當然也不例外?,F(xiàn)在在車載屏幕上你能看到最大尺寸多大?
拿特斯拉為例,Model S 和 Model X 車型都是 17英寸,Model 3 為 15 英尺。
當然他肯定不是最大的,熟悉汽車朋友你應(yīng)該知道我想說誰了,沒錯就是他!擁有 48 寸可多段升降屏幕的 BYTON 新能源概念車 M-Byte!48 寸的確很夸張,難道屏幕越來越大就是未來 HMI 的方向嗎?
當然這個問題肯定是否定的,為什么?那就要從車載屏幕的作用來說起。
首先我是作為一個曾經(jīng)就職于汽車公司的設(shè)計師,并且是一名地道的汽車發(fā)燒友,憑借對汽車還算熟悉和熱愛做出一些產(chǎn)品交互分析,以下如有不妥之處還望海涵。
按照功能場景總體可分為三類:主行駛狀態(tài)信息、附設(shè)備狀態(tài)信息、多媒體 & 外設(shè)
不可缺少還需要與使用者、場景結(jié)合,我們先來做一個大概的用戶畫像。
對應(yīng)這些需求,汽車需要有儀表臺(屏)控制和顯示的區(qū)域有五個。
五個區(qū)域分別是:
其中前三個是主流配置,后兩個比較少見。
關(guān)于汽車設(shè)備這塊我們不做深入展開了,畢竟這篇文章主要討論的還是設(shè)計,直接看結(jié)果!
題外音:屏幕安全性的考量
汽車是比較特殊的設(shè)備,基于安全性考慮,汽車內(nèi)屏幕尺寸不宜太大與太多。
屏幕總體為玻璃材質(zhì),但與車窗擋風玻璃的材質(zhì)不同,當汽車遭遇碰撞的時候,車內(nèi)屏幕極易破損并形成尖銳物,極大可能會乘坐人員造成二次傷害,所以車內(nèi)屏幕不易太多,更不易太大。雖然車載屏幕變大變多已不可逆轉(zhuǎn),而且隨著屏幕技術(shù)的提升,柔性 OLED 的應(yīng)用也將會在一定范圍解決安全問題。但也需要汽車相關(guān)設(shè)計者多在安全方面進行考慮,任何產(chǎn)品體驗應(yīng)該建立在安全基礎(chǔ)之上的,特別是交通工具。
為什么大屏幕操控成為了當前的 HMI 主流了呢?那不得不去提一下另外一個我們熟悉的設(shè)備——手機!
同樣一個有限的區(qū)域,如果用物理按鍵那么這個區(qū)域只能是固定的功能,而屏幕就可以無限擴展。特別是在汽車中控屏上集成內(nèi)容會很多,體現(xiàn)就更加突出。
但是在汽車上的全部使用屏幕真的是最佳選擇嗎?顯然這是有待商榷的。
不可否認屏幕的確有很強的擴展性,但是缺點也是明顯的:1.觸控反饋缺乏 2.交互效率不高
對于這樣的判斷,我們可以通過兩個實驗來進行驗證。
將類似于 Surface Dial 這種智能按鈕交互裝置引入汽車的屏幕控制中,每個按鈕可以根據(jù)情景進行自定義,并且吸附到汽車屏幕的任何位置進行交互操作,相信這一定是一種全新的使用體驗。當然這一定是需要解決比如吸附力、安全性等一系列問題。
雖然目前的屏幕還無法做到完美觸控反饋,但已經(jīng)出現(xiàn)了一些新的硬件技術(shù)來試圖解決這些問題,比如 Tanvas Touch,其定義為 「手指與觸摸界面之間的電子壓力控制」。簡單來說他們的產(chǎn)品就 「皮膚的磁鐵」 一樣,能夠更加精準地感應(yīng)手指的動作,最后結(jié)果就是比 Apple 的 3D Touch 更加具有壓感的觸摸操作表現(xiàn)。
原理是利用手指尖觸摸顯示屏時產(chǎn)生的靜電引力來模擬觸感,通過電磁脈沖把更的反饋發(fā)送到用戶的指尖。
Tanvas 也正在與汽車制造商們合作把這項技術(shù)嵌入到汽車或屏幕上,讓人們更容易感觸受到不同物體的表面。
也許在未來我們真的會遇到他。
文章來源:優(yōu)設(shè) 作者:殘酷de樂章
坐標系是能夠使每個數(shù)組在維度空間內(nèi)找到映射關(guān)系的定位系統(tǒng),更偏向數(shù)學/物理概念。在數(shù)據(jù)可視化中,最常用的坐標系分為笛卡爾坐標系和極坐標系,本文介紹的坐標軸設(shè)計主要也是圍繞直角坐標系展開。
在說坐標軸之前先來介紹下什么是坐標系。坐標系是能夠使每個數(shù)組在維度空間內(nèi)找到映射關(guān)系的定位系統(tǒng),更偏向數(shù)學/物理概念。
維基百科對坐標系的定義是:對于一個 n 維系統(tǒng),能夠使每一個點和一組 n 個標量構(gòu)成一一對應(yīng)的系統(tǒng),它可以用一個有序多元組表示一個點的位置。
數(shù)據(jù)可視化中,最常用的坐標系有兩種:笛卡爾坐標系和極坐標系,均為二維坐標系。
下文介紹的坐標軸設(shè)計主要也是圍繞直角坐標系展開,用到極坐標系的圖表有餅圖、圓環(huán)圖、雷達圖等。
坐標軸是坐標系的構(gòu)成部分,是定義域軸和值域軸的統(tǒng)稱。系的范圍更大,而軸包含在系的概念里。由于可視化圖表繪制的數(shù)據(jù)大部分都有一定的現(xiàn)實意義,因此我們可以根據(jù)坐標軸對應(yīng)的變量是連續(xù)數(shù)據(jù)還是離散數(shù)據(jù),將坐標軸分成連續(xù)軸、時間軸、分類軸三大類。軸的類型不同在設(shè)計處理上也有差異。
介紹坐標軸設(shè)計前,我們先將坐標軸拆分成「原子」要素,具體分為軸線、軸刻度、軸標簽、軸標題/單位、網(wǎng)格線。
根據(jù)坐標軸的構(gòu)成,分類討論下每個構(gòu)成要素容易被忽視的設(shè)計細節(jié)。
軸線一般只考慮是否顯示,例如柱狀圖、折線圖等,在有背景網(wǎng)格線的情況下,會隱藏 y 軸線,條形圖則是隱藏 x 軸線,以達到信息降噪,突出視覺重點的目的。
軸刻度通常不顯示,只有在肉眼無法定位到某個標簽對應(yīng)的數(shù)據(jù)點時,會顯示刻度線,輔助用戶定位,比如折線圖,或抽樣顯示的柱狀圖。
網(wǎng)格線用于定位數(shù)據(jù)點的值域范圍,跟隨值域軸的位置單向顯示,柱狀圖采用水平網(wǎng)格,條形圖采用垂直網(wǎng)格。樣式為虛實線的最多,斑馬線由于感知過強,一般不用。
軸標題/單位主要用于說明定義域軸、值域軸的數(shù)據(jù)含義。當可視化圖表標題、圖例、軸標簽已經(jīng)能充分表達數(shù)據(jù)含義,無需單獨顯示標題/單位,「如無必要,勿增實體」。
軸標簽的設(shè)計就比較復雜,涉及到的細節(jié)點很多,而且對于定義域軸和值域軸上的標簽和單位設(shè)計要考慮的細節(jié)點還有差異。下文將定義域軸和值域軸看成 x 軸和 y 軸,便于說明。
x 軸標簽的設(shè)計重點在顯示規(guī)則上,不同的坐標軸類型有不同的處理方式。
連續(xù)軸/時間軸的標簽顯示
連續(xù)軸/時間軸,是由一組前后包含同等差值的等差數(shù)列組成,缺少幾個數(shù)值也能明顯看出中間的對應(yīng)關(guān)系。當多個標簽在容器內(nèi)全顯示發(fā)生重疊,我們可以利用抽樣顯示的手段來避免這種情況。這里不推薦使用旋轉(zhuǎn),一方面從美觀度上,旋轉(zhuǎn)可能會破壞界面整體協(xié)調(diào),另一方面,連續(xù)/時間軸非必須顯示所有軸標簽,抽樣標簽已經(jīng)能滿足用戶對當前數(shù)組定義域的理解。
介紹一種常見的抽樣方式:等分抽樣
當多個標簽在 x 軸無法完全顯示,優(yōu)先保留首尾標簽,其余標簽按同等步長間隔顯示。間隔等分的前提是間隔數(shù)是合數(shù),能被 1 和其本身以外的數(shù)整除。如果間隔數(shù)為質(zhì)數(shù),就需要「-1」轉(zhuǎn)成合數(shù)。
舉個例子:11 個標簽,間隔數(shù)是 10,能被 2 和 5 整除,即分成 2 等分和 5 等分。12 個標簽,間隔數(shù)是 11,無法等分,需要在間隔數(shù)基礎(chǔ)上再「-1」,轉(zhuǎn)成合數(shù) 10 后再等分,此時最后一個標簽顯示在倒數(shù)第二個數(shù)據(jù)點上。
有人會問了,能被那么多數(shù)等分,到底該選哪個呢?這就要根據(jù)標簽長度來定,選擇能放下最多標簽的等分值。由于連續(xù)軸/時間軸,一般是數(shù)值、日期、時間等,字符長度有限,即使抽樣后也能保證顯示出一定數(shù)量的標簽。
等分抽樣不太適用于表達某個時間周期內(nèi)的走勢折線圖,因為最后一個標簽不一定對應(yīng)最后一個數(shù)據(jù)點。對于這類折線圖,能清楚表明起始時間和末尾時間,相比顯示更多時間標簽重要性來的更高。設(shè)計上可以只顯示首尾標簽,或首尾 + 中間值。
分類軸的標簽顯示
分類軸是由幾組離散數(shù)據(jù)組成,相互之間獨立存在,無緊密邏輯關(guān)聯(lián)。若采用抽樣規(guī)則,隱藏一些標簽,用戶對圖表認知就會有困難,違背了數(shù)據(jù)可視化清晰、有效的設(shè)計原則。分類軸最佳處理方式是標簽旋轉(zhuǎn) 45 度,若 45 度仍顯示不下,繼續(xù)旋轉(zhuǎn) 90 度。如果 90 度還是放不下就要考慮結(jié)合圖表交互或反轉(zhuǎn)圖表。
標簽旋轉(zhuǎn)方向也有講究,因為人的視覺習慣是從左到右,從上到下,標簽順時針旋轉(zhuǎn) 45 度更符合用戶的瀏覽動線。
分類軸標簽字段有長有短,長文本標簽直接旋轉(zhuǎn)不僅影響美觀,而且也不利于用戶閱讀。如果數(shù)據(jù)量比較少只有 2~4 個,長文本標簽更適合水平展示,顯示不下省略即可;如果數(shù)據(jù)量比較多,就限定字符數(shù)后旋轉(zhuǎn)。
y 軸標簽的設(shè)計重點在標簽數(shù)量、取值范圍和數(shù)據(jù)格式上。標簽顯示區(qū)域一般根據(jù)最長標簽寬度自適應(yīng)縮放。如果數(shù)組是固定的,就寫成固定寬度,節(jié)省圖表計算量,提高渲染速度。
y軸標簽數(shù)量
標簽數(shù)量不建議過多,太多的標簽必定導致橫向網(wǎng)格線變多,造成元素冗余,干擾圖形信息表達。根據(jù) 7±2 設(shè)計原則,y 軸標簽數(shù)量最多不超過這個范圍。
y軸標簽取值范圍
y 軸標簽的取值范圍決定了圖形在整個繪圖區(qū)域的顯示高度。
折線圖 y 軸標簽取值一般保證圖形約占繪圖區(qū)域的 2/3,以更有效的傳達數(shù)據(jù)波動幅度,避免掩蓋和夸大變化趨勢。2/3 即斐波那契數(shù)列第二位起,相鄰兩數(shù)之比,也是黃金分割最簡單的計算方法。
柱狀圖的 y 軸標簽取值應(yīng)從 0 基線開始,以恰當反映數(shù)值。如果展示被截斷的柱狀圖,可能會誤導觀眾做出錯誤的判斷。
y軸標簽數(shù)據(jù)格式
y 軸標簽的數(shù)據(jù)格式在 ant.vision 寫的比較詳細,重復內(nèi)容不在此說明,重點講下一些特殊的設(shè)計細節(jié)。標簽保留的小數(shù)位數(shù)保持統(tǒng)一,不要因為某些軸標簽是整數(shù)值,就略去小數(shù)點。
正負向的 y 軸標簽,由于負值帶「-」符號,整個 y 軸看起來會有視覺偏差,特別是雙軸圖的右 y 軸更明顯。這里建議正負向 y 軸給正值標簽帶上「+」,以達到視覺平衡的效果。
寫了那么多關(guān)于坐標軸的設(shè)計,你是不是恍然大悟,原來小小的坐標軸還有如此之多的細節(jié)。往常我們做圖表設(shè)計,可能只是用網(wǎng)上自動生成的圖表簡單調(diào)整下,或者按照通用樣式來設(shè)計。然而,通用樣式雖然能表達數(shù)據(jù)意義,但也缺少了對圖表細節(jié)的把控,失了精致優(yōu)雅的感覺。
作為數(shù)據(jù)可視化設(shè)計的一小部分,就是這些設(shè)計細節(jié),決定了圖表最終的傳達效果。
文章來源:優(yōu)設(shè) 作者:米粒的DesignNote
與傳統(tǒng)PC桌面不同,手機屏幕的尺寸更加小巧操作,方式也已觸控為主,APP界面設(shè)計不但要保證APP功能的完整性和合理性,又要保證APP的功能性和實用性,在保證其擁有流暢的操作感受的同時,滿足人們的審美需求。
接下來為大家介紹幾款手機appui界面設(shè)計
--手機appUI設(shè)計--
--手機appUI設(shè)計--
--手機appUI設(shè)計--
--手機appUI設(shè)計--
--手機appUI設(shè)計--
--手機appUI設(shè)計--
--手機appUI設(shè)計--
--手機appUI設(shè)計--
--手機appUI設(shè)計--
--專業(yè)又貼心醫(yī)療App頁面設(shè)計--
--專業(yè)又貼心醫(yī)療App頁面設(shè)計--
--專業(yè)又貼心醫(yī)療App頁面設(shè)計--
--專業(yè)又貼心醫(yī)療App頁面設(shè)計--
--專業(yè)又貼心醫(yī)療App頁面設(shè)計--
--手機appUI設(shè)計--
--手機appUI設(shè)計--
--手機appUI設(shè)計--
--手機appUI設(shè)計--
--手機appUI設(shè)計--
--手機appUI設(shè)計--
--手機appUI設(shè)計--
--手機appUI設(shè)計--
--手機appUI設(shè)計--
--手機appUI設(shè)計--
--手機appUI設(shè)計--
--手機appUI設(shè)計--
--手機appUI設(shè)計--
--手機appUI設(shè)計--
(以上圖片均來源于網(wǎng)絡(luò))
藍藍設(shè)計( m.yvirxh.cn )是一家專注而深入的界面設(shè)計公司,為期望卓越的國內(nèi)外企業(yè)提供卓越的UI界面設(shè)計、BS界面設(shè)計 、 cs界面設(shè)計 、 ipad界面設(shè)計 、 包裝設(shè)計 、 圖標定制 、 用戶體驗 、交互設(shè)計、 網(wǎng)站建設(shè) 、平面設(shè)計服務(wù)
更多精彩文章:
數(shù)組——最簡單的內(nèi)存數(shù)據(jù)結(jié)構(gòu)
數(shù)組存儲一系列同一種數(shù)據(jù)類型的值。( Javascript 中不存在這種限制)
對數(shù)據(jù)的隨機訪問,數(shù)組是更好的選擇,否則幾乎可以完全用 「鏈表」 來代替
在很多編程語言中,數(shù)組的長度是固定的,當數(shù)組被填滿時,再要加入新元素就很困難。Javascript 中數(shù)組不存在這個問題。
但是 Javascript 中的數(shù)組被實現(xiàn)成了對象,與其他語言相比,效率低下。
數(shù)組的一些核心方法
方法 描述
push 方法將一個或多個元素添加到數(shù)組的末尾,并返回該數(shù)組的新長度。(改變原數(shù)組)
pop 方法從數(shù)組中刪除最后一個元素,并返回該元素的值。(改變原數(shù)組)
shift 方法從數(shù)組中刪除第一個元素,并返回該元素的值,如果數(shù)組為空則返回 undefined 。(改變原數(shù)組)
unshift 將一個或多個元素添加到數(shù)組的開頭,并返回該數(shù)組的新長度(改變原數(shù)組)
concat 連接兩個或多個數(shù)組,并返回結(jié)果(返回一個新數(shù)組,不影響原有的數(shù)組。)
every 對數(shù)組中的每個元素運行給定函數(shù),如果該函數(shù)對每個元素都返回 true,則返回 true。若為一個空數(shù)組,,始終返回 true。 (不會改變原數(shù)組,[].every(callback)始終返回 true)
some 對數(shù)組中的每個元素運行給定函數(shù),如果任一元素返回 true,則返回 true。若為一個空數(shù)組,,始終返回 false。(不會改變原數(shù)組,)
forEach 對數(shù)組中的每個元素運行給定函數(shù)。這個方法沒有返回值,沒有辦法中止或者跳出 forEach() 循環(huán),除了拋出一個異常(foreach不直接改變原數(shù)組,但原數(shù)組可能會被 callback 函數(shù)該改變。)
map 對數(shù)組中的每個元素運行給定函數(shù),返回每次函數(shù)調(diào)用的結(jié)果組成的數(shù)組(map不直接改變原數(shù)組,但原數(shù)組可能會被 callback 函數(shù)該改變。)
sort 按照Unicode位點對數(shù)組排序,支持傳入指定排序方法的函數(shù)作為參數(shù)(改變原數(shù)組)
reverse 方法將數(shù)組中元素的位置顛倒,并返回該數(shù)組(改變原數(shù)組)
join 將所有的數(shù)組元素連接成一個字符串
indexOf 返回第一個與給定參數(shù)相等的數(shù)組元素的索引,沒有找到則返回 -1
lastIndexOf 返回在數(shù)組中搜索到的與給定參數(shù)相等的元素的索引里最大的值,沒有找到則返回 -1
slice 傳入索引值,將數(shù)組里對應(yīng)索引范圍內(nèi)的元素(淺復制原數(shù)組中的元素)作為新數(shù)組返回(原始數(shù)組不會被改變)
splice 刪除或替換現(xiàn)有元素或者原地添加新的元素來修改數(shù)組,并以數(shù)組形式返回被修改的內(nèi)容(改變原數(shù)組)
toString 將數(shù)組作為字符串返回
valueOf 和 toString 類似,將數(shù)組作為字符串返回
棧是一種遵循后進先出(LIFO)原則的有序集合,新添加或待刪除的元素都保存在棧的同一端,稱作棧頂,另一端就叫棧底。在棧里,新元素都靠近棧頂,舊元素都接近棧底。
通俗來講,就是你向一個桶里放書本或者盤子,你要想取出最下面的書或者盤子,你必須要先把上面的都先取出來。
棧也被用在編程語言的編譯器和內(nèi)存中保存變量、方法調(diào)用等,也被用于瀏覽器歷史記錄 (瀏覽器的返回按鈕)。
代碼實現(xiàn)
// 封裝棧隊列是遵循先進先出(FIFO,也稱為先來先服務(wù))原則的一組有序的項。隊列在尾部添加新
元素,并從頂部移除元素。添加的元素必須排在隊列的末尾。
生活中常見的就是排隊
代碼實現(xiàn)
function Queue() {代碼實現(xiàn)
鏈表——存儲有序的元素集合
,但在內(nèi)存中不是連續(xù)放置
的。
鏈表(單向鏈表)中的元素
由存放元素本身「data」
的節(jié)點和一個指向下一個「next」
元素的指針組成。牢記這個特點
相比數(shù)組,鏈表添加或者移除元素不需要移動其他元素,但是需要使用指針
。訪問元素每次都需要從表頭
開始查找。
代碼實現(xiàn):
單向鏈表
表頭
、表尾
和 存儲數(shù)據(jù)的 節(jié)點
,其中節(jié)點
包含三部分:一個鏈向下一個元素的next
, 另一個鏈向前一個元素的prev
和存儲數(shù)據(jù)的 data
。牢記這個特點
function doublyLinkedList() {
this.head = null // 表頭:始終指向第一個節(jié)點,默認為 null
this.tail = null // 表尾:始終指向最后一個節(jié)點,默認為 null
this.length = 0 // 鏈表長度
function Node(data) {
this.data = data
this.prev = null
this.next = null
}
doublyLinkedList.prototype.append = function (data) {
let newNode = new Node(data)
if (this.length === 0) {
// 當插入的節(jié)點為鏈表的第一個節(jié)點時
// 表頭和表尾都指向這個節(jié)點
this.head = newNode
this.tail = newNode
} else {
// 當鏈表中已經(jīng)有節(jié)點存在時
// 注意tail指向的始終是最后一個節(jié)點
// 注意head指向的始終是第一個節(jié)點
// 因為是雙向鏈表,可以從頭部插入新節(jié)點,也可以從尾部插入
// 這里以從尾部插入為例,將新節(jié)點插入到鏈表最后
// 首先將新節(jié)點的 prev 指向上一個節(jié)點,即之前tail指向的位置
newNode.prev = this.tail
// 然后前一個節(jié)點的next(及之前tail指向的節(jié)點)指向新的節(jié)點
// 此時新的節(jié)點變成了鏈表的最后一個節(jié)點
this.tail.next = newNode
// 因為 tail 始終指向的是最后一個節(jié)點,所以最后修改tail的指向
this.tail = newNode
}
this.length++
}
doublyLinkedList.prototype.toString = function () {
return this.backwardString()
}
doublyLinkedList.prototype.forwardString = function () {
let current = this.tail
let str = ''
while (current) {
str += current.data + ''
current = current.prev
}
return str
}
doublyLinkedList.prototype.backwardString = function () {
let current = this.head
let str = ''
while (current) {
str += current.data + ''
current = current.next
}
return str
}
doublyLinkedList.prototype.insert = function (position, data) {
if (position < 0 || position > this.length) return false
let newNode = new Node(data)
if (this.length === 0) {
this.head = newNode
this.tail = newNode
} else {
if (position == 0) {
this.head.prev = newNode
newNode.next = this.head
this.head = newNode
} else if (position == this.length) {
newNode.prev = this.tail
this.tail.next = newNode
this.tail = newNode
} else {
let current = this.head
let index = 0
while( index++ < position){
current = current.next
}
newNode.next = current
newNode.prev = current.prev
current.prev.next = newNode
current.prev = newNode
}
}
this.length++
return true
}
doublyLinkedList.prototype.get = function (position) {
if (position < 0 || position >= this.length) return null
let current = this.head
let index = 0
while (index++) {
current = current.next
}
return current.data
}
doublyLinkedList.prototype.indexOf = function (data) {
let current = this.head
let index = 0
while (current) {
if (current.data === data) {
return index
}
current = current.next
index++
}
return -1
}
doublyLinkedList.prototype.update = function (position, newData) {
if (position < 0 || position >= this.length) return false
let current = this.head
let index = 0
while(index++ < position){
current = current.next
}
current.data = newData
return true
}
doublyLinkedList.prototype.removeAt = function (position) {
if (position < 0 || position >= this.length) return null
let current = this.head
if (this.length === 1) {
this.head = null
this.tail = null
} else {
if (position === 0) { // 刪除第一個節(jié)點
this.head.next.prev = null
this.head = this.head.next
} else if (position === this.length - 1) { // 刪除最后一個節(jié)點
this.tail.prev.next = null
this.tail = this.tail.prev
} else {
let index = 0
while (index++ < position) {
current = current.next
}
current.prev.next = current.next
current.next.prev = current.prev
}
}
this.length--
return current.data
}
doublyLinkedList.prototype.remove = function (data) {
let index = this.indexOf(data)
return this.removeAt(index)
}
}
感謝你的閱讀~
————————————————
版權(quán)聲明:本文為CSDN博主「重慶崽兒Brand」的原創(chuàng)文章,遵循CC 4.0 BY-SA版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/brand2014/java/article/details/106134844
如今大數(shù)據(jù)產(chǎn)業(yè)正在超出我們的想象悄然發(fā)展,而隨著大數(shù)據(jù)時代的到來,越來越多的公司開始意識到數(shù)據(jù)資源的管理和運用。今天就給大家介紹一些可視化大屏的UI設(shè)計。
--大屏UI設(shè)計--
--大屏UI設(shè)計--
--大屏UI設(shè)計--
--大屏UI設(shè)計--
--大屏UI設(shè)計--
--大屏UI設(shè)計--
--大屏UI設(shè)計--
--大屏UI設(shè)計--
--大屏UI設(shè)計--
--大屏UI設(shè)計--
--大屏UI設(shè)計--
--大屏UI設(shè)計--
--大屏UI設(shè)計--
--大屏UI設(shè)計--
--大屏UI設(shè)計--
--大屏UI設(shè)計--
--大屏UI設(shè)計--
--大屏UI設(shè)計--
--大屏UI設(shè)計--
--大屏UI設(shè)計--
--大屏UI設(shè)計--
--大屏UI設(shè)計--
--大屏UI設(shè)計--
--大屏UI設(shè)計--
--大屏UI設(shè)計--
(以上圖片均來自于網(wǎng)絡(luò))
其實可視化大屏的UI設(shè)計并不只是一個簡單的設(shè)計,其核心就是要以展示數(shù)據(jù)為核心,不管在多么炫目的情況下都不會影響數(shù)據(jù)的展示。
藍藍設(shè)計( m.yvirxh.cn )是一家專注而深入的界面設(shè)計公司,為期望卓越的國內(nèi)外企業(yè)提供卓越的UI界面設(shè)計、BS界面設(shè)計 、 cs界面設(shè)計 、 ipad界面設(shè)計 、 包裝設(shè)計 、 圖標定制 、 用戶體驗 、交互設(shè)計、 網(wǎng)站建設(shè) 、平面設(shè)計服務(wù)
更多精彩文章:
藍藍設(shè)計的小編 http://m.yvirxh.cn