<!DOCTYPE html>
<title>遅延時間を考えて移動する</title>
<meta charset="UTF-8">
<style>
</style>
<canvas id="hoge" width="800" height="600"></canvas>
<script>
(function () {
function Graffiti (canvas) {
this.ctx = canvas.getContext ('2d');
}
function line () {
var index = 0;
var x = arguments[index][0];
var y = arguments[index][1];
var arg;
var ctx = this.ctx;
ctx.beginPath ();
ctx.moveTo (x, y);
while (arg = arguments[++index]) {
if ('b' === arg) {
ctx.closePath ();
break;
}
if ('bx' === arg) {
ctx.closePath ();
ctx.fillRect ();
break;
}
ctx.lineTo (arg[0], arg[1]);
}
ctx.stroke ();
return this;
}
function pset (x, y, c) {
var ctx = this.ctx;
if (c instanceof Array) {
ctx.fillStyle = 'rgb(' + c[0] + ',' + c[1] +',' + c[2] + ')';
}
ctx.fillRect (x, y, 1, 1);
return this;
}
function create (canvas) {
if (! canvas.getContext)
return null;
return new Graffiti (canvas);
}
Graffiti.prototype.line = line;
Graffiti.prototype.pset = pset;
Graffiti.create = create;
this.Graffiti = Graffiti;
})();
(function () {
function IntervalCompletion (cbFunc, interval, maxCompletion) {
this.cbFunc = cbFunc;
this.interval = interval;
this.maxCompletion = maxCompletion;
this.startTime = null;
this.count = null;
}
var loop =
(function () {
var now = (new Date).getTime ();
var delay = (now - this.startTime) - this.interval * this.count;
var completion = 0;
var result;
if (0 < delay) {
completion = Math.floor (delay / this.interval);
if (this.maxCompletion < completion) {
completion = this.maxCompletion;
}
}
do {
result = this.cbFunc ((new Date).getTime ());
this.count++;
if (! result)
break;
} while (completion--);
if (result)
setTimeout (loop.bind (this), this.interval);
});
IntervalCompletion.prototype.start =
(function () {
this.startTime = (new Date).getTime ();
this.count = 0;
loop.call (this);
});
IntervalCompletion.create =
(function (cbFunc, interval) {
if (1 > arguments.length)
throw new Error;
return new IntervalCompletion (cbFunc, interval);
});
this.IntervalCompletion = IntervalCompletion;
}) ();
function QBezierCurve_create (x0, y0, x1, y1, x2, y2, x3, y3) {
return function (t) {
if (t < 0 || 1 < t)
throw new Error;
var a = 1 - t, b = a * a, c = 3 * a * t, d = t * t * t;
var e = a * b, f = c * a, g = c * t;
return [
e * x0 + f * x1 + g * x2 + d * x3,
e * y0 + f * y1 + g * y2 + d * y3
];
};
}
function TransitionTimingFunction_create (cbFunc, step) {
var t = 0;
return function () {
var result = cbFunc (t);
t += step;
if (t == 1)
return false;
if (1 < t)
t = 1;
return true;
}
}
var points = [40, 300, 150, 0, 400, 600, 550, 300];
var canvas = Graffiti.create (document.querySelector ('#hoge'));
var fx = QBezierCurve_create.apply (null, points);
function draw (t) {
var p = fx (t);
canvas.pset (p[0], p[1], [255,0,0]);
return (t != 1);
}
var time = 5000;
var span = 500;
var draw_ = TransitionTimingFunction_create (draw, 1 / span);
var obj = new IntervalCompletion (draw_, time / span, 4)
obj.start ();
</script>