由一個emoji引發的思考


由一個emoji引發的思考

從畢業以來,基本就一直在做移動端,但是一直就關於移動端的開發,各種適配問題的解決,在日常搬磚中處理了就過了,也沒有把東西都沉淀下來,覺得甚是寒顏。現就一個小bug,讓我們來了解一下我們天天都在用的emoji,對於開發來說,是一個怎么樣的存在。

背景

之前在做一個留言功能時,發現在其中一台安卓5.0的手機上,輸入emoji糊掉了,成了如下這樣的情況

這是skr啥玩意兒呀,怎么看上去像某白色幼蟲。

與是我又試了好幾個手機,ios都沒有問題,甚至一台安卓機中之霸(安卓4.0),隨便進個頁面都要加載十幾秒的手機都沒有問題,是亂碼了嗎?

為啥emoji會出現亂碼呢?相信很多人都遇到過關於emoji的問題,比如輸入emoji,傳給后端,再經過一系列操作后從接口中取到后端返回的emoji字符就亂了。又比如為了限制輸入字數,給字符做截斷時出現的問題。

初步懷疑是編碼問題,那我們就來看看emoji究竟是何方神聖。

emoji的歷史

emoji對於我們來說並不陌生,我們很早就開始接觸它了。emoji這個詞來源於日語里的“絵文字”(假名為“えもじ”,讀音即emoji)。它是1999年,當時還在日本無線運營商NTT DoCoMo工作的Shigetaka Kurita(栗田穣崇)發明的。

emoji的編碼

emoji雖然看上去是一個有顏色有形狀的表情,但它屬於計算機中的字符。在計算機中,我們把文字、標點符號、圖形符號、數字等統一稱為字符,由字符組成的集合,我們稱為字符集。為了讓計算機識別字符集里的字符,我們設計了一套字符集編碼規則,比如ASCII碼,由於ASCII只規定了128個字符的編碼,隨着計算機的發展,人們意識到這些編碼顯然是不夠的,為了統一世界上的所有字符,誕生出了Unicode字符集,而emoji字符就是Unicode字符集中的一部分。

Unicode

Unicode從0開始,為每個符號指定一個編號,稱做"碼點",如U+0000,U+表示緊跟在后面的十六進制數是Unicode的碼點。Unicode只規定了每個字符的碼點,到底用什么樣的字節序表示這個碼點,就涉及到編碼方法,比如我們html上常用的UTF-8。關於不同的編碼方法怎么表示Unicode,以及JavaScript是怎么處理Unicode,這里就不詳細闡述了,可參考Unicode與JavaScript詳解
鏈接地址:http://www.ruanyifeng.com/blog/2014/12/unicode.html

所以emoji作為unicode,那在計算機上是怎么顯示的?

之前我在一微信群里@我一朋友,結果出現了下面的情況。

@符號跑右邊去了,當時覺得很奇怪,后來了解到,這是阿拉伯文,因為阿拉伯文的書寫規則是從右向左,所以@符號跑到右邊去了,可見微信對不同unicode字符排版做的兼容還挺好。再比如這幾個字符,熱҈得҈字҈出҈汗҈了҈。

這就涉及到了復雜文字編排(Complex text layout,縮寫:CTL)。要求復雜文字編排以適當顯示的書寫系統稱為復雜文本,比如阿拉伯文字、婆羅米系文字的天城文、泰文等。

拿泰文來說,根據拼寫規則,泰文可形象地分為鞋子字符、主體字符、帽子字符、聲調字符等。泰文的每個基本字符對應一個unicode碼,人們在輸入多個基本字符時,新輸入的字符與之前的字符做匹配,如果可以組合,則這時前面的輸入就拼合成了一個泰文字符然后顯示出來。

薩瓦迪卡~

英文也是,我們在輸入英文時會習慣以空格來拆分前后單詞,你如果輸入一串連續的英文字母,計算機在識別上也會有困難。phpisthebestlanguageintheworld(手動滑稽臉)這句話就很有爭議!!

人為可以輕松識別一個泰文是否拼寫正確,但是計算機在顯示時就很難判斷。

像泰文這種特殊合成字符的本質,你無法避免人們在計算機上都會有哪些奇妙的創造。

於是乎,不同字符之間的組合,就誕生出了流行的顏文字:

ฅ՞•ﻌ•՞ฅ

ʕ•̼͛͡•ʕ-̺͛͡•ʔ•̮͛͡•ʔ

(⑉꒦ິ^꒦ິ⑉)

₊˚‧(๑σ̴̶̷̥́ ₃σ̴̶̷̀)·˚₊

୧(๑•̀⌄•́๑)૭✧

而字符的顯示,還有一個影響就是字體,在瀏覽器中,如果對應的編碼在字體文件中為空,一般會展示成□□□□,這樣至少不會影響排版,但是unicode作為萬國碼實在太龐大了,在一些字體里,對一些特殊字符還是會產生一些錯誤的排版,唉҈~真҈是惆҈悵~~

對於emoji來說,它雖然也是一種特殊字符,但它並不屬於復雜文本,並且我是通過移動終端規范輸入,排版也不會有什么問題。我設置的font-family在其他手機上是好的也說明,這些字體對輸入的emoji也是支持的,出問題的終端上,非emoji的字體正常顯示,那暫時可以排除字體對emoji的影響了。

回歸問題

到這里,還沒有解決我的問題。本來以為是常見問題,比如數據提交時或者數據庫儲存的編碼問題。可是,我也沒傳給后端啊!我剛在自己的頁面上輸入顯示就成這樣了!

可惡,這個鍋甩不動了。還是得自己解決,我input框剛輸入,本地看到就亂了,看來還是自己的問題。

我一氣之下瘋狂亂點,發現不同的表情對應的這些小蟲長得還不一樣,於是,我決定把它放大看一看

這不就是表情么,只是因為某些原因看上去被壓縮了。我的表情啊,你到底是經歷了什么才變得如此面目全非。我一定要找到毀你容的真凶。

先分析一下表象,emoji的顯示被截斷、壓縮。為什么被壓縮?回歸場景,移動端切圖,那么移動端的多終端適配,可不可能是問題的原因?

切圖是UI給的以iphone6的屏幕寬度為准的750px2倍視覺稿,組內方案選擇參考了手淘的flexible。具體原理和這次主題無關,我就不在這里闡述了。關於移動端多端適配方案的原理詳細,可以參考
手淘H5頁面的終端適配

鏈接地址: https://www.w3cplus.com/mobile/lib-flexible-for-html5-layout.html

那么哪些代碼是影響emoji縮放的代碼呢?最先想到的是,我的emoji在輸入框里面,設置了font-size,這個font-size的值是rem,
那會不會是某些安卓系統emoji對rem支持不好?於是我換成px,依然如此。

那么頁面上還有哪兒還有會影響縮放呢?於是定位到了這里。

<meta name="viewport" content="initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=0,width=device-width" />

viewport是我們設備屏幕上用來顯示網頁的區域,在移動端上,viewport一般都是大於瀏覽器可視區域。

理論上,移動端有三個viewport。

  • layout viewport:移動瀏覽器為了讓所有網站正常顯示(包括那些PC的頁面),把默認的viewport設為了一個較寬值,這個值一般都是大於移動端可視區(比如iPhone 980px)。也就是document.documentElement.clientWidth
  • visual viewport:代表瀏覽器可視區域的大小。也就是window.innerWidth
  • ideal viewport:能完美適配移動設備的viewport,用戶不需要縮放和橫向滾動條就能完美看到網頁內容,並且文字圖片,在不同分辨率屏幕下顯示出來太小應該是差不多的(比如iPhone的ideal viewport寬度是320px)

關於各個設備的ideal viewport 可以從這里查詢,鏈接地址:http://viewportsizes.com/

所以我們利用meta標簽,設置viewport的寬度等於設備的寬度,並且不允許用戶手動縮放。讓viewport的寬度等於設備的寬度,這個應該就是我們想要的理想寬度。

實際上,只設置initial-scale=1,我們也能把當前的viewport寬度變成ideal viewport的寬度(這里不考慮iphone下不同dpr的縮放),因為這個縮放就是相對於ideal viewport來進行縮放的。當同時設置了width與initial-scale=1,瀏覽器會選擇兩者中較大的那個值。

說了這么多,那么我的問題出在哪兒呢?猜想是不是該安卓版本對設置width和initial-scale會有一些意想不到的問題,於是我去掉了width=device-width,保留initial-scale=1等屬性,結果emoji竟然好了。

所以我遇到的情況就是,同時設置了width=device-width和initial-scale=1,會造成某些廠商手機的安卓5.0(目前只遇到這個)emoji被拉伸,去掉width=device-width,(不寫width=device-width也就是windows phone上的IE無論是橫豎屏都把寬度設為豎屏時ideal viewport寬度,個人覺得這個無傷大雅),至於為什么會這樣,我暫時只能深入到這啦 (╥╯^╰╥)

結論

每一個emoji,就是一個Unicode字符,由統一碼聯盟(The Unicode Consortium)來投票選拔和公布,世界各地的人們可以向聯盟提交 emoji 提案。而統一碼聯盟的 emoji 規范,只是定義了某個字符的語義,再由 Emojipedia 這個網站對 emoji 進行描述表達,最后允許大家按照對描述的理解,自由地去設計圖案。

所以不同的廠商以及不同的系統,甚至瀏覽器、瀏覽器版本以及系統字體等,對emoji的支持程度與兼容性是不一樣的。比如同一個emoji笑臉表情,在ios和安卓上顯示的效果也不一樣。為了統一emoji表情,很多公司都有自己的一套emoji mapping,來做Unicode碼與emoji表情的映射。

碎碎念

移動端開發總會遇到各種問題,有時候做兼容也會遇到無法完全兼容兩頭的情況,這時只能放棄受眾更小,選擇兼容影響面、嚴重性更大的方案了。在解決問題的有時候深究下去,也會收獲很多。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM