<canvas>タグを使った、画像のスクラッチ表現を紹介します。
キャンペーンサイトに使えそう!<CANVAS>タグを使った画像のスクラッチ表現
Scratch Reveal with <canvas>は、<canvas>タグとJSで実装する、画像のスクラッチ表現です。
カラフルな写真にマウスを載せて、ドラッグすると、スクラッチを削るようにグレースケースの写真が現れます。
もちろん、デフォルトをグレースケールの写真にして、スクラッチでカラフルな写真を表示させることも可能です。
例えば、キャンペーンサイトなどで、画像にシリアルコードや当たり、ハズレのマークを埋め込んでおいて、ユーザーが画像を削ると表示される、という使い方ができそうです。
実装方法
デフォルトに表示される画像と、スクラッチで削った後に表示される画像の2枚を用意しておきます。
HTML
<canvas>を用意します。
<figure id="bridgeContainer"> <canvas id="bridge" width="750" height="465"></canvas> <figcaption>Downtown Calgary in 2013 and 1943; mouse down or touch on photo to reveal</figcaption> </figure>
CSS
背景のbackground-image
のhttps://s3-us-west-2.amazonaws.com/s.cdpn.io/4273/calgary-bridge-1943.jpg
の部分が最初に表示される画像です。
body { margin: 0; } #bridge { display: block; margin: 0 auto; background-image: url('https://s3-us-west-2.amazonaws.com/s.cdpn.io/4273/calgary-bridge-1943.jpg'); background-image: -webkit-image-set(url('https://s3-us-west-2.amazonaws.com/s.cdpn.io/4273/calgary-bridge-1943.jpg') 1x, url('https://s3-us-west-2.amazonaws.com/s.cdpn.io/4273/calgary-bridge-1943-2x.jpg') 2x ); background-size: cover; width: 100%; max-width: 750px; height: auto; cursor: crosshair; cursor: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/4273/circular-cursor.png) 53 53, crosshair; } #bridgeContainer { text-align: center; font-family: Avenir, sans-serif; } #bridgeContainer figcaption { margin-top: 2rem; }
JS
元の画像のURLを書き換える形で、スクラッチ後に表示する画像のURLを指定します。img.loc = 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/4273/';
の部分で、デフォルトの画像URLの内、書き換えない部分を指定します。img.filename = 'calgary-bridge-2013.jpg';
の部分で、デフォルトの画像URLの内、書き換える部分を指定します。
var bridge = document.getElementById("bridge"), bridgeCanvas = bridge.getContext('2d'), brushRadius = (bridge.width / 100) * 5, img = new Image(); if (brushRadius < 50) { brushRadius = 50 } img.onload = function(){ bridgeCanvas.drawImage(img, 0, 0, bridge.width, bridge.height); } img.loc = 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/4273/'; img.filename = 'calgary-bridge-2013.jpg'; if (window.devicePixelRatio >= 2) { var nameParts = img.filename.split('.'); img.src = img.loc + nameParts[0]+"-2x"+"."+nameParts[1]; } else { img.src = img.loc + img.filename; } function detectLeftButton(event) { if ('buttons' in event) { return event.buttons === 1; } else if ('which' in event) { return event.which === 1; } else { return event.button === 1; } } function getBrushPos(xRef, yRef) { var bridgeRect = bridge.getBoundingClientRect(); return { x: Math.floor((xRef-bridgeRect.left)/(bridgeRect.right-bridgeRect.left)*bridge.width), y: Math.floor((yRef-bridgeRect.top)/(bridgeRect.bottom-bridgeRect.top)*bridge.height) }; } function drawDot(mouseX,mouseY){ bridgeCanvas.beginPath(); bridgeCanvas.arc(mouseX, mouseY, brushRadius, 0, 2*Math.PI, true); bridgeCanvas.fillStyle = '#000'; bridgeCanvas.globalCompositeOperation = "destination-out"; bridgeCanvas.fill(); } bridge.addEventListener("mousemove", function(e) { var brushPos = getBrushPos(e.clientX, e.clientY); var leftBut = detectLeftButton(e); if (leftBut == 1) { drawDot(brushPos.x, brushPos.y); } }, false); bridge.addEventListener("touchmove", function(e) { e.preventDefault(); var touch = e.targetTouches[0]; if (touch) { var brushPos = getBrushPos(touch.pageX, touch.pageY); drawDot(brushPos.x, brushPos.y); } }, false);