#javascript #canvas
#javascript #холст
Вопрос:
У меня есть фоновое изображение, которое занимает всю ширину и высоту моего холста, и я хочу иметь возможность ссылаться на разные местоположения на изображении, поэтому я размещаю несколько кругов в этих точках изображения, чтобы я мог визуально подтвердить, что у меня есть правильное место.
Я делаю это, щелкая мышью в том месте, где я хочу нарисовать точку, со следующим кодом в моем событии прослушивания щелчка мыши:
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("WidthnPosition: " (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)};
Любая помощь была бы высоко оценена.
Ответ №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("WidthnPosition: " (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();
}
#rect-canvas {
}
.border {
border:5px solid red;
}
body {
background-color:#cccccc;
}
<canvas id='rect-canvas' class='border' width="300" height="150"></canvas>
<p>
Border
<input type='checkbox' id='no-border-checkbox' value='on' checked>
</p>