Maison  >  Article  >  interface Web  >  Exemple de détails de l'effet de grattage pratique HTML5 Canvas

Exemple de détails de l'effet de grattage pratique HTML5 Canvas

黄舟
黄舟original
2017-03-30 11:15:571728parcourir

Ces dernières années, en raison d'une meilleure prise en charge des appareils mobiles pour HTML5, il sont souvent des activités L'effet des prix à gratter. J'ai également lu le contenu H5 récemment et j'en ai mis un moi-même. Maintenant, je vais le partager avec tout le monde

1. >Le principe est très simple, c'est-à-dire ajouter deux

toiles

dans la zone de grattage. La première toile sert à afficher le contenu après grattage. Il peut s'agir d'une

image ou une

String , la deuxième toile sert à afficher le revêtement, qui peut être rempli d'une image ou d'une couleur unie. La deuxième toile recouvre la première toile lorsqu'elle est dans la seconde. un. Lorsque vous cliquez ou étalez sur la toile (cliquez et faites glisser la souris), rendez la zone cliquée transparente, afin que vous puissiez voir le contenu sur la première toile, ce qui permet d'obtenir l'effet scratch 3. Implémentation.

(1) Définir la classe Loterie

Expliquez les paramètres :

function Lottery(id, cover, coverType, width, height, drawPercentCallback) {
    this.conId = id;
    this.conNode = document.getElementById(this.conId);
    this.cover = cover || '#CCC';
    this.coverType = coverType || 'color';
    this.background = null;
    this.backCtx = null;
    this.mask = null;
    this.maskCtx = null;
    this.lottery = null;
    this.lotteryType = 'image';
    this.width = width || 300;
    this.height = height || 100;
    this.clientRect = null;
    this.drawPercentCallback = drawPercentCallback;
}
id : l'identifiant du conteneur à gratter

  • cover : le contenu du revêtement, qui peut être une adresse d'image ou une valeur de couleur, peut être vide, la valeur par défaut est #ccc

  • coverType : type de revêtement , la valeur est image ou couleur, peut être vide, la valeur par défaut est couleur

  • width : la largeur de la zone de travail, la valeur par défaut est 300px, peut être vide

  • hauteur : la hauteur de la zone de grattage, la valeur par défaut est 100 px, nullable

  • drawPercentCallback : rappel du pourcentage de la zone grattée, nullable

  • Ensuite, plusieurs exigences sont définies.

    variables utilisées

     :

background : le premier élément du canevas

  • backCtx : contexte 2D de l'élément d'arrière-plan (context)

  • masque : le deuxième élément du canevas

  • maskCtx : contexte 2D de l'élément masque

  • lottery : Le contenu affiché après le grattage, qui peut être une adresse d'image ou une chaîne

  • lotteryType : Le type de contenu affiché après le grattage, la valeur est une image ou un texte , pour être Matches

  • clientRect : utilisé pour enregistrer la valeur lotterygetBoundingClientRect() de l'élément de masque

  • (2) Ajoutez deux canevas au conteneur scratch et obtenez le contexte 2D

La méthode de l'outil createElement est utilisée ici, et l'événement est. également lié introduire.

this.background = this.background || this.createElement('canvas', {
    style: 'position:absolute;left:0;top:0;'
});
this.mask = this.mask || this.createElement('canvas', {
    style: 'position:absolute;left:0;top:0;'
});

if (!this.conNode.innerHTML.replace(/[\w\W]| /g, '')) {
    this.conNode.appendChild(this.background);
    this.conNode.appendChild(this.mask);
    this.clientRect = this.conNode ? this.conNode.getBoundingClientRect() : null;
    this.bindEvent();
}

this.backCtx = this.backCtx || this.background.getContext('2d');
this.maskCtx = this.maskCtx || this.mask.getContext('2d');

(3) Dessinez la première toile

La première toile est divisée en deux types, image et chaîne, si vous utilisez simplement drawImage de la toile directement pour l'image. S'il s'agit d'une chaîne, remplissez-la d'abord de blanc, puis dessinez la chaîne au centre en haut, en bas, à gauche et à droite. Le code est le suivant :

(4) Dessin La deuxième toileLa deuxième toile peut également être remplie d'image ou de couleur.

Il y a une difficulté ici, c'est-à-dire comment rendre la zone de clic de la souris transparente ? La réponse est ici : Developer.mozilla.org/en/docs/Web/Guide/HTML/Canvas_tutorial/Compositing
if (this.lotteryType == 'image') {
    var image = new Image(),
        _this = this;
    image.onload = function () {
        _this.width = this.width;
        _this.height = this.height;
        _this.resizeCanvas(_this.background, this.width, this.height);
        _this.backCtx.drawImage(this, 0, 0);
    }
    image.src = this.lottery;
} else if (this.lotteryType == 'text') {
    this.width = this.width;
    this.height = this.height;
    this.resizeCanvas(this.background, this.width, this.height);
    this.backCtx.save();
    this.backCtx.fillStyle = '#FFF';
    this.backCtx.fillRect(0, 0, this.width, this.height);
    this.backCtx.restore();
    this.backCtx.save();
    var fontSize = 30;
    this.backCtx.font = 'Bold ' + fontSize + 'px Arial';
    this.backCtx.textAlign = 'center';
    this.backCtx.fillStyle = '#F60';
    this.backCtx.fillText(this.lottery, this.width / 2, this.height / 2 + fontSize / 2);
    this.backCtx.restore();
}

c'est-à-dire que nous allons masquer le

de Ctx alors dessinez le deuxième Le code du canevas est le suivant :

Ici, resizeCanvas est une méthode outil pour changer la taille du canevas. globalCompositeOperation 设置为 destination-out ,详细的用法请参考上面给出的链接。

(5) Liaison d'événements

Une fois le dessin terminé, liez l'événement à la deuxième toile. Il y a ici deux situations : les appareils mobiles et PC-WEB. Les appareils mobiles ont des événements touchstart et touchmove, et les événements PC-WEB correspondants sont des événements
this.resizeCanvas(this.mask, this.width, this.height);
if (this.coverType == 'color') {    
this.maskCtx.fillStyle = this.cover;    
this.maskCtx.fillRect(0, 0, this.width, this.height);    
this.maskCtx.globalCompositeOperation = 'destination-out';
} else if (this.coverType == 'image'){    var image = new Image(),
        _this = this;
    image.onload = function () {
        _this.maskCtx.drawImage(this, 0, 0);
        _this.maskCtx.globalCompositeOperation = 'destination-out';
    }
    image.src = this.cover;
}
key

down et mousemove. De plus, en mode PC-WEB, un événement mouseup doit être lié au document pour déterminer si. la souris est enfoncée. Le code est le suivant :

Ici, les coordonnées de la souris sont supprimées dans l'événement et drawPoint est appelé pour dessiner, ce qui sera discuté ci-dessous.

(6) Dessinez la zone de clic et de maculage

Le dégradé radial du canevas est utilisé ici pour dessiner un cercle au niveau du pointeur de la souris. Le code est le suivant :
bindEvent: function () {
    var _this = this;
    var device = (/android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(navigator.userAgent.toLowerCase()));
    var clickEvtName = device ? 'touchstart' : 'mousedown';
    var moveEvtName = device? 'touchmove': 'mousemove';
    if (!device) {
        var isMouseDown = false;
        document.addEventListener('mouseup', function(e) {
            isMouseDown = false;
        }, false);
    }
    this.mask.addEventListener(clickEvtName, function (e) {
        isMouseDown = true;
        var docEle = document.documentElement;
        if (!_this.clientRect) {
            _this.clientRect = {
                left: 0,
                top:0
            };
        }
        var x = (device ? e.touches[0].clientX : e.clientX) - _this.clientRect.left + docEle.scrollLeft - docEle.clientLeft;
        var y = (device ? e.touches[0].clientY : e.clientY) - _this.clientRect.top + docEle.scrollTop - docEle.clientTop;
        _this.drawPoint(x, y);
    }, false);

    this.mask.addEventListener(moveEvtName, function (e) {
        if (!device && !isMouseDown) {
            return false;
        }
        var docEle = document.documentElement;
        if (!_this.clientRect) {
            _this.clientRect = {
                left: 0,
                top:0
            };
        }
        var x = (device ? e.touches[0].clientX : e.clientX) - _this.clientRect.left + docEle.scrollLeft - docEle.clientLeft;
        var y = (device ? e.touches[0].clientY : e.clientY) - _this.clientRect.top + docEle.scrollTop - docEle.clientTop;
        _this.drawPoint(x, y);
    }, false);
}

.

(7) Pourcentage de zone maculée

drawPoint: function (x, y) {
    this.maskCtx.beginPath();
    var radgrad = this.maskCtx.createRadialGradient(x, y, 0, x, y, 30);
    radgrad.addColorStop(0, 'rgba(0,0,0,0.6)');
    radgrad.addColorStop(1, 'rgba(255, 255, 255, 0)');
    this.maskCtx.fillStyle = radgrad;
    this.maskCtx.arc(x, y, 30, 0, Math.PI * 2, true);
    this.maskCtx.fill();
    if (this.drawPercentCallback) {
        this.drawPercentCallback.call(null, this.getTransparentPercent(this.maskCtx, this.width, this.height));
    }
}
Dans de nombreux cas, nous devons également savoir combien l'utilisateur a barbouillé avant de passer à l'interaction suivante. Par exemple, lorsque l'utilisateur a enduit 80%, autorisez l'affichage du suivant.

Comment calculer ce pourcentage ? En fait, c'est très simple. Nous pouvons utiliser la méthode getImageData pour spécifier les données de pixel du rectangle sur le canevas. Puisque chaque pixel est représenté par rgba et que la zone peinte est transparente, il suffit de juger la valeur du. canal alpha à savoir. Est-ce transparent ? Le code est le suivant :

(8) Appeler l'entrée init

et enfin fournir une entrée pour le dessin et la réinitialisation. Le code est le suivant : .

getTransparentPercent: function(ctx, width, height) {
    var imgData = ctx.getImageData(0, 0, width, height),
        pixles = imgData.data,
        transPixs = [];
    for (var i = 0, j = pixles.length; i < j; i += 4) {
        var a = pixles[i + 3];
        if (a < 128) {
            transPixs.push(i);
        }
    }
    return (transPixs.length / (pixles.length / 4) * 100).toFixed(2);
}
À ce stade, tous les codes clés ont été expliqués.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn