Creo que todo el mundo debería haber encontrado esa necesidad al aprender sobre lienzo o utilizarlo en el desarrollo de proyectos: implementar un dispositivo de bloc de dibujo que se pueda escribir.
Bueno, creo que para los niños que están más familiarizados con Canvas, esto se puede hacer con solo unas pocas docenas de líneas de código. La siguiente demostración es un ejemplo simple:
<!DOCTYPE html><html><head> <title>Demostración de Sketchpad</title> <style type=text/css> lienzo { borde: 1px azul sólido } </style></head><body> <canvas id=ancho del lienzo=800 alto=500></canvas> <tipo de script=text/javascript> let isDown = false let beginPoint = null; document.querySelector('#canvas'); const ctx = canvas.getContext('2d'); // Establece el color de la línea ctx.strokeStyle = 'ctx.lineWidth = 1; .lineCap = 'redondo'; lienzo.addEventListener('mousedown', abajo, falso); mover, falso); lienzo.addEventListener('mouseup', arriba, falso); lienzo.addEventListener('mouseout', arriba, falso); función abajo(evt) {isDown = true; mover(evt) { if (!isDown) return; const endPoint = getPos(evt); drawLine(beginPoint, endPoint = endPoint); up(evt) { if (!isDown) return; const endPoint = getPos(evt); drawLine(beginPoint, endPoint); y: evt.clientY } } function drawLine(beginPoint, endPoint) { ctx.beginPath(); ctx.moveTo(beginPoint.x, beginPoint.y); ctx.lineTo(endPoint.x, endPoint.y); ctx.closePath() } </script></body></html >
Su lógica de implementación también es muy simple:
mousedown
, mouseup
y mousemove
, y también creamos una variable isDown
;mousedown
), establezca isDown
en true
, y cuando el usuario baje el mouse ( mouseup
), configúrelo en false
. La ventaja de esto es que puede determinar si el usuario se encuentra actualmente en un estado de dibujo. ;mousemove
. Si y solo si isDown
es true
(es decir, en el estado de escritura), el punto actual se conectará y dibujará con el punto anterior a través del método lineTo
. lienzo;A través de los pasos anteriores, podemos realizar la función básica del tablero de dibujo. Sin embargo, las cosas no son tan simples. Los zapatos de los niños cuidadosos pueden encontrar un problema muy serio: las líneas dibujadas de esta manera son irregulares y no lo suficientemente suaves, y usted será más rápido. Cuanto más dibujes, más fuerte será la sensación de líneas discontinuas. El rendimiento se muestra a continuación:
¿Por qué sucede esto? Análisis de problemasLas principales razones de este fenómeno son:
Conectamos los puntos usando el método lineTo
del lienzo. Lo que conecta dos puntos adyacentes es una línea recta, no una curva, por lo que lo que se dibuja de esta manera es una polilínea;
Limitado por la frecuencia de recopilación de eventos de mousemove
por parte del navegador, todos saben que durante mousemove
, el navegador recopila las coordenadas del mouse actual cada corto período de tiempo. Por lo tanto, cuanto más rápido se mueve el mouse, mayor es la distancia recopilada entre los dos puntos adyacentes. cuanto más lejos, más evidente es la sensación de líneas plegables;
En realidad, hay formas de dibujar curvas suaves. Si lineTo
no es confiable, podemos usar otra API de dibujo de canvas: quadraticCurveTo
, que se usa para dibujar curvas de Bézier cuadráticas.
curva de Bézier cuadrática
quadraticCurveTo(cp1x, cp1y, x, y)
Llamar quadraticCurveTo
requiere cuatro parámetros cp1x
y cp1y
que describen los puntos de control, mientras y
x
los puntos finales de la curva:
Puede encontrar información más detallada en MDN.
Como queremos utilizar una curva de Bézier, es obvio que nuestros datos no son suficientes. Para describir completamente una curva de Bézier cuadrática, necesitamos: punto inicial, punto de control y punto final.
Existe un algoritmo muy inteligente que puede ayudarnos a obtener esta información.
Algoritmo para obtener puntos clave de Bézier cuadráticosEste algoritmo no es difícil de entender. Déjame dar un ejemplo directamente:
Supongamos que recopilamos un total de 6 coordenadas del mouse en una pintura, a saber, A, B, C, D, E, F
Tomamos los tres puntos anteriores A, B, C
, calculamos el punto medio B1
de B
y C
, y usamos A
; el punto inicial, B
es el punto de control B1
es el punto final. Utilice quadraticCurveTo
para dibujar un segmento de curva de Bézier cuadrático;
A continuación, calcule el punto medio C1
entre los puntos C
y D
y continúe dibujando la curva con B1
como punto inicial, C
como punto de control y C1
como punto final;
El dibujo continúa por analogía. Cuando se alcanza el último punto F
, la curva de Bézier termina con D1
, el punto medio de D
y E
, como punto inicial, E
como punto de control y F
como punto final.
Bien, el algoritmo es así, luego actualizaremos el código existente según este algoritmo:
let isDown = false;let pointes = [];let beginPoint = null;const canvas = document.querySelector('#canvas');const ctx = canvas.getContext('2d');//Establecer el color de la línea ctx.strokeStyle = 'rojo';ctx.lineWidth = 1;ctx.lineJoin = 'redondo';ctx.lineCap = 'ronda';canvas.addEventListener('mousedown', abajo, falso);canvas.addEventListener('mousemove', mover, falso);canvas.addEventListener('mouseup', arriba, falso);canvas.addEventListener('mouseout' , arriba, falso); función abajo(evt) { isDown = true; const { x, y } = getPos(evt); puntos.push({x, y}); comenzarPoint = {x, y};}función mover(evt) { if (!isDown) return; const { x, y} = getPos(evt); x, y}); if (puntos.longitud > 3) { const últimosdospuntos = puntos.slice(-2); const controlPoint = últimosdospuntos[0]; x: (últimosDosPuntos[0].x + últimosDosPuntos[1].x) / 2, y: (últimosDosPuntos[0].y + últimosDosPuntos[1].y) / 2, } drawLine(beginPoint, controlPoint, endPoint); comenzarPoint = endPoint; }}función arriba(evt) { if (!isDown) return; const { x, y } = getPos(evt); puntos.push({x, y}); if (puntos.longitud > 3) { const últimosdospuntos = puntos.slice(-2); const controlPoint = últimosdospuntos[0]; const últimosdospuntos[1]; , controlPoint, endPoint); } startPoint = null; isDown = false; puntos = [];}función getPos(evt) { return { x: evt.clientX, y: evt.clientY }}function drawLine(beginPoint, controlPoint, endPoint) { ctx.beginPath(); ctx.moveTo(beginPoint.x, BeginPoint.y); y, punto final.x, punto final.y; ctx.stroke(); ctx.closePath();}
Sobre la base del original, creamos points
variables para guardar los puntos por los que pasó el mouse en el evento mousemove
anterior. Según este algoritmo, se necesitan al menos 3 puntos para dibujar una curva de Bézier cuadrática, por lo que solo tenemos el. puntos en points
El sorteo comienza solo cuando el número de puntos es mayor que 3. El procesamiento posterior es exactamente el mismo que el de este algoritmo, por lo que no entraré en detalles aquí.
Después de la actualización del código, nuestra curva se ha vuelto mucho más suave, como se muestra en la siguiente figura:
Este artículo termina aquí Espero que todos se diviertan dibujando en lienzo ~ Nos vemos la próxima vez :)
Si está interesado en zapatos para niños, puede hacer clic aquí para seguir mi blog. Cualquier publicación nueva e interesante se compartirá aquí lo antes posible ~.
Lo anterior es el contenido completo de este artículo. Espero que sea útil para el estudio de todos. También espero que todos apoyen VeVb Wulin Network.