我的页面上有一个画布,我有一个工具,允许用户选择他/她想要裁剪的区域。它看起来像这样:
要裁剪图像,我计算左上角像素坐标[xmin, ymin]
和右下角坐标[xmax,ymax]
。裁剪本身就像这样:
context.drawImage(image,xmin,ymin,xmax-xmin,ymax-ymin,0,0,xmax-xmin,ymax-ymin);
问题是,在一些随机计算机和一些随机浏览器上,这段代码会生成正确的块,而另一些则不正确。这就是为什么我甚至无法提供演示或小提琴。在我的笔记本电脑上,在所有浏览器(FF,IE,Opera,Chrome,Safari)上都可以,但在我的用户计算机上它是不正确的。
所以,我的问题是,这次电话会出现什么问题:
context.drawImage(image,xmin,ymin,xmax-xmin,ymax-ymin,0,0,xmax-xmin,ymax-ymin);
有什么东西,我应该考虑使这个代码跨浏览器和跨平台?
答案 0 :(得分:2)
您的问题是*您的某些用户将其浏览器的缩放级别设置为100%以外的其他用户。
根据您当前的逻辑,您假设图像以原始大小显示,这是drawImage
使用的大小。但是当放大或缩小时,浏览器会缩放渲染图像,使光标坐标在图像的自然尺寸方面出错。
为避免这种情况,您需要相对于显示的比例缩放坐标尺寸/自然尺寸。
这是一个简单的例子。
onload = function() {
const ctx = c.getContext('2d');
c.width = img.width;
c.height = img.height;
img.onmousedown = c.onmousedown = handleMouseDown;
img.onmousemove = c.onmousemove = handleMouseMove;
img.onmouseup = c.onmouseup = handleMouseUp;
var rect = { min_x: 0, min_y: 0, max_x: 0, max_y: 0, updating: false};
draw();
function handleMouseDown(evt) {
evt.preventDefault();
var targetBB = evt.target.getBoundingClientRect();
rect.updating = true;
rect.min_x = rect.max_x = evt.clientX - targetBB.left;
rect.min_y = rect.max_y = evt.clientY - targetBB.top;
draw();
}
function handleMouseUp(evt) {
rect.updating = false;
draw();
}
function handleMouseMove(evt) {
if(!rect.updating) return;
var targetBB = evt.target.getBoundingClientRect();
rect.max_x = evt.clientX - targetBB.left;
rect.max_y = evt.clientY - targetBB.top;
draw();
}
function draw() {
ctx.filter = 'blur(2px)';
ctx.drawImage(img, 0,0);
ctx.filter = 'none';
var dx = Math.min(rect.min_x, rect.max_x),
dy = Math.min(rect.min_y, rect.max_y),
dw = Math.abs(rect.min_x - rect.max_x),
dh = Math.abs(rect.min_y - rect.max_y);
if(!dh || !dw) return;
ctx.strokeRect(dx, dy, dw, dh);
var ratio_W = img.clientWidth / img.naturalWidth,
ratio_H = img.clientHeight / img.naturalHeight,
sx = dx * ratio_W,
sy = dy * ratio_H,
sw = dw * ratio_W,
sh = dh * ratio_H;
ctx.drawImage(img, sx, sy, sw, sh, dx, dy, dw, dh);
}
}
<h3>Try to zoom-in/out your browser</h3>
<img id="img" src="https://i.stack.imgur.com/ujq5W.png">
<canvas id="c"></canvas>
*根据your comment。