Este artículo presenta principalmente:
Nombre: Tablero de dibujo inteligente
Pila de tecnología: HTML5, CSS3, JavaScript, móvil
Descripción de la función:
Dirección de vista previa de la dirección del proyecto
Avance
Vista previa de PC:
Vista previa móvil:
Después de leer la vista previa anterior y experimentar Smart Drawing Pad , creo que está bien. Recuerda darle el visto bueno, independientemente de si estás muy emocionado o no, después de todo, estoy muy emocionado. Logré los resultados del proyecto. Lo he dicho un montón de tonterías, ¡ahora puedes comenzar a escribir código para lograr el efecto que deseas! ! !
Nota: Los siguientes efectos del proyecto están relacionados principalmente con JavaScript. Lo siguiente es solo el código que proporciona ideas de implementación , no el código completo .
3. Lograr los resultados del proyecto paso a paso(1) Página de análisis
A través del diagrama de casos de uso , ¿sabemos qué funciones pueden utilizar los usuarios para ingresar a nuestro sitio web?
Qué pueden hacer los usuarios:
(2) diseño HTML
Cuando escribí html, introduje archivos css y js.
<!DOCTYPE html><html lang=en><head> <meta charset=UTF-8> <meta nombre=viewport content=ancho=ancho del dispositivo, escala inicial=1.0> <meta http-equiv=X-UA -Contenido compatible=ie=edge> <title>Smart Drawing Pad</title> <link rel=icono de acceso directo href=./image/favicon.png tipo=imagen/x-icon> <link rel=hoja de estilo href=./css/style.css></head><body> <canvas id=canvas></canvas> <div class=bg-btn></ div> <div class=color-group id=bgGroup> <h3>Seleccione color de fondo:</h3> <ul class=clearfix> <li class=bgcolor-item style=fondo-color: azul;></li> <li class=bgcolor-item estilo=fondo-color: negro;></li> <li clase=bgcolor-item estilo=fondo-color: #FF3333;></li> <li class=bgcolor-item estilo=color-fondo: #0066FF;></li> <li class=bgcolor-item estilo=color-fondo: #FFFF33;></li> <li class=bgcolor-item estilo=fondo-color: #33CC66;></li> <li class=bgcolor-item estilo=fondo-color: gris;></li> <li class=bgcolor-item estilo=fondo- color: #F34334;></li> <li class=bgcolor-item estilo=fondo-color: #fff;box-shadow: 0 1px 2px 0 rgba(32,33,36,0.28);></li> <li class=bgcolor-item estilo=fondo-color: #9B27AC;></li> <li class=bgcolor-item estilo=fondo-color: #4CB050;></li> <li class=bgcolor-item style=fondo-color: #029688;></li> </ul> <i class=closeBtn></i> </div> <div clase=herramientas> <div clase=contenedor> <botón clase=guardar id=guardar <botón clase=pincel activo id=pincel <botón clase=borrador id=borrador < botón clase=borrar id=borrar <botón clase=deshacer id=deshacer <botón clase=rehacer id=rehacer </div> </div> <div clase=pen-detail id=penDetail> <i class=closeBtn></i> <p>Tamaño del bolígrafo</p> <span class=circle-box><i id=grosor></i></span> <tipo de entrada=rango id=rango1 min=1 max=10 valor=1> <p>Color de lápiz</p> <ul class=pen-color clearfix> <li class=color-item estilo activo=color de fondo: negro;></ li> <li class=color-item estilo=fondo-color: #FF3333;></li> <li class=color-item estilo=fondo-color: #99CC00;></li> <li class=color-item estilo=fondo -color: #0066FF;></li> <li clase=color-elemento estilo=fondo-color: #FFFF33;></li> <li clase=color-elemento estilo=fondo-color: #33CC66;></li> </ul> <p>Opacidad</p> <i class=showOpacity></i> <tipo de entrada=rango id=rango2 min=1 max=10 valor=1> < / div> <script src=./js/main.js></script></body></html>
(3) Utilice CSS para embellecer la interfaz
El código CSS puede embellecer la interfaz según sus hábitos personales, por lo que no escribiré el código CSS aquí. Puede mirar directamente el código del proyecto o revisar los elementos de las herramientas de desarrollador. Si tienes alguna pregunta, puedes chatear conmigo en privado. No creo que sea un gran problema.
(4) Utilice JS para implementar funciones específicas del proyecto.
1. Preparación
Primero, prepare un contenedor, que es una mesa de dibujo. El contenedor se ha escrito en el HTML anterior. Esto es una tontería.
<canvas id=canvas></canvas>
Luego inicializa js
let lienzo = document.getElementById('canvas');let contexto = canvas.getContext('2d'); Planeo hacer que la mesa de trabajo sea de pantalla completa, así que a continuación estableceré el ancho y el alto del canvas
let pageWidth = document.documentElement.clientWidth;let pageHeight = document.documentElement.clientHeight;canvas.width = pageWidth;canvas.height = pageHeight;
Dado que algunos IE no admiten canvas , si queremos ser compatibles con IE, podemos crear un canvas , luego inicializarlo con excanvas y agregar exCanvas.js para IE. Aquí no consideramos explícitamente IE.
Pero cuando cambio la ventana del navegador en mi computadora, el tablero de dibujo no se escala de manera adaptable. Solución:
// Recuerde ejecutar la función autoSetSize function autoSetSize(){ canvasSetSize(); // Al ejecutar esta función, el ancho y el alto del lienzo se establecerán primero function canvasSetSize(){ let pageWidth = document.documentElement.clientWidth; altura de la página = documento.documentElement.altura del cliente; lienzo.ancho = ancho de la página; altura del lienzo = altura de la página } // Después de que cambie el tamaño de la ventana, se activará el evento de cambio de tamaño para restablecer el ancho y el alto de la ventana del lienzo.onresize = function(){ canvasSetSize();2. Realizar la función del dibujo.
Idea de implementación: escuche los eventos del mouse y use drawLine() para dibujar los datos grabados.
painting = false .mousedown ), establezca painting en true , lo que indica que se está pintando y no se suelta el mouse. Registre los clics del mouse.mousemove ). Si el mouse se mueve demasiado rápido, el navegador no puede mantener la velocidad de dibujo y aparecerán espacios entre los puntos, por lo que debemos conectar los puntos dibujados con líneas ( lineTo() ).mouseup ), configure painting en false . Nota: En realidad, no es necesario escribir el método drawCircle . Esto es solo para que todos entiendan dónde comenzar a hacer clic.
function listeningToUser() { // Definir una variable para inicializar el estado del pincel let paint = false; // Registra la última posición del pincel let lastPoint = {x: undefined, y: undefinido} // Evento de pulsación del mouse canvas.onmousedown = función (e){ pintura = verdadero; let x = e.clientX; let y = e.clientY = {'x':x,'y':y}; drawCircle(x,y,5); } // Evento de movimiento del mouse canvas.onmousemove = function(e){ if(painting){ let x = e.clientX; let y = e.clientY; :x,'y':y}; drawLine(últimoPunto.x, últimoPunto.y, nuevoPunto.x, nuevoPunto = nuevoPunto; Evento de liberación del mouse canvas.onmouseup = function(){ paint = false }}// Función de punto de dibujo function drawCircle(x,y,radius){ // Crea una nueva ruta después de la generación, el comando de dibujo de gráficos apunta a. ruta Generar ruta. context.beginPath(); // Dibuja un arco (círculo) con (x, y) como centro y radio como radio, // comenzando desde startAngle y terminando en endAngle, en la dirección indicada en sentido antihorario (el valor predeterminado es en el sentido de las agujas del reloj). ) para generar. context.arc(x,y,radius,0,Math.PI*2); // Genera un gráfico sólido llenando el área de contenido de la ruta context.fill(); // Después de cerrar la ruta, el gráfico El comando de dibujo se redirige al contexto. context.closePath();}function drawLine(x1,y1,x2,y2){ //Establece el ancho de la línea context.lineWidth = 10; //Establece el estilo del final de la línea. context.lineCap = round; // Establece el estilo de la unión entre líneas context.lineJoin = round; // moveTo(x,y) mueve el trazo a las coordenadas especificadas x e y context.moveTo(x1,y1); / lineTo(x, y) dibuja una línea recta desde la posición actual hasta la posición x e y especificada context.lineTo(x2,y2 // Dibuja el contorno gráfico a través de líneas context.stroke(); contexto.closePath();}3. Implementar la función de borrador.
Ideas de implementación:
eraserEnabled = false .click del borrador, haga clic en el borrador, cambie el estado del borrador, eraserEnabled = true y cambie la clase para lograr el efecto activado .eraserEnabled es true , mueva el mouse y use context.clearRect() para implementar el borrador. Pero descubrí que en la API del lienzo, el método clearRect puede borrar píxeles, pero el método clearRect borra el área rectangular. Después de todo, los borradores de la mayoría de las personas están acostumbrados a ser redondos, por lo que se introduce la poderosa función del área de recorte. es el método de clip. El siguiente código utiliza context.clearRect() para implementar el borrador. Consulte la sección paso a paso para aprender cómo implementar mejor el sasafrás de caucho.
let eraser = document.getElementById(eraser);let eraserEnabled = false;// Recuerde ejecutar la función listeningToUser function listeningToUser() { // ... significa que se omite el código escrito previamente // ... // Presionar el mouse Próximo evento canvas.onmousedown = function(e){ // ... if(eraserEnabled){//Para usar el borrador context.clearRect(x-5,y-5,10,10) }else{ lastPoint = {'x':x,'y':y} } } // Evento de movimiento del mouse canvas.onmousemove = function(e){ let x = e.clientX; let y = e.clientY; !pintura){return} if(eraserEnabled){ context.clearRect(x-5,y-5,10,10 }else{ var newPoint =); {'x':x,'y':y}; drawLine(lastPoint.x, lastPoint.y,newPoint.x, newPoint.y); eraser.onclick = function(){ eraserEnabled = true; eraser.classList.add('active'); brush.classList.remove('active');}4. Implementar la función de limpieza de pantalla.
Ideas de implementación:
Obtenga el nodo del elemento.
Haga clic en el botón Borrar para borrar el lienzo.
let reSetCanvas = document.getElementById(clear);//Realizar el borrado de la pantalla reSetCanvas.onclick = function(){ ctx.clearRect(0,0,canvas.width,canvas.height); setCanvasBg('white');}// Restablecer el color de fondo del lienzo function setCanvasBg(color) { ctx.fillStyle = color; 0, lienzo.ancho, lienzo.alto);}5. Implementar la función de guardar como imagen.
Ideas de implementación:
let save = document.getElementById(save); // Descargar imagen save.onclick = function(){ let imgUrl = canvas.toDataURL('image/png'); let saveA = document.createElement('a'); body.appendChild(saveA); saveA.href = imgUrl; saveA.download = 'mypic'+(nueva fecha).getTime(); saveA.target = '_blank'; saveA.click();}6. Implementar la función de cambiar el color de fondo.
Ideas de implementación:
let selectBg = document.querySelector('.bg-btn');let bgGroup = document.querySelector('.color-group');let bgcolorBtn = document.querySelectorAll('.bgcolor-item');let penDetail = documento. getElementById(penDetail);let activeBgColor = '#fff';//cambio de color de fondo implementado para (let i = 0; i < bgcolorBtn.length; i++) { bgcolorBtn[i].onclick = function (e) { // Deja de burbujear e.stopPropagation(); for (let i = 0; i < bgcolorBtn.length; i++) { bgcolorBtn[i].classList.remove(activo); this.classList.add(activeBgColor =); this.style.backgroundColor; setCanvasBg(activeBgColor); } }}document.onclick = function(){ bgGroup.classList.remove('active');}selectBg.onclick = function(e){ bgGroup.classList.add(' activo'); e.stopPropagation();}7. Implementar la función de cambiar el grosor del cepillo.
Ideas de implementación:
let range1 = document.getElementById('range1');let lWidth = 2;let ifPop = false;range1.onchange = function(){ console.log(range1.value console.log(typeof range1.value) espesor; style.transform = 'escala('+ (parseInt(range1.value)) +')'; parseInt(range1.value*2);}// Función de dibujo de líneas function drawLine(x1,y1,x2,y2){ // ... context.lineWidth = lWidth // ...}// Haga clic en el pincel; onclick = function(){ eraserEnabled = false; brush.classList.add('active'); eraser.classList.remove('active'); Cuadro emergente console.log('pop') penDetail.classList.add('active'); }else{ penDetail.classList.remove('active');8. Implementar la función de cambiar el color del pincel.
La idea de implementación es similar a la de cambiar el color de fondo del tablero de dibujo .
let aColorBtn = document.getElementsByClassName(color-item);getColor();function getColor(){ for (let i = 0; i < aColorBtn.length; i++) { aColorBtn[i].onclick = function () { for ( sea yo = 0; yo < aColorBtn.length; aColorBtn[i].classList.remove(active); this.classList.add(activeColor = this.style.backgroundColor; ctx.fillStyle = activeColor;9. Implementar las funciones de deshacer y rehacer cambios.
Ideas de implementación:
canvasHistory cada vez que se complete una operación de dibujo (use toDataURL() del lienzo para generar una instantánea, que genera una imagen base64);canvasHistory utilizando drawImage() del lienzo; let deshacer = document.getElementById(undo);let redo = document.getElementById(redo);// ...canvas.onmouseup = function(){ pintura = canvasDraw();}let canvasHistory = [];let step; = -1; // Función del método de dibujo canvasDraw(){ paso++; if(paso < canvasHistory.length){ canvasHistory.length = paso; Agregue un nuevo sorteo al historial canvasHistory.push(canvas.toDataURL());}//Método Deshacer function canvasUndo(){ if(step > 0){ step-- // ctx.clearRect(0,0,canvas) .ancho,canvas.height); let canvasPic = nueva Imagen(); canvasPic.src = canvasHistory[paso]; ctx.drawImage(canvasPic, 0, 0); } undo.classList.add('active'); }else{ deshacer.classList.remove('active'); alerta('No se puede continuar deshacer'); / Función del método Rehacer canvasRedo(){ if(step < canvasHistory.length - 1){ step++; let canvasPic = new Image(); canvasHistory[paso]; canvasPic.onload = function () { // ctx.clearRect(0,0,canvas.width,canvas.height); ctx.drawImage(canvasPic, 0, 0); 'activo'); }else { redo.classList.remove('activo') alert('Ya es el último registro'); }}undo.onclick = función(){ lienzoUndo();}redo.onclick = función(){ lienzoRedo();}10. Compatible con terminales móviles
Ideas de implementación:
true , se usa el evento touch ; false , se usa mouse ; // ...if (document.body.ontouchstart !== undefinido) { // Usar evento táctil anvas.ontouchstart = function (e) { // Comienza a tocar} canvas.ontouchmove = function (e) { // Comienza a deslizar } canvas.ontouchend = function () { // Fin del deslizamiento }}else{ // Usar evento del mouse // ... } // ... 4. Pisoteando las trampas Problema 1: cuando cambia la ventana del navegador en su computadora, la mesa de dibujo no se adaptará.Solución:
En el procesamiento de eventos de respuesta onresize, los parámetros de tamaño de página obtenidos son los parámetros modificados.
Cuando cambie el tamaño de la ventana, restablezca el ancho y el alto del lienzo. En pocas palabras, después de que la ventana cambie, reasigne canvas.width y canvas.height.
// Recuerde ejecutar la función autoSetSize function autoSetSize(){ canvasSetSize(); // Al ejecutar esta función, el ancho y el alto del lienzo se establecerán primero function canvasSetSize(){ let pageWidth = document.documentElement.clientWidth; altura de la página = documento.documentElement.altura del cliente; lienzo.ancho = ancho de la página; altura del lienzo = altura de la página } // Después de que cambie el tamaño de la ventana, se activará el evento de cambio de tamaño para restablecer el ancho y el alto de la ventana del lienzo.onresize = function(){ canvasSetSize(); Pregunta 2: Cuando el ancho de la línea dibujada es relativamente pequeño, está bien, pero una vez que sea más gruesa, ocurrirán problemas.Solución: eche un vistazo a la documentación y descubra el método. Solo necesita modificar el código para dibujar líneas .
// Función de dibujo de línea function drawLine(x1,y1,x2,y2){ context.beginPath(); context.lineWidth = lWidth; //-----Add----- // Establece el estilo de final de línea. context.lineCap = round; // Establece el estilo de la unión entre líneas context.lineJoin = round //-----Join----- context.moveTo(x1,y1); y2); contexto.stroke(); contexto.closePath();} Pregunta 3: ¿Cómo conseguir un sasafrás de goma redondo?Solución:
En la API del lienzo, el método clearRect puede borrar píxeles, pero el método clearRect borra un área rectangular. Después de todo, los borradores de la mayoría de las personas están acostumbrados a ser redondos, por lo que se introduce la poderosa función del área de recorte, es decir, el método de recorte. El uso es muy simple:
ctx.save()ctx.beginPath()ctx.arc(x2,y2,a,0,2*Math.PI);ctx.clip()ctx.clearRect(0,0,canvas.width,canvas.height) ;ctx.restaurar();
El código anterior realiza el borrado de un área circular, es decir, primero implementa una ruta circular, luego usa esta ruta como área de recorte y luego borra los píxeles. Una cosa a tener en cuenta es que primero debe guardar el entorno de dibujo y restablecerlo después de borrar los píxeles. Si no lo restablece, los dibujos futuros se limitarán a esa área de recorte.
Pregunta 4: ¿Cómo ser compatible con terminales móviles?1.Agregar metaetiqueta
Debido a que el navegador inicialmente escalará la página cuando se muestra en el teléfono móvil, podemos configurar el atributo de ventana gráfica meta en la etiqueta meta para indicarle al navegador que no escale la página Ancho de página = ancho de pantalla del dispositivo del usuario.
<meta nombre=ventana gráfica contenido=ancho=ancho-dispositivo,escala-inicial=1,escalable-usuario=no,escala-máxima=1.0,escala-minima=1.0/>/*Ancho de página=Ancho móvil:ancho=ancho-dispositivo El usuario no puede escalar: escalable por el usuario = sin escala: escala inicial = 1 escala máxima: escala máxima = 1,0 escala mínima: escala mínima = 1,0 */
2. Casi todos los eventos táctiles se utilizan en el lado móvil, que es diferente del lado de la PC.
Dado que el lado móvil usa eventos táctiles, se usan los atributos H5 touchstart/touchmove/touchend. Sin embargo, el lado de la PC solo admite eventos de mouse, por lo que se requiere la detección de funciones.
En el evento touch , las coordenadas se obtienen a través de .touches[0].clientX y .touches[0].clientY , que deben distinguirse del evento mouse .
Bueno, no es un gran problema, es solo que no escribí context.beginPath(); y pasé algún tiempo resolviendo el error. Me recuerda que hay decenas de millones de líneas de código y la primera línea. Los comentarios no están estandarizados; la programación no está estandarizada y mi colega tiene dos líneas, es mejor operar de acuerdo con las especificaciones operativas documentadas, ¡huele tan bien! ! !
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.