Get dimensions of a HTML5 canvas graphic (Arc), when an event occurs

ぐ巨炮叔叔 提交于 2020-01-05 07:18:10

问题


My question is: how should I do the logical and mathematical part, in order to calculate the position of each arc, when an event is emitted: "click", "mouseover", etc.

Points to consider:

. Line width

. They are rounded lines.

. Arc length in percentage.

. Which element is first, ej: z-index position.

My source code

Thank you for your time.


回答1:


There is a convenient isPointInStroke() method, just for that.

To take the z-index into consideration, just check in the reverse order you drew:

const ctx = canvas.getContext('2d');
const centerX = canvas.width/2;
const centerY = canvas.height/2;
const rad = Math.min(centerX, centerY) * 0.75;
const pathes = [
  {
    a: Math.PI/4,
    color: 'white'
  },
  {
    a: Math.PI/1.5,
    color: 'cyan'
  },
  {
    a: Math.PI,
    color: 'violet'
  },
  {
    a: Math.PI*2,
    color: 'gray'
  }
];
pathes.forEach(obj => {
  const p = new Path2D();
  p.arc(centerX, centerY, rad, -Math.PI/2, obj.a-Math.PI/2);
  obj.path = p;
});

ctx.lineWidth = 12;
ctx.lineCap = 'round';

function draw() {
  ctx.clearRect(0,0,canvas.width,canvas.height);
  // since we sorted first => higher z-index
  for(let i = pathes.length-1; i>=0; i--) {
    let p = pathes[i];
    ctx.strokeStyle = p.hovered ? 'green' : p.color;
    ctx.stroke(p.path);
  };
}
function checkHovering(evt) {
  const rect = canvas.getBoundingClientRect();
  const x = evt.clientX - rect.left;
  const y = evt.clientY - rect.top;
  let found = false;
  pathes.forEach(obj => {
    if(found) {
      obj.hovered = false;
    }
    else {
      found = obj.hovered = ctx.isPointInStroke(obj.path, x, y);
    }
  });
  draw();
}

draw();
canvas.onmousemove = canvas.onclick = checkHovering;

 
canvas{background: lightgray}
<canvas id="canvas"></canvas>

And if you need IE support, this polyfill should do.




回答2:


It's much better to "remember" the objects you drew, rather than drawing them and trying to gather what they are from what you drew. So, for example, you could store the render information: (I don't know typescript)

let curves = [{start: 30, length: 40, color: "white"}/*...*/];

Then, render it:

ctx.fillStyle = curve.color;
ctx.arc(CENTER_X, CENTER_Y, RADIUS, percentToRadians(curve.start), percentToRadians(curve.start + curve.length));

Then, to retrieve the information, simply reference curves. The z values depend on the order of the render queue (curves).

Of course, you probably could gather that data from the canvas, but I wouldn't recommend it.



来源:https://stackoverflow.com/questions/52731097/get-dimensions-of-a-html5-canvas-graphic-arc-when-an-event-occurs

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!