我的背景图片占据了画布的整个宽度和高度,我希望能够在图像上引用不同的位置,所以我在图像中的这些点放置一些圆圈,这样我就可以在视觉上确认我有合适的位置。
我通过在我想要绘制点的位置单击鼠标来执行此操作,在鼠标单击侦听器事件中使用以下代码:
var rectCanvas = canvas.getBoundingClientRect();
var positionX = Math.round(((e.clientX - rectCanvas.left) / canvas.width * 100) * 1000) / 1000;
var positionY = Math.round(((e.clientY - rectCanvas.top) / canvas.height * 100) * 1000) / 1000;
//alert(positionX + ", " + positionY);
alert("Width\nPosition: " + (e.clientX - rectCanvas.left) + "\nPercentage Position: " + positionX + "\nBack to position: " + percentToPxHor(positionX));
我声明了以下例程:
function percentToPxHor(intPx) {
return intPx * canvas.width / 100;
}
function percentToPxVert(intPx) {
return intPx * canvas.height / 100;
}
点击背景图片的显着特征,我得到一个有意义的值。例如,点击图像的中间位置会提示我:
宽度
位置:532.5
百分比位置:53.091
回到位置:532.50273
由此我可以清楚地告诉我将例程宽度的百分比转换回像素值。但是,当我尝试将其付诸实践时,它并没有起作用。
当我尝试绘制前面提到的圆圈时,它会将它们正确放置在Y轴上,但在X轴上向右偏移。我怀疑这与我考虑画布相对于窗口的位置的方式有关,但是我不能完全把手指放在它上面。放置在图像左侧的圆圈稍微偏右,放置在图像右侧的圆圈偏得太远(几乎就像问题一样,它应用指数问题)所涉及的数字越大越糟糕。
当我添加这些圈子时,我使用以下代码片段在矩形的每个角上放置四个,一个:
var topLeft = {x:percentToPxHor(17.275),y:percentToPxVert(59.691)};
var bottomLeft = {x:percentToPxHor(17.275),y:percentToPxVert(60.72)};
var topRight = {x:percentToPxHor(71.459),y:percentToPxVert(61.407)};
var bottomRight = {x:percentToPxHor(71.352),y:percentToPxVert(62.436)};
非常感谢任何帮助。
答案 0 :(得分:1)
我为鼠标位置做了一个测试仪,显示了边界时的偏移量。可能还有其他因素,但这表明getBoundingClientRect是如何不准确的。我在FireFox上测试过,你可以清楚地看到偏移量。
var canvas = document.getElementById('rect-canvas');
var check = document.getElementById('no-border-checkbox');
var ctx = canvas.getContext('2d');
var mouse = {p:{x:0, y:0}, frame:0, frames:30};
var topLeft = {x:percentToPxHor(17.275),y:percentToPxVert(59.691)};
var bottomLeft = {x:percentToPxHor(17.275),y:percentToPxVert(60.72)};
var topRight = {x:percentToPxHor(71.459),y:percentToPxVert(61.407)};
var bottomRight = {x:percentToPxHor(71.352),y:percentToPxVert(62.436)};
main();
function main() {
check.addEventListener('change', function(e) {
var className = check.checked ? 'border' : '';
canvas.setAttribute('class',className);
});
canvas.addEventListener('mousemove',function(e){
var rectCanvas = canvas.getBoundingClientRect();
var positionX = Math.round(((e.clientX - rectCanvas.left) / canvas.width * 100) * 1000) / 1000;
var positionY = Math.round(((e.clientY - rectCanvas.top) / canvas.height * 100) * 1000) / 1000;
//alert("Width\nPosition: " + (e.clientX - rectCanvas.left) + "\nPercentage Position: " + positionX + "\nBack to position: " + percentToPxHor(positionX));
mouse.p.x = percentToPxHor(positionX);
mouse.p.y = percentToPxVert(positionY);
render();
});
}
function render() {
// clear canvas
ctx.fillStyle='white';
ctx.fillRect(0,0,canvas.width,canvas.height);
// draw points and connect
drawCircle(topLeft, "blue");
drawCircle(bottomLeft, "green");
drawCircle(topRight, "red");
drawCircle(bottomRight, "orange");
drawPoly([topLeft, bottomLeft, bottomRight, topRight]);
// draw mouse circle
drawCircle(mouse.p, 'rgba(255,200,0,.75)', 10);
// draw mouse lines
var h1 = {x:0, y: mouse.p.y};
var h2 = {x:canvas.width, y: mouse.p.y};
var v1 = {x: mouse.p.x, y:0};
var v2 = {x: mouse.p.x, y:canvas.height};
drawPoly([h1, h2], "rgba(0,0,0,.25)");
drawPoly([v1, v2], "rgba(0,0,0,.25)");
}
function percentToPxHor(intPx) {
return intPx * canvas.width / 100;
}
function percentToPxVert(intPx) {
return intPx * canvas.height / 100;
}
function drawCircle(p, color, radius) {
if (typeof radius == 'undefined') radius = 2;
if (typeof color == 'undefined') color = 'red';
ctx.beginPath();
ctx.fillStyle = color;
ctx.arc(p.x,p.y,radius,0,2*Math.PI);
ctx.fill();
}
function drawPoly(points, color) {
ctx.strokeStyle = color ? color : 'red';
ctx.beginPath();
var p = points[points.length-1];
ctx.moveTo(p.x, p.y);
for(var i = 0; i < points.length; i++) {
var p = points[i];
ctx.lineTo(p.x, p.y);
}
ctx.stroke();
}
&#13;
#rect-canvas {
}
.border {
border:5px solid red;
}
body {
background-color:#cccccc;
}
&#13;
<canvas id='rect-canvas' class='border' width="300" height="150"></canvas>
<p>
Border
<input type='checkbox' id='no-border-checkbox' value='on' checked>
</p>
&#13;