Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Image Masking
<canvas id='stage'></canvas>
<h1>Mouse over image</h1>
<footer>
<a href="http://insidedown.com">Paul Mealy | InsideDown</a>
</footer>
//*** SHIM ***
window.requestAnimFrame = (function() {
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(callback) {
window.setTimeout(callback, 1000 / 60);
};
})();
(function() {
"use strict";
//************
//VARIABLES
//************
var _Canvas;
let _frontImageSrc = 'http://insidedown.com/codepen/stock/mountain-tan.jpg';
let _backImageSrc = 'http://insidedown.com/codepen/stock/mountain.jpg';
let _frontImage;
let _backImage;
let _blackMask;
let _mouseX = 0;
let _mouseY = 0;
let _maskCount = 25;
let _tweenTime = 0.5;
let _pauseTime = 0.25;
let _delayTime = 0.08;
let _maskArray = [];
let _srcArray = ["http://insidedown.com/codepen/stock/newstain1.png", "http://insidedown.com/codepen/stock/newstain2.png", "http://insidedown.com/codepen/stock/newstain3.png"];
//************
//METHODS
//************
function init() {
_Canvas = new Canvas({stage:document.getElementById('stage')});
_backImage = new MaskedImage({src:_backImageSrc});
_frontImage = new MaskedImage({src:_frontImageSrc});
for(let i=0;i<_maskCount;i++){
let ranSrc = _srcArray[Math.floor(Math.random() * _srcArray.length)];
let mask = new MaskedImage({src:ranSrc, delay:i, width:300});
_maskArray.push(mask);
}
addListeners();
}
//************
//EVENTS
//************
function addListeners() {
_Canvas.el.addEventListener('mousemove', onCanvasMouseMove);
_Canvas.el.addEventListener('mouseout', onCanvasMouseOut);
}
function onCanvasMouseMove(event) {
_mouseX = event.pageX - $(this).offset().left;
_mouseY = event.pageY - $(this).offset().top;
}
function onCanvasMouseOut(event) {
}
function onEnterFrame() {
_Canvas.clearStage();
drawStage();
window.requestAnimFrame(onEnterFrame, 60);
}
function drawStage() {
_Canvas.context.save();
for(let i=0;i<_maskCount;i++){
let mask = _maskArray[i];
mask.tweenDraw();
}
//_blackMask.draw(_mouseX,_mouseY);
_Canvas.context.globalCompositeOperation = 'source-in';
_backImage.draw();
_Canvas.context.globalCompositeOperation = 'destination-over';
_frontImage.draw();
_Canvas.context.restore();
}
//************
//CLASSES
//************
class MaskedImage {
constructor(options) {
this.hasImg = false;
this.img = new Image();
this.empty = {scale:0, alpha:1, x:0, y:0};
this.delay = options.delay;
this.rotation = Math.random() * 360;
this.width = options.width;
this.halfWidth = this.width/2;
this.img.src = options.src;
this.img.onload = function() {
this.hasImg = true;
if(this.delay){
setTimeout(function() {this.scale();}.bind(this), this.delay*(_delayTime * 1000));
}
this.draw();
}.bind(this);
}
draw(x=0,y=0) {
if(this.hasImg) {
_Canvas.context.drawImage(this.img,x,y);
}
}
tweenDraw() {
if(this.hasImg) {
let curWidth = this.width * this.empty.scale;
_Canvas.context.save();
_Canvas.context.globalAlpha = this.empty.alpha;
_Canvas.context.translate(this.empty.x, this.empty.y);
_Canvas.context.rotate(this.rotation * Math.PI / 180);
_Canvas.context.scale(1.5 * (curWidth/this.width), 1.5*(curWidth/this.width));
_Canvas.context.translate(-this.empty.x, -this.empty.y);
_Canvas.context.drawImage(this.img,this.empty.x-this.halfWidth,this.empty.y-this.halfWidth);
_Canvas.context.globalAlpha = 1;
_Canvas.context.restore();
}
}
scale() {
this.empty.x = _mouseX;
this.empty.y = _mouseY;
this.rotation = Math.random() * 360;
TweenMax.fromTo(this.empty, _tweenTime, {alpha:1, scale:0},{alpha:1, scale:1, onComplete:function(){
setTimeout(this.fadeOut.bind(this), _pauseTime * 1000);
}.bind(this)
});
}
fadeOut() {
TweenMax.to(this.empty, _tweenTime,{alpha:0, onComplete:this.scale.bind(this)});
}
}
class Canvas {
constructor(options) {
this._stage = options.stage;
this._stageWidth = this._stage.width = window.innerWidth;
this._stageHeight = this._stage.height = window.innerHeight;
this._stageContext = this._stage.getContext('2d');
}
// clear stage of current content
clearStage(options) {
if(typeof options === "undefined") {
this._stageContext.clearRect(0,0,this._stageWidth, this._stageHeight);
}
}
get width() { return this._stageWidth; }
get height() { return this._stageHeight; }
get el() {return this._stage; }
get context() {return this._stageContext; }
} //end Canvas class
init();
onEnterFrame();
})();
<script src="//cdnjs.cloudflare.com/ajax/libs/zepto/1.1.4/zepto.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.19.1/TweenMax.min.js"></script>
@import url(https://fonts.googleapis.com/css?family=Lato:300,400,700, 400italic);
body {
background-color: #000;
height: 100%;
margin: 0;
overflow: hidden;
padding: 0;
width: 100%;
}
h1 {
color: #999;
font-family: 'Lato', helvetica, arial, sans-serif;
font-weight: normal;
font-size: 16px;
position: absolute;
text-align: center;
top: 0;
width: 100%;
}
canvas {
background-color: #111;
}
footer {
background: rgba(0,0,0,0.35);
border-radius: 0 10px 0px 0;
bottom: 0px;
color: #fff;
font-family: 'Lato', helvetica, arial, sans-serif;
font-size: 11px;
font-weight: 300;
padding: 8px 12px 8px 12px;
position: absolute;
text-shadow: -1px 1px #000000;
text-transform: uppercase;
z-index: 2;
}
footer a {
color: #fff;
text-decoration: none;
}
footer a:hover {
color: #ddd;
}
@dt24tared

This comment has been minimized.

Copy link

commented Jan 14, 2018

I downloaded the zip file, because I was having issues when copying the code from Codepen, however the same problem arose from the zip files. The text shows up fine but the images aren't shown and it only shows the black background from the css. It doesn't work either with the precoded images or with images I included from file. It reads the Javascript file as being linked but doesn't seam to implement anything from it. I did very little to the code, and yet it doesn't work in any browser I've tried. Is there something I need to do?

@thepragg

This comment has been minimized.

Copy link

commented Apr 28, 2018

@dt24tared
I had almost the same problem after using this same zip file, until I noticed that the html file wasn't complete; it's exactly as it appears on codePen. Just edit that and you should be fine. i.e here's my edit

From This;

<canvas id='stage'></canvas>
<h1>Mouse over image</h1>
<footer>
	<a href="http://insidedown.com">Paul Mealy | InsideDown</a>
</footer>

To This;

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<meta http-equiv="X-UA-Compatible" content="IE=edge">
		<meta name="description" content="">
		<meta name="viewport" content="width=device-width, initial-scale=1">
		<title>Image Masking [local]</title>
		<link rel="stylesheet" type="text/css" href="style.css">
	</head>
	<body>
		<canvas id='stage'></canvas>
		<h1>Mouse over image</h1>
		<footer>
			<a href="http://insidedown.com">Paul Mealy | InsideDown</a>
		</footer>
		<script src="https://cdnjs.cloudflare.com/ajax/libs/zepto/1.1.4/zepto.min.js"></script>
		<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.19.1/TweenMax.min.js"></script>
		<script src="script.js"></script>
	</body>
</html>

Worked well afterwards...cheers

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.