HTML5 Canvas の実践的なスクラッチ効果の例の詳細

黄舟
リリース: 2017-03-30 11:15:57
オリジナル
1777 人が閲覧しました

近年、モバイルデバイスのHTML5のサポートが向上したため、スクラッチの効果を伴うアクティビティが頻繁に行われています。最近も H5 のコンテンツを見て、自分で実装しました。

1. 原理

原理は非常に簡単で、

キャンバス

を 2 つ追加するだけです。スクラッチ領域、最初のキャンバスは、スクラッチ後のコンテンツを表示するために使用されます。2 番目のキャンバスは、コーティングを表示するために使用されます。 2 番目のキャンバスが最初のキャンバスで覆われています。 2 番目のキャンバスをクリックまたは塗りつぶす (マウスをクリックしてドラッグする) と、最初のキャンバスのコンテンツが見えるように、クリックされた領域が透明になります。つまり、3. 実装します (1) Lottory クラスを定義します

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: スクラッチコンテナーの ID

    cover: コーティングコンテンツ (画像にすることができます)アドレスまたは色の値、空にすることができます、デフォルトは #ccc
  • coverType: コーティングのタイプ、値は画像または色、空にすることができます、デフォルトは color です
  • width: スクラッチ領域の幅、デフォルトは 300px、できますbe Empty
  • height: スクラッチ領域の高さ、デフォルトは 100px、空でも可
  • drawPercentCallback: スクラッチ領域のパーセンテージコールバック、空でも可
  • 次に、いくつかの
  • 変数

    も定義されています。使用されます

    :

background: 最初のキャンバス要素

  • backCtx: 背景要素の 2D コンテキスト

  • mask: 2 番目の Canvas 要素

  • maskCtx: マスク要素の 2D コンテキスト)

  • lottery: スクラッチ後に表示されるコンテンツ。画像アドレスまたは文字列にすることができます。

  • lotteryType: スクラッチ後に表示されるコンテンツ タイプ。値は画像またはテキストで、その後に が続く必要があります。 lottery</code >一致 <p></p></li><li>clientRect: マスク要素の <span class="function call">getBoundingClientRect() 値を記録するために使用されます<p><code>lottery匹配

  • clientRect:用于记录mask元素的 getBoundingClientRect() 值

(2)添加二个canvas到刮奖容器,并获取2d上下文

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

if (!this.conNode.innerHTML.replace(/[\w\W]| /g, &#39;&#39;)) {
    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(&#39;2d&#39;);
this.maskCtx = this.maskCtx || this.mask.getContext(&#39;2d&#39;);
ログイン後にコピー

这里用于了createElement工具方法,另外还绑定了事件,后面介绍。

(3)绘制第一个canvas

第一个canvas分两种类型,image 和 string,如果是图片直接用canvas的drawImage就可以了,如果是string,要先用白色填充,然后在上下左右居中的地方绘制字符串,代码如下:

if (this.lotteryType == &#39;image&#39;) {
    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 == &#39;text&#39;) {
    this.width = this.width;
    this.height = this.height;
    this.resizeCanvas(this.background, this.width, this.height);
    this.backCtx.save();
    this.backCtx.fillStyle = &#39;#FFF&#39;;
    this.backCtx.fillRect(0, 0, this.width, this.height);
    this.backCtx.restore();
    this.backCtx.save();
    var fontSize = 30;
    this.backCtx.font = &#39;Bold &#39; + fontSize + &#39;px Arial&#39;;
    this.backCtx.textAlign = &#39;center&#39;;
    this.backCtx.fillStyle = &#39;#F60&#39;;
    this.backCtx.fillText(this.lottery, this.width / 2, this.height / 2 + fontSize / 2);
    this.backCtx.restore();
}
ログイン後にコピー

(4)绘制第二个canvas

第二个canvas也分 image 或 color 填充两种情况。

这里有一个难点,就是如何把鼠标点击区域变成透明的呢?答案在这里:developer.mozilla.org/en/docs/Web/Guide/HTML/Canvas_tutorial/Compositing

即我们要把 maskCtx的 globalCompositeOperation 设置为 destination-out ,详细的用法请参考上面给出的链接。

(2) 2 つのキャンバスをスクレイパー Award コンテナに追加し、2D コンテキストを取得します

this.resizeCanvas(this.mask, this.width, this.height);
if (this.coverType == &#39;color&#39;) {    
this.maskCtx.fillStyle = this.cover;    
this.maskCtx.fillRect(0, 0, this.width, this.height);    
this.maskCtx.globalCompositeOperation = &#39;destination-out&#39;;
} else if (this.coverType == &#39;image&#39;){    var image = new Image(),
        _this = this;
    image.onload = function () {
        _this.maskCtx.drawImage(this, 0, 0);
        _this.maskCtx.globalCompositeOperation = &#39;destination-out&#39;;
    }
    image.src = this.cover;
}
ログイン後にコピー

ここでは createElement ツール メソッドが使用されており、後で紹介するイベント

(3) 最初のキャンバスを描画します

最初のキャンバスは、画像の場合は画像と

文字列

の2種類に分かれます直接キャンバスのdrawImageを使うだけです。文字列の場合は、まず白で塗りつぶしてから上下左右の中央に文字列を描画します。 コードは次のとおりです:

bindEvent: function () {
    var _this = this;
    var device = (/android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(navigator.userAgent.toLowerCase()));
    var clickEvtName = device ? &#39;touchstart&#39; : &#39;mousedown&#39;;
    var moveEvtName = device? &#39;touchmove&#39;: &#39;mousemove&#39;;
    if (!device) {
        var isMouseDown = false;
        document.addEventListener(&#39;mouseup&#39;, 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);
}
ログイン後にコピー

(4) 2 番目のキャンバスを描画します

2 番目のキャンバスは画像や色で塗りつぶすこともできます。

ここで問題があります。それは、マウスのクリック領域を透明にする方法です。答えはここにあります:developer.mozilla.org/en/docs/Web/Guide/HTML/Canvas_tutorial/Compositing

つまり、maskCtx の globalCompositeOperation を destination-out に設定する必要があります。詳しい使用方法については、を参照してください。上記のリンクを参照してください。

したがって、2番目のキャンバスを描画するコードは次のようになります:

drawPoint: function (x, y) {
    this.maskCtx.beginPath();
    var radgrad = this.maskCtx.createRadialGradient(x, y, 0, x, y, 30);
    radgrad.addColorStop(0, &#39;rgba(0,0,0,0.6)&#39;);
    radgrad.addColorStop(1, &#39;rgba(255, 255, 255, 0)&#39;);
    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));
    }
}
ログイン後にコピー

ここで、resizeCanvasは、キャンバスのサイズを変更するためのツールメソッドです。

(5)イベントをバインド

描画が完了したら、2番目のキャンバスにイベントをバインドします。ここでは、モバイルデバイスと PC-WEB の 2 つの状況が考えられます。モバイル デバイスには touchstart イベントと touchmove イベントがあり、対応する PC-WEB イベントは

key

down イベントと Mousemove イベントです。さらに、PC-WEB モードでは、マウスが押されたかどうかを判断するために、mouseup イベントをドキュメントにバインドする必要があります。コードは次のとおりです。

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);
}
ログイン後にコピー

ここでは、マウス座標がイベントで取得され、drawPoint が呼び出されて描画されます。これについては後述します。

(6) クリックとスミア領域を描画します🎜🎜 ここでは、キャンバスの放射状グラデーションを使用して、マウス ポインタから円を描画します。 コードは次のとおりです: 🎜
init: function (lottery, lotteryType) {
    this.lottery = lottery;
    this.lotteryType = lotteryType || &#39;image&#39;;
    this.drawLottery();
}
ログイン後にコピー
🎜🎜(7) スミア領域の割合🎜🎜。 🎜🎜同時に、次のインタラクションを実行する前に、ユーザーがどれだけスミアしたかを知る必要もあります。たとえば、ユーザーが 80% をスミアした場合、次の画像の表示が許可されます。 🎜🎜🎜🎜このパーセンテージを計算するにはどうすればよいですか?実際には、getImageData メソッドを使用して、キャンバス上の四角形のピクセル データを指定することができます。各ピクセルは rgba で表現され、描画された領域は透明なので、その値を判断するだけで済みます。アルファチャンネルは透明ですか?コードは次のとおりです。 🎜🎜rrreee🎜(8) 入り口の init を呼び出します🎜🎜 最後に、描画とリセットのための入り口が提供されます。 コードは次のとおりです。 🎜rrreee🎜 この時点で、すべてのキー コードが説明されました。 。 🎜

以上がHTML5 Canvas の実践的なスクラッチ効果の例の詳細の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート