方案一:
原文:https://segmentfault.com/a/1190000003730246
前提條件
假設(shè)我們要在 canvas 中繪制一張 300 x 90 的圖片,并且要保證它在高清屏中不模糊旁趟。那么我們首先要準(zhǔn)備一張 600 x 180 的圖片昼激,處理過(guò)高清屏的同學(xué)應(yīng)該會(huì)有這方面的經(jīng)驗(yàn)。
問(wèn)題重現(xiàn)
OK锡搜,我們先把問(wèn)題重現(xiàn)一下橙困,以便有一個(gè)更直觀的了解。下面是相關(guān)的代碼(為了簡(jiǎn)單起見(jiàn)耕餐,我把代碼都寫(xiě)在了 HTML 文檔里面):
<!-- 通過(guò) img 標(biāo)簽引入圖片凡傅,以便繪制到 canvas 中 -->
<img src="html5rocks.png" alt="" width="300" height="90">
<!-- canvas -->
<canvas width="300" height="90"></canvas>
<script>
function init() {
var canvas = document.querySelector('canvas');
var ctx = canvas.getContext('2d');
ctx.drawImage(document.querySelector('img'), 0, 0, 300, 90);
}
window.onload = init;
</script>
解決問(wèn)題
其實(shí),不只是繪制圖片時(shí)會(huì)出現(xiàn)模糊的問(wèn)題肠缔,正常情況下夏跷,在高清屏的設(shè)備中,任何繪制在 canvas 中的圖形(包括文字)都會(huì)出現(xiàn)模糊的問(wèn)題明未。上面這個(gè) polyfill 就是為了解決這個(gè)問(wèn)題槽华,但是它沒(méi)有處理圖片。
接下來(lái)趟妥,修改繪制圖片的代碼
將 init 函數(shù)修改成下面這樣:
function init() {
var canvas = document.querySelector('canvas');
var ctx = canvas.getContext('2d');
// polyfill 提供了這個(gè)方法用來(lái)獲取設(shè)備的 pixel ratio
var getPixelRatio = function(context) {
var backingStore = context.backingStorePixelRatio ||
context.webkitBackingStorePixelRatio ||
context.mozBackingStorePixelRatio ||
context.msBackingStorePixelRatio ||
context.oBackingStorePixelRatio ||
context.backingStorePixelRatio || 1;
return (window.devicePixelRatio || 1) / backingStore;
};
var ratio = getPixelRatio(ctx);
// 注意猫态,這里的 width 和 height 變成了 width * ratio 和 height * ratio
ctx.drawImage(document.querySelector('img'), 0, 0, 300 * ratio, 90 * ratio);
}
說(shuō)明
這個(gè)解決方案本質(zhì)上和 @白一梓 的答案是一樣的:先放大 canvas,再用 CSS 將其限制回原始大小。
如果你看了 polyfill 的代碼就會(huì)明白其中的原理了懂鸵,這個(gè) polyfill 的代碼十分簡(jiǎn)短明了偏螺,它做了兩件事:
一是將 canvas 的高和寬分別乘以 ratio 將其放大,然后又用 CSS 將高和寬限制成初始的大写夜狻套像;
二是 hack canvas 中常用的函數(shù),如:fillRect, clearRect, lineTo, arc 等终息,將它們的參數(shù)都乘以 ratio夺巩,以方便我們可以像以前那樣使用這些方法,而不用在傳參的時(shí)候手動(dòng)乘以 ratio周崭。
方案二:
@白一梓的解決辦法:
不管當(dāng)前的devicePixelRatio的值是多少柳譬,統(tǒng)一將canvasDOM節(jié)點(diǎn)的width屬性設(shè)置為其csswidth屬性的兩倍,同理將height屬性也設(shè)置為cssheight屬性的兩倍
<canvas width="320" height="180" style="width:160px;height:90px;"></canvas>
這樣整個(gè)canvas的坐標(biāo)系范圍就擴(kuò)大為兩倍续镇,但是在瀏覽器的顯示大小沒(méi)有變美澳,canvas畫(huà)圖的時(shí)候,按照擴(kuò)大化的坐標(biāo)系來(lái)顯示摸航,不清晰的問(wèn)題就得以改善了制跟。