Skip to content

Instantly share code, notes, and snippets.

@CodeMyUI
Created November 17, 2017 23:37
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save CodeMyUI/ce65bc02163e1137403f427e70236792 to your computer and use it in GitHub Desktop.
Save CodeMyUI/ce65bc02163e1137403f427e70236792 to your computer and use it in GitHub Desktop.
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
Copy link

dt24tared 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
Copy link

@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

@bhanusantosh
Copy link

how to set the height an width of the image....

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment