最近在作項目的時候,須要把文字以圖片形式在前端顯示出來,發現canvas這個好東西。可是在手機端顯示的時候老是很模糊,查找資料發現是devicePixelRatio惹的禍javascript
下面是作的簡單測試,先貼代碼:html
<script type="text/javascript"> var canvas = document.createElement("canvas"); canvas.width = 414; var ctx = canvas.getContext("2d"); ctx.font = "30px Arial"; ctx.fillText("Low DPI Text", 10, 40); document.body.appendChild(canvas); var HiDPIcanvas = document.createElement("canvas"); HiDPIcanvas.width = 414 * window.devicePixelRatio; HiDPIcanvas.style.width = 414; var HiDPIctx = HiDPIcanvas.getContext("2d"); HiDPIctx.scale(window.devicePixelRatio,window.devicePixelRatio); HiDPIctx.font = "30px Arial"; HiDPIctx.fillText("High DPI Text", 10, 40); document.body.appendChild(HiDPIcanvas); </script>
Chrome開發模式下,能夠看出前者是正常的,然後者「太」清晰了,由於電腦屏幕通常devicePixelRatio都是1,沒有影響前端
而在手機上顯示就不一樣了,iPhone 6sp下,後者正常,而前者其實有些模糊了,iPhone 6sp的devicePixelRatio爲3html5
因爲canvas的fillText方法不支持自動換行,因此須要手動截斷字符串,找好canvas的X和Y座標位置後,像畫畫同樣把文字畫上去。java
代碼以下,(自定義字節長度進行截斷,不截斷數字)canvas
1 // Create HiDPI canvas based on custom ratio or device pixel ratio 2 function createCanvas(str, pixelRatio) { 3 var w = window.screen.width * 0.935; // 0.935 is the canvas' width proportion 4 if (!pixelRatio) { pixelRatio = window.devicePixelRatio || 1; } 5 var can = document.createElement("canvas"); 6 can.width = w * pixelRatio; 7 can.style.width = w + "px"; 8 return drawImage(str, can, pixelRatio); 9 } 10 11 // Draw text on HTML canvas 12 function drawImage(text, canvas, pixelRatio) { 13 var ratio = window.screen.width / 414; // Fit with iPhone 6sp as the standard 14 var rowLength = 39; // Byte length of canvas row 15 var k = 0; // rowLength counter 16 var fontSize = 20 * ratio; 17 18 // adjust canvas height according to text byte length 19 var h = (function (text) { 20 var strLength = 0; // text byte length 21 for (var j = 0; j < text.length; j++) { 22 if (text.charCodeAt(j) > 255) { 23 strLength += 2; 24 } else { 25 strLength++; 26 } 27 } 28 return (strLength / rowLength + 1) * (fontSize*1.3); 29 })(text); 30 canvas.height = h * pixelRatio; 31 canvas.style.height = h + "px"; 32 canvas.getContext("2d").scale(pixelRatio,pixelRatio); 33 34 var ctx = canvas.getContext("2d"); 35 ctx.font = fontSize + "px Arial"; 36 var x = 10 * ratio; // X axis position of canvas 37 var y = 20 * ratio; // Y axis position of canvas 38 39 for (var j = 0; j < text.length; j++) { 40 if (k == rowLength || k == rowLength - 1) { 41 // move forward when you encounter numbers 42 while (text.charCodeAt(j - 1) >= 48 && text.charCodeAt(j - 1) <= 57) { 43 j--; 44 } 45 text = text.substr(0, j) + "<br>" + text.substr(j); 46 k = 0; // truncate for next line 47 j += 4; // plus the "<br>" length 48 } 49 // plus 2 bytes when you encounter chinese character 50 if (text.charCodeAt(j) > 255) { 51 k += 2; 52 } else { 53 k++; 54 } 55 } 56 var textArray = text.split("<br>"); // truncate text to array 57 // Fill text on canvas 58 for (var j = 0; j < textArray.length; j++) { 59 ctx.fillText(textArray[j], x, y); 60 y += 25 * ratio; 61 } 62 return canvas; 63 }
參考:(這篇文章寫得很好,能夠看看,不過須要注意提到的backingStorePixelRatio已經棄用)app
www.html5rocks.com/en/tutorials/canvas/hidpi/測試
https://stackoverflow.com/questions/15661339/how-do-i-fix-blurry-text-in-my-html5-canvasspa
https://stackoverflow.com/questions/24332639/why-context2d-backingstorepixelratio-deprecatedcode