Tratando de dibujar un patrón dividido en algunas partes con canvas html5

Necesito dibujar con el canvas html5 de esta forma, puedo dibujarlo como un canvas.

http://postimg.org/image/li5mpoot3/

Necesito manejar cada parte de como un object único: escucho el mouse sobre cada parte, determino en cuál de las partes está colocando el mouse, y también le doy la opción al usuario de rellenar la parte relevante de la forma.

var canvas = document.getElementById('shape'); var context = canvas.getContext('2d'), width = $('#shape').width(), part_width = width / parts_num; context.beginPath(); var start_x = 17, end_x = 17 + part_width; for (var i = 0; i < parts_num; i++) { context.moveTo(start_x, 0); context.lineTo(end_x,0); context.moveTo(start_x, 0); context.bezierCurveTo(50+start_x, 30, 40+start_x, 45, 13+start_x, 89); context.moveTo(13+start_x, 89); context.bezierCurveTo(0+start_x, 110, 0+start_x, 126, 27+start_x, 174); context.moveTo(28+start_x, 174); context.lineTo(85+start_x,174); start_x += part_width;//80 is x starting point }; context.lineWidth = 5; context.strokeStyle = "networking"; context.stroke(); 

Sugeriría usar CreateJS . Haría su vida mucho más fácil al trabajar con canvas.

Aquí hay una demostración de cómo puedes manejar cada forma como un object con CreateJS.

Haga clic en la forma individual para ver cómo cada uno activa su propio controller.

 function curveShape(index, start_x, end_x) { var shape = new createjs.Shape(); var context = shape.graphics.beginStroke("networking").beginFill("#ffffee"); context.moveTo(start_x, 0); context.bezierCurveTo(start_x + 10, 30, start_x + 10, 45, start_x - 15, 90); context.bezierCurveTo(start_x - 30, 120, start_x - 30, 135, start_x, 180); context.lineTo(end_x, 180); context.bezierCurveTo(end_x - 30, 135, end_x - 30, 120, end_x - 15, 90); context.bezierCurveTo(end_x + 10, 45, end_x + 10, 30, end_x, 0); context.lineTo(start_x, 0); shape.name = "shape " + index; shape.x = shape.y = 30; shape.addEventListener("mousedown", function () { alert("I am " + shape.name); }); return shape; } var stage = new createjs.Stage("shape"); for(var i = 0; i < 4; i++) stage.addChild(new curveShape(i+1, i * 80, (i + 1) * 80)); stage.update(); 

Solución con JavasScript y canvas de vainilla

Puede incrustar la forma compleja en un object que maneje la position y las verificaciones. Un object podría verse así:

Demostración de trabajo completo aquí

Extraer:

Objeto principal –

 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 = "networking"; 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; } 

Asegúrese de que la ruta sea autónoma, lo que significa que es una forma completa que no depende de las partes vecinas (es decir, que no utiliza las líneas vecinas). Eso es básicamente todo lo que necesita hacer para manejar forms complejas.

Hacer

Para renderizar simplemente haz esto:

 for(;i < parts_num; i++) { parts.push( new wave(context, i * part_width, part_width) ); } 

Comprobar

Como verificar si hay un punto en la parte puedes hacer esto:

 /// 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 } } } 

Aquí hay espacio para la optimization (reutilización de la última ruta dentro del object, almacenamiento en caching de la forma como imágenes, range de verificación del segmento, etc.) pero muestra que no es realmente tan complejo manejar esto usando vainilla canvas y JavaScript.

Con esto como base, debería poder manejar los clics y demás.

(Nota: no he sido muy preciso con el cierre en el bezier; le dejo ajustarlo si debe usar esta solución …).