Comme nous le savons tous, le canevas est un bitmap. Dans un bitmap, nous pouvons y dessiner diverses choses, notamment des images, des lignes, etc. Alors, que devons-nous faire si nous voulons ajouter un événement de clic à une certaine image du canevas. Et js ne peut surveiller que les événements du canevas. Évidemment, cette image n'existe pas et l'image dans le dom est simplement dessinée dans le canevas. Ensuite, je vais simplement implémenter la liaison d'événements pour chaque image à l'intérieur d'un canevas.
Permettez-moi d'abord de parler du principe de mise en œuvre : il s'agit en fait de lier les événements liés au canevas. En enregistrant les coordonnées du canevas où se trouve l'image, on détermine sur quelle image l'événement agit. De cette façon, cela ressemble un peu à l’agent événementiel. Cependant, cela reste encore un peu compliqué à mettre en œuvre.
ps : j'ai écrit le code suivant dans ts. Vous pouvez simplement le lire comme es6. Vous pouvez le vérifier s'il est légèrement différent.
Documentation Typescript (TypeScript est vraiment simple à utiliser, je vous recommande d'en apprendre davantage).
1. Établissez une connexion entre l'image et la toile (ici j'utilise des blocs de couleurs au lieu d'images)Ici, nous devons établir une certaine connexion entre le bloc de couleur et le canevas, plutôt que simplement le rendu. Enregistrez également les coordonnées, la largeur et la hauteur du bloc de couleur. Mettons-le en œuvre étape par étape
Écrivez d’abord une page HTML de base pour créer un canevas :
<!DOCTYPE html><html lang=en><head> <meta charset=UTF-8> <meta name=viewport content=width=device-width, initial-scale=1.0> <meta http-equiv=X-UA -Compatible content=ie=edge> <title>événement canvas</title> <style> html, body { hauteur : 100 % ; arrière-plan : #eee } toile { arrière-plan : #fff; affichage : bloc ; marge : 0 auto ; } </style></head><body> <canvas width=500 height=500 id=canvas></canvas></body>
Ensuite, nous devons définir une classe Canvas. Quelles fonctions cette classe doit-elle avoir ?
Étant donné que les blocs de couleur ont également leurs propres paramètres, afin de faciliter l'expansion, nous définissons également une classe pour les blocs de couleur. Les fonctions requises pour ce type sont :
Largeur, hauteur, couleur, coordonnées (x, y) et instance de Canvas, décidons-en d'abord ;
OK, commence à écrire
// Classe Canvas class Canvas { blockList: Block[] ctx: any canvas: any createBlock (option) { option.Canvas = this this.blockList.push(new Block(option)) this.painting() } rendu (bloc) { // Fonction de bloc de couleur de rendu this.ctx.fillStyle = block.color this.ctx.fillRect(block.x, block.y, block.w, block.h) } painting() { // Rendre tous les blocs de couleur du conteneur sur le canevas // Effacer le canevas (l'ancien doit être effacé avant le rendu) this.ctx.fillStyle = '#fff' this.ctx.fillRect(0, 0, this.canvas. width, this .canvas.height) this.blockList.forEach(ele => { this.rendering(ele) }) } constructor (ele) { // Fonction d'initialisation (l'entrée est canvas) // Définir le canevas this.canvas = ele this.ctx = this.canvas.getContext('2d') // Conteneur de bloc de couleur this.blockList = [] }}class Block { w: numéro h: numéro x: numéro y: numéro couleur : string Canvas : Hiérarchie du Canvas : constructeur numérique ({ w, h, x, y, color, Canvas }) { // Initialise et définit les propriétés liées au bloc de couleur this.w = w this.h = h this.x = x this.y = y this.color = couleur this.Canvas = Canvas }}
Essayons de lancer une vague ci-dessous
//Créez une instance Canvas et ajoutez un bloc de couleur bleu d'une largeur et d'une hauteur de 100 px, position (100 100), (300 100), blocs de couleur rouge et bleu var canvas = new Canvas(document.getElementById('canvas')) canvas .createBlock({ // rouge x : 100, y : 100, l : 100, h : 100, couleur : '#f00' }) canvas.createBlock({ // bleu x : 100, y : 100, l : 300, h : 100, couleur : '#00f' })
Les résultats en cours d'exécution sont les suivants :
2. Ajoutez un événement de clic au bloc de couleurVous ne pouvez pas ajouter directement un événement de clic au bloc de couleur ici, vous devez donc utiliser des coordonnées pour déterminer sur quel bloc de couleur est actuellement cliqué.
class Block { // ... Omettre une partie du code checkBoundary (x, y) { // Déterminer la méthode de limite return x > this.x && x < (this.x + this.w) && y > this.y && y < (this.y + this.h) } mousedownEvent () { // Cliquez sur l'événement console.log(`Cliqué sur le bloc de couleur avec la couleur ${this.color}`) }}class Canvas { // .. .Constructeur de code de pièce omis (ele) { this.canvas = ele this.ctx = this.canvas.getContext('2d') this.blockList = [] // Liaison d'événement (il y a une chose à noter ici. J'ai utilisé la méthode bind ici, qui is Afin de basculer le pointeur this dans la méthode mousedownEvent vers Canvas) this.canvas.addEventListener('click', this.mousedownEvent.bind(this)) // Cliquez sur l'événement} mousedownEvent () { // Événement de clic const x = e.offsetX const y = e.offsetY // Ici, les coordonnées du clic sont transmises à tous les blocs de couleur et la méthode de jugement des limites est utilisée pour déterminer si le clic est à l'intérieur. Si oui, exécutez la méthode événementielle du bloc de couleur. this.blockList.forEach(ele => { if (ele.checkBoundary(x, y)) ele.mousedownEvent(e) }) }}
Jusqu'à présent, nous avons implémenté la liaison des événements de clic correspondants à différents blocs de couleur dans différents canevas. Cependant, cet événement de clic n'est pas parfait, car jusqu'à présent, nous n'avons pas introduit le concept de hiérarchie, ce qui signifie que si deux blocs de couleur superposés sont cliqués, les deux seront déclenchés. Nous devons donc également ajouter des attributs hiérarchiques aux blocs de couleur. Si vous cliquez sur un bloc de couleur pour changer le bloc de couleur, le niveau du bloc de couleur sera élevé au niveau le plus élevé.
class Block { // ... Omettre une partie du constructeur de code ({ w, h, x, y, color, Canvas, hierarchie }) { // Initialiser et définir les propriétés liées au bloc de couleur this.w = w this .h = h this. x = x this.y = y this.color = color this.Canvas = Canvas this.hierarchy = 0 }}class Canvas { // ... omettre une partie du constructeur de code (ele) { this .canvas = ele this.ctx = this.canvas.getContext('2d') this.blockList = [] // Liaison d'événement (il y a une chose à noter ici. J'ai utilisé la méthode bind ici pour basculer le pointeur this dans la méthode mousedownEvent vers Canvas) this .canvas .addEventListener('click', this.mousedownEvent.bind(this)) // Événement de clic this.nowBlock = null // Bloc de couleur actuellement sélectionné} createBlock (option) { // Option Créer une fonction de bloc de couleur (Block est ici la classe de bloc de couleur).Canvas = this // Le niveau de création du dernier bloc de couleur doit être le plus élevé option.hierarchy = this.blockList.length this.blockList.push (new Block (option)) this.rendering() } mousedownEvent (e) { // Cliquez sur l'événement const x = e.offsetX const y = e.offsetY // Récupère le bloc de couleur de niveau le plus élevé au point this.nowBlock = (this.blockList.filter(ele => ele.checkBoundary(x, y))).pop() // S'il n'y a pas de bloc de couleur capturé, quittez directement si (!this .nowBlock) return // Augmente le niveau du bloc de couleur cliqué au plus haut this.nowBlock.hierarchy = this.blockList.length // Réorganiser (de petit à grand) this.blockList.sort((a, b) = > a.hierarchy - b.hierarchy) // Réaffecter la hiérarchie à partir de 0 this.blockList.forEach((ele, idx) => ele.hierarchy = idx) // Re-trier dans l'ordre inverse puis restituer. this.painting() this.nowBlock.mousedownEvent(e) // Déclenche uniquement des événements pour le bloc de couleur sélectionné}}// Ici, nous devons également ajouter un troisième bloc de couleur qui chevauche le bloc de couleur rouge canvas.createBlock({ x : 150, y : 150, l : 100, h : 100, couleur : '#0f0'})
Le code de la méthode mousedownEvent dans Canvas est un peu compliqué, principalement parce qu'il est un peu alambiqué.
L'effet après l'exécution est le suivant :
3. Faites glisser et déposez différents blocs de couleursCi-dessus, nous avons implémenté l'obtention de différents blocs de couleurs et la modification de leurs niveaux. Ensuite, nous devons implémenter le glissement des blocs de couleur, principalement pour obtenir les changements de coordonnées de position lors du mouvement de la souris et lors du premier clic de la souris. Ce principe est le même que celui de l’implémentation du glisser-déposer DOM ordinaire.
Obtenez le point où le bloc de couleur est cliqué et la distance (disX, disY) entre la gauche et le haut du bloc de couleur.
Lorsque la souris bouge, soustrayez (disX, disY) de la distance actuelle de la souris par rapport à la gauche et au haut de la toile. Ce sont les coordonnées x et y du bloc de couleur.
class Block { // ...omettre une partie du code mousedownEvent (e: MouseEvent) { /* La méthode de calcul de disX et disY ici : e.offsetX obtient la distance entre le clic de la souris et le côté gauche du canevas, et this.x est la distance du bloc de couleur. La distance à gauche du canevas. e.offsetX-this.x est la distance à gauche du bloc de couleur. Cela devrait être facile à comprendre*/ const disX = e.offsetX - this.x // La distance depuis le côté gauche du bloc de couleur lorsque vous cliquez dessus const disY = e.offsetY - this.y // La distance depuis le haut de le bloc de couleur lorsque vous cliquez dessus // Lier l'événement de glissement de la souris ; ici mouseEvent.offsetX est également la distance entre la souris et le côté gauche du canevas, mouseEvent.offsetX - disX est la coordonnée x du bloc de couleur. De la même manière, y est calculé de la même manière. Enfin, refaites simplement le rendu. document.onmousemove = (mouseEvent) => { this.x = mouseEvent.offsetX - disX this.y = mouseEvent.offsetY - disY this.Canvas.painting() } // Efface tous les événements lorsque la souris est relâchée document.onmouseup = ( ) => { document.onmousemove = document.onmousedown = null } // console.log(`Clic sur le bloc de couleur 22` avec la couleur ${this.color}) }}
L'effet est le suivant :
Le code complet est collé ci-dessous (le HTML et les méthodes d'appel ne seront pas inclus). Cet exemple est juste une simple implémentation de liaison d'événements au contenu du canevas. Vous pouvez en implémenter des plus complexes, comme le remplacement de blocs de couleur par des images. En plus de faire glisser, vous pouvez zoomer, faire pivoter, supprimer, etc. des images.
class Canvas { blockList : Block[] ctx : any canvas : any nowBlock : Block createBlock (option) { option.hierarchy = this.blockList.length option.Canvas = this this.blockList.push(new Block(option)) this. painting() } rendu (block) { this.ctx.fillStyle = block.color this.ctx.fillRect(block.x, block.y, block.w, block.h) } painting () { // Effacer le canevas 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) { // Cliquez sur l'événement const x = e.offsetX const y = e.offsetY // Récupère le bloc de couleur de niveau le plus élevé au point this.nowBlock = (this.blockList.filter(ele => ele.checkBoundary(x, y))).pop() // S'il n'y a pas de bloc de couleur capturé, quittez directement si (!this .nowBlock) return // Augmente le niveau du bloc de couleur cliqué au plus haut this.nowBlock.hierarchy = this.blockList.length // Réorganiser (de petit à grand) this.blockList.sort((a, b) = > a.hierarchy - b.hierarchy) // Réaffecter la hiérarchie à partir de 0 this.blockList.forEach((ele, idx) => ele.hierarchy = idx) // Re-trier dans l'ordre inverse puis restituer. this.painting() this.nowBlock.mousedownEvent(e) // this.blockList.forEach(ele => { // if (ele.checkBoundary(x, y)) ele.clickEvent(e) // }) } constructeur (ele) { this.canvas = ele this.ctx = this.canvas.getContext('2d') this.blockList = [] // Liaison d'événement this.canvas.addEventListener('mousedown', this.mousedownEvent.bind(this)) }}class Block { w : numéro h : numéro x : numéro y : numéro couleur : chaîne Canvas : hiérarchie du canevas : constructeur numérique ( { w, h, x, y, couleur, canevas, hiérarchie }) { this.w = w this.h = h this.x = x this.y = y this.color = color this.Canvas = Canvas this.hierarchy = hierarchie } 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(`Le bloc de couleur 22 avec la couleur ${this.color} a été cliqué`) }}
Ce qui précède représente l’intégralité du contenu de cet article. J’espère qu’il sera utile à l’étude de chacun. J’espère également que tout le monde soutiendra le réseau VeVb Wulin.