如何删除 canvas 元素两侧的细边框?
How to remove thin border on 2 sides of canvas element?
更新: Link to JSFiddle with workable code
我正在制作一个网站并创建了两个 canvas 元素的堆栈:顶部 canvas 上下文是一个白色矩形,它“擦除”以显示加载到底部的图像 canvas上下文。该功能正常工作。我的问题是,当我包含 setInterval 代码行时,canvas 堆栈 的右侧和底部会出现灰色细边框。
当我删除这个计时器变量(见下面的代码)时它会消失,但如果我向 canvas 元素添加任何类型的状态检查(如 onmouseout),它会重新出现。这是屏幕截图:
知道为什么会这样吗?类似的SOquestions/solutions没有解决我的问题
window.onload = function() {
var speaker = document.getElementById('speaker');
//speaker.onload = MoveElement(speaker, "right", 1000);
//Create canvases & contexts
var canvas = document.getElementById('canvas');
var ctxB = canvas.getContext('2d');
var canvas2 = document.getElementById('canvas2');
var ctxT = canvas2.getContext('2d');
//Get waterfall image object
var waterfall = document.getElementById('waterfall');
//Set canvas w&h properties
canvas.width = canvas2.width = .3*waterfall.width;
canvas.height = canvas2.height = .3*waterfall.height;
//Populate Bottom canvas with waterfall image
ctxB.drawImage(waterfall, 0, 0, canvas.width, canvas.height);
//Populate Top canvas with white rectangle
ctxT.fillStyle = "white";
ctxT.fillRect(0, 0, canvas2.width, canvas2.height);
//Make Top canvas "erasable"
canvas2.addEventListener('mousemove', event => {
var x = event.offsetX;
var y = event.offsetY;
const eraseSize = 15;
ctxT.clearRect(x-eraseSize/2, y-eraseSize/2, eraseSize, eraseSize);
});
}
//Set interval timer to repeatedly execute TransparencyCheck()
var timer = setInterval(TransparencyCheck, 500);
//Check that all pixel alpha values = 0
function TransparencyCheck() {
var canvas2 = document.getElementById('canvas2');
var ctxT = canvas2.getContext('2d');
var imageDataTop = ctxT.getImageData(0, 0, canvas2.width, canvas2.height);
var counter = 0;
for (var i = 3; i < imageDataTop.data.length; i += 4) {
if (imageDataTop.data[i] == 0) {
counter++;
}
if (counter == imageDataTop.data.length/4) {
canvas2.style.opacity = "0";
}
}
}
#stack {
position: relative;
}
#stack canvas {
position: absolute;
display: block;
left: 50%;
transform: translateX(-50%);
margin-top: 150px;
}
<img hidden src="https://sample-videos.com/img/Sample-jpg-image-50kb.jpg" alt="issue here" id="waterfall" />
<div id="stack">
<canvas id="canvas"></canvas>
<canvas id="canvas2" onmouseout="TransparencyCheck()"></canvas>
</div>
问题是 canvas 的尺寸被计算为基础图像尺寸的分数 (0.3)。这可能会导致 'part pixel' 问题。也就是说,系统必须决定如何显示 CSS 像素的一小部分,而在现代屏幕上,几个屏幕像素用于显示一个 CSS 像素。一个screen pixwl在这个过程中可以得到'left behind'(即还在显示)
绕过这个问题的一个稍微老套的方法(但我不知道其他方法)是将底部 canvas 的大小减小几个像素,这样我们就可以绝对确定任何剩余的都在开始时顶部的白色 canvas。
此代码段通过将宽度和高度减去 2 像素来加倍确定。
顺便说一句,我从问题指向的代码笔中复制了代码,它作为一个 SO 代码段工作正常。这是:
window.onload = function() {
var speaker = document.getElementById('speaker');
//speaker.onload = MoveElement(speaker, "right", 1000);
//Create canvases & contexts
var canvas = document.getElementById('canvas');
var ctxB = canvas.getContext('2d');
var canvas2 = document.getElementById('canvas2');
var ctxT = canvas2.getContext('2d');
//Get waterfall image object
var waterfall = document.getElementById('waterfall');
//Set canvas w&h properties
canvas.width = canvas2.width = .3 * waterfall.width;
canvas.width = canvas.width - 2;
canvas.height = canvas2.height = .3 * waterfall.height;
canvas.height = canvas.height - 2;
//Populate Bottom canvas with waterfall image
ctxB.drawImage(waterfall, 0, 0, canvas.width, canvas.height);
//Populate Top canvas with white rectangle
ctxT.fillStyle = "white";
ctxT.fillRect(0, 0, canvas2.width, canvas2.height);
//Make Top canvas "erasable"
canvas2.addEventListener('mousemove', event => {
var x = event.offsetX;
var y = event.offsetY;
const eraseSize = 15;
ctxT.clearRect(x - eraseSize / 2, y - eraseSize / 2, eraseSize, eraseSize);
});
}
//Set interval timer to repeatedly execute TransparencyCheck()
var timer = setInterval(TransparencyCheck, 5000);
//Check that all pixel alpha values = 0
function TransparencyCheck() {
var canvas2 = document.getElementById('canvas2');
var ctxT = canvas2.getContext('2d');
var imageDataTop = ctxT.getImageData(0, 0, canvas2.width, canvas2.height);
var counter = 0;
for (var i = 3; i < imageDataTop.data.length; i += 4) {
if (imageDataTop.data[i] == 0) {
counter++;
}
if (counter >= imageDataTop.data.length / 4) {
canvas2.style.opacity = "0";
clearTimeout(timer);
alert('all top canvas erased');
}
}
}
#stack {
position: relative;
}
#stack canvas {
position: absolute;
display: block;
left: 50%;
transform: translateX(-50%);
margin-top: 150px;
}
<img hidden src="https://sample-videos.com/img/Sample-jpg-image-50kb.jpg" alt="issue here" id="waterfall" />
<div id="stack">
<canvas id="canvas"></canvas>
<canvas id="canvas2" onmouseout="TransparencyCheck()"></canvas>
</div>
更新: Link to JSFiddle with workable code
我正在制作一个网站并创建了两个 canvas 元素的堆栈:顶部 canvas 上下文是一个白色矩形,它“擦除”以显示加载到底部的图像 canvas上下文。该功能正常工作。我的问题是,当我包含 setInterval 代码行时,canvas 堆栈 的右侧和底部会出现灰色细边框。
当我删除这个计时器变量(见下面的代码)时它会消失,但如果我向 canvas 元素添加任何类型的状态检查(如 onmouseout),它会重新出现。这是屏幕截图:
知道为什么会这样吗?类似的SOquestions/solutions没有解决我的问题
window.onload = function() {
var speaker = document.getElementById('speaker');
//speaker.onload = MoveElement(speaker, "right", 1000);
//Create canvases & contexts
var canvas = document.getElementById('canvas');
var ctxB = canvas.getContext('2d');
var canvas2 = document.getElementById('canvas2');
var ctxT = canvas2.getContext('2d');
//Get waterfall image object
var waterfall = document.getElementById('waterfall');
//Set canvas w&h properties
canvas.width = canvas2.width = .3*waterfall.width;
canvas.height = canvas2.height = .3*waterfall.height;
//Populate Bottom canvas with waterfall image
ctxB.drawImage(waterfall, 0, 0, canvas.width, canvas.height);
//Populate Top canvas with white rectangle
ctxT.fillStyle = "white";
ctxT.fillRect(0, 0, canvas2.width, canvas2.height);
//Make Top canvas "erasable"
canvas2.addEventListener('mousemove', event => {
var x = event.offsetX;
var y = event.offsetY;
const eraseSize = 15;
ctxT.clearRect(x-eraseSize/2, y-eraseSize/2, eraseSize, eraseSize);
});
}
//Set interval timer to repeatedly execute TransparencyCheck()
var timer = setInterval(TransparencyCheck, 500);
//Check that all pixel alpha values = 0
function TransparencyCheck() {
var canvas2 = document.getElementById('canvas2');
var ctxT = canvas2.getContext('2d');
var imageDataTop = ctxT.getImageData(0, 0, canvas2.width, canvas2.height);
var counter = 0;
for (var i = 3; i < imageDataTop.data.length; i += 4) {
if (imageDataTop.data[i] == 0) {
counter++;
}
if (counter == imageDataTop.data.length/4) {
canvas2.style.opacity = "0";
}
}
}
#stack {
position: relative;
}
#stack canvas {
position: absolute;
display: block;
left: 50%;
transform: translateX(-50%);
margin-top: 150px;
}
<img hidden src="https://sample-videos.com/img/Sample-jpg-image-50kb.jpg" alt="issue here" id="waterfall" />
<div id="stack">
<canvas id="canvas"></canvas>
<canvas id="canvas2" onmouseout="TransparencyCheck()"></canvas>
</div>
问题是 canvas 的尺寸被计算为基础图像尺寸的分数 (0.3)。这可能会导致 'part pixel' 问题。也就是说,系统必须决定如何显示 CSS 像素的一小部分,而在现代屏幕上,几个屏幕像素用于显示一个 CSS 像素。一个screen pixwl在这个过程中可以得到'left behind'(即还在显示)
绕过这个问题的一个稍微老套的方法(但我不知道其他方法)是将底部 canvas 的大小减小几个像素,这样我们就可以绝对确定任何剩余的都在开始时顶部的白色 canvas。
此代码段通过将宽度和高度减去 2 像素来加倍确定。
顺便说一句,我从问题指向的代码笔中复制了代码,它作为一个 SO 代码段工作正常。这是:
window.onload = function() {
var speaker = document.getElementById('speaker');
//speaker.onload = MoveElement(speaker, "right", 1000);
//Create canvases & contexts
var canvas = document.getElementById('canvas');
var ctxB = canvas.getContext('2d');
var canvas2 = document.getElementById('canvas2');
var ctxT = canvas2.getContext('2d');
//Get waterfall image object
var waterfall = document.getElementById('waterfall');
//Set canvas w&h properties
canvas.width = canvas2.width = .3 * waterfall.width;
canvas.width = canvas.width - 2;
canvas.height = canvas2.height = .3 * waterfall.height;
canvas.height = canvas.height - 2;
//Populate Bottom canvas with waterfall image
ctxB.drawImage(waterfall, 0, 0, canvas.width, canvas.height);
//Populate Top canvas with white rectangle
ctxT.fillStyle = "white";
ctxT.fillRect(0, 0, canvas2.width, canvas2.height);
//Make Top canvas "erasable"
canvas2.addEventListener('mousemove', event => {
var x = event.offsetX;
var y = event.offsetY;
const eraseSize = 15;
ctxT.clearRect(x - eraseSize / 2, y - eraseSize / 2, eraseSize, eraseSize);
});
}
//Set interval timer to repeatedly execute TransparencyCheck()
var timer = setInterval(TransparencyCheck, 5000);
//Check that all pixel alpha values = 0
function TransparencyCheck() {
var canvas2 = document.getElementById('canvas2');
var ctxT = canvas2.getContext('2d');
var imageDataTop = ctxT.getImageData(0, 0, canvas2.width, canvas2.height);
var counter = 0;
for (var i = 3; i < imageDataTop.data.length; i += 4) {
if (imageDataTop.data[i] == 0) {
counter++;
}
if (counter >= imageDataTop.data.length / 4) {
canvas2.style.opacity = "0";
clearTimeout(timer);
alert('all top canvas erased');
}
}
}
#stack {
position: relative;
}
#stack canvas {
position: absolute;
display: block;
left: 50%;
transform: translateX(-50%);
margin-top: 150px;
}
<img hidden src="https://sample-videos.com/img/Sample-jpg-image-50kb.jpg" alt="issue here" id="waterfall" />
<div id="stack">
<canvas id="canvas"></canvas>
<canvas id="canvas2" onmouseout="TransparencyCheck()"></canvas>
</div>