Como todos sabemos, el lienzo es un mapa de bits. En un mapa de bits, podemos dibujar varias cosas en él, incluidas imágenes, líneas, etc. Entonces, ¿qué debemos hacer si queremos agregar un evento de clic a una determinada imagen en el lienzo? Y js solo puede monitorear eventos del lienzo. Obviamente, esta imagen no existe y la imagen en el dom simplemente está dibujada en el lienzo. A continuación, simplemente implementaré el enlace de eventos para cada imagen dentro de un lienzo.
Permítanme hablar primero sobre el principio de implementación: en realidad se trata de vincular eventos relacionados al lienzo. Al registrar las coordenadas del lienzo donde se encuentra la imagen, se juzga en qué imagen actúa el evento. De esta manera, se parece un poco al agente de eventos. Sin embargo, todavía es un poco complicado de implementar.
PD: Escribí el siguiente código en ts. Puedes leerlo como es6. Puedes comprobarlo si es ligeramente diferente.
Documentación mecanografiada (el mecanografiado es realmente fácil de usar, te recomiendo que aprendas más al respecto).
1. Establezca una conexión entre la imagen y el lienzo (aquí uso bloques de colores en lugar de imágenes)Aquí necesitamos establecer una cierta conexión entre el bloque de color y el lienzo, en lugar de simplemente renderizar. También registre las coordenadas, ancho y alto del bloque de color. Implementémoslo paso a paso.
Primero escriba una página html básica para crear un lienzo:
<!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 = es decir = borde> <título>evento de lienzo</título> <estilo> html, cuerpo {altura: 100%; fondo: #eee} lienzo {fondo: #fff; mostrar: bloque; margen: 0 auto; </style></head><body> <canvas width=500 height=500 id=canvas></canvas></body>A continuación, necesitamos definir una clase Canvas. ¿Qué funciones debería tener esta clase?
Debido a que los bloques de colores también tienen algunos parámetros propios, para facilitar la expansión, también definimos una clase para los bloques de colores. Las funciones requeridas para este tipo son:
Ancho, alto, color, coordenadas (x, y) y instancia de Canvas, decidamos esto inicialmente;
ok empieza a escribir
// Clase de lienzo clase Lienzo { blockList: Block[] ctx: cualquier lienzo: cualquier createBlock (opción) { option.Canvas = this this.blockList.push(new Block(option)) this.painting() } renderizado (bloque) { // Función de bloque de color de renderizado this.ctx.fillStyle = block.color this.ctx.fillRect(block.x, block.y, block.w, block.h) } pintura () { // Renderice todos los bloques de color del contenedor en el lienzo // Borre el lienzo (el antiguo debe borrarse antes de renderizar) this.ctx.fillStyle = '#fff' this.ctx.fillRect(0, 0, this.canvas. ancho, this .canvas.height) this.blockList.forEach(ele => { this.rendering(ele) }) } constructor (ele) { // Función de inicialización (la entrada es lienzo) // Establecer lienzo this.canvas = ele this.ctx = this.canvas.getContext('2d') // Contenedor de bloques de color this.blockList = [] }}class Block { w: número h: número x: número y: número color : string Canvas: Jerarquía del lienzo: constructor numérico ({ w, h, x, y, color, Canvas }) { // Inicializa y establece las propiedades relacionadas con el bloque de color this.w = w this.h = h this.x = x this.y = y this.color = color this.Canvas = Canvas }}Intentemos correr una ola debajo
//Crea una instancia de Canvas y agrega un bloque de color azul con un ancho y alto de 100px, posición (100,100), (300,100), bloques de color rojo y azul var canvas = new Canvas(document.getElementById('canvas')) canvas .createBlock({ // rojo x: 100, y: 100, w: 100, h: 100, color: '#f00' }) canvas.createBlock({ // azul x: 100, y: 100, w: 300, h: 100, color: '#00f' })Los resultados de ejecución son los siguientes:
2. Agregue un evento de clic al bloque de color.No puede agregar directamente un evento de clic al bloque de color aquí, por lo que debe usar coordenadas para determinar en qué bloque de color se hace clic actualmente.
class Block { // ...Omitir parte del código checkBoundary (x, y) { // Determinar el método de límite return x > this.x && x < (this.x + this.w) && y > this.y && y < (this.y + this.h) } mousedownEvent () { // Evento de clic console.log(`Se hizo clic en el bloque de color con color ${this.color}`) }}class Canvas { // .. .constructor de código de pieza omitido (ele) { this.canvas = ele this.ctx = this.canvas.getContext('2d') this.blockList = [] // Enlace de evento (hay una cosa a tener en cuenta aquí. Utilicé el método de enlace aquí, que es para cambiar este puntero en el método mousedownEvent a Canvas) this.canvas.addEventListener('click', this.mousedownEvent.bind(this)) // Evento de clic} mousedownEvent () { // Evento de clic const x = e.offsetX const y = e.offsetY // Aquí las coordenadas del clic se pasan a todos los bloques de color y se utiliza el método de juicio de límites para determinar si el clic está dentro. En caso afirmativo, ejecute el método de evento del bloque de color. this.blockList.forEach(ele => { if (ele.checkBoundary(x, y)) ele.mousedownEvent(e) }) }}Hasta ahora, hemos implementado la vinculación de los eventos de clic correspondientes a diferentes bloques de color en diferentes lienzos. Sin embargo, este evento de clic no es perfecto, porque hasta ahora no hemos introducido el concepto de jerarquía, lo que significa que si se hace clic en dos bloques de colores superpuestos, ambos se activarán. Entonces también necesitamos agregar atributos jerárquicos a los bloques de color. Si hace clic en un bloque de color para cambiarlo, el nivel del bloque de color se elevará al nivel más alto.
class Block { // ...Omitir parte del constructor de código ({ w, h, x, y, color, Canvas, jerarquía }) { // Inicializa y establece las propiedades relacionadas con el bloque de color this.w = w this .h = h this x = x this.y = y this.color = color this.Canvas = Canvas this.hierarchy = 0 }}class Canvas { // ...omitir parte del código constructor (ele) { this. .canvas = ele this.ctx = this.canvas.getContext('2d') this.blockList = [] // Enlace de evento (hay una cosa a tener en cuenta aquí. Utilicé el método de enlace aquí para cambiar el puntero this en el método mousedownEvent a Canvas) this .canvas .addEventListener('click', this.mousedownEvent.bind(this)) // Evento de clic this.nowBlock = null // Bloque de color actualmente seleccionado} createBlock (opción) { // Crear función de bloque de color (Bloque aquí es la clase de bloque de color) opción.Canvas = this // El nivel de creación del último bloque de color debe ser el más alto option.hierarchy = this.blockList.length this.blockList.push(new Block (opción)) this.rendering() } mousedownEvent (e) { // Haga clic en evento const x = e.offsetX const y = e.offsetY // Obtenga el bloque de color de nivel más alto en el punto this.nowBlock = (this.blockList.filter(ele => ele.checkBoundary(x, y))).pop() // Si no hay ningún bloque de color capturado, salga directamente si (!this .nowBlock) return // Eleva el nivel del bloque de color en el que se hizo clic al más alto this.nowBlock.hierarchy = this.blockList.length // Reordena (de pequeño a grande) this.blockList.sort((a, b) = > a.hierarchy - b.hierarchy) // Reasignar la jerarquía desde 0 this.blockList.forEach((ele, idx) => ele.hierarchy = idx) // Reordenar en orden inverso y luego volver a renderizar. this.painting() this.nowBlock.mousedownEvent(e) // Solo activa eventos para el bloque de color seleccionado}}// Aquí también tenemos que agregar un tercer bloque de color que se superponga al bloque de color rojo canvas.createBlock({ x: 150, y: 150, ancho: 100, alto: 100, color: '#0f0'})El código del método mousedownEvent en Canvas es un poco complicado, principalmente porque es un poco complicado.
El efecto después de correr es el siguiente:
3. Arrastra y suelta bloques de diferentes colores.Arriba hemos implementado la obtención de diferentes bloques de colores y la modificación de sus niveles. A continuación, necesitamos implementar el arrastre de bloques de color, principalmente para obtener los cambios en las coordenadas de posición durante el movimiento del mouse y cuando se hace clic inicialmente. Este principio es el mismo que el de la implementación normal de arrastrar y soltar de DOM.
Obtenga el punto donde se hace clic en el bloque de color y la distancia (disX, disY) desde la izquierda y la parte superior del bloque de color.
Cuando el mouse se mueve, reste (disX, disY) de la distancia actual del mouse desde la izquierda y la parte superior del lienzo. Estas son las coordenadas xey del bloque de color.
class Block { // ... omitir parte del código mousedownEvent (e: MouseEvent) { /* El método de cálculo de disX y disY aquí: e.offsetX obtiene la distancia entre el clic del mouse y el lado izquierdo del lienzo, y this.x es la distancia del bloque de color La distancia a la izquierda del lienzo. e.offsetX-this.x es la distancia a la izquierda del bloque de color. Esto debería ser fácil de entender*/ const disX = e.offsetX - this.x // La distancia desde el lado izquierdo del bloque de color cuando se hace clic const disY = e.offsetY - this.y // La distancia desde la parte superior de el bloque de color al hacer clic // Vincula el evento de deslizamiento del mouse; aquí mouseEvent.offsetX también es la distancia entre el mouse y el lado izquierdo del lienzo, mouseEvent.offsetX - disX es la coordenada x del bloque de color. De la misma forma, y se calcula de la misma forma. Finalmente, simplemente vuelva a renderizar. document.onmousemove = (mouseEvent) => { this.x = mouseEvent.offsetX - disX this.y = mouseEvent.offsetY - disY this.Canvas.painting() } // Borra todos los eventos cuando se suelta el mouse document.onmouseup = ( ) => { documento.onmousemove = documento.onmousedown = nulo } // console.log(`Bloque de color 22 en el que se hizo clic` con color ${this.color}) }}El efecto es el siguiente:
El código completo se pega a continuación (el HTML y los métodos de llamada no se incluirán). Este ejemplo es solo una implementación simple de vincular eventos al contenido en el lienzo. Puede implementar otros más complejos, como reemplazar bloques de colores con imágenes. Además de arrastrar, puede hacer zoom, rotar, eliminar, etc., imágenes.
clase Canvas { blockList: Block[] ctx: cualquier lienzo: cualquiera ahoraBlock: Block createBlock (opción) { option.hierarchy = this.blockList.length option.Canvas = this this.blockList.push(new Block(option)) this. pintura() } renderizado (bloque) { this.ctx.fillStyle = block.color this.ctx.fillRect(block.x, block.y, block.w, block.h) } pintura () { // Limpiar el lienzo this.ctx.fillStyle = '#fff' this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height) this.blockList.forEach(ele => { this.rendering(ele) }) } mousedownEvent (e: MouseEvent) { // Haga clic en evento const x = e.offsetX const y = e.offsetY // Obtenga el bloque de color de nivel más alto en el punto this.nowBlock = (this.blockList.filter(ele => ele.checkBoundary(x, y))).pop() // Si no hay ningún bloque de color capturado, salga directamente si (!this .nowBlock) return // Eleva el nivel del bloque de color en el que se hizo clic al más alto this.nowBlock.hierarchy = this.blockList.length // Reordena (de pequeño a grande) this.blockList.sort((a, b) = > a.hierarchy - b.hierarchy) // Reasignar la jerarquía desde 0 this.blockList.forEach((ele, idx) => ele.hierarchy = idx) // Reordenar en orden inverso y luego volver a renderizar. this.painting() this.nowBlock.mousedownEvent(e) // this.blockList.forEach(ele => { // if (ele.checkBoundary(x, y)) ele.clickEvent(e) // }) } constructor (ele) { this.canvas = ele this.ctx = this.canvas.getContext('2d') this.blockList = [] // Enlace de evento this.canvas.addEventListener('mousedown', this.mousedownEvent.bind(this)) }}clase Bloque { w: número h: número x: número y: número color: cadena Lienzo: Jerarquía del lienzo: constructor de números ( { w, h, x, y, color, Canvas, jerarquía }) { this.w = w this.h = h this.x = x this.y = y this.color = color this.Canvas = Lienzo this.hierarchy = jerarquía } checkBoundary (x, y) { return x > this.x && x < (this.x + this.w) && y > this.y && y < (this.y + this.h) } mousedownEvent (e: MouseEvent) { const disX = e.offsetX - this.x const disY = e.offsetY - this.y document.onmousemove = (mouseEvent) => { this.x = mouseEvent.offsetX - disX this.y = mouseEvent.offsetY - disY this.Canvas.painting() } document.onmouseup = () => { document.onmousemove = document.onmousedown = null } // console.log(`Se hizo clic en el bloque de color 22 con el color ${this.color}`) }}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.