gpt4 book ai didi

javascript - 缩放时JS Canvas 白线

转载 作者:行者123 更新时间:2023-11-29 23:08:08 30 4
gpt4 key购买 nike

我使用 JavaScript 在 html 5 Canvas 上显示一个数组。该程序对数组中的每个值使用 c.fillRect()。一切看起来都很正常,直到我使用 c.scale() 缩放它。缩放后,方 block 之间可以看到白线。我知道它们是白色的,因为那是背景的颜色(当背景改变时,它们的颜色也会改变)。

由于正方形相隔 5 个单位,我尝试将它们的宽度设置为 5.5 而不是 5;这只会在放大到足够远时去除白线,但当缩小时白线仍然存在。

这是我的代码(删除了不必要的部分):

function loop()
{
c.resetTransform();

c.fillStyle = "white";
c.fillRect(0, 0, c.canvas.width, c.canvas.height);

c.scale(scale, scale);
c.translate(xViewportOffset, yViewportOffset);

...

for(var x = 0; x < array.length; x++)
{
for(var y = 0; y < array[x].length; y++)
{
...

c.fillStyle = 'rgb(' + r + ',' + g + ',' + b + ')';
c.fillRect(0 + x * 5, 200 + y * 5, 5, 5);
}
}

...
}

无缩放:

no scaling image

放大:

zoomed in image

缩小:

zoomed out image

(图案根据缩放量而变化)

感谢您的帮助,如果需要任何其他信息,请告诉我。

更新:

我正在使用谷歌浏览器

版本 71.0.3578.98(官方构建)(64 位)

最佳答案

这可能是因为您使用非整数值来设置上下文的比例和/或翻译。

这样做,您的 rects 不再位于像素边界上,而是位于 float 值上。

举个简单的例子:

两个像素,一个坐标为 (x,y) (11,10),另一个坐标为 (12,10)。
在默认比例下,两个像素应该是相邻的。
现在,如果我们应用 1.3 的比例,第一个方 block 的实际像素坐标将在 (14.3,13),第二个方 block 的坐标在 ( 15.6,13).
这些坐标都不能容纳单个像素,因此浏览器将应用抗锯齿,这包括使您的颜色与背景颜色平滑,以给人以较小像素的印象。这就是您制作网格的原因。

const ctx = small.getContext('2d');

ctx.scale(1.3, 1.3);

ctx.fillRect(2,10,10,10);

ctx.fillRect(12,10,10,10);


const mag = magnifier.getContext('2d');
mag.scale(10,10);
mag.imageSmoothingEnabled = false;
mag.drawImage(small, 0,-10);
/* it is actually transparent, not just more white */
body:hover{background:yellow}
<canvas id="small" width="50" height="50"></canvas><br>
<canvas id="magnifier" width="300" height="300"></canvas>

为避免这种情况,有几种解决方案,都取决于您的具体操作。

在您的情况下,您似乎可以通过研究 ImageData 赢得很多这将允许您将所有这些 fillRect 调用替换为更简单和更快的像素操作。
通过使用矩阵大小的小 ImageData,您可以将每个 rect 替换为单个像素。然后你只需要把这个矩阵放在你的 Canvas 上,并在禁用 imageSmootingEnabled 后以正确的比例重新绘制 Canvas 。标志,它允许我们仅对 drawImageCanvasPatterns 禁用抗锯齿。

// the original matrix will be 20x20 squares
const width = 20;
const height = 20;
const ctx = canvas.getContext('2d');
// create an ImageData the size of our matrix
const img = ctx.createImageData(width, height);
// wrap it inside an Uint32Array so that we can work on it faster
const pixels = new Uint32Array(img.data.buffer);
// we could have worked directly with the Uint8 version
// but our loop would have needed to iterate 4 pixels every time

// just to draw a radial-gradient
const rad = width / 2;
// iterate over every pixels
for(let x=0; x<width; x++) {
for(let y=0; y<height; y++) {
// make a radial-gradient
const dist = Math.min(Math.hypot(rad - x, rad - y), rad);
const color = 0xFF * ((rad - dist) / rad) + 0xFF000000;
pixels[(y * width) + x] = color;
}
}
// here we are still at 50x50 pixels
ctx.putImageData(img, 0, 0);
// in case we had transparency, this composite mode will ensure
// that only what we draw after is kept on the canvas
ctx.globalCompositeOperation = "copy";
// remove anti-aliasing for drawImage
ctx.imageSmoothingEnabled = false;
// make it bigger
ctx.scale(30,30);
// draw the canvas over itself
ctx.drawImage(canvas, 0,0);

// In case we draw again, reset all to defaults
ctx.setTransform(1,0,0,1,0,0);
ctx.globalCompositeOperation = "source-over";
body:hover{background:yellow}
<canvas id="canvas" width="600" height="600"></canvas>

关于javascript - 缩放时JS Canvas 白线,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54390894/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com