html5 canvas - tipos - Prueba de impacto contra formas de texto
innerhtml javascript ejemplo (2)
Puedes probar la forma de un texto (o cualquier otra forma matemáticamente irregular) enviando un mensaje de texto indicando si el píxel debajo del mouse es transparente o no.
Puede obtener la matriz de píxeles para todo el lienzo usando:
var data=context.getImageData(0,0,canvas.width,canvas.height).data;
Luego puede obtener el valor de opacidad (alfa) para el píxel debajo del mouse de esta manera:
var pixelIsTransparent = data[(mouseY*canvas.width+mouseX)*4+3]==0
Si el píxel no es transparente, entonces está sobre la forma del texto.
Si tiene otros dibujos que no sean de texto en el lienzo, los dibujos que no sean de texto pueden dar falsos positivos para sus pruebas de aciertos. Una solución alternativa consiste en utilizar un segundo lienzo en memoria que solo contenga su forma de texto y luego realizar una prueba de golpe contra los píxeles en ese segundo lienzo.
Aquí hay un código de ejemplo y una demostración:
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
var $canvas=$("#canvas");
var canvasOffset=$canvas.offset();
var offsetX=canvasOffset.left;
var offsetY=canvasOffset.top;
ctx.strokeStyle=''gray'';
ctx.font=''300px verdana'';
var wasHit=false;
var isHit=false;
draw();
var data=ctx.getImageData(0,0,canvas.width,canvas.height).data;
$("#canvas").mousemove(function(e){handleMouseMove(e);});
function draw(){
ctx.fillStyle=(isHit)?''green'':''lightgray'';
ctx.fillText("M",25,250);
ctx.strokeText("M",25,250);
}
function handleMouseMove(e){
e.preventDefault();
e.stopPropagation();
mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
isHit=(data[(mouseY*cw+mouseX)*4+3]>10)
if(!isHit==wasHit){
draw();
wasHit=isHit;
}
}
body{ background-color: ivory; }
#canvas{border:1px solid red;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<p>Hit test: Move mouse over letter</p>
<canvas id="canvas" width=300 height=300></canvas>
Quiero saber si un punto dado está dentro o fuera de una forma de texto. Como notará en la muestra que proporcioné a continuación, hitTest
devolverá true
tan pronto como el punto esté dentro de los TextItem
del artículo de texto, y no solo si el punto está dentro del mismo carácter. (Puede experimentar este comportamiento mejor cuando coloca el puntero del mouse en el medio del #
)
Muestra: prueba de golpes contra TextItem
También traté de dibujar el personaje en función de las rutas (como lo hace Raphaël
en sus muestras de fuentes ) para usar las rutas en sí para la prueba de golpes, pero tropecé con un comportamiento bastante extraño en el que (algunos) los caracteres no se dibujan correctamente. (Si copia la definición de ruta en un software de imagen vectorial como Inkscape
las formas de texto se dibujan correctamente)
Muestra: dibujar texto como ruta
¿Cuál es la forma más prometedora de averiguar si un punto dado está dentro o fuera de una forma de texto?
Después de pasar bastante tiempo depurando el código de paper.js
, finalmente encontré la solución para este problema.
En lugar de usar Path
, se supone que debes usar CompoundPath
:
Un camino compuesto contiene dos o más caminos, se dibujan agujeros donde los caminos se superponen. Todas las rutas en una ruta compuesta adoptan el estilo de la ruta más atrás y se puede acceder a través de su lista item.children.
También actualicé el ejemplo de arriba: