Skip to content

Instantly share code, notes, and snippets.

@kmdsbng
Created February 1, 2010 14:56
Show Gist options
  • Save kmdsbng/291727 to your computer and use it in GitHub Desktop.
Save kmdsbng/291727 to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>HTML5 Canvas</title>
<script src="3d.js" type="text/javascript"></script>
<style type="text/css">
html, body, canvas { overflow: hidden; width: 100%; height: 100%; margin: 0; padding: 0; border: 0 }
textarea { display: none }
</style>
</head>
<body>
<canvas></canvas>
<textarea class="10 Mona">
     ∧_∧   
   _( ´・ω・)_
  /\`'⊃(;;゚;;) \ ___  
/ ※ \_____|\__ヽ
\※ ※      |  |_三三|_< はじまるよ!
  \ / ※ ※ ※!、_ |||__|、
   `─────||ヽ───i§
           ヽi      |`??
</textarea>
<textarea class="10">
JavaScript でも
3D くらい
できるさ!
</textarea>
<textarea class="10 Mona">
amachang 先生の
次回作にご期待ください
   ∧∧
  (  ・ω・)
  _| ⊃/(___
/ └-(____/
 ̄ ̄ ̄ ̄ ̄ ̄ ̄
</textarea>
<textarea class="10">
- 完 -
</textarea>
<textarea class="10">
long one line by alphabet. Is this showed valid? if not showed, bug.
</textarea>
<textarea class="10">
日本語による長い行。表示できてる?表示できてなかったらバグです。どうかな?
</textarea>
<textarea class="10">
ごめんなさい
ごめんなさい><
</textarea>
<textarea class="15">
DOM パフォーマンス
チューニング
</textarea>
<textarea class="10">
JavaScript の
誤解
</textarea>
<textarea class="10">
JavaScript は
遅い
</textarea>
<textarea class="12">
JavaScript は
そこそこ速い
</textarea>
<textarea class="10">
論より証拠。
ベンチマーク
</textarea>
<textarea class="10">
マージソート
100 numbers
× 3000 times
</textarea>
<textarea class="10">
JavaScript ActionScript code:
http://svn.coderepos.org/share/docs/amachang/
Ruby, PHP, Python, Perl code:
http://izumi.plan99.net/blog/index.php/
2008/01/17/ruby-vs-php-performance/
</textarea>
<textarea class="10">
PHP 5.2.6 (cli) (built: Jul 15 2008 12:18:21) [9.595s]
Ruby 1.8.6 (2007-09-24 patchlevel 111) [5.239s]
Perl v5.8.8 built for darwin-2level [5.000s]
JavaScript (V8 version 0.2.5) [4.931s]
Python 2.5.2 (r252:60911, Sep 3 2008, 10:08:55) [3.975s]
ActionScript 3.0
(Flex SDK 3.2 &amp; Flash Player 10.0.12.36) [1.329s]
</textarea>
<textarea class="10">
ASはえーw
</textarea>
<textarea class="10">
JavaScript も
悪くないでしょ?
</textarea>
<textarea class="10">
JavaScript は
そこそこ速い
</textarea>
<textarea class="10">
では、何故
遅くなって
しまうのか
</textarea>
<textarea class="10">
よく言われるのが
「DOM が遅い」
</textarea>
<textarea class="10">
よく言われるのが
「ドットを減らせばいい」
</textarea>
<textarea class="10">
でも、
それだけじゃない
</textarea>
<textarea class="10">
1. 再描画のための計算が行われる
タイミングを知ろう
2. HTML の属性変更の
影響範囲を考えよう
3. スタイル変更の
影響範囲を考えよう
</textarea>
<textarea class="10">
1. 再描画のための
計算が行われる
タイミングを知ろう
</textarea>
<textarea class="10">
基本的には、
一つのイベントが
終わったあと
</textarea>
<textarea class="10">
elm.onclick = function() {
elm.style.fontSize = '10px';
elm.style.width = '2em';
// JavaScript 実行後
// ここで計算が走る
}
</textarea>
<textarea class="10">
教訓 1
JavaScript 実行後の
再描画の計算は
ベンチマークには出ない
</textarea>
<textarea class="10">
elm.onclick = function() {
elm.style.fontSize = '10px';
var w = elm.offsetWidth; // ここで計算が走る
elm.style.width = '2em';
// さらに、ここで計算が走る
}
</textarea>
<textarea class="10">
elm.onclick = function() {
elm.style.fontSize = '10px';
elm.style.width = '2em';
var w = elm.offsetWidth; // ここで計算が走る
// 実行後は、計算が走らない
}
</textarea>
<textarea class="10">
教訓 2
値の取得、変更は
それぞれ
まとめて行う
</textarea>
<textarea class="10">
2. HTML 属性変更
の影響範囲を
考えよう
</textarea>
<textarea class="10">
elm.onclick = function() {
elm.className = 'hoge';
// 計算が走る要素は
// いくつあるか?
}
</textarea>
<textarea class="10">
<div>
<div>...</div>
<div>...</div>
<div class="hoge"> - この影響範囲は?
<div>...</div>
<div>...</div>
</div>
<div>...</div>
<div>...</div>
</div>
</textarea>
<textarea class="10">
<div>
<div>...</div>
<div>...</div>
<div class="hoge"> *
<div>...</div> * ┬ 子孫セレクタの影響範囲
<div>...</div> * ┘
</div>
<div>...</div> * ┬ 兄弟セレクタの影響範囲
<div>...</div> * ┘
</div>
</textarea>
<textarea class="10">
<div>
<div>...</div>
<div>...</div>
<div> ─ ここに要素を追加
<div class="hoge"> *
<div>...</div> *
<div>...</div> *
</div>
</div> ─ ここで閉じる
<div>...</div>
<div>...</div>
</div>
</textarea>
<textarea class="10">
教訓 3
HTML の属性を
変更する要素は
きちんと隔離しよう
</textarea>
<textarea class="10">
3. スタイル変更の
影響範囲を
考えよう
</textarea>
<textarea class="10">
width プロパティ
- 子要素の width
- 子要素の margin
- 子要素の padding
- 子要素の border
</textarea>
<textarea class="10">
height プロパティ
- 親要素の height
- 子要素の height
</textarea>
<textarea class="10">
font-size プロパティ
- 自要素の em 指定の値
- 子要素の font-size の値
</textarea>
<textarea class="10">
などなど
</textarea>
<textarea class="10">
様々な
変更が
連鎖する
</textarea>
<textarea class="10">
教訓 4
すべての
包含ボックスと
inherit 値と
相対値 (%, em, auto) を
意識する
</textarea>
<textarea class="10">
CSS の勉強
超重要?
</textarea>
<textarea class="10">
まとめ
</textarea>
<textarea class="10">
Flash は
軽くて
いいですね><
</textarea>
<textarea class="10">
でも JavaScript も
頑張れば
Flash 並みに
出来るよ!
</textarea>
<textarea class="10">
最後に
</textarea>
<textarea class="10">
I ? Web
Standard!
</textarea>
<script type="text/javascript">
function Matrix3D(data) {
this.data = data || [ [1, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 1] ];
}
Matrix3D.prototype = {
multiplyMatrix: function(a, b, n, m) {
var r = [];
for (var i = 0; i < n; i ++) {
r[i] = [];
for (var j = 0; j < m; j ++) {
r[i][j] = 0;
for (var k = 0; k < n; k ++) {
r[i][j] += a[i][k] * b[k][j];
}
}
}
return r;
},
clone: function() {
var data = this.data;
var result = [];
for (var i = 0; i < data.length; i ++) {
var d = data[i];
var r = result[i] = [];
for (var j = 0; j < d.length; j ++) {
r[j] = d[j];
}
}
return new Matrix3D(result);
},
transform: function(p) {
var data = this.multiplyMatrix(this.data, p.data, 3, 1);
var result = [];
for (var i = 0; i < data.length; i ++) {
result[i] = [data[i][0] + this.data[i][3]];
}
return new Point3D(result);
},
rotateX: function(rad) {
return this.concat(new Matrix3D([ [1, 0, 0, 0],
[0, Math.cos(rad), -Math.sin(rad), 0],
[0, Math.sin(rad), Math.cos(rad), 0],
[0, 0, 0, 1] ]));
},
rotateY: function(rad) {
return this.concat(new Matrix3D([ [ Math.cos(rad), 0, Math.sin(rad), 0],
[ 0, 1, 0, 0],
[-Math.sin(rad), 0, Math.cos(rad), 0],
[ 0, 0, 0, 1] ]));
},
rotateZ: function(rad) {
return this.concat(new Matrix3D([ [Math.cos(rad), -Math.sin(rad), 0, 0],
[Math.sin(rad), Math.cos(rad), 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 1] ]));
},
scale: function(x, y, z) {
return this.concat(new Matrix3D([ [x, 0, 0, 0],
[0, y, 0, 0],
[0, 0, z, 0]
[0, 0, 0, 1] ]));
},
translate: function(x, y, z) {
var m = this.clone();
m.data[0][3] += x;
m.data[1][3] += y;
m.data[2][3] += z;
return m;
},
concat: function(m) {
return new Matrix3D(this.multiplyMatrix(m.data, this.data, 4, 4));
},
toString: function() {
return this.data.map(function(d) {
return d.join(', ');
}).join('\n');
}
};
function Point3D(data) {
this.data = data || [[0], [0], [0]];
}
Point3D.prototype = {
get x() {
return this.data[0][0];
},
get y() {
return this.data[1][0];
},
get z() {
return this.data[2][0];
},
getProjectionPoint: function(dist) {
var prs = dist / (this.z + dist);
return new Point3D([[this.x * prs], [this.y * prs], [0]]);
},
dot: function(v) {
return x * v.x + y * v.y + z * v.z;
}
};
function Scene3D(elm, backgroundStyle, dist) {
this.shapes = [];
this.elm = elm;
var ctx = elm.getContext('2d');
var width = elm.width;
var height = elm.height
ctx.translate(width / 2, height / 2);
this.ctx = new Context3D(ctx, dist || 3000, width, height);
this.backgroundStyle = backgroundStyle || 'black';
}
Scene3D.prototype = {
set viewDistance(dist) {
this.ctx.viewDistance = dist;
this.redraw();
return dist;
},
get viewDistance(dist) {
return this.ctx.viewDistance;
},
redraw: function() {
var shapes = this.shapes;
for (var i = 0; i < shapes.length; i ++) {
shapes[i].redraw();
}
return this;
},
append: function(shape) {
this.shapes.push(shape);
return this;
},
remove: function(shape) {
var shapes = this.shapes;
for (var i = 0; i < shapes.length; i ++) {
if (shapes[i] === shape) {
shapes.splice(i, 1);
}
}
return this;
},
render: function() {
this.shapes.sort(function(a, b) { return b.getCenterZ() - a.getCenterZ(); });
var shapes = this.shapes;
var ctx = this.ctx;
ctx.ctx.save();
try {
ctx.ctx.fillStyle = this.backgroundStyle;
ctx.ctx.fillRect(-ctx.width / 2, -ctx.height / 2, ctx.width, ctx.height);
}
finally {
ctx.ctx.restore();
}
for (var i = 0; i < shapes.length; i ++) {
shapes[i].render(ctx);
}
return this;
}
};
function Context3D(ctx, dist, width, height) {
this.ctx = ctx;
// TODO: 莉翫?豎コ繧∵遠縺。
this.ctx.textBaseline = 'top';
this.ctx.textAlign = 'left';
this.dist = dist;
this.m = new Matrix3D();
this.originX = 0;
this.originY = 0;
this.stateStack = [];
this.width = width;
this.height = height;
}
Context3D.prototype = {
set viewDistance(dist) {
return this.dist = dist;
},
get viewDistance() {
return this.dist;
},
set matrix(m) {
return this.m = m;
},
get matrix() {
return this.m;
},
set fillStyle(fillStyle) {
return this.ctx.fillStyle = fillStyle;
},
get fillStyle() {
return this.ctx.fillStyle;
},
createProjectionPoint: function(x, y) {
return this.m.translate(this.originX, this.originY, 0).transform(new Point3D([[x], [y], [0]])).getProjectionPoint(this.dist);
},
// back-reference to the canvas
get canvas() {
return this.ctx.canvas;
},
// state
save: function() {
this.stateStack.push({
matrix: this.m
});
this.ctx.save();
},
restore: function() {
var state = this.stateStack.pop();
this.m = state.matrix;
this.ctx.restore();
},
// rects
rect: function(x, y, w, h) {
this.moveTo(x, y);
this.lineTo(x + w, y);
this.lineTo(x + w, y + h);
this.lineTo(x, y + h);
this.lineTo(x, y);
},
fillRect: function(x, y, w, h) {
this.beginPath();
this.rect(x, y, w, h);
this.fill();
this.closePath();
},
strokeRect: function(x, y, w, h) {
this.beginPath();
this.rect(x, y, w, h);
this.stroke();
this.closePath();
},
// path API
beginPath: function() {
this.ctx.beginPath();
},
closePath: function() {
this.ctx.closePath();
},
moveTo: function(x, y) {
var p = this.createProjectionPoint(x, y);
this.ctx.moveTo(p.x, p.y);
},
lineTo: function(x, y) {
var p = this.createProjectionPoint(x, y);
this.ctx.lineTo(p.x, p.y);
},
quadraticCurveTo: function(cpx, cpy, x, y) {
var cp = this.createProjectionPoint(cpx, cpy);
var p = this.createProjectionPoint(x, y);
this.ctx.quadraticCurveTo(cp.x, cp.y, p.x, p.y);
},
bezierCurveTo: function(cp0x, cp0y, cp1x, cp1y, x, y) {
var cp0 = this.createProjectionPoint(cp0x, cp0y);
var cp1 = this.createProjectionPoint(cp1x, cp1y);
var p = this.createProjectionPoint(x, y);
this.ctx.quadraticCurveTo(cp0.x, cp0.y, cp1.x, cp1.y, p.x, p.y);
},
arc: function(x, y, radius, startAngle, endAngle, anticlockwise) {
if (startAngle == endAngle) {
return;
}
if (anticlockwise) {
while (startAngle <= endAngle) {
endAngle -= Math.PI * 2;
}
}
else {
while (startAngle >= endAngle) {
endAngle += Math.PI * 2;
}
}
var angleSpan = endAngle - startAngle;
var stepNum = Math.ceil(Math.abs(angleSpan / (Math.PI / 4)));
var angleStep = angleSpan / stepNum;
this.moveTo(
x + radius * Math.cos(startAngle),
y + radius * Math.sin(startAngle)
);
for (var i = 1; i <= stepNum; i++) {
angle = startAngle + angleStep * i;
var ax = radius * Math.cos(angle);
var ay = radius * Math.sin(angle);
var cx = ax + radius * Math.tan(angleStep / 2) * Math.cos(angle - Math.PI/2);
var cy = ay + radius * Math.tan(angleStep / 2) * Math.sin(angle - Math.PI/2);
this.quadraticCurveTo(cx + x, cy + y, ax + x, ay + y);
}
},
drawImage: function(img, dx, dy, width, height) {
var num = 10;
var imgWidth = img.width;
var imgHeight = img.height;
var stepWidth = width / num;
var stepHeight = height / num;
var stepImgWidth = imgWidth / num;
var stepImgHeight = imgHeight / num;
if (!imgWidth || !imgHeight) {
return
}
var points = [];
for (var i = 0, x = dx; i <= num; i++, x += stepWidth) {
var subpoints = [];
points.push(subpoints);
for (var j = 0, y = dy; j <= num; j++, y += stepHeight) {
subpoints.push([x, y]);
}
}
var ctx = this.ctx;
for (var i = 0; i < num; i ++) {
for (var j = 0; j < num; j++) {
var p0 = this.createProjectionPoint.apply(this, points[i][j]);
var p1 = this.createProjectionPoint.apply(this, points[i + 1][j]);
var p2 = this.createProjectionPoint.apply(this, points[i][j + 1]);
var p3 = this.createProjectionPoint.apply(this, points[i + 1][j + 1]);
if ((p2.y - p0.y) < (p3.y - p1.y)) {
var fixHeight = (p3.y - p1.y) / (p2.y - p0.y);
}
else {
fixHeight = 1;
}
ctx.save();
try {
ctx.transform(Math.ceil(p1.x - p0.x), Math.ceil(p1.y - p0.y), Math.ceil(p2.x - p0.x), Math.ceil(p2.y - p0.y), Math.floor(p0.x), Math.floor(p0.y));
ctx.scale(1 / stepWidth, 1 / stepHeight);
ctx.drawImage(
img,
i * stepImgWidth, j * stepImgHeight, stepImgWidth, stepImgHeight,
0, 0, stepWidth + 1, stepHeight * fixHeight + 2
);
}
finally {
ctx.restore();
}
}
}
},
set font(font) {
var m;
if (!(m = font.match(/\b([\d\.]+)\s*?px\b/))) {
console.log(font);
throw Error();
}
this.fontSize = parseInt(m[1], 10);
return this.ctx.font = font;
},
fontSize: 10,
fillText: function(text, x, y) {
var ctx = this.ctx;
var height = this.fontSize;
for (var i = 0; i < text.length; i ++) {
var t = text[i];
if (ctx.mozMeasureText) {
var width = ctx.mozMeasureText(t);
}
else {
var width = ctx.measureText(t).width;
}
var p0 = this.createProjectionPoint(x, y);
var p1 = this.createProjectionPoint(x + width, y);
var p2 = this.createProjectionPoint(x, y + height);
ctx.save();
try {
ctx.transform(
p1.x - p0.x, (p1.y - p0.y || 0.0000000000000000000000000000001), // for Google Chrome's Bug
p2.x - p0.x, p2.y - p0.y,
p0.x, p0.y);
ctx.scale(1 / width, 1 / height);
if (ctx.mozDrawText) {
ctx.mozDrawText(t);
}
else {
ctx.fillText(t, 0, 0);
}
}
finally {
ctx.restore();
}
x = x + width;
}
},
fill: function() {
this.ctx.fill();
},
stroke: function() {
this.ctx.stroke();
}
};
function Shape3D(properties) {
for (var name in properties) {
this[name] = properties[name];
}
}
Shape3D.prototype = {
center: [0, 0],
normalPoint: new Point3D([[0], [0], [-1]]),
matrix: new Matrix3D(),
redraw: function() {
return this;
},
getCenterZ: function() {
return this.matrix.transform(new Point3D([[this.center[0]], [this.center[1]], [0]])).z;
},
getBright: function() {
return (this.matrix.transform(this.normalPoint).z - this.getCenterZ()) * -1;
},
isBack: function() {
return (this.matrix.transform(this.normalPoint).z - this.getCenterZ()) >= 0;
},
render: function(ctx) {
if (!this.isBack()) {
ctx.save();
try {
ctx.matrix = this.matrix;
var shadowRect = this.renderImpl(ctx, ctx.width, ctx.height);
if (!shadowRect) {
shadowRect = [-ctx.width / 2, -ctx.height / 2, ctx.width, ctx.height];
}
ctx.beginPath();
ctx.rect.apply(ctx, shadowRect);
var dark = 1 - this.getBright();
if (dark > 0.001) {
ctx.save();
try {
ctx.fillStyle = 'rgba(0, 0, 0, ' + dark + ')'
ctx.fill();
}
finally {
ctx.restore();
}
}
ctx.closePath();
}
finally {
ctx.restore();
}
return this;
4}
}
};
function go(i) {
window.localStorage.index = i;
history.go(0);
}
// Version Check
if (!navigator.userAgent.match(/AppleWebKit\//) ||
!window.CanvasRenderingContext2D ||
!window.CanvasRenderingContext2D.prototype ||
!window.CanvasRenderingContext2D.prototype.measureText ||
!window.CanvasRenderingContext2D.prototype.fillText ||
!window.CanvasRenderingContext2D.prototype.transform
) {
if (!confirm('このプレゼンテーションを実行するには以下のブラウザが必要です。\n\n- 最新の Google Chrome Dev Branch\n- WebKit Nightly Build\n\nこのブラウザでは、正常に動きませんが、実行してみますか?')) {
throw Error();
}
}
if (!window.localStorage) {
if (window.globalStorage) {
window.localStorage = window.globalStorage[location.hostname]
}
else {
window.localStorage = {};
window.localStorage.__defineGetter__('index', function() {
var m;
if (m = document.cookie.match(/\bindex=(\d+)/)) {
return +m[1] || 0;
}
else {
return 0;
}
});
window.localStorage.__defineSetter__('index', function(index) {
document.cookie = 'index=' + index;
});
}
}
var randoms = [];
for (var i = 0; i < 1000; i++)
randoms.push(Math.random());
var randomIndex = 0;
var randomStart = function(i) {
randomIndex = i;
};
var random = function() {
return randoms[randomIndex++];
};
var textareas = document.getElementsByTagName('textarea');
var data = [];
for (var i = 0, l = textareas.length; i < l; i ++) {
var textarea = textareas[i];
var classes = textarea.className.split(' ');
data[i] = [classes[0], classes[1] || 'sans-serif', textarea.value];
}
function PageShape(data, font) {
if (font == 'javascript') {
this.js = new Function('ctx', 'width', 'height', data);
}
else if (data.substring(0, 4) == 'img:') {
this.img = new Image();
this.img.src = data.substring(4);
}
else {
this.datas = data.split('\n');
this.datas.pop();
this.font = font;
}
}
PageShape.prototype = new Shape3D({
renderImpl: function(ctx, width, height) {
if (this.js) {
this.js(ctx, width, height);
}
else if (this.img) {
ctx.fillStyle = 'white';
ctx.fillRect(-width / 2, -height / 2, width, height);
ctx.drawImage(this.img, -width * .8 / 2, -height * .8 / 2, width * .8, height * .8);
}
else if (this.datas) {
ctx.fillStyle = 'white';
ctx.fillRect(-width / 2, -height / 2, width, height);
ctx.fillStyle = 'black';
var lineHeight = this.calcLineHeight(width, height);
fontSize = lineHeight * 0.85;
ctx.font = fontSize + 'px ' + this.font;
for (var i = 0; i < this.datas.length; i ++) {
var data = this.datas[i];
ctx.fillText(data, -width / 2, -height / 2 + i * lineHeight + ((lineHeight - fontSize) / 2));
}
}
},
calcLineHeight: function(width, height) {
return Math.min(height / this.datas.length,
width / this.getMaxRowSize() * 2);
},
// 最長の行の文字数を返す。
getMaxRowSize: function(height, width) {
var maxRowSize = 1;
for (var i=0; i < this.datas.length; i++) {
maxRowSize = Math.max(maxRowSize, this.getCharacterLength(this.datas[i]));
}
return maxRowSize;
},
// 半角英数字以外は2文字換算で文字数を返す
getCharacterLength: function(str) {
return str.length * 2 - this.getHankakuCount(str);
},
getHankakuCount: function(str) {
var pattern = /[a-z0-9 ]/ig;
return str.length - str.replace(pattern, '').length;
}
});
var shapes = [];
for (var i = 0; i < data.length; i ++) {
shapes[i] = [data[i][0], new PageShape(data[i][2], data[i][1])];
}
function sinoidal(x) { return (-Math.cos(x*Math.PI)/2) + 0.5;
}
function sinoidalN(x, n) {
x /= n;
return (-Math.cos(x*Math.PI)/2) + 0.5;
}
window.addEventListener('DOMContentLoaded', function(evt) {
var elm = document.getElementsByTagName('canvas')[0];
var width = elm.offsetWidth;
var height = elm.offsetHeight;
elm.width = width;
elm.height = height;
var ctx = elm.getContext('2d');
var scene = new Scene3D(elm);
var index = + localStorage.index || 0;
if (index >= shapes.length) {
index = shapes.length - 1;
}
var shape = shapes[index][1];
scene.append(shape);
scene.render();
var pos = 0;
var busy = false;
document.oncontextmenu = function() {
next(-1);
return false;
};
document.onclick = function() {
next(1);
return false;
};
function next(dir) {
if (busy) return;
if (!shapes[index + dir]) {
return;
}
busy = true;
var nextShape = shapes[index + dir][1]
if (dir == 1) {
var mode = shapes[index + dir][0];
}
else {
var mode = shapes[index][0];
}
var frameCount = 10;
var submode = Math.floor(mode / 10) % 10;
if (submode == 1) {
var d = 1000;
var finishZ = 5;
}
else if (submode == 2) {
var d = 10000;
var finishZ = 20;
}
else {
var d = 0;
var finishZ = 0;
}
switch(mode % 10) {
case 0:
var finish = frameCount;
nextShape.matrix = new Matrix3D().translate(dir * width, 0, 0);
var matrix = new Matrix3D().translate(- dir * width / finish, 0, 0);
break;
case 1:
finish = frameCount;
nextShape.matrix = new Matrix3D().translate(- dir * width, 0, 0);
var matrix = new Matrix3D().translate(dir * width / finish, 0, 0);
break;
case 2:
finish = frameCount;
nextShape.matrix = new Matrix3D().translate(dir * width, 0, 0);
var matrix = new Matrix3D().translate(- dir * width / finish, 0, 0);
break;
case 3:
finish = frameCount;
nextShape.matrix = new Matrix3D().translate(- dir * width, 0, 0);
var matrix = new Matrix3D().translate(dir * width / finish, 0, 0);
break;
case 4:
finish = frameCount;
nextShape.matrix = new Matrix3D().translate(0, - dir * height, 0);
var matrix = new Matrix3D().translate(0, dir * height / finish, 0);
break;
case 5:
finish = frameCount;
nextShape.matrix = new Matrix3D().translate(0, dir * height, 0);
var matrix = new Matrix3D().translate(0, - dir * height / finish, 0);
break;
case 6:
finish = frameCount;
nextShape.matrix = new Matrix3D().translate(0, dir * height, 0);
var matrix = new Matrix3D().translate(0, - dir * height / finish, 0);
break;
case 7:
finish = frameCount;
nextShape.matrix = new Matrix3D().translate(0, dir * height, 0);
var matrix = new Matrix3D().translate(0, - dir * height / finish, 0);
break;
case 8:
finish = frameCount;
nextShape.matrix = new Matrix3D().translate(0, dir * height, 0);
var matrix = new Matrix3D().translate(0, - dir * height / finish, 0);
break;
case 9:
finish = frameCount;
nextShape.matrix = new Matrix3D().translate(0, dir * height, 0);
var matrix = new Matrix3D().translate(0, - dir * height / finish, 0);
break;
}
scene.append(nextShape);
var m = shape.matrix;
var nm = nextShape.matrix;
var interval1 = setInterval(function() {
shape.matrix = shape.matrix.concat(matrix);
nextShape.matrix = nextShape.matrix.concat(matrix);
if (++pos == finish) {
clearInterval(interval1);
pos = 0;
index += dir;
localStorage.index = index;
scene.remove(shape);
shape = nextShape;
shape.matrix = new Matrix3D();
nextShape = null;
busy = false;
}
scene.render();
}, 40);
}
}, false);
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment