Javascript - 使用宽度和宽度的百分比在画布上绘图高度

时间:2016-10-19 03:10:53

标签: javascript canvas

我的背景图片占据了画布的整个宽度和高度,我希望能够在图像上引用不同的位置,所以我在图像中的这些点放置一些圆圈,这样我就可以在视觉上确认我有合适的位置。

我通过在我想要绘制点的位置单击鼠标来执行此操作,在鼠标单击侦听器事件中使用以下代码:

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)};

非常感谢任何帮助。

1 个答案:

答案 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;
&#13;
&#13;