javascript - Obține dimensiunile unui grafic HTML5 canvas (Arc), atunci când are loc un eveniment
Întrebarea mea este: cum ar trebui să fac partea logică și matematică, pentru a calcula poziția fiecărui arc, atunci când este emis un eveniment: „click”, „mouseover”, etc.
Puncte de luat în considerare:
. Lățimea liniei
. Ele sunt linii rotunjite.
. Lungimea arcului în procent.
. Care element este primul, de ex: poziția z-index.
Codul meu sursă
Îți mulțumesc pentru timpul acordat.
Răspuns #1
Există o metodă convenabilă isPointInStroke(), exact pentru asta.
Pentru a lua în considerare z-index-ul, pur și simplu verificați în ordinea inversă în care ați desenat:
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>Și dacă ai nevoie de suport pentru IE, acest polyfill ar trebui să fie potrivit.
Răspunsul #2
Este mult mai bine să „-ți amintești” obiectele pe care le-ai desenat, decât să le desenezi și să încerci să afli ce sunt din ceea ce ai desenat. Așadar, de exemplu, ai putea stoca informațiile de redare: (Nu știu TypeScript)
let curves = [{start: 30, length: 40, color: "white"}/*...*/];
Apoi, redă-l:
ctx.fillStyle = curve.color;
ctx.arc(CENTER_X, CENTER_Y, RADIUS, percentToRadians(curve.start), percentToRadians(curve.start + curve.length));
Apoi, pentru a prelua informațiile, referiți-vă pur și simplu la curves. Valorile z depind de ordinea cozii de redare (curves).
Desigur, probabil că ați putea colecta acele date de pe pânză, dar nu aș recomanda asta.
