Skip to content

Instantly share code, notes, and snippets.

@dannyko
Forked from anonymous/index.html
Last active December 21, 2015 02:41
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 dannyko/cdf4bc979c1566851170 to your computer and use it in GitHub Desktop.
Save dannyko/cdf4bc979c1566851170 to your computer and use it in GitHub Desktop.
Canvas rendering test

Canvas-based rendering test.

This is a work in progress.

Uses vizflow.js - an application-agnostic interactive visualization engine written using EcmaScript.6 (ES6) with no other external dependencies. The compiled/minified size is under 10 kilobytes, providing a lighter-weight library for adding transition effects to HTML5 documents compared to D3js.

"format register";!function(e){function t(e){for(var t=[],r=0,n=e.length;n>r;r++)-1==d.call(t,e[r])&&t.push(e[r]);return t}function r(e,r,n,i){if("string"!=typeof e)throw"System.register provided no module name";var u;u="boolean"==typeof n?{declarative:!1,deps:r,execute:i,executingRequire:n}:{declarative:!0,deps:r,declare:n},u.name=e,l[e]||(l[e]=u),u.deps=t(u.deps),u.normalizedDeps=u.deps}function n(e,t){if(t[e.groupIndex]=t[e.groupIndex]||[],-1==d.call(t[e.groupIndex],e)){t[e.groupIndex].push(e);for(var r=0,i=e.normalizedDeps.length;i>r;r++){var u=e.normalizedDeps[r],o=l[u];if(o&&!o.evaluated){var s=e.groupIndex+(o.declarative!=e.declarative);if(void 0===o.groupIndex||o.groupIndex<s){if(void 0!==o.groupIndex&&(t[o.groupIndex].splice(d.call(t[o.groupIndex],o),1),0==t[o.groupIndex].length))throw new TypeError("Mixed dependency cycle detected");o.groupIndex=s}n(o,t)}}}}function i(e){var t=l[e];t.groupIndex=0;var r=[];n(t,r);for(var i=!!t.declarative==r.length%2,u=r.length-1;u>=0;u--){for(var s=r[u],c=0;c<s.length;c++){var f=s[c];i?o(f):a(f)}i=!i}}function u(e){return p[e]||(p[e]={name:e,dependencies:[],exports:{},importers:[]})}function o(t){if(!t.module){var r=t.module=u(t.name),n=t.module.exports,i=t.declare.call(e,function(e,t){r.locked=!0,n[e]=t;for(var i=0,u=r.importers.length;u>i;i++){var o=r.importers[i];if(!o.locked){var s=d.call(o.dependencies,r);o.setters[s](n)}}return r.locked=!1,t});if(r.setters=i.setters,r.execute=i.execute,!r.setters||!r.execute)throw new TypeError("Invalid System.register form for "+t.name);for(var s=0,a=t.normalizedDeps.length;a>s;s++){var c,m=t.normalizedDeps[s],v=l[m],g=p[m];g?c=g.exports:v&&!v.declarative?c={"default":v.module.exports,__useDefault:!0}:v?(o(v),g=v.module,c=g.exports):c=f(m),g&&g.importers?(g.importers.push(r),r.dependencies.push(g)):r.dependencies.push(null),r.setters[s]&&r.setters[s](c)}}}function s(e){var t,r=l[e];if(r)r.declarative?c(e,[]):r.evaluated||a(r),t=r.module.exports;else if(t=f(e),!t)throw new Error("Unable to load dependency "+e+".");return(!r||r.declarative)&&t&&t.__useDefault?t["default"]:t}function a(t){if(!t.module){var r={},n=t.module={exports:r,id:t.name};if(!t.executingRequire)for(var i=0,u=t.normalizedDeps.length;u>i;i++){var o=t.normalizedDeps[i],c=l[o];c&&a(c)}t.evaluated=!0;var f=t.execute.call(e,function(e){for(var r=0,n=t.deps.length;n>r;r++)if(t.deps[r]==e)return s(t.normalizedDeps[r]);throw new TypeError("Module "+e+" not declared as a dependency.")},r,n);f&&(n.exports=f)}}function c(t,r){var n=l[t];if(!n.evaluated&&n.declarative){r.push(t);for(var i=0,u=n.normalizedDeps.length;u>i;i++){var o=n.normalizedDeps[i];-1==d.call(r,o)&&(l[o]?c(o,r):f(o))}n.evaluated||(n.evaluated=!0,n.module.execute.call(e))}}function f(e){if(m[e])return m[e];var t=l[e];if(!t)throw"Module "+e+" not present.";i(e),c(e,[]),l[e]=void 0;var r=t.declarative?t.module.exports:{"default":t.module.exports,__useDefault:!0};return m[e]=r}var l={},d=Array.prototype.indexOf||function(e){for(var t=0,r=this.length;r>t;t++)if(this[t]===e)return t;return-1},p={},m={};return function(t,n){var i;"undefined"!=typeof i&&i.register?(n(i),i["import"](t)):(n(i={register:r,get:f,set:function(e,t){m[e]=t},newModule:function(e){return e},global:e}),i.set("@empty",i.newModule({})),f(t))}}("undefined"!=typeof window?window:global)("src/vizflow",function(e){e.register("src/step",[],function(e){function t(){$Z.sim=$Z.pipe($Z.task)}function r(){$Z.iter++,window.requestAnimationFrame(t)}return e("default",r),{setters:[],execute:function(){"use strict"}}}),e.register("src/item",[],function(e){function t(){for(var e=arguments.length,t=Array(e),r=0;e>r;r++)t[r]=arguments[r];return 0==t.length?$Z._item:($Z._item=t[0],$Z)}return e("default",t),{setters:[],execute:function(){"use strict"}}}),e.register("src/prep",[],function(e){function t(){for(var e=arguments.length,t=Array(e),r=0;e>r;r++)t[r]=arguments[r];return 0==t.length?$Z._prep.map(function(e){return Promise.resolve(e())}):($Z._prep=t[0],$Z)}return e("default",t),{setters:[],execute:function(){"use strict"}}}),e.register("src/action",[],function(e){function t(){for(var e=arguments.length,t=Array(e),r=0;e>r;r++)t[r]=arguments[r];return 0==t.length?$Z._action.map(function(e){return e()}):($Z._action=t[0],$Z)}return e("default",t),{setters:[],execute:function(){"use strict"}}}),e.register("src/pipe",[],function(e){function t(e){for(var t=Promise.resolve(),r=0;r<e.length;r++)t=t.then(e[r]);return t}return e("default",t),{setters:[],execute:function(){"use strict"}}}),e.register("src/done",[],function(e){function t(){return 0==$Z._item.length||$Z.iter>$Z.maxIter?!0:!1}return e("default",t),{setters:[],execute:function(){"use strict"}}}),e.register("src/exit",[],function(e){function t(){return!1}return e("default",t),{setters:[],execute:function(){"use strict"}}}),e.register("src/run",[],function(e){function t(){$Z.sim=$Z.pipe($Z.task)}return e("default",t),{setters:[],execute:function(){"use strict"}}}),e.register("src/update",[],function(e){function t(){var e=this,t=[],r=[];if(void 0!==e.transition){for(var n=0;n<e.transition.length;n++){var i=e.transition[n],u=0;void 0===i.startTime?i.startTime=Date.now():u=Date.now()-i.startTime;var o=i.duration-u;if(0==u)i.startValue=e[i.varName];else if(o>0){var s=1-o/i.duration;e[i.varName]=i.interpFunc(s)}else e[i.varName]=i.endValue,t.push(n),void 0!==i.child&&r.push(i.child)}for(var a=t.length-1;a>=0;a--){if(t[a]<e.transition.length-1){var c=e.transition[e.transition.length-1];e.transition[e.transition.length-1]=e.transition[t[a]],e.transition[t[a]]=c}e.transition.pop()}for(var f=0;f<r.length;f++)e.transition.push(r[f])}}return e("default",t),{setters:[],execute:function(){"use strict"}}}),e.register("src/transition",[],function(e){var t;return{setters:[],execute:function(){"use strict";t={linear_interp:function(e){return(1-e)*this.startValue+e*this.endValue},color_interp:function(e){var t=this.startValue,r=this.endValue;t=t.slice(1),r=r.slice(1),3===t.length&&(t=t.replace(/([0-9a-f])/gi,"$1$1")),3===r.length&&(r=r.replace(/([0-9a-f])/gi,"$1$1"));for(var n="#",i=0;3>i;i++){var u=parseInt(t.slice(2*i,2*(i+1)),16),o=parseInt(r.slice(2*i,2*(i+1)),16),s=Math.min(255,Math.round((1-e)*u+e*o));s=s.toString(16).toUpperCase(),1===s.length&&(s="0"+s),n+=s}return n},build_func:function(e,t,r){return function(n){return{varName:e,duration:t,interpFunc:r,endValue:n}}},linear_transition_func:function(e,t){return this.build_func(e,t,this.linear_interp)},color_transition_func:function(e,t){return this.build_func(e,t,this.color_interp)}},e("default",t)}}}),e.register("src/preprocess",[],function(e){function t(){return Promise.all($Z.prep())}return e("default",t),{setters:[],execute:function(){"use strict"}}}),e.register("src/update_items",[],function(e){function t(){return Promise.all($Z.item().map(function(e){return e.update?e.update():$Z.update.call(e)}))}return e("default",t),{setters:[],execute:function(){"use strict"}}}),e.register("src/detect_actions",[],function(e){function t(){var e=this;return new Promise(function(t){t(e.name)})}return e("default",t),{setters:[],execute:function(){"use strict"}}}),e.register("src/perform_actions",[],function(e){function t(){return Promise.all($Z.action())}return e("default",t),{setters:[],execute:function(){"use strict"}}}),e.register("src/render_image",[],function(e){function t(){return Promise.all($Z.item().map(function(e){return Promise.resolve(e.render())}))}return e("default",t),{setters:[],execute:function(){"use strict"}}}),e.register("src/step_or_exit",[],function(e){function t(){return $Z.done()?($Z.exit(),Promise.resolve(!0)):($Z.step(),Promise.resolve(!1))}return e("default",t),{setters:[],execute:function(){"use strict"}}}),e.register("src/vizflow",["src/step","src/item","src/prep","src/action","src/pipe","src/done","src/exit","src/run","src/update","src/transition","src/preprocess","src/update_items","src/detect_actions","src/perform_actions","src/render_image","src/step_or_exit"],function(e){var t,r,n,i,u,o,s,a,c,f,l,d,p,m,v,g,h,x,_,$,Z,w,y;return{setters:[function(e){t=e["default"]},function(e){r=e["default"]},function(e){n=e["default"]},function(e){i=e["default"]},function(e){u=e["default"]},function(e){o=e["default"]},function(e){s=e["default"]},function(e){a=e["default"]},function(e){c=e["default"]},function(e){f=e["default"]},function(e){l=e["default"]},function(e){d=e["default"]},function(e){p=e["default"]},function(e){m=e["default"]},function(e){v=e["default"]},function(e){g=e["default"]}],execute:function(){"use strict";h=[],x=[],_=[],$=0,Z=!1,w=1/0,y=[l,d,p,m,v,g],window.$Z={verbose:Z,iter:$,maxIter:w,transition:f,_item:h,_action:_,_prep:x,item:r,action:i,prep:n,update:c,pipe:u,step:t,done:o,exit:s,task:y,run:a},e("default",{})}}})});
//# sourceMappingURL=build.js.map
function set_canvas_position(canvas) {
var position = {} ;
var windowWidth = window.innerWidth ;
var widthRatio = canvas.width / windowWidth ;
var windowHeight = window.innerHeight ;
var heightRatio = canvas.height / windowHeight ;
var scaleWidth = true ; // toggles width or height scaling (height by default)
var landscape = canvas.width >= canvas.height ;
if( landscape && (heightRatio > widthRatio) ) scaleWidth = false ;
if( !landscape && !(heightRatio < widthRatio) ) scaleWidth = false ;
if(scaleWidth) { // fit width to window and center vertically
position.width = windowWidth ;
position.height = Math.round(canvas.height / widthRatio) ;
position.left = 0 ;
position.top = Math.round(0.5 * (windowHeight - position.height)) ;
position.scale = 1 / widthRatio ;
} else { // fit height to window and center horizontally
position.height = windowHeight ;
position.width = Math.round(canvas.width / heightRatio) ;
position.top = 0 ;
position.left = Math.round(0.5 * (windowWidth - position.width)) ;
position.scale = 1 / heightRatio ;
}
// console.log('rw', widthRatio, 'rh', heightRatio, 'pos', position)
canvas.style.width = position.width ;
canvas.style.height = position.height ;
canvas.style.left = position.left ;
canvas.style.top = position.top ;
}
function draw_circle(ctx, circ) {
ctx.beginPath() ;
var x = circ.x ;
var y = circ.y ;
var r = circ.radius ;
ctx.arc(x, y, r, 0, Math.PI * 2, true) ;
ctx.fillStyle = circ.color ;
ctx.fill() ;
ctx.closePath() ;
}
function draw_rect() {
var rect = this ;
context.beginPath() ;
context.rect(rect.x, rect.y, rect.width, rect.height) ;
context.fillStyle = rect.color ;
context.fill() ;
context.closePath() ;
}
function create_canvas(Nrect) {
var canvas = document.createElement('canvas') ;
canvas.setAttribute('id', 'vizCanvas') ;
canvas.setAttribute('width', Nrect) ;
canvas.setAttribute('height', Nrect) ;
canvas.style.position = 'fixed' ;
return canvas ;
}
function dec2bin (x) {
x = x.toString(2) ;
for (var k = x.length ; k < 4; k++) {
x = '0' + x ;
}
return x ;
}
function bstrsplit (x) {
var y = [] ;
for (var k = 0; k < x.length; k++) {
y[k] = parseInt (x[k]) ;
}
return y ;
}
function code2color (x) {
var y;
if (x === 0) y = black ;
else y = white ;
return y ;
}
function greycode2color (x) {
return '#'+ x + x + x ;
}
function greycode2tint (x, channel) {
var color = '#' ;
var b = '99' ;
if(x === '00') {
color += x + x + x ;
return color ;
}
if(channel === 0) {
color += x + b + b ;
} else if(channel === 1) {
color += b + x + b ;
} else {
color += b + b + x ;
}
return color ;
}
function apply_code (code) {
for (var k = 0; k < code.length; k++) {
rect[k].color = code2color(code[k]) ;
}
}
function apply_greycode (code) {
for (var k = 0; k < code.length; k++) {
rect[k].color = greycode2color(code[k]) ;
}
}
function create_rect(Nrect) {
var rect = [] ;
for (var krow = 0; krow < Nrect; krow++) {
for (var kcol = 0; kcol < Nrect; kcol++) {
rect.push({x: kcol, y: krow, width: 1, height: 1, color: black, render: draw_rect}) ;
}
}
return rect;
}
function levelup_patch(code) {
var code2 = [] ;
var Nquad = 4 ;
var temp = [] ;
for (var kquad = 0; kquad < Nquad; kquad++) {
temp.push([]) ;
}
for (var kcode = 0; kcode < code.length; kcode++) {
var kquad = 0 ; // don't need to loop over all quads to avoid duplication:
{ // no need to use "for (var kquad= 0; kquad < Nquad;kquad++)"
var openQuad = [] ;
for (var kquad2 = 0; kquad2 < Nquad; kquad2++) {
if (kquad2 === kquad) {
continue;
}
openQuad.push(kquad2) ;
}
temp[kquad] = code[kcode] ;
for (var kcode2 = 0; kcode2 < code.length; kcode2++) {
for (var kcode3 = 0; kcode3 < code.length; kcode3++) {
for (var kcode4 = 0; kcode4 < code.length; kcode4++) {
temp[openQuad[0]] = code[kcode2] ;
temp[openQuad[1]] = code[kcode3] ;
temp[openQuad[2]] = code[kcode4] ;
var flat = [] ;
for(var kflat = 0; kflat < Nquad; kflat++) {
flat = flat.concat(temp[kflat]) ;
}
code2.push(flat) ;
}
}
}
}
}
return code2 ;
}
function code2grey(code, greyIndex) {
var greyval = [] ;
for (var kval = 0; kval < Ngrey; kval++) {
greyval.push((kval * 256 / Ngrey) + ((256 / Ngrey) - 1)) ;
}
return code * greyval[greyIndex] ;
}
function bin2grey(code) {
var greyval = [] ;
for (var kval = 0; kval < Ngrey; kval++) {
greyval.push((kval * 256 / Ngrey) + ((256 / Ngrey) - 1)) ;
}
var grey = [] ;
for (var kcode = 0 ; kcode < code.length; kcode++) {
var greyk = [] ;
for (var kgrey = 0; kgrey < Ngrey; kgrey++) {
greyk.push(code[kcode].map (function(d) {
return d * greyval[kgrey] ;
})) ;
}
grey = grey.concat(greyk) ;
// console.log ('grey', grey) ;
// afasdasd
}
return grey ;
}
function grey2rgb(grey) {
var rgb = grey.map(function(d) {
var tmp = d.toString(16) ;
if (tmp.length === 1) {
tmp = '0' + tmp ;
}
return tmp ;
}) ;
return rgb ;
}
function prep() {
context.clearRect(0, 0, canvas.width, canvas.height) ;
return true ;
}
function rgb2hex( rgb ) {
var c = Math.round( rgb ).toString( 16 ) ;
if ( c.length === 1 ) c += c ; // make sure it is the right length
return c ;
}
function random_color() {
return '#'
+ rgb2hex( 255 * Math.random() ) // r
+ rgb2hex( 255 * Math.random() ) // g
+ rgb2hex( 255 * Math.random() ) ; // b
}
<!doctype html5>
<html>
<head>
<style>
canvas {
image-rendering: optimizeSpeed; /* STOP SMOOTHING, GIVE ME SPEED */
image-rendering: -moz-crisp-edges; /* Firefox */
image-rendering: -o-crisp-edges; /* Opera */
image-rendering: -webkit-optimize-contrast; /* Chrome (and eventually Safari) */
image-rendering: pixelated; /* Chrome */
image-rendering: optimize-contrast; /* CSS3 Proposed */
-ms-interpolation-mode: nearest-neighbor; /* IE8+ */
}
</style>
</head>
<body>
<script src="build.js"></script>
<script src="greycode.js"></script>
<script src="jsbin.direve.js"></script>
</body>
</html>
var Nrect = 2 ;
var perf = window.performance ;
var black = '#000';
var white = '#fff';
document.body.style.backgroundColor = white ;
document.body.style.overflowY = 'hidden';
document.body.style.margin = 0 ;
var canvas = create_canvas(Nrect) ;
//var hiddenCanvas = set_canvas(width, height) ;
//hiddenCanvas.style.display = 'none' ; // hide this canvas
var context = canvas.getContext('2d') ;
context.mozImageSmoothingEnabled = false ;
context.imageSmoothingEnabled = false ;
context.font = "48px Arial" ;
context.globalAlpha = 1.0 ;
// context.webkitImageSmoothingEnabled = false ;
document.body.appendChild(canvas) ;
var code = [] ;
for ( var k = 0 ; k < Math.pow( 2, Nrect * Nrect) ; k++ ) {
code[k] = bstrsplit( dec2bin( k ) ) ;
}
code = levelup_patch( code ) ;
Nrect = 2 * Nrect ;
var Nbit = 2 ;
var Ngrey = Math.pow( 2, Nbit ) ;
// reset the canvas:
canvas.width = Nrect ;
canvas.height = Nrect ;
function resize() {
set_canvas_position( canvas ) ;
}
resize() ;
var tResize = 85 ; // how often to check for window resize events (85 is five 17 ms frames)
setInterval( resize, tResize ) ;
var rect = create_rect( Nrect ) ;
//rect.forEach( function(d) { draw_rect.call(d, context) } ) ;
// setInterval(function(){
// var integer = Math.round(Math.random()* (Ngrey * Math.pow(2, Nrect * Nrect) - 1)) ;
// //console.log('int', integer, 'code', code[integer] ) ;
// apply_greycode(greycode[integer]);
// prep() ;
// rect.forEach(function(d) {draw_rect.call(d, context)}) ;
// }, 100) ;
$Z.item(rect) ; // load the user data into the visualization engine to initialize the time equals zero (t = 0) state
$Z.prep([prep]) ; // sets the preprocessing to perform on each frame of the animation (prior to updating and rendering the elements)
$Z.run() ; // run the interactive visualization (infinite loop by default)
var dur = 100 ; // transition duration in milliseconds
var c_transition = $Z.transition.color_transition_func ( 'color', dur ) ; // function accepting a color end-value and returning a transition object
function grey_transition() {
var nextCodeId = Math.round( Math.random() * ( Math.pow( 2, Nrect * Nrect ) - 1 ) ) ;
var greyIndex = Math.round((Ngrey * Math.randomm())) ;
for ( var krect = 0 ; krect < Nrect * Nrect ; krect++ ) {
var greycode = code2grey( code[nextCodeId][krect], greyIndex ) ;
var tc = c_transition ( grey2rgb ( greycode ) ) ; // transient color transition object
rect[krect].transition = [tc] ; // set the transitions for this item, also cancels all existing transitions for this item (side-effect)
}
}
function tint_transition() {
var nextCodeId = Math.round( Math.random() * ( Math.pow( 2, Nrect * Nrect ) - 1 ) ) ;
var channel = Math.round(2 * Math.random()) ;
var greyIndex = Math.round((Ngrey - 1) * Math.random()) ;
var greycode = grey2rgb( code[nextCodeId].map( function(d) { return code2grey( d, greyIndex ) ; }) ) ;
for ( var krect = 0 ; krect < Nrect * Nrect ; krect++ ) {
var tc = c_transition ( greycode2tint ( greycode[krect], channel ) ) ; // transient color transition object
rect[krect].transition = [tc] ; // set the transitions for this item, also cancels all existing transitions for this item (side-effect)
}
}
var minTotalTime = 250 ;
var delay = Math.max(0, minTotalTime - dur) ;
var tFlash = dur + delay ;
setInterval(tint_transition, tFlash) ;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment