美文网首页
Canvas 在高清屏下绘制图片变模糊的解决方法

Canvas 在高清屏下绘制图片变模糊的解决方法

作者: 夏日清风_期待 | 来源:发表于2017-11-15 15:01 被阅读0次

    方案一:

    原文:https://segmentfault.com/a/1190000003730246

    前提条件

    假设我们要在 canvas 中绘制一张 300 x 90 的图片,并且要保证它在高清屏中不模糊。那么我们首先要准备一张 600 x 180 的图片,处理过高清屏的同学应该会有这方面的经验。

    问题重现

    OK,我们先把问题重现一下,以便有一个更直观的了解。下面是相关的代码(为了简单起见,我把代码都写在了 HTML 文档里面):

    <!-- 通过 img 标签引入图片,以便绘制到 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>
    

    解决问题

    其实,不只是绘制图片时会出现模糊的问题,正常情况下,在高清屏的设备中,任何绘制在 canvas 中的图形(包括文字)都会出现模糊的问题。上面这个 polyfill 就是为了解决这个问题,但是它没有处理图片。

    接下来,修改绘制图片的代码

    将 init 函数修改成下面这样:

    function init() {
        var canvas = document.querySelector('canvas');
        var ctx = canvas.getContext('2d');
    
        // polyfill 提供了这个方法用来获取设备的 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);
    }
    

    说明

    这个解决方案本质上和 @白一梓答案是一样的:先放大 canvas,再用 CSS 将其限制回原始大小。

    如果你看了 polyfill 的代码就会明白其中的原理了,这个 polyfill 的代码十分简短明了,它做了两件事:

    一是将 canvas 的高和宽分别乘以 ratio 将其放大,然后又用 CSS 将高和宽限制成初始的大小;

    二是 hack canvas 中常用的函数,如:fillRect, clearRect, lineTo, arc 等,将它们的参数都乘以 ratio,以方便我们可以像以前那样使用这些方法,而不用在传参的时候手动乘以 ratio。


    方案二:

    @白一梓解决办法

    不管当前的devicePixelRatio的值是多少,统一将canvasDOM节点的width属性设置为其csswidth属性的两倍,同理将height属性也设置为cssheight属性的两倍

    <canvas width="320" height="180" style="width:160px;height:90px;"></canvas>
    

    这样整个canvas的坐标系范围就扩大为两倍,但是在浏览器的显示大小没有变,canvas画图的时候,按照扩大化的坐标系来显示,不清晰的问题就得以改善了。

    相关文章

      网友评论

          本文标题:Canvas 在高清屏下绘制图片变模糊的解决方法

          本文链接:https://www.haomeiwen.com/subject/ghzcvxtx.html