作者:娇娇jojo
时间:2018年6月13日
到公司那么久,时间接触最长的组件是 canvas,没想到 canvas 的坑踩之不尽。前段时间恰好做了一活动,需要在 canvas 上绘制图片,但老生常谈的问题出现了:绘制后生成的图片模糊了!!! WTF ?别着急别着急,用 hidpi-canvas-polyfill 就能解决啦。
一、安装
<script src=".../dist/hidpi-canvas.min.js"></script>
或者:
bower install hidpi-canvas
二、原理
在 window 中有一个 devicePixelRatio 的属性,类似的,在 canvas context 中也存在一个BackingStorePixelRatio 的属性,该属性的值决定了浏览器在渲染 canvas 之前会用几个像素来来存储画布信息。如果 BackingStorePixelRatio 值是2,将一张100x100像素的图片绘制到浏览器中,该图片首先会在内存中生成一张200x200的图片,然后浏览器渲染的时候,会按100x100的图片来渲染,因此就变成了200x200,正好和内存中的图片大小一致,因此不会出现失真的问题。
那我们怎样让所有手机都不失真呢?我们可以根据 devicePixelRatio 与 BackingStorePixelRatio 的比值来决定canvas绘制时的坐标和大小。对应的canvas画布大小也要根据比值来设置。
三、使用
使用起来其实也很简单,下面举一个栗子(在 canvas 上绘制2张图片):
// 获取设备像素比 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 canvas = document.getElementById("canvas"); var ctx = canvas.getContext('2d'); // 加载图片 var img1 = new Image(); img1.src = "img/1.png"; img1.onload = function() { var img2 = new Image(); img2.src = "img/2.png"; img2.onload = function() { drawImg(ctx, getPixelRatio, img1, img2); } }
// 绘制图片 function drawImg(ctx, ratio, image1, image2){ // 对图片先缩小再放大 var swidth1 = image1.width; var sheight1 = image1.height; var width1 = 0.5 * swidth1; var height1 = 0.5 * sheight1; var img1Width = width1 * ratio; var img1Height = height1 * ratio; // 第二张图片的大小必须依据第一张图片的尺寸来(比如第一张图片的 width 是526,height 是1112),不然展示出来的图片大小就不对 var swidth2 = img1Width * 484 / 526; var sheight2 = img1Height * 768 / 1112; var img2Left = img1Width * 25 / 526; var img2Top = img1Height * 172 / 1112; // 绘制图片 ctx.drawImage(image1, 0, 0, img1Width, img1Height); ctx.drawImage(image2, img2Left, img2Top, swidth2, sheight2); // 生成 base64 的图片 var img = new Image(); img.src = canvas.toDataURL('image/jpeg', 0.5); // 压缩图片,默认压缩比是0.5 $("body").prepend(img); }
对应的这样处理之后,文字绘制在 canvas 上也会很清晰,就不举例了,大家自行去尝试~