Toggle navigation
Sign Up
Log In
Explore
Works
Folders
Tools
Collections
Artists
Groups
Groups
Topics
Tasks
Tasks
Jobs
Teams
Jobs
Recommendation
More Effects...
JS
var mViewWidth = 0, mViewHeight = 0, mCanvas = document.getElementById("canvas"), mCtx; var mRootDisplayNode; var mTrees = []; var mTreeImage = 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/175711/tree.png', mMonsterImage = 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/175711/monster-01.png'; var mUrls = [ mTreeImage, mMonsterImage ]; var mImages = {}; var mLoadedCount = 0; mUrls.forEach(function(url) { var img = mImages[url] = document.createElement('img'); img.onload = function() { if (++mLoadedCount === mUrls.length) { init(); } }; img.crossOrigin = 'Anonymous'; img.src = url; }); function init() { initCanvas(); createMist(); createTrees(300); createMist(); createTrees(250); createMist(); createMonster(); createTrees(160); createMist(); createTrees(120); createMist(); createTrees(90); createMist(); createTrees(70); requestAnimationFrame(loop); } function initCanvas() { mViewWidth = mCanvas.width = mCanvas.clientWidth; mViewHeight = mCanvas.height = mCanvas.clientHeight; mCtx = mCanvas.getContext('2d'); mRootDisplayNode = new Node(); } function createMist() { var mist = new Node(new Mist(mViewWidth * 1.2, mViewHeight * 1.2)); var range = randomRange(0, 100); mist.x = -mViewWidth * 0.1; mist.y = -mViewHeight * 0.1; TweenMax.fromTo(mist, randomRange(6, 8), {y:'-='+range}, {y:'-='+range, ease:Power1.easeInOut, repeat:-1, yoyo:true}); mRootDisplayNode.add(mist); } function createMonster() { var monster = new Node(new Monster(mImages[mMonsterImage])); monster.y = 135; monster.x = -150; var stepDeltaX = 30, stepDeltaY = 10; var stepDuration = 1.6, startOffset = 0.6; function step() { var tl = new TimelineMax(); if (monster.x > mViewWidth) { monster.x = -150; } tl.to(monster, stepDuration * 0.4, {y:'-=' + stepDeltaY, ease:Power2.easeOut}, startOffset); tl.to(monster, stepDuration * 0.6, {y:'+=' + stepDeltaY, ease:Power4.easeIn}); tl.add('shake'); tl.to(monster, stepDuration, {x:'+=' + stepDeltaX, ease:Power1.easeOut}, startOffset); tl.addCallback(function() { mTrees.forEach(function(t) { TweenMax.to(t, randomRange(0.3, 0.4), {y:'+=' + randomRange(4, 16), ease:Back.easeIn, repeat:1, yoyo:true}); }); }, 'shake-=0.25'); tl.eventCallback('onComplete', step); } mRootDisplayNode.add(monster); step(); } function createTrees(yOffset) { var tree; var dx = mViewWidth / 12; for (var i = 0; i < 12; i++) { tree = createTree( mImages[mTreeImage], dx * i + 35 * randomRange(0.8, 1.2), (mViewHeight - yOffset) * randomRange(1.0, 1.2) ); tree._segments.forEach(function(c) { var range = randomRange(0.01, 0.02); TweenMax.fromTo(c, randomRange(2, 10), {rotation:-range}, {rotation:range, ease:Power1.easeInOut, repeat:-1, yoyo:true} ); }); mRootDisplayNode.add(tree); mTrees.push(tree); } } function createTree(image, x, y) { var totalWidth = image.naturalWidth, totalHeight = image.naturalHeight; var steps = 6, deltaHeight = totalHeight / steps; var treeRoot = new Node(); var prevSegment = treeRoot; treeRoot.x = x; treeRoot.y = y; treeRoot._segments = []; for (var i = 0; i < steps; i++) { var sourceX = 0, sourceY = totalHeight - deltaHeight * (i + 1), sourceWidth = totalWidth, sourceHeight = deltaHeight; var segment = new Node(new ImageFragment(image, sourceX, sourceY, sourceWidth, sourceHeight)); if (i === 0) { segment.x = -totalWidth * 0.5; } segment.y = -deltaHeight * 0.95; segment.pivotX = totalWidth * 0.5; segment.pivotY = deltaHeight; prevSegment.add(segment); prevSegment = segment; treeRoot._segments.push(segment); } return treeRoot; } ///////////////////////////// // LOOP ///////////////////////////// function update() { } function draw() { mCtx.clearRect(0, 0, mViewWidth, mViewHeight); mRootDisplayNode.render(); } function loop() { update(); draw(); requestAnimationFrame(loop); } ///////////////////////////// // Classes ///////////////////////////// function Monster(img) { this.img = img; } Monster.prototype = { draw:function() { mCtx.drawImage(this.img, 0, 0); } }; function Mist(w, h) { this.w = w; this.h = h; this.gradient = mCtx.createLinearGradient(w * 0.5, h, w * randomRange(0.6, 0.9), 0); this.gradient.addColorStop(0.25, 'rgba(0,0,0,0)'); this.gradient.addColorStop(randomRange(0.5, 0.7), 'rgba(255,255,255,0.3)'); this.gradient.addColorStop(0.9, 'rgba(0,0,0,0)'); } Mist.prototype = { draw:function() { mCtx.fillStyle = this.gradient; mCtx.fillRect(0, 0, this.w, this.h); } }; function ImageFragment(img, sx, sy, sw, sh) { this.img = img; this.sx = sx; this.sy = sy; this.sw = sw; this.sh = sh; } ImageFragment.prototype = { draw:function() { mCtx.drawImage(this.img, this.sx, this.sy, this.sw, this.sh, 0, 0, this.sw, this.sh); } }; function Node(graphics) { this.graphics = graphics; this.x = 0; this.y = 0; this.pivotX = 0; this.pivotY = 0; this.scaleX = 1; this.scaleY = 1; this.rotation = 0; this.children = []; } Node.prototype = { add:function(node) { this.children.push(node); }, remove:function(node) { var i = this.children.indexOf(node); if (i >= 0) { this.children.splice(i, 1); } }, render:function() { mCtx.save(); mCtx.translate(this.pivotX + this.x, this.pivotY + this.y); mCtx.rotate(this.rotation); mCtx.scale(this.scaleX, this.scaleY); mCtx.translate(-this.pivotX, -this.pivotY); this.graphics && this.graphics.draw(); for (var i = 0; i < this.children.length; i++) { this.children[i].render(); } mCtx.restore(); } }; ///////////////////////////// // utils ///////////////////////////// function randomRange(min, max) { return min + Math.random() * (max - min); }
CSS
body { margin: 0; background: #000000; } #canvas { position: absolute; margin: auto; width: 600px; height: 600px; top: 0; bottom: 0; left: 0; right: 0; background: #000; }
HTML
Join Effecthub.com
Working with Global Gaming Artists and Developers!
Login
Sign Up
Or Login with Your Email Address:
Email
Password
Remember
Or Sign Up with Your Email Address:
Your Email
This field must contain a valid email
Set Password
Password should be at least 1 character
Stay informed via email