使用 vanilla JavaScript 和 canvas 的解决方案
您可以将复杂形状嵌入到处理位置和检查的对象中。一个对象可能如下所示:
Full working demo here
提炼:
主要对象——
function wave(ctx, offset, width) {
/// the check function which checks point x, y in last path
this.isInPath = function(x, y) {
getPath();
return ctx.isPointInPath(x, y);
}
/// this render the object with the set fill color
this.draw = function(color) {
getPath();
ctx.fillStyle = color;
ctx.fill();
ctx.lineWidth = 5;
ctx.strokeStyle = "red";
ctx.stroke();
}
/// common function to generate just the path.
function getPath() {
ctx.beginPath();
ctx.moveTo(offset, 0);
ctx.bezierCurveTo(50 + offset, 30, 40 + offset, 45, 13 + offset, 89);
ctx.bezierCurveTo(offset, 110, offset, 126, 27 + offset, 174);
ctx.lineTo(27 + offset + width, 174);
ctx.bezierCurveTo(offset + width, 100, offset + width + 0, 126, 27 + offset + width, 65);
ctx.bezierCurveTo(43 + offset + width, 40, 40 + offset + width, 25, offset + width, 0);
ctx.closePath();
}
this.draw('white');
return this;
}
确保路径是独立的,这意味着它是一个完整的形状,不依赖于相邻部分(即不使用相邻线)。这基本上就是您处理复杂形状所需要做的所有事情。
使成为
要渲染只需这样做:
for(;i < parts_num; i++) {
parts.push( new wave(context, i * part_width, part_width) );
}
查看
至于检查点是否在零件中,您可以这样做:
/// check mouse move in this example
canvas.addEventListener('mousemove', hover, false);
/// the function to check parts
function hover(e) {
///get mouse coord relative to canvas
var r = canvas.getBoundingClientRect();
var x = e.clientX - r.left;
var y = e.clientY - r.top;
///optimize so we only clear last selected part
if (lastPart > -1) {
parts[lastPart].draw('white');
lastPart = -1;
}
for(i = 0 ;i < parts_num; i++) {
if (parts[i].isInPath(x, y) === true) {
parts[i].draw('green');
lastPart = i;
break; //don't need to check more
}
}
}
这里有优化的空间(重用对象内部的最后一条路径,将形状缓存为图像,分段检查范围等),但表明使用 vanilla canvas 和 JavaScript 处理它并不是那么复杂。
以此为基础,您应该能够自己处理点击等。
(注意:我对贝塞尔曲线的结束端不太准确 - 如果您应该选择使用此解决方案,我会留给您微调它..)。