Skip to content

Instantly share code, notes, and snippets.

@vivekseth
Created July 8, 2017 17:55
Show Gist options
  • Save vivekseth/b697d949a76a95ab1c0713d128f77509 to your computer and use it in GitHub Desktop.
Save vivekseth/b697d949a76a95ab1c0713d128f77509 to your computer and use it in GitHub Desktop.
var HEIGHT = 600;
var WIDTH = 600;
var body = document.body;
body.style.margin = 0;
body.style.backgroundColor = '#eee';
var canvas = document.getElementById('canvas')
canvas.style.position = 'absolute'
canvas.style.top = '50%';
canvas.style.left = '50%';
canvas.style.marginTop = (-1 * HEIGHT / 2.0) + 'px'
canvas.style.marginLeft = (-1 * WIDTH / 2.0) + 'px'
canvas.style.height = HEIGHT;
canvas.height = HEIGHT;
canvas.style.width = WIDTH;
canvas.width = WIDTH;
canvas.style.backgroundColor = '#000';
var ctx = canvas.getContext("2d");
function drawParametric(ctx, fx, fy, tarr) {
ctx.beginPath();
for (var i=0; i<tarr.length; i++) {
var x = fx(tarr[i]), WIDTH;
var y = fy(tarr[i]), HEIGHT;
if (i == 0) {
ctx.moveTo(x, y);
}
else {
ctx.lineTo(x, y);
}
}
ctx.stroke();
}
function drawLine(ctx, x1, y1, x2, y2) {
ctx.beginPath();
ctx.moveTo(x1, y1);
ctx.lineTo(x2, y2);
ctx.stroke();
}
function drawParametric2(ctx, fx, fy, tarr) {
function center(coordinate, dimensionLength) {
return coordinate;
}
for (var i=0; i<(tarr.length - 1); i++) {
var x1 = center(fx(tarr[i]), WIDTH);
var y1 = center(fy(tarr[i]), HEIGHT);
var x2 = center(fx(tarr[i + 1]), WIDTH);
var y2 = center(fy(tarr[i + 1]), HEIGHT);
drawLine(ctx, x1, y1, x2, y2);
}
}
function range(low, high, N) {
var delta = (high - low);
var step = delta / N;
var arr = [];
for (var i=0; i<(N+1); i++) {
arr.push(low + step * i);
}
return arr;
}
function drawPolar(ctx, fth, tr, tarr) {
var fx = function(t) {
return tr(t) * Math.cos(fth(t));
}
var fy = function(t) {
return tr(t) * Math.sin(fth(t));
}
drawParametric(ctx, fx, fy, tarr);
}
function drawPolar2(ctx, fth, tr, tarr) {
var fx = function(t) {
return tr(t) * Math.cos(fth(t));
}
var fy = function(t) {
return tr(t) * Math.sin(fth(t));
}
drawParametric2(ctx, fx, fy, tarr);
}
function CreateAnimation(drawFrame) {
var animationStart = -1;
var continueAnimation = false;
var previousTimestamp = 0;
var animWrapper = function(currentTimestamp) {
if (previousTimestamp == 0) {
previousTimestamp = currentTimestamp;
}
if (animationStart == -1) {
animationStart = currentTimestamp;
}
var relativeTimestamp = currentTimestamp - animationStart;
var duration = currentTimestamp - previousTimestamp;
drawFrame(relativeTimestamp, duration);
if (continueAnimation) {
requestAnimationFrame(animWrapper);
}
}
var startAnimation = function() {
continueAnimation = true;
requestAnimationFrame(animWrapper);
}
var stopAnimation = function() {
continueAnimation = false;
}
return {
'start': startAnimation,
'stop': stopAnimation,
}
}
function normalizedSin(t) {
return ((Math.sin(t) + 1) * 0.5);
}
function normalizedCos(t) {
return ((Math.cos(t) + 1) * 0.5);
}
function oscillation(low, high, period) {
var diff = high - low;
return function(t) {
return diff * (1 - normalizedCos(Math.PI * 2 * t / period)) + low;
}
}
function remap(prevLow, prevHigh, newLow, newHigh) {
return function(t) {
var prevDiff = (prevHigh - prevLow);
var newT = ((t - prevLow) / prevDiff);
var newDiff = (newHigh - newLow);
return newLow + newT * newDiff;
}
}
function drawCircle(ctx, R, x, y) {
drawParametric(ctx, function(t){
return R * Math.cos(t) + x;
}, function(t) {
return R * Math.sin(t) + y;
}, range(0, 2 * Math.PI, 100))
}
function drawX(ctx, size, x, y) {
var halfSize = size / 2.0;
drawParametric(ctx, function(t){
return t + x
}, function(t) {
return t + y;
}, range(-halfSize, halfSize, 2));
drawParametric(ctx, function(t){
return t + x
}, function(t) {
return -t + y;
}, range(-halfSize, halfSize, 2));
}
function drawMarker(ctx, size, x, y) {
drawCircle(ctx, size, x, y);
drawX(ctx, 0.5 * size * Math.sqrt(2), x, y);
}
function CGTransformIdentity() {
return [1, 0, 0, 1, 0, 0];
}
function CGTransformTranslate(tx, ty) {
return [1, 0, 0, 1, tx, ty];
}
function CGTransformScale(sx, sy) {
return [sx, 0, 0, sy, 0, 0];
}
function CGTransformRotate(angle) {
return [Math.cos(angle), Math.sin(angle), -Math.sin(angle), Math.cos(angle), 0, 0];
}
function CGTransformConcat(t1, t2) {
var m1 = _matrixFromTransform(t1);
var m2 = _matrixFromTransform(t2);
return _transformFromMatrix(_matrixMultiply(m1, m2));
}
function _matrixFromTransform(t) {
var a = t[0];
var b = t[1];
var c = t[2];
var d = t[3];
var e = t[4];
var f = t[5];
return [
[a, c, e],
[b, d, f],
[0, 0, 1],
];
}
function _transformFromMatrix(m) {
var a = m[0][0];
var b = m[1][0];
var c = m[0][1];
var d = m[1][1];
var e = m[0][2];
var f = m[1][2];
return [a, b, c, d, e, f];
}
// return A * B
function _matrixMultiply(a, b) {
var aNumRows = a.length, aNumCols = a[0].length,
bNumRows = b.length, bNumCols = b[0].length,
m = new Array(aNumRows); // initialize array of rows
for (var r = 0; r < aNumRows; ++r) {
m[r] = new Array(bNumCols); // initialize the current row
for (var c = 0; c < bNumCols; ++c) {
m[r][c] = 0; // initialize the current cell
for (var i = 0; i < aNumCols; ++i) {
m[r][c] += a[r][i] * b[i][c];
}
}
}
return m;
}
function applyTransform(ctx, transform) {
ctx.transform.apply(ctx, transform);
}
var anim = CreateAnimation(function(curr, duration) {
var L = 2
var N = 8;
var Mstart = 4.0
var Mend = 4.0;
var animLow = N / Mstart;
var animHigh = N * (0.5 - (0.5 / Mend));
var osc = oscillation(animLow, animHigh, 30000)
var scaleMap = remap(animLow, animHigh, -0.4, 0.4);
var rotMap = remap(animLow, animHigh, 0.0, Math.PI * 2);
// DEBUG
// osc = function(t) {
// return 3;
// }
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Apply centering transform
ctx.save();
var trans = CGTransformConcat(CGTransformScale(WIDTH, HEIGHT), CGTransformTranslate(0.5, 0.5));
applyTransform(ctx, trans);
// Apply rotation
ctx.save();
var trans = CGTransformRotate(rotMap(osc(curr)));
applyTransform(ctx, trans);
ctx.save();
ctx.lineWidth=0.03;
ctx.strokeStyle = 'rgba(255,255,255,0.3)';
drawPolar2(ctx, function(t){
return t
}, function(t){
return 0.4
}, range(0, L * osc(curr) * 2 * Math.PI, N * L));
ctx.restore();
ctx.restore();
// ctx.save();
// var markerX = scaleMap(osc(curr))
// var markerY = -0.4;
// ctx.lineWidth=0.003;
// ctx.strokeStyle = 'rgba(255,0,0,1.0)';
// drawMarker(ctx, 0.02, markerX, markerY);
// ctx.restore();
ctx.restore();
// ctx.font = "14px Avenir";
// ctx.fillStyle = 'rgba(255,0,0,1.0)';
// ctx.fillText("" + Math.floor(100 * osc(curr)) / 100, 0 + 15, 10 + 15);
});
anim.start()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment