浜村拓夫(・∀・)作品集

頭の中にあるイメージを表現できるデザイン力が欲しいです(><)

ぼかした画像を鮮明にするJavaScriptのスニペット「Cursor Traits」

Webページのアニメーションとして、スクラッチカードのような「Cursor Traits」という面白いスニペットが紹介されていました。

設置方法がよく分からなかったので、設置のテストをしてみました。(メモ)

 

photoshopvip.net

 

Cursor Traits
スクリーンをこすると、下に配置されたbackground-imageが現れるCanvasを利用したユニークなレイアウト。

 

スニペット(snippet)とは、英語で「断片」という意味で、Web制作においてはHTMLやCSSJavaScript等の短いコードのことを指します。つまり、Webページ作成で使われるパーツのことですね。

 

● Cursor Traits

「Cursor Traits」というスニペットは、こちらで紹介されています。

 

codepen.io

 

Chris Dobleさんという方が作られたようです。

 

twitter.com

 

●Cursor Traits 動作サンプル

(環境によっては、表示に時間がかかります!)

See the Pen Cursor trails by Chris Doble (@chrisdoble) on CodePen.

 

HTML5Canvas機能を利用

・ぼかした画像の上にマウスを当てると、カーソルの部分に鮮明な画像が表示されるアニメーション

 

●設置テスト方法

上記のサンプルページのソースコードは、画像ファイルがエンコードされた文字列として扱われており、見づらくていまいちよく分かりませんでした。

そこで、エンコードされていた画像ファイルをデコードして、普通のJPEG画像ファイルに戻してから、表示確認を行いました。

 

テスト方法は、以下の手順です。

(テスト環境:Windows7Google Chrome

 

(1) デスクトップに「test」というフォルダを作る。(名前は適当でOK)

 

(2) 「test」フォルダの中に、以下のJPEG画像を「clear.jpg」という名前で保存する。(鮮明な画像を用意)

f:id:hamamuratakuo:20160531210659j:plain

 

 

(3) 「test」フォルダの中に、以下のJPEG画像を「blur.jpg」という名前で保存する。(ぼけた画像を用意) 

f:id:hamamuratakuo:20160531210714j:plain

 

(4) 「test」フォルダの中に、以下のHTMLコードを「index.html」というファイル名で保存する。

<!DOCTYPE html>
<html>
<head>
<meta charset='UTF-8'>
<style>
html,
body {
font-size: 0;
height: 100%;
margin: 0;
padding: 0;
width: 100%;
}

body {
background: url("blur.jpg") 0 0 / cover;
}

img {
display: none;
}
</style>
</head>
<body>
<img src="clear.jpg">

<script>
var image = document.querySelector('img');
var imageCanvas = document.createElement('canvas');
var imageCanvasContext = imageCanvas.getContext('2d');
var lineCanvas = document.createElement('canvas');
var lineCanvasContext = lineCanvas.getContext('2d');
var pointLifetime = 1000;
var points = [];

if (image.complete) {
start();
} else {
image.onload = start;
}

/**
* Attaches event listeners and starts the effect.
*/
function start() {
document.addEventListener('mousemove', onMouseMove);
window.addEventListener('resize', resizeCanvases);
document.body.appendChild(imageCanvas);
resizeCanvases();
tick();
}

/**
* Records the user's cursor position.
*
* @param {!MouseEvent} event
*/
function onMouseMove(event) {
points.push({
time: Date.now(),
x: event.clientX,
y: event.clientY
});
}

/**
* Resizes both canvases to fill the window.
*/
function resizeCanvases() {
imageCanvas.width = lineCanvas.width = window.innerWidth;
imageCanvas.height = lineCanvas.height = window.innerHeight;
}

/**
* The main loop, called at ~60hz.
*/
function tick() {
// Remove old points
points = points.filter(function(point) {
var age = Date.now() - point.time;
return age < pointLifetime;
});

drawLineCanvas();
drawImageCanvas();
requestAnimationFrame(tick);
}

/**
* Draws a line using the recorded cursor positions.
*
* This line is used to mask the original image.
*/
function drawLineCanvas() {
var minimumLineWidth = 25;
var maximumLineWidth = 100;
var lineWidthRange = maximumLineWidth - minimumLineWidth;
var maximumSpeed = 50;

lineCanvasContext.clearRect(0, 0, lineCanvas.width, lineCanvas.height);
lineCanvasContext.lineCap = 'round';
lineCanvasContext.shadowBlur = 30;
lineCanvasContext.shadowColor = '#000';

for (var i = 1; i < points.length; i++) {
var point = points[i];
var previousPoint = points[i - 1];

// Change line width based on speed
var distance = getDistanceBetween(point, previousPoint);
var speed = Math.max(0, Math.min(maximumSpeed, distance));
var percentageLineWidth = (maximumSpeed - speed) / maximumSpeed;
lineCanvasContext.lineWidth = minimumLineWidth + percentageLineWidth * lineWidthRange;

// Fade points as they age
var age = Date.now() - point.time;
var opacity = (pointLifetime - age) / pointLifetime;
lineCanvasContext.strokeStyle = 'rgba(0, 0, 0, ' + opacity + ')';

lineCanvasContext.beginPath();
lineCanvasContext.moveTo(previousPoint.x, previousPoint.y);
lineCanvasContext.lineTo(point.x, point.y);
lineCanvasContext.stroke();
}
}

/**
* @param {{x: number, y: number}} a
* @param {{x: number, y: number}} b
* @return {number} The distance between points a and b
*/
function getDistanceBetween(a, b) {
return Math.sqrt(Math.pow(a.x - b.x, 2) + Math.pow(a.y - b.y, 2));
}

/**
* Draws the original image, masked by the line drawn in drawLineToCanvas.
*/
function drawImageCanvas() {
// Emulate background-size: cover
var width = imageCanvas.width;
var height = imageCanvas.width / image.naturalWidth * image.naturalHeight;

if (height < imageCanvas.height) {
width = imageCanvas.height / image.naturalHeight * image.naturalWidth;
height = imageCanvas.height;
}

imageCanvasContext.clearRect(0, 0, imageCanvas.width, imageCanvas.height);
imageCanvasContext.globalCompositeOperation = 'source-over';
imageCanvasContext.drawImage(image, 0, 0, width, height);
imageCanvasContext.globalCompositeOperation = 'destination-in';
imageCanvasContext.drawImage(lineCanvas, 0, 0);
}

</script>
</body>
</html>

 

(5) 「test」フォルダの中にある「index.html」をWebブラウザーで開く。

 

すると、上記の動作サンプルと同様のWebページが表示されました。

めでたし、めでたし!

 

●ぼかした画像を用意する方法

jQueryプラグイン等で、画像をぼかすJavaScriptライブラリーもあるみたいなので、それらをうまく活用すれば、ぼかした画像を別途用意しなくても済むかも?

 

・鮮明な画像ファイルを1枚用意する。

jQueryプラグイン等で、鮮明な画像をぼかす。

 

●スクラッチカード

「Cursor Traits」で、スクラッチカードのようなWebページが作れそうだな~。

 

f:id:hamamuratakuo:20160531212618j:plain

(via スクラッチ -パンフレット印刷・印刷通販で植林活動!ユニオン印刷

 

何かの機会に使ってみよう♪

 

 

確かな力が身につくJavaScript「超」入門 (確かな力が身につく「超」入門シリーズ)

確かな力が身につくJavaScript「超」入門 (確かな力が身につく「超」入門シリーズ)

 

 

 

 

Kaoma / Lambada