這是一個由亂碼引起的故事。抱歉我暫時找不到更加慘烈的圖,請相信我,還有更目不忍視的畫面。請看下圖那些框框,那都是些什麼鬼!這是要害死強迫症嗎?若是同時看到幾十個框,簡直讓人崩潰。javascript
問題來了,這到底是些什麼鬼?css
既然是亂碼,固然要看編碼,那什麼是編碼呢?咱們都知道,計算機本質上不就是01
組成的一坨東西在運做着麼?01
這叫二進制,也就是最基本最底層的編碼。html
那麼你們日常看到的網頁也好,APP也好,上面的這些文字符號是怎麼表現出來的?固然是根據標記打印出來的,但計算機只能是二進制的存儲,並不能真正存ABCD呀,那就要把字母映射爲相應的二進制。前端
上個世紀60年代,美國製定了一套字符編碼,對英語字符與二進制位之間的關係,作了統一規定。這被稱爲ASCII碼,一直沿用至今。java
ASCII碼一共規定了128個字符的編碼,好比大寫的字母A是65(二進制01000001)。這128個符號(包括32個不能打印出來的控制符號),只佔用了一個字節的後面7位,最前面的1位統一規定爲0。但你美國英文字母少啊,我中文怎麼辦呢?全世界其餘國家的字母其餘語言怎麼辦呢,那就多加一些字節來表示咯。node
若是有一種編碼,將世界上全部的符號都歸入其中。每個符號都給予一個獨一無二的編碼,那麼亂碼問題就會消失了,這就是Unicode。Unicode規定了每一個符號都有本身的二進制碼。標準雖是標準,但各平臺實現標準的進度不一啊,有的各自爲政,這就有問題了,就像各大瀏覽器產商,沒給咱們前端少帶來麻煩啊。簡單點說,雖然你蘋果實現了這個標準能夠顯示這個符號,但我Android沒有,也不知道這個符號表達成啥,因此暫時給個框吧。android
所以致使亂碼的真正緣由:就是各平臺間對Unicode標準實現不一致(包括實現的時間前後不一樣,以及Unicode所表明含義不一樣)。ios
那框框的Unicode編碼究竟是什麼呢?charCodeAt()
(這個方法有侷限性,後面說)方法可返回指定位置的字符的 Unicode 編碼。這個返回值是 0 - 65535 之間的整數。git
" 追求簡單的小生活".charCodeAt(0) // 57614
57614是個十進制數,對應16進製爲E10E,Unicode也能夠表示爲U+E10E。經過這個網站查詢得知結果以下:github
一頭霧水,PRIVATE USE CODEPOINT這是個什麼意思呢?幸虧下面有wiki的解釋:
In Unicode, the Private Use Areas (PUA) are three ranges of code points (U+E000–U+F8FF in the BMP, and in planes 15 and 16) that, by definition, will not be assigned characters by the Unicode Consortium. The code points in these areas can not be considered as standardized characters in Unicode itself. They are intentionally left undefined so that third parties may define their own characters without conflicting with Unicode Consortium assignments. Under the Unicode Stability Policy, the Private Use Areas will remain allocated for that purpose in all future Unicode versions.
咳咳,因爲英文水平問題,但我仍是勉強翻譯下。大意就是:位於BMP的U+E000–U+F8FF
編碼,和第15以及16平面的區域的編碼,Unicode協會表示不會對該區域的編碼指定符號,且這些區域編碼不是標準符號,故意留下未定義的區域是讓第三方本身去玩。
那什麼又是BMP,第一個平面稱爲基本多語言平面(Basic Multilingual Plane, BMP),或稱第零平面(Plane 0)。其餘平面稱爲輔助平面(Supplementary Planes)。最前面的65536個字符位,都在BMP中。
好了,回到前面看,U+E10E這個Unicode恰好落到了(U+E000–U+F8FF)區間內。因此這個字符是由於第三方自定義的。
網上找到了一份表,http://www.easyapns.com/iphone-emoji-alerts 。U+E10E
對應符號以下:
那框真的是這個皇冠emoji嗎?由於是用戶暱稱,查一下就知道了
事實證實,確實沒錯。那麼既然是emoji表情,爲何iphone(9.3.1)都不能正常解析?這編碼又是怎麼被用戶輸入進去的?
說到emoji,那咱們先來扒一扒emoji的歷史故事。
emoji表情源於日本,叫作繪(e=圖)文字(moji=字符)。
Emoji were initially used by Japanese mobile operators, NTT DoCoMo, au, and SoftBank Mobile (formerly Vodafone).
日本幾家公司各自定義了一套標準,用兩個字節表示符號,Shift-JIS(日本電腦系統的一種編碼)編碼是從F89F到F9FC。固然這已是上世紀的事情了,其中被普遍採用的是SoftBank標準,也稱之爲SB (SoftBank,這裏不是ShaBi的縮寫,咳咳)emoji表情。
發展到今天,Unicode協會把emoji表情歸入標準中,但編碼範圍從新劃分了。前面說了,Private Use Areas 是留給第三方用的,不能瞎佔用。
在這個網站查到E10E
以下信息:
能夠初步懷疑是SoftBank的emoji表情。
剛好手中有臺舊的華爲手機,有一個系統自帶的華爲輸入法,輸入法裏面有一些跟蘋果emoji同樣的表情,只不過數量沒這麼多。下面四個是華爲輸入法鍵盤上的表情:
這四個表情在Unicode中的標準編碼是:
注意,若是使用charCodeAt方法來獲取Unicode編碼的時候要注意了,前面咱們提到了該方法有缺陷。簡單的緣由就是JavaScript使用的編碼與utf-8不同致使,這裏不展開講,有興趣能夠看這篇文章。ES6提供了新的接口來獲取碼點,codePointAt
。
輸入的結果展現以下:
iphone6sp 顯示框框
huawei 顯示空白
雖然在兩臺機器的表現形式不同,但都是沒法正確顯示,那咱們看下這究竟是什麼編碼。
上面四個編碼落入的區域也是在(U+E000–U+F8FF)內,而後根據上面的網站查詢,能夠確認是來自SoftBank標準的emoji表情了。
因此只要替換這些編碼就行了。
也就是說SoftBank emoji表情如今的系統基本不支持,由於已通過時了。
但爲何用戶還可以輸入這些SoftBank emoji呢?緣由就在於有些手機輸入法(相對古老了)廠商對emoji的實現仍是參照SoftBank的標準。
所以把SoftBank emoji編碼轉換爲Unicode標準的就是解決之道。在github上找到了SoftBank與標準emoji Unicode的對應關係。
有兩種解決方案:
一、轉換爲html實體編碼
\uE10E -> \u1F451 -> 👑
優勢:
高清,依賴系統編碼;
不須要加載css和emoji圖片,省流量。
缺點:
全部平臺表情不統一,各系統自定義的圖標,風格不一樣,但表達意思基本同樣
部分平臺不支持emoji
ios:
android:
二、轉換爲html標籤
code 對應emoji圖標的classID,用雪碧圖。
<i class="emoji emoji'+code+'" text=""></i>
優勢:
全部平臺表情統一(若是統一算優勢的話,有爭議,畢竟Android用戶看習慣了Android表情)。
缺點:
須要加載額外的css和emoji圖標;若是要高清(暫時沒法找到,圖片會模糊),則圖標會很大。
綜上,結合方案一二,在Android版本小於4.4的時候採用方案二,其餘採用方案一。
(左邊爲處理前,右邊爲處理後)
不一樣系統的處理結果
問題來了,若是遇到了其餘編碼標準(google, DoCoMo,KDDI 等等)的表情該怎麼辦?若是沒有Unicode的與符號的映射關係真是白搭,你絲毫沒有辦法。就像你不學習英文單詞,你還想看懂英文文章?
emoji表情不斷在豐富,這也給前端(各類終端)工做者帶來麻煩,只能儘量的補上已知的。