var SPEED = {
RANGE: {
MIN: 1,
MAX: 3
}
}
var COLOR_TIMER = {
RANGE: {
MIN: 30,
MAX: 50
},
VELOCITY: 5
};
var ANGLE_TIMER = {
RANGE: {
MIN: 30,
MAX: 50
}
};
var RESET_TIMER = {
RANGE: {
MIN: 60,
MAX: 180
}
};
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
window.addEventListener('resize', resizeCanvas, false);
function resizeCanvas() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
resizeCanvas();
setLineWidth();
var speed = getSpeed();
var position = getPosition();
var angle = getAngle();
var angleVelocity = getAngleVelocity();
var color = getColor();
var colorVelocity = getColorVelocity();
var timers = [];
var timersToAdd = [];
timers.push(createColorTimer());
timers.push(createAngleTimer());
timers.push(createResetTimer());
function Timer(ticks, callback, ticker) {
this.ticks = ticks;
this.callback = callback;
this.ticker = ticker;
}
function createColorTimer() {
return new Timer(
COLOR_TIMER.RANGE.MIN + Math.round(Math.random() * (COLOR_TIMER.RANGE.MAX - COLOR_TIMER.RANGE.MIN)),
function() {
colorVelocity = getColorVelocity();
timersToAdd.push(createColorTimer());
},
function() {
this.ticks--;
if(this.ticks === 0) {
return true;
}
/*for(var i = 0; i < 3; i++) {
if(color[i] === 0 || color[i] == 255) {
return true;
}
}*/
return false;
});
}
function createAngleTimer() {
return new Timer(
ANGLE_TIMER.RANGE.MIN + Math.round(Math.random() * (ANGLE_TIMER.RANGE.MAX - ANGLE_TIMER.RANGE.MIN)),
function() {
angleVelocity = getAngleVelocity();
timersToAdd.push(createAngleTimer());
});
}
var forceReset = false;
function createResetTimer() {
return new Timer(
RESET_TIMER.RANGE.MIN + Math.round(Math.random() * (RESET_TIMER.RANGE.MAX - RESET_TIMER.RANGE.MIN)),
function() {
setLineWidth();
speed = getSpeed();
position = getPosition();
color = getColor();
colorVelocity = getColorVelocity();
angle = getAngle();
angleVelocity = getAngleVelocity();
forceReset = false;
timers.push(createResetTimer());
},
function() {
this.ticks--;
return this.ticks === 0 || forceReset;
});
}
function setLineWidth() {
context.lineWidth = 1 + Math.random() * 2;
}
function getPosition() {
return {
x: Math.round(Math.random() * canvas.width),
y: Math.round(Math.random() * canvas.height)
};
}
function getColor() {
return [
Math.round(Math.random() * 255),
Math.round(Math.random() * 255),
Math.round(Math.random() * 255)];
}
function getColorVelocity() {
var colorVelocity = [];
for(var i = 0; i < 3; i++) {
colorVelocity.push(Math.round((Math.random() - 0.5) * COLOR_TIMER.VELOCITY));
}
return colorVelocity;
}
function getAngle() {
return Math.random() * Math.PI * 2;
}
function getAngleVelocity() {
return (Math.random() - 0.5) * 0.1;
}
function getSpeed() {
return SPEED.RANGE.MIN + Math.random() * (SPEED.RANGE.MAX - SPEED.RANGE.MIN);
}
window.setInterval(
main,
Math.round(1000 / 90));
function rgbToHex(rgb) {
var hex = '#';
for(var i = 0; i < 3; i++) {
var part = rgb[i].toString(16);
if(part.length == 1) {
part = '0' + part;
}
hex += part;
}
return hex;
}
function main() {
updateTimers();
draw();
}
function updateTimers() {
for(var i = 0; i < timers.length; i++) {
var timerFinished;
if(timers[i].ticker) {
timerFinished = timers[i].ticker();
} else {
timers[i].ticks--;
if(timers[i].ticks === 0) {
timerFinished = true;
}
}
if(timerFinished) {
timers[i].callback();
timers.splice(i, 1);
i--;
}
}
while(timersToAdd.length > 0) {
var timer = timersToAdd.splice(0, 1)[0];
timers.push(timer);
}
}
context.beginPath();
context.moveTo(position.x, position.y);
function draw() {
context.strokeStyle = rgbToHex(color);
var newPosition = {
x: position.x + Math.cos(angle) * speed,
y: position.y + Math.sin(angle) * speed
};
context.beginPath();
context.moveTo(position.x, position.y);
context.lineTo(newPosition.x, newPosition.y);
/*if(newPosition.x > canvas.width || newPosition.x < 0) {
newPosition.x = canvas.width - newPosition.x;
}
if(newPosition.y > canvas.height || newPosition.y < 0) {
newPosition.y = canvas.height - newPosition.y;
}
context.moveTo(newPosition.x, newPosition.y);*/
if(newPosition.y > canvas.height || newPosition.y < 0
|| newPosition.x > canvas.width || newPosition.x < 0) {
forceReset = true;
}
context.stroke();
position = newPosition;
angle += angleVelocity;
for(var i = 0; i < 3; i++) {
color[i] = Math.min(Math.max(colorVelocity[i] + color[i], 0), 255);
}
}
<div>
<b>Doodler</b>
</div>
<canvas id="canvas"></canvas>
* { margin:0; padding:0; }
html, body { width:100%; height:100%; }
canvas { display:block; }
div {
position: absolute;
top: 10px;
left: 10px;
font-family: helvetica;
}