【问题标题】:Pattern gets shifted when painting at the bottom edge of the canvas在画布的底部边缘绘画时图案会发生变化
【发布时间】:2015-12-26 09:26:09
【问题描述】:

我想在画布底部绘制一个重复的草图案。图像确实重复,但它是垂直移动的。

图案基于 192x50 图像:

我注意到,如果我从 y 坐标 50、100、150 等进行绘制,则图案会正确显示。它不适用于其他坐标。

生成的画布具有垂直移动的草图案:

我不知道为什么它会变成那样。

下面是我的代码。

HTML:

<canvas id="myCanvas" style="display: block;">  
</canvas> 

JavaScript:

canvas.height = window.innerHeight;
canvas.width = window.innerWidth;
// Grass Background Image
var bgReady = false;
var bgImage = new Image();
bgImage.onload = function () {
    bgReady = true; 
};
bgImage.src = "img/grass.png";

我循环执行以下操作:

if (bgReady) {
        ctx.drawImage(bgImage,0, canvas.height -50,192,50);
        var ptrn = ctx.createPattern(bgImage, "repeat"); // Create a pattern with this image, and set it to repeat".
        ctx.fillStyle = ptrn;
        ctx.fillRect(0,canvas.height - bgImage.height,canvas.width, 50); // context.fillRect(x, y, width, height);
    }

【问题讨论】:

    标签: javascript html image canvas graphics


    【解决方案1】:

    我尝试将您的代码放在 jsFiddle 中,它似乎按预期工作:

    var canvas = document.getElementById('myCanvas'); 
    canvas.height = window.innerHeight;
    canvas.width = window.innerWidth;
    // Grass Background Image
    var bgImage = new Image();
    bgImage.onload = function () {
         var ctx = canvas.getContext("2d");
         ctx.drawImage(bgImage,0, canvas.height -50,192,50);
            var ptrn = ctx.createPattern(bgImage, "repeat"); // Create a pattern with this image, and set it to repeat".
            ctx.fillStyle = ptrn;
            ctx.fillRect(0,canvas.height - bgImage.height,canvas.width, 50); // context.fillRect(x, y, width, height);
    };
    bgImage.src = "data:image/png;base64,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";
    

    https://jsfiddle.net/or68kcpc/

    错误一定在其他地方。

    【讨论】:

      【解决方案2】:

      问题是图案是从画布的左上角开始计算的。如果您从不是图像高度整数倍的画布 y 坐标开始绘制,则图案的可见部分不会从图像顶部开始。

      要解决此问题,请在使用图案绘制之前将绘图上下文向下移动,然后在向上移动的位置绘制图案,然后将上下文向上移动:

        var shiftY = canvas.height % image.height;
        context.translate(0, shiftY);
        context.fillRect(0, canvas.height - image.height - shiftY,
                         canvas.width, image.height);
        context.translate(0, -shiftY);
      

      运行下面的 sn -p 来查看演示。画布高度为 120,也就是说我们从 y 坐标 120 - 50 = 70 开始绘制,这不是 50 的倍数。

      为了纠正这个问题,我们将上下文向下移动 120 % 50 = 20,然后将绘制位置向上移动 20。因此,图案在 y 坐标 (70 - 20) = 50,是图片高度的倍数。

      var canvas = document.getElementById('myCanvas'),
          context = canvas.getContext('2d');
      canvas.height = 120;
      canvas.width = 500;
      
      var image = new Image();
      image.src = 'http://i.stack.imgur.com/2bfPb.png';
      image.onload = function () {
        var pattern = context.createPattern(image, "repeat");
        context.fillStyle = pattern;
        var shiftY = canvas.height % image.height;
        context.translate(0, shiftY);
        context.fillRect(0, canvas.height - image.height - shiftY,
                         canvas.width, image.height);
        context.translate(0, -shiftY);
      };
      #myCanvas {
        border: 1px solid #666;
      }
      &lt;canvas id="myCanvas"&gt;&lt;/canvas&gt;

      让我再做一个观察。代码中的循环效率低下,bgReady 标志是不必要的,因为您可以在 image.onload 函数中运行绘画代码,就像我在 sn-p 中所做的那样。

      【讨论】:

      • 感谢您的指示和代码。它有效:-)
      猜你喜欢
      • 2017-07-24
      • 2021-07-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多