Skip to content

Instantly share code, notes, and snippets.

@ne-sachirou
Last active August 29, 2015 14:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ne-sachirou/48f02783837cf712286a to your computer and use it in GitHub Desktop.
Save ne-sachirou/48f02783837cf712286a to your computer and use it in GitHub Desktop.
Gassen Animation Demo (CSS+JavaScript) http://jsdo.it/ne_sachirou/7wwz
Gassen Animation Demo
https://gist.github.com/ne-sachirou/48f02783837cf712286a
Author : ne_Sachirou <utakata.c4se@gmail.com>
Date : 2014-2014
License : GPLv3 or later http://www.gnu.org/licenses/gpl.html
Music:
1. hainezu (FuniSaya,Crain) "gad1" CC by-sa 2014
2. hainezu (FuniSaya,Crain) "gad2" CC by-sa 2014
3. hainezu (FuniSaya,Crain) "gad3" CC by-sa 2014
@charset "UTF-8";
html, body {
height : 100%;
margin : 0;
overflow : hidden;
padding : 0;
position : relative;
width : 100%;
}
.obj {
box-shadow : 0 0 1px #aaa;
position : absolute;
transition-property : left top transform opacity;
transition-timing-function : linear linear linear ease-in-out;
}
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8"/>
<title>Gassen Animation Demo</title>
<link rel="stylesheet" href="index.css"/>
<style>
</style>
</head>
<body>
<script src="index.js"></script>
<script>
window.addEventListener('DOMContentLoaded', function () {
new App().init();
});
</script>
</body>
</html>
(function (global) {
'use strict';
/**
* @param {number} min int
* @param {number} max int
* @return {number} int
*/
function rand(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
// {{{ App
/**
* @class
*/
function App() {
if (App.instance) { return App.instance; }
this.start = 0;
this.scene = null;
App.instance = this;
}
/** @type {App} */
App.instance = null;
App.prototype.init = function () {
this.start = Date.now();
this.scene = new Scene(0);
requestAnimationFrame(this.animate);
};
App.prototype.animate = function () {
var me = App.instance,
scene = me.scene,
ms = Date.now() - me.start;
if (scene.isEnded) {
scene.destruct();
me.scene = new Scene(ms);
return requestAnimationFrame(me.animate);
}
scene.animate(ms);
requestAnimationFrame(me.animate);
};
// }}} App
// {{{ Scene
/**
* @class
* @param {number} now Time ms of the app.
*/
function Scene(now) {
var level, i = 0, iz = 0;
this.start = now;
this.isEnded = false;
this.bgm = new Bgm();
this.bg = new Bg();
this.objs = [];
for (i = 0, iz = Scene.OBJ_NUMBER; i < iz; ++i) {
level = Scene.OBJ_LEVEL_MAP[rand(0, Scene.OBJ_LEVEL_MAP.length - 1)];
this.objs.push(new ObjFactory().createRandom(level));
}
}
/** @const {number} */
Scene.SCENE_SEC = 10;
/** @const {number} */
Scene.OBJ_NUMBER = 12;
/** @const {number[]} */
Scene.OBJ_LEVEL_MAP = [1, 1, 1, 2, 2, 3];
Scene.prototype.destruct = function () {
var obj,
i = -1,
objs = this.objs;
this.isEnded = true;
while (obj = objs[++i]) { obj.destruct(); }
};
/**
* @param {number} ms Time ms of the app.
*/
Scene.prototype.animate = function (ms) {
var obj,
i = -1,
objs = this.objs;
if (this.start + Scene.SCENE_SEC * 1000 < ms) {
this.isEnded = true;
return;
}
ms = ms - this.start;
this.bgm.animate(ms);
this.bg.animate(ms);
while (obj = objs[++i]) { obj.animate(ms); }
};
// }}} Scene
// {{{ Bgm
/**
* @class
*/
function Bgm() {
this.player = BgmPlayer.init();
this.player.play();
}
/** @const {string[]} */
Bgm.SRCS = ['gad1.ogg', 'gad2.ogg', 'gad3.ogg'];
/**
* @param {number} ms Time ms of the scene.
*/
Bgm.prototype.animate = function (ms) {
};
// }}} Bgm
// {{{ BgmPlayer
/**
* @class
*/
function BgmPlayer() {
this.audios = [];
this.current = -1;
}
BgmPlayer.init = function () {
var player = new BgmPlayer();
BgmPlayer.init = function () { return player; };
Bgm.SRCS.forEach(function (src, i) {
var audio = new Audio(src);
audio.autoplay = false;
audio.loop = false;
audio.volume = 0.8;
audio.addEventListener('canplaythrough', function () {
player.audios.push(audio);
});
audio.addEventListener('ended', function () {
var next;
if (player.audios.length === 1) {
player.current = 0;
} else {
next = rand(0, player.audios.length - 2);
if (next === player.current) { ++next; }
player.current = next;
}
player.audios[player.current].play();
});
});
return player;
};
BgmPlayer.prototype.play = function () {
var timer,
me = this;
if (this.current >= 0) { return; }
if (this.audios.length) {
this.current = 0;
this.audios[0].play();
} else {
timer = setInterval(function () {
if (me.audios.length) {
clearInterval(timer);
me.play();
}
}, 1000 / 6);
}
};
// }}} BgmPlayer
// {{{ Bg
/**
* @class
*/
function Bg() {
Bg.beforeColor = (Bg.beforeColor + 1) % Bg.COLORS.length;
document.body.style.background = Bg.COLORS[Bg.beforeColor];
}
/** @type {number} */
Bg.beforeColor = -1;
/** @const {string[]} */
Bg.COLORS = ['#faa', '#afa', '#aaf', '#ffa', '#faf', '#aff'];
/**
* @param {number} ms Time ms of the scene.
*/
Bg.prototype.animate = function (ms) {
};
// }}} Bg
// {{{ ObjFactory
/**
* @class
*/
function ObjFactory() {
}
/**
* @param {number} level Low=1 Middle=2 High=3
* @return {Obj}
*/
ObjFactory.prototype.createRandom = function (level) {
var color, size, startAt, fadeinMs, fadeoutMs, startXyz, turningXyz, endXyz, objClass,
halfScene = Scene.SCENE_SEC / 2 * 1000,
r = Obj.RADIUS,
displayHeight = window.innerHeight / 3.78,
displayWidth = window.innerWidth / 3.78;
if (level === void 0) { level = rand(1, 3); }
color = 'rgb(' +
rand(0, 255) + ',' +
rand(0, 255) + ',' +
rand(0, 255) + ')';
size = rand(r, r * 2);
startAt = rand(0, halfScene);
fadeinMs = rand(halfScene - 3000, halfScene);
fadeoutMs = rand(halfScene - 3000, halfScene)
if (rand(0, 4)) { // Don't scale at fadein.
startXyz = [
rand(0, 1) ? rand(-r * 2, -r) : rand(r, r * 2) + displayWidth,
rand(0, 1) ? rand(-r * 2, -r) : rand(r, r * 2) + displayHeight,
rand(0, r / 2)
];
} else { // Scale at fadein.
startXyz = [
rand(0, displayWidth),
rand(0, displayHeight),
r * 2
];
}
turningXyz = [
rand(r, displayWidth - r),
rand(r, displayHeight - r),
0
];
if (rand(0, 4)) { // Don't scale at fadeout.
endXyz = [
rand(0, 1) ? rand(-r * 2, -r) : rand(r, r) + displayWidth,
rand(0, 1) ? rand(-r * 2, -r) : rand(r, r) + displayHeight,
rand(0, r / 2)
];
} else { // Scale at fadeout.
endXyz = [
rand(0, displayWidth),
rand(0, displayHeight),
r * 2
];
}
objClass = [Obj, ObjLow, ObjMiddle, ObjHigh][level];
return new objClass(color, size, startAt, fadeinMs, fadeoutMs, startXyz, turningXyz, endXyz);
};
// }}} ObjFactory
// {{{ Obj
/**
* @class
* @param {string} color CSS color
* @param {number} size mm
* @param {number} startAt ms
* @param {number} fadeinMs
* @param {number} fadeoutMs
* @param {number[]} startXyz [x mm, y mm, z mm] Right-handed system
* @param {number[]} turningXyz [x mm, y mm, z mm] Right-handed system
* @param {number[]} endXyz [x mm, y mm, z mm] Right-handed system
*/
function Obj(color, size, startAt, fadeinMs, fadeoutMs, startXyz, turningXyz, endXyz) {
this.size = size;
this.startAt = startAt;
this.fadeinMs = fadeinMs;
this.fadeoutMs = fadeoutMs;
this.startXyz = startXyz;
this.turningXyz = turningXyz;
this.endXyz = endXyz;
this.node = document.createElement('div');
this.node.classList.add('obj');
this.node.style.backgroundColor = color;
this.node.style.height = size + 'mm';
this.node.style.width = size + 'mm';
this.isStarted = false;
this.isEnded = false;
}
/** @const mm */
Obj.RADIUS = 60;
Obj.prototype.destruct = function () {
this.isEnded = true;
if (this.node.parentNode) {
document.body.removeChild(this.node);
}
};
/**
* @param {number} ms Time ms of the scene.
*/
Obj.prototype.animate = function (ms) {
var me = this;
function turn(evt) {
me.node.removeEventListener(turn);
me.node.style.transitionDuration = me.fadeoutMs + 'ms';
me.placeAt(me.endXyz[0], me.endXyz[1], me.endXyz[2], 720);
setTimeout(function() {
me.node.addEventListener('transitionend', function (evt) {
me.isEnded = true;
me.destruct();
});
}, 0);
}
if (this.isEnded || this.isStarted || ms < this.startAt) { return; }
this.isStarted = true;
this.placeAt(this.startXyz[0], this.startXyz[1], this.startXyz[2], 0);
document.body.appendChild(this.node);
this.node.addEventListener('transitionend', turn);
setTimeout(function () {
me.node.style.transitionDuration = me.fadeinMs + 'ms';
me.placeAt(me.turningXyz[0], me.turningXyz[1], me.turningXyz[2], 360);
}, 0);
};
/**
* @param {number} x mm
* @param {number} y mm
* @param {number} z mm
* @param {number} deg 0-360
*/
Obj.prototype.placeAt = function (x, y, z, deg) {
var size = this.size,
r2 = Obj.RADIUS * 2,
scale = (r2 - z) / r2,
style = this.node.style;
if (deg === void 0) { deg = scale * 360; }
style.left = (x - size / 2) + 'mm';
style.top = (y - size / 2) + 'mm';
style.transform = 'rotate(' + deg + 'deg) scale(' + scale + ')';
style.opacity = Math.sin(scale);
};
// }}} Obj
// {{{ ObjLow
/**
* @class
* @augments Obj
*/
function ObjLow() {
Obj.apply(this, arguments);
this.node.style.borderRadius = (this.size / 2) + 'mm';
}
ObjLow.prototype = Object.create(Obj.prototype);
ObjLow.prototype.constructor = ObjLow;
// }}} ObjLow
// {{{ ObjMiddle
/**
* @class
* @augments Obj
*/
function ObjMiddle() {
Obj.apply(this, arguments);
this.node.style.borderRadius = (this.size / 5) + 'mm';
}
ObjMiddle.prototype = Object.create(Obj.prototype);
ObjMiddle.prototype.constructor = ObjMiddle;
// }}} ObjMiddle
// {{{ ObjHigh
/**
* @class
* @augments Obj
*/
function ObjHigh() {
Obj.apply(this, arguments);
}
ObjHigh.prototype = Object.create(Obj.prototype);
ObjHigh.prototype.constructor = ObjHigh;
// }}} ObjHigh
global['App'] = App;
}(this));
// vim:et sw=2 ts=2 sts=2 ff=unix fdm=marker:
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment