← Back to articles

javascript creative coding 01

· by @Elout de Kok · View on fxhash · IPFS · 256 editions

javascripttutorialelout

lets start with a simple index.html file

<!-- text and commenting in html: use  < ! -- and  -- > without spaces
first test  <p>start of a paragraph <br> line break / <b> bold  -->

<html>
<body>

<p> 
<b>hiyaaaaa!</b> 

<br> - my fist html page - 
<br> but no code at all yet!

</p>

</body>
</html>

001. Copy the code, in a 'plain' text-editor ( I use the notepad ++ myself ) and save it as like index01.html - and open/run it in a browser


html is like this text, that you can give all fancy colors, sizes, with tags \this is bold\


the \
tag is a linebreak


Next:

my first javascript. Copy the code and save it like index02.html. and run-open it in a web-browser!

<html>
<body>

<script> // with 2 // you can comment in your javascript code

alert('yo!');

var a=4; // I have an 'a' with 4
var b=5; // I have a 'b' with 5
var c=a+b; // I add a and b, and put the result in 'c'

alert('hiyaa.. 4+5 is like: ' + c);  // and show some text, and c in an alert window-pop-up


// never forget to close it as well!
</script>

</body>
</html>

002. The alert gives like a pop-up window, you can output some text. and I do my first calculation

next setting up the basics for my javascript template


<html>
<head>

<script> 
//--------------javascript start------------------
// also changed the script now to the top of the page
// inbetween head and /head !!!!


//----------- window events --- 
window.addEventListener('load',mywindow_page_loaded, false );

// this sets an window event listener in javascript - 

// it looks technical; but it's just simple/default 'browser' tech
// for this case: when the page gets loaded, it will jump to the routine 
// mywindow_page_loaded()

// I use eventlisteners - for like checking the windowsize, mouse, touch and keyboard input
// this is default 'tech' -> the browser needs when windows-actions changes

// now  handle those events
// is the page loaded for the first time? then do this function!!
function mywindow_page_loaded() 
{
    //alert('yo!');

    var a=5; // I have an 'a' with 4
    var b=15; // I have a 'b' with 5
    var c = a + b; // I add a and b, and put the result in 'c'

    // I added a and b not as text, but as like a variable,
    // if I change it above; it also will show in the 'my_text' variable
    var my_text =  "Adding "+  a + " and "+ b + " gives me "+ c;

    alert(my_text);     
}

</script>

</head>
<body>

</body>
</html>

003. I will setup the basics of my javascript template next. the windows.event looks complicated tech, but it's needed for like when I do interactions with the screen, get the mouse position, window scale, keyboard etc. etc. then I need windows.events

For this example, I use a windows event, when the page gets loaded!


<html>

<head>
<script>  //--------------javascript start------------------


//----------- window events --- 

// jump to mywindow_page_loaded when the page is loaded
window.addEventListener('load',mywindow_page_loaded, false ); // ! default browser tech! call the function  mywindow_page_loaded

// page loaded? do this function; you can give it other names as well!!
function mywindow_page_loaded() 
{
    var a=5; // I have an 'a' with 4
    var b=15; // I have a 'b' with 5
    var c = a + b; // I add a and b, and put the result in 'c'

    var my_text =  "Adding "+  a + " and "+ b + " gives me "+ c;

    // you can use javascript to write and change the html! - 
    document.getElementById('infoblock').innerHTML = my_text; // ! default browser tech! to select my div containers etc.

    // In the body on the bottom I declared this  div 'container' 
    // and gave it a name; an id called --> !!!!!!! 'infoblock' !!! 
    // and next I use javascript, to select that block and write into it! 
}

</script>
</head>

<body>

<div id="infoblock">0__.</div>

</body>
</html>

004. Here I added a new div container in the html part, and use javascript next to write and change the text of the html page.



<html>

<head>
<script>  //javascript start


//----------- window events --- 
// jump to mywindow_page_loaded when the page is loaded
window.addEventListener('load',mywindow_page_loaded, false );

// page loaded? do this function!!
function mywindow_page_loaded() 
{

    // you can use javascript to write and change the html!
    document.getElementById('infoblock').innerHTML = 'page loaded - next draw in my canvas';


    // I added a canvas as well, I want to get creative! - I also gave it my own name called 'my_canvas'

    var canvas = document.getElementById("my_canvas"); // select the canvas with the name 'my_canvas'!
    var ctx = canvas.getContext("2d"); // browser tech - this is how it's done, I didnt made this up myself!
    ctx.font = "30px Arial"; // font size
    ctx.fillText("Hiiyyaaaa", 30, 50); // text, x,y 
    ctx.strokeText("yooz!", 60, 100); // outline text x,y

}

</script>
</head>

<body>

<div id="infoblock">0__.</div>

<canvas id="my_canvas">- needs a javascript enabled browser to see the drawing-animation!-</canvas>

</body>
</html>

005. Ok want to get creative next. Added also a 'canvas' with the id 'my_canvas'

and can use javascript to write and draw in it as well!



<html>

<head>

 <!-- css stylesheet -->
<style type="text/css">
body
{
    /*  background color  #rgb   you can do like 907070 or 977  just a bit more red, then green and blue*/
    background-color: #977; 
    /* these numbers are in hexadecimal! see photoshop-gimp for hex colors incase! #ffffff is white!*/

    margin: 0;padding: 0;   
    font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; color: #ffffff;  
}

/* my info block*/
.info_css
{
    background-color: #555;
}

.canvas_css
{
    background-color: #ccc;

    position: absolute;  
    max-height: 100%; max-width: 100%;

    object-fit: contain;
    top: 50%; left: 50%;
    transform: translate(-50%, -50%);   
}
</style>


<script>  //javascript start


//----------- window events --- 
// when the page is loaded
window.addEventListener('load',mywindow_page_loaded, false );

// page loaded? do this function!!
function mywindow_page_loaded() 
{

    // you can use javascript to write and change the html!
    document.getElementById('infoblock').innerHTML = 'page loaded - next draw in my canvas';


    var canvas = document.getElementById("my_canvas"); // select the canvas with the name 'my_canvas'!
    var ctx = canvas.getContext("2d"); // browser tech - this is how it's done, I didnt made this up myself!
    ctx.font = "30px Arial"; // font size
    ctx.fillText("Hiiyyaaaa", 30, 50); // text, x,y 
    ctx.strokeText("yooz!", 60, 100); // outline text x,y

}

</script>
</head>

<body>

<div class="info_css" id="infoblock">0__.</div>

<canvas class="canvas_css" id="my_canvas">- error message: - needs a javascript enabled browser to see the drawing-animation!-</canvas>

</body>
</html>

006. Added a css stylesheet; where you can set the html background colors etc. so I can see the different blocks; give them different colors. and do positioning!


<html>

<head>

 <!-- css stylesheet -->
<style type="text/css">
body
{
    /*  background color  #rgb   you can do like 907070 or 977  just a bit more red, then green and blue*/
    background-color: #977; 
    /* these numbers are in hexadecimal! see photoshop-gimp for hex colors incase! #ffffff is white!*/

    margin: 0;padding: 0;   
    font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; color: #ffffff;  
}

/* my info block*/
.info_css
{
    top: 0px;left: 0px; background-color: #558; font-size: 14px;
    border-style:none; border-width:0px; margin:0px 0px 0px 0px; 
    padding:2px 2px 2px 2px;color: #fff;  z-index:21;border-width:4px;
    position: fixed;
}

.canvas_css
{

    background-color: #ccc; /*grey now*/

    top:  0px; left: 0px; 
    z-index:20;
    position: absolute;

    border-style:solid; border-width:0px;margin:0px 0px 0px 0px; padding:0px 0px 0px 0px; 

    /* you can set different cursor's type's' gets set again in javascript! */
    cursor: crosshair;
    /* cursor:none;   cursor: url(./cursor.cur),auto.*/

    /*this next shows my image like pixel-sharp - no pixel blurring by the browser!! */
    image-rendering:optimizeSpeed;             /* Legal fallback */
    image-rendering:-moz-crisp-edges;          /* Firefox        */
    image-rendering:-o-crisp-edges;            /* Opera          */
    image-rendering:-webkit-optimize-contrast; /* Safari         */
    image-rendering:optimize-contrast;         /* CSS3 Proposed  */
    image-rendering:crisp-edges;               /* CSS4 Proposed  */
    image-rendering:pixelated;                 /* CSS4 Proposed  */
    -ms-interpolation-mode:nearest-neighbor;   /* IE8+           */

}
</style>


<script>  //javascript start


//----------- window events --- 
// when the page is loaded
window.addEventListener('load',mywindow_page_loaded, false );

// page loaded? do this function!!
function mywindow_page_loaded() 
{
    // you can use javascript to write and change the html!
    document.getElementById('infoblock').innerHTML = 'page loaded - next draw in my canvas';


    var canvas = document.getElementById("my_canvas"); // select canvas: 'my_canvas'!

    // set my canvas
    var im_w = 800;  // image width 
    var im_h = 800;  // image height

        // now set the canvas width and height size 
    canvas.width = im_w; 
    canvas.height = im_h;



    var ctx = canvas.getContext("2d"); // browser tech 

    // introducing the for next loop! do this now 50 times
    for (var i = 0; i < 50; i++)
    {
        var red   = Math.floor(Math.random() * 255); // get a color between 0 and 255!
        var green = Math.floor(Math.random() * 255);
        var blue  = Math.floor(Math.random() * 255);

        var my_fontsize=Math.floor(Math.random() *  55)+9;
        ctx.font = my_fontsize+"px Verdana"; // random font size now



        var x = Math.floor(Math.random() * 420)+20; // random x and y screen position
        var y = Math.floor(Math.random() * 720)+20;

        ctx.fillStyle =  "rgb(0,0,0)";
        ctx.fillText("fxhash - " + i, x , y+1); // black text little offset on y!

        ctx.fillStyle =  "rgb("+red+", "+green+", "+blue+")"; // color text
        ctx.fillText("fxhash - " + i, x, y); // text, x,y position, also show the i-number !


        // emulate like a random dice - between 1 and 6
        var myrandom_dice = Math.floor(Math.random()*6) + 1; 
        // random number between 1 and 6 now         

        x = Math.floor(Math.random() * 520)+20; // random x and y screen position
        y = Math.floor(Math.random() * 720)+20;

        ctx.font = "40px Arial"; // font size
        ctx.fillStyle =  "rgb( 0,0,0)";
        ctx.fillText(myrandom_dice, x, y); // text, x,y 

    }// end for-next loop!


} //end mywindow_page_loaded

</script>
</head>

<body>

<div class="info_css" id="infoblock">0__.</div>

<canvas class="canvas_css" id="my_canvas">- error message: - needs a javascript enabled browser to see the drawing-animation!-</canvas>

</body>
</html>

007. Added different cursor support in the css, and no pixel blurring on the canvas.

(browser-tech - I didn't created that myself)


Added a for-next loop, that does a loop like x-times. A great thing to use!


And introducing Math.random! that gives a random floating point number like between 0 and 0.9999999 I can round it with Math.floor to make it like 'rounded' numbers. Also using the random; to Emulate like a dice.


And I'm going to ditch this ctx-drawing asap. since I guess you can better do that stuff in p5js- and like can be different in browsers-platforms? I'm really going to focus on rgb-pixel 'perfect' drawing and using RGB-pixel buffers!


<html>

<head>

 <!-- css stylesheet -->
<style type="text/css">
body
{
    background-color: #777; 
    margin: 0;padding: 0;   
    font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; color: #ffffff;  
}
/* my info block*/
.info_css
{
    top: 0px;left: 0px; background-color: #558; font-size: 14px;
    border-style:none; border-width:0px; margin:0px 0px 0px 0px; 
    padding:2px 2px 2px 2px;color: #fff;  z-index:21;border-width:4px;
    position: fixed;
}
.canvas_css
{
    background-color: #ccc; /*grey now*/

    top:  0px; left: 0px; 
    z-index:20;
    position: absolute;

    border-style:solid; border-width:0px;margin:0px 0px 0px 0px; padding:0px 0px 0px 0px; 

    /* you can set different cursor's type's' gets set again in javascript! */
    cursor: crosshair;
    /* cursor:none;   cursor: url(./cursor.cur),auto.*/

    /*this next shows my image like pixel-sharp - no pixel blurring by the browser!! */
    image-rendering:optimizeSpeed;             /* Legal fallback */
    image-rendering:-moz-crisp-edges;          /* Firefox        */
    image-rendering:-o-crisp-edges;            /* Opera          */
    image-rendering:-webkit-optimize-contrast; /* Safari         */
    image-rendering:optimize-contrast;         /* CSS3 Proposed  */
    image-rendering:crisp-edges;               /* CSS4 Proposed  */
    image-rendering:pixelated;                 /* CSS4 Proposed  */
    -ms-interpolation-mode:nearest-neighbor;   /* IE8+           */
}
</style>


<script>  //javascript start

// using some global variables now! I can use every where!

// my screen - canvas size now!
var im_w = 800;  // image - canvas width 
var im_h = 800;  // image - canvas height


//----------- window events --- 
// when the page is loaded
window.addEventListener('load',mywindow_page_loaded, false );

// page loaded? do this function!!
function mywindow_page_loaded() 
{
    // get the browser window size! - browser tech!
    var win_w=window.innerWidth;
    var win_h=window.innerHeight;

    // and show the window size in the text: info block! - nice for testing!
    document.getElementById('infoblock').innerHTML = 'window width: '+win_w +' window height: '+win_h;

    var c = document.getElementById("my_canvas"); // select canvas: 'my_canvas'!
    var ctx=c.getContext("2d");

    c.width = im_w; // set my canvas to my im_w and im_h size!
    c.height = im_h;


    // set the canvas position now with javascript! 
    // pretty simple-crude now; will do better later on
    var xpos=(win_w - im_w)/2;
    var ypos=(win_h - im_h)/2;

    // position my canvas!
    c.style.left= xpos+'px';
    c.style.top = ypos+'px';


    // make a new empty'data' image
    // and fill my canvas with it!
    // now with some random grey-noise!
    var img1 = ctx.createImageData(im_w, im_h); // create an empty data image - with width, height

    for (var p=0, j = 0; j < im_h*im_w; j++) // do for every pixel on the screen!
    {           
            var grey = Math.floor(Math.random() * 256);
            img1.data[p++] = grey;  // red
            img1.data[p++] = grey;  // green
            img1.data[p++] = grey;  // blue
            img1.data[p++] = 255;   // alpha channel; not used atm
    }
    ctx.putImageData(img1, 0, 0);   // and draw it to my canvas!


} //end mywindow_page_loaded

</script>
</head>

<body>

<div class="info_css" id="infoblock">0__.</div>

<canvas class="canvas_css" id="my_canvas">- error message: - needs a javascript enabled browser to see the drawing-animation!-</canvas>

</body>
</html>

008. Next I'm going to use like a data image; and write it to my canvas. The data-pixels I fill now with a random grey color: between 0 and 255 (0= total black 255=total white)


<html>

<head>

 <!-- css stylesheet -->
<style type="text/css">
body
{
    background-color: #777; 
    margin: 0;padding: 0;   
    font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; color: #ffffff;  
}
/* my info block*/
.info_css
{
    top: 0px;left: 0px; background-color: #558; font-size: 14px;
    border-style:none; border-width:0px; margin:0px 0px 0px 0px; 
    padding:2px 2px 2px 2px;color: #fff;  z-index:21;border-width:4px;
    position: fixed;
}
.canvas_css
{
    background-color: #ccc; /*grey now*/

    top:  20px; left: 20px; 
    z-index:20;
    position: absolute;

    border-style:solid; border-width:0px;margin:0px 0px 0px 0px; padding:0px 0px 0px 0px; 

    /* you can set different cursor's type's' gets set again in javascript! */
    cursor: crosshair;
    /* cursor:none;   cursor: url(./cursor.cur),auto.*/

    /*this next shows my image like pixel-sharp - no pixel blurring by the browser!! - old legacy code from the internet  */
    image-rendering:optimizeSpeed;             /* Legal fallback */ 
    image-rendering:-moz-crisp-edges;          /* Firefox        */ 
    image-rendering:-o-crisp-edges;            /* Opera          */ 
    image-rendering:-webkit-optimize-contrast; /* Safari         */ 
    image-rendering:optimize-contrast;         /* CSS3 Proposed  */ 
    image-rendering:crisp-edges;               /* CSS4 Proposed  */ 
    image-rendering:pixelated;                 /* CSS4 Proposed  * 
    -ms-interpolation-mode:nearest-neighbor;   /* IE8+           */
}
</style>


<script>  //javascript start

// using some global variables now! I  use all the time now! and I can tune

//- my image / canvas size -
var im_w = 320;  // image - canvas width 
var im_h = 240;  // image - canvas height



//---------init tech - window management -  window scaling etc. - tech -
var win_w; // window width - gets set in mywindow_page_loaded
var win_h; // window height

//----------- window events --- 
//----------legacy code, from the internet-tech------------------------------------
// sets the animation at 60 fps
if ( !window.requestAnimationFrame ) 
{
    window.requestAnimationFrame = ( function() {
        return window.webkitRequestAnimationFrame ||
        window.mozRequestAnimationFrame ||
        window.oRequestAnimationFrame ||
        window.msRequestAnimationFrame ||
        function(callback, element ) {window.setTimeout( callback, 1000 / 60 );};
    } )();
}

    //!!!!!!!____Init here_____!!!!!!!!!!!!
// do wen the page is loaded - tech -
window.addEventListener('load',init_mywindow, false ); 


// init  - tech -
function init_mywindow() 
{
    // get the browser window size! - browser tech!
    win_w=window.innerWidth;
    win_h=window.innerHeight;

    // and show the window size in the text: info block! - nice for testing!
    document.getElementById('infoblock').innerHTML = 'window width: '+win_w +' window height: '+win_h;

    // but hide it for now~! since animation !
    document.getElementById('infoblock').style.visibility = "hidden";

    //---------------------------windows check on resize
    win_w=window.innerWidth;
    win_h=window.innerHeight;

    // when browser window gets resized - tech -
    window.addEventListener( 'resize', onWindowResize, false );

    // set the size of the canvas
    document.getElementById('my_canvas').style.width = win_w+'px'; 
    document.getElementById('my_canvas').style.height= win_h+'px';  
    document.getElementById('my_canvas').style.left= 0+'px';
    document.getElementById('my_canvas').style.top = 0+'px';

    animate(); // !!!____Init__ and trigger-start the animation
} 

//---window stuff
function onWindowResize() 
{
    win_w=window.innerWidth;
    win_h=window.innerHeight;   
}

function animate() 
{
    requestAnimationFrame( animate );
    draw();
}

// the animation-drawing set at 60fps frames per second atm
function draw()
{
    //now blit bomb data to the screen
    var c = document.getElementById("my_canvas"); // select canvas: 'my_canvas'!
    var ctx=c.getContext("2d");

    c.width = im_w; // set my canvas to my im_w and im_h size!
    c.height = im_h;

    document.getElementById('my_canvas').style.width = win_w+'px'; 
    document.getElementById('my_canvas').style.height= win_h+'px';  
    document.getElementById('my_canvas').style.left= 0+'px';
    document.getElementById('my_canvas').style.top = 0+'px';


    // Now finally draw something on the screen !!~ 
    // now  some random grey-noise pixels!
    var img1 = ctx.createImageData(im_w, im_h); // browser tech - create a new image: width, height

    for (var p=0, j = 0; j < im_h*im_w; j++) // draw those pixels on the screen!
    {           
            var grey = Math.floor(Math.random() * 256); // get a random grey color
            img1.data[p++] = grey;  // red
            img1.data[p++] = grey;  // green
            img1.data[p++] = grey;  // blue
            img1.data[p++] = 255;   // alpha channel; not used atm
    }
    ctx.putImageData(img1, 0, 0);   // and draw the data image to the canvas!

}

// javascript end
</script>
</head>

<body>

<div class="info_css" id="infoblock">0__.</div>

<canvas class="canvas_css" id="my_canvas">-__-</canvas>

</body>
</html>

009. Next Lets start to animate these pixels ! Full-screen; real low res for now! Added a window_resizing check and the animation support (tech)



nxt plz!

-simple fxhash templates- 0__.


lil break:
!!!! Always use latest fxhash snippet!! this example below uses an older one!!!
<!doctype html>
<html>
<head>

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

<title>0__.</title>

<!--the favicon a 16x16 .png image 
- why ? cause we can!
- ipfs often gives an error message, when you don't have a favicon
 I convert my 16x16 .png here -  www.base64-image.de -->

<link rel="icon" type="image/png" sizes="16x16" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH5wIDFzsQl4w3vQAAATFJREFUOMudk7GNwzAMRd8xFuA0LpIuEGDIO3iFjBDAC6TMEBmHI6RxmYJDpMgS7nTFnQRZgYs7AsLH//wgJUrCOReBGEKIQKz5lp64+PcdEYHnla7r8O87XdfB85r1aZoofSKCf9+ZpglSpXolPXcSyfx4PGbEzCIQ/4JN02ROfdaEaW3ls8/M4m63i2YWD4fDCpN+u91WvNSpO21Ou5hBuUMJIZDCOcd+v8c5lzXvPcMwcDqdMgcIITAMA3kGaSg138LkE1XN3dq2RVVp25YyxnGkDlVlHEekFJdl4XK5sCzLymxmnM/njyJm9lMgnbnve1SVvu9XxnmeeTwe2Zdwnme+fqf57xAzo2kazAzv/QqTrqorXurUb37rF9b5/A7SvSZM8Xq9si4iH/kQAiLCNyE2CBjl+pJJAAAAAElFTkSuQmCC" />


 <!-- css stylesheet -->
<style type="text/css">
body
{
    background-color: #777; 
    margin: 0;padding: 0;   
    font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; color: #fff;  
}
/* my info block*/
.info_css
{
    color: #fff; font-size: 14px; background-color: #558; 
    z-index:21;
    position: fixed;    
    top:0px;left:0px;
    border-style:none; border-width:4px;
    margin:0px 0px 0px 0px; padding:2px 2px 2px 2px;
}
.canvas_css
{
    z-index:20;
    position: absolute;

    border-style:solid; border-width:0px;
    margin:0px 0px 0px 0px; padding:0px 0px 0px 0px; 

    /*this next shows my image like pixel-sharp - no pixel blurring by the browser!! - old legacy code from the internet  */
    image-rendering:optimizeSpeed;             /* Legal fallback */ 
    image-rendering:-moz-crisp-edges;          /* Firefox        */ 
    image-rendering:-o-crisp-edges;            /* Opera          */ 
    image-rendering:-webkit-optimize-contrast; /* Safari         */ 
    image-rendering:optimize-contrast;         /* CSS3 Proposed  */ 
    image-rendering:crisp-edges;               /* CSS4 Proposed  */ 
    image-rendering:pixelated;                 /* CSS4 Proposed  * 
    -ms-interpolation-mode:nearest-neighbor;   /* IE8+           */
}
</style>


<script id="fxhash-snippet">
  //---- do not edit the following code (you can indent as you wish)
  let alphabet = "123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ"
  var fxhash = "oo" + Array(49).fill(0).map(_=>alphabet[(Math.random()*alphabet.length)|0]).join('')
  let b58dec = str=>[...str].reduce((p,c)=>p*alphabet.length+alphabet.indexOf(c)|0, 0)
  let fxhashTrunc = fxhash.slice(2)
  let regex = new RegExp(".{" + ((fxhashTrunc.length/4)|0) + "}", 'g')
  let hashes = fxhashTrunc.match(regex).map(h => b58dec(h))
  let sfc32 = (a, b, c, d) => {
    return () => {
      a |= 0; b |= 0; c |= 0; d |= 0
      var t = (a + b | 0) + d | 0
      d = d + 1 | 0
      a = b ^ b >>> 9
      b = c + (c << 3) | 0
      c = c << 21 | c >>> 11
      c = c + t | 0
      return (t >>> 0) / 4294967296
    }
  }
  var fxrand = sfc32(...hashes)
  // true if preview mode active, false otherwise
  // you can append preview=1 to the URL to simulate preview active
  var isFxpreview = new URLSearchParams(window.location.search).get('preview') === "1"
  // call this method to trigger the preview
  function fxpreview() {
    console.log("fxhash: TRIGGER PREVIEW")
  }
  //---- /do not edit the following code
</script>



<script type="text/javascript">  //my javascript start

// using some global variables now! I  use all the time now! and I can tune


// you can change this when starting something new
var cversion="pixeldrop"; // title of the page, also name of the saved image
document.title =cversion;

var show_fps =    false;//     true;//  false;  // put this on wen testing!


var win_w;
var win_h;


//- my image / canvas / animation screen-pixel size -
var im_w = 1024;  // image - canvas width 
var im_h = 768;  // image - canvas height


var temp_my_r=my_random_int(255);
var temp_my_g=my_random_int(255);
var temp_my_b=my_random_int(255);   

//-----------------------------------tech--------------------------------------------------------


// my r g b pixel buffer  
var pix_r = new Uint8ClampedArray(im_w*im_h); // I only use Uint8ClampedArray for the image output buffer! 
var pix_g = new Uint8ClampedArray(im_w*im_h); // it can be 'buggy/funky', wen using it like a normal array
var pix_b = new Uint8ClampedArray(im_w*im_h);

// You don't need to understand the tech too much, but it's needed to get the car running smooth.

// globals to keep track of the animation
var animation_part=0;
var anim_loop=0;
var do_once=0;
var my_pause=false;
//---------init tech - window management -  window scaling etc. - tech -
var save_image=false;

//----------- show fps------------
var my_timer=setInterval(function(){timer_fps()},1000);//1000
var data_fps=0;
var counter_fps=0;
var timeCurrent, timeLast = Date.now(); 
var test=""; // for testing  

//----------- window events --- 
//----------legacy code, from the internet (not mine)- tech------------------------------------
// sets the animation at 60 fps
if ( !window.requestAnimationFrame ) 
{
    window.requestAnimationFrame = ( function() {
        return window.webkitRequestAnimationFrame ||
        window.mozRequestAnimationFrame ||
        window.oRequestAnimationFrame ||
        window.msRequestAnimationFrame ||
        function(callback, element ) {window.setTimeout( callback, 1000 / 60 );};
    } )();
}

    //!!!!!!!____Init here_____!!!!!!!!!!!!
// do wen the page is loaded - tech -
window.addEventListener('load',init_mywindow, false ); 


// ------------tech next: keys, mouse and windows handling --------------------

document.addEventListener('keyup', function(event)
{
    // saving is now handled in the draw() function!
    if (event.code == 'KeyS') // s key
    {  
        save_image=true;
    }
    if (event.code == 'Space') // spacebar key gets paused in  the draw() function!
    {  
        if(my_pause==false){my_pause=true;}else {my_pause=false;}
    }   

}); 

// init  - tech -
function init_mywindow() 
{

    // hide info text block when showfps is  false
    if(show_fps==false){document.getElementById('infoblock').style.visibility = "hidden";}
    else {document.getElementById('infoblock').style.visibility = "visible";}

    //---------------------------windows check on resize
    win_w=window.innerWidth;
    win_h=window.innerHeight;

    // when browser window gets resized - tech -
    window.addEventListener( 'resize', onWindowResize, false );

    // set the size of the canvas
    document.getElementById('my_canvas').style.width = win_w+'px'; 
    document.getElementById('my_canvas').style.height= win_h+'px';  
    document.getElementById('my_canvas').style.left= 0+'px';
    document.getElementById('my_canvas').style.top = 0+'px';

    animate(); // !!!____Init__ and trigger-start the animation
} 

//---window stuff
function onWindowResize() 
{
    win_w=window.innerWidth;
    win_h=window.innerHeight;

    // set the size of the canvas
    document.getElementById('my_canvas').style.width = win_w+'px'; 
    document.getElementById('my_canvas').style.height= win_h+'px';  
    document.getElementById('my_canvas').style.left= 0+'px';
    document.getElementById('my_canvas').style.top = 0+'px';
}



// html - set text; and dump the html/text in a div
function set_msg(div, msg){document.getElementById(div).innerHTML = msg;}
function go_msg(div, msg) {document.getElementById(div).innerHTML += msg;} // add to your text message


// legacy code from the internet - quick and dirty fps counter!
function timer_fps() // dirty fps counter 
{
    timeCurrent = Date.now();
    if (show_fps==true)
    {
        var fpsThisFrame = 1000 / (timeCurrent - timeLast);
        if(timeCurrent > timeLast) 
        {
            set_msg('infoblock', 'fps:' + counter_fps + test);
            timeLast = timeCurrent;
            counter_fps=0;
        }
    }   
}


 //--- my random functions based on fxrand()------------

    function my_random_int(nummer){return ( ((fxrand()*nummer) << 0) );} //int: returns random number int!
    //   << 0 is a fast hack for Math.floor or Math.round

    function my_random_dub(nummer){return ( fxrand()*nummer );} //float: return random number float! 

    function my_random_int_minplus(nummer){return  (  ( (fxrand() * (nummer*2)) - nummer) << 0 );} 
    //int: returns random number int! between -num +num

    function my_random_dub_minplus(nummer){return  ( (fxrand() * (nummer*2)) - nummer)  ;} 
    //float: return random number float! between -num +num

//-------------------------------------------------------------------------------
function animate() 
{
    requestAnimationFrame( animate );
    if (show_fps==true){counter_fps++;}
    draw();
}

// the animation-drawing set at 60fps frames per second atm
function draw()
{

    if(my_pause==false) // check if the animation is not paused with spacebar
    {
        my_animation();
    }

    //now blit-bomb the data to the screen
    var c = document.getElementById("my_canvas"); // select canvas: 'my_canvas'!
    var ctx=c.getContext("2d"); 
    c.width = im_w; // set my canvas to my im_w and im_h size!
    c.height = im_h;

    // dump the rgb buffer to the screen
    var img1 = ctx.createImageData(im_w, im_h); // browser tech - create a new image: width, height 
    for (var p=0, j = 0; j < im_h*im_w; j++) // draw those pixels on the screen!
    {           
            var grey = Math.floor(Math.random() * 256); // get a random grey color
            img1.data[p++] = pix_r[j];  // red
            img1.data[p++] = pix_g[j];  // green
            img1.data[p++] = pix_b[j];  // blue
            img1.data[p++] = 255;   // alpha channel; not used atm
    }
    ctx.putImageData(img1, 0, 0);   // and draw the data image to the canvas!


    if (save_image==true) // save image 
    {
        var imagename=cversion+'_'+fxhash+'_'+'.png';
        var my_download = document.createElement('a');
        my_download.setAttribute('download', imagename);

        var mcanvas = document.getElementById('my_canvas');
        mcanvas.toBlob(function(blob) {
                        var url = URL.createObjectURL(blob);
                        my_download.setAttribute('href', url);
                        my_download.click();    
                        });                         
        save_image=false;
    }

} // end draw()
//---------------------------end tech--------------------

// !-------------- --- next the creative part -----------!


function my_animation()
{



    if (animation_part==0)
    {   
        animation_part++; // go next!
    }

    // init animation part
    else if (animation_part==1)
    {   
        anim_loop=0;
        animation_part++;
    }

    // draw random grey background 
    else if (animation_part==2)
    {

        // fill the screen with random noise                
        for (var j = 0; j < im_h; j++) // y
        {
            var grey=my_random_int(255); // just grey horizontal bars   now     
            var p1=j*im_w;
            for (var i = 0; i <  im_w; i++) // x
            {
                var p2=p1+i; // pixel position! 
                pix_r[p2]=grey;
                pix_g[p2]=grey;
                pix_b[p2]=grey;
            }   
        }   

        anim_loop=0;
        animation_part++;
    }


    // init next drawing
    else if (animation_part==3)
    {   
        anim_loop=0;
        animation_part++; // go next
    }

    // draw 'grate' squares
    else if (animation_part==4)
    {

        for (var soz = 0; soz <  100; soz++) // draw faster and more ! watch fps!
        {           
            var x1 = my_random_int(im_w) + my_random_int_minplus(100);
            var y1 = my_random_int(im_h) + my_random_int_minplus(100);

            var randomsizex= 1+my_random_int(700);
            var randomsizey= 1+my_random_int(30);

            var x2 = x1+randomsizex;
            var y2 = y1+randomsizey;

            // important don't draw outside my screen! - check the position when drawing
            if(x1<0){x1=0;} if(y1<0){y1=0;} if(x2<0){x2=0;} if(y2<0){y2=0;}
            if(x1 >= im_w){x1=im_w-1;} if(y1 >= im_h){y1=im_h-1;}
            if(x2 >= im_w){x2=im_w-1;} if(y2 >= im_h){y2=im_h-1;}

            if(my_random_int(6999)==0)  //  new random color!
            {
                temp_my_r=my_random_int(255);
                temp_my_g=my_random_int(255);
                temp_my_b=my_random_int(255);           
            }
            var r=temp_my_r;//my_random_int(255);
            var g=temp_my_g;//my_random_int(255); 
            var b=temp_my_b;//my_random_int(255); 

            if(my_random_int(2)==0)  //  random color green and blue
            {
                r=temp_my_r/2<<0;
                g=temp_my_g/2<<0;
                b=temp_my_b/2<<0;           
            }   

            if(my_random_int(14)==0)  //  random grey
            {
                g=r;//my_random_int(255);
                b=r;//my_random_int(255);
            }

            var istep= 1 + my_random_int(16); // do extra step on x or y
            var jstep= 1 + my_random_int(16);

            // draw a rectangle

            var mode2 = my_random_int(3); // choose a random drawing mode   
            if(mode2 == 0) // draw hard r-g-b
            {
                var num=2+my_random_int(61);
                var deel=num+1;
                var bright=0.5+my_random_dub(7);
                for (var j = y1; j < y2; j=j+jstep) // y
                {
                    var p1=j*im_w;
                    for (var i = x1; i <  x2; i=i+istep) // x
                    {
                        var p2=p1+i; // pixel position!                 
                        pix_r[p2]=( ( (num*pix_r[p2])+(r*bright) ) / deel) <<0;
                        pix_g[p2]=( ( (num*pix_g[p2])+(g*bright) ) / deel) <<0;
                        pix_b[p2]=( ( (num*pix_b[p2])+(b*bright) ) / deel) <<0;
                    }   
                }       
            }       
            else if(mode2 == 1) // draw simple blend mode r-g-b
            {
                var num=17+ my_random_int(41);
                var deel=num+1; 
                for (var j = y1; j < y2; j=j+jstep) // y
                {
                    var p1=j*im_w;
                    for (var i = x1; i <  x2; i=i+istep) // x
                    {
                        var p2=p1+i; // pixel position!
                        pix_r[p2]=(( (num*pix_r[p2]) + r)/deel) <<0;
                        pix_g[p2]=(( (num*pix_g[p2]) + g)/deel) <<0;
                        pix_b[p2]=(( (num*pix_b[p2]) + b)/deel) <<0;
                    }   
                }       
            }
            else if(mode2 == 2) ////min - darken - the shade
            {
                x1 = my_random_int(im_w)-1100 + my_random_int_minplus(1400);
                y1 = my_random_int(im_h)-1100 + my_random_int_minplus(1400);

                randomsizex= 1+my_random_int(1100);
                randomsizey= 1+my_random_int(1100);

                x2 = x1+randomsizex;
                y2 = y1+randomsizey;

                // important don't draw outside my screen! - check the position when drawing
                if(x1<0){x1=0;} if(y1<0){y1=0;} if(x2<0){x2=0;} if(y2<0){y2=0;}
                if(x1 >= im_w){x1=im_w;} if(y1 >= im_h){y1=im_h;}
                if(x2 >= im_w){x2=im_w;} if(y2 >= im_h){y2=im_h;}

                for (var j = y1; j < y2; j=j+jstep) // y
                {
                    var p1=j*im_w;
                    for (var i = x1; i <  x2; i=i+istep) // x
                    {
                        var p2=p1+i; // pixel position!
                        pix_r[p2]=pix_r[p2]/3 << 0; 
                        pix_g[p2]=pix_g[p2]/3 << 0; 
                        pix_b[p2]=pix_b[p2]/3 << 0; 
                    }   
                }       
            }// end mode2   

        }   // end draw faster  


        // go next
        anim_loop++;             
        if(anim_loop>51) // draw x times!
        {
            anim_loop=0;
            animation_part= 100; // go to the end
        }
    }


    // ------------------- end of animation, wrap it up-----------------------------
    else if (animation_part==100)
    {       
        anim_loop++;    
        if(anim_loop==100 && do_once==0)
        {
            fxpreview(); // now make the fxhash thumbnail - preview image
            do_once=1; // and do this only at the start 
        }        
        if(anim_loop>200) // wait a bit to go next
        {
            anim_loop=0;
            animation_part= 101; // go next - end
        }

        if(do_once==1)
        {
            animation_part= 101; // directly go to end, no need to wait or fxpreview anymore+
        }

    }
    else if (animation_part==101)
    {       
            animation_part=3;   // reset-continue with the animation; restart at 3 now 
    }


} // end my_animation()


// javascript end
</script>
</head>

<body>

<div class="info_css" id="infoblock">0__.</div>

<canvas class="canvas_css" id="my_canvas">-__-</canvas>

</body>
</html>

10. Ok what's in this one?

  • css and favicon
  • the fxhash snippet - using fxrand now - using fxpreview() - canvas#my_canvas
  • basic rgb-pixel-buffer animation and drawing
  • window management on scaling and resizing
  • a fps counter for testing
  • s-key = saves image
  • spacebar = pause animation and drawing

coding hacks I use a lot

  • I use << 0 It will converts a floating number to int; faster hack? then using like Math.round
  • I use number++ a lot. This is like the same like: number = number + 1

see it working here - https://elout.home.xs4all.nl/drawz/index10e.html



- template 11 -

11. Animation template #2

  • added a palette - 2 random colors now and 1 greyscale
  • I make different darker shades of each palette color; using a palette array
  • stripped some info text in the source
  • 18kb unzipped now - 6kb zipped

see it working on https://elout.home.xs4all.nl/drawz/index11_strip.html

index.html - source for 11 - pixeldrop


!!! Note: These examples use an older fxhash-snippet! Always use the latest one, when you want to test and upload it on fxhash !!!


<!doctype html>
<html>
<head>

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

<title>0__.</title>

<!--favicon 16x16 .png -  created at www.base64-image.de -->
<link rel="icon" type="image/png" sizes="16x16" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH5wIEFwEbuCAI9QAAAItJREFUOMul0jELwkAMhuHXa8TRQXBw082f7x+qW4eu4lh0uaHoGwg0kOUhHN/lbveADz81Ajf+yzwGGXwDVY9FBl9A1TXBNUlg3mSOCS9zvcI5uYJ5G3qsdc9imWsCkgRUl3hJlmjeln7qup9imW9/xq0J9B8ckgWax0nwDlQ9wk7tXfHYy+ARqPoXAl41bXJi4ncAAAAASUVORK5CYII=" />


 <!-- css stylesheet -->
<style type="text/css">
body
{
    background-color: #777; 
    margin: 0;padding: 0;   
    font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; color: #fff;  
}

.info_css
{
    color: #fff; font-size: 14px; background-color: #558; 
    z-index:21;
    position: fixed;    
    top:0px;left:0px;
    border-style:none; border-width:4px;
    margin:0px 0px 0px 0px; padding:2px 2px 2px 2px;
}

.canvas_css
{
    z-index:20;
    position: absolute;

    border-style:solid; border-width:0px;
    margin:0px 0px 0px 0px; padding:0px 0px 0px 0px; 

    /*this next shows my image like pixel-sharp - no pixel blurring by the browser!! - old legacy code from the internet  */
    image-rendering:optimizeSpeed;             /* Legal fallback */ 
    image-rendering:-moz-crisp-edges;          /* Firefox        */ 
    image-rendering:-o-crisp-edges;            /* Opera          */ 
    image-rendering:-webkit-optimize-contrast; /* Safari         */ 
    image-rendering:optimize-contrast;         /* CSS3 Proposed  */ 
    image-rendering:crisp-edges;               /* CSS4 Proposed  */ 
    image-rendering:pixelated;                 /* CSS4 Proposed  * 
    -ms-interpolation-mode:nearest-neighbor;   /* IE8+           */
}
</style>


<script id="fxhash-snippet">
  //---- do not edit the following code (you can indent as you wish)
  let alphabet = "123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ"
  var fxhash = "oo" + Array(49).fill(0).map(_=>alphabet[(Math.random()*alphabet.length)|0]).join('')
  let b58dec = str=>[...str].reduce((p,c)=>p*alphabet.length+alphabet.indexOf(c)|0, 0)
  let fxhashTrunc = fxhash.slice(2)
  let regex = new RegExp(".{" + ((fxhashTrunc.length/4)|0) + "}", 'g')
  let hashes = fxhashTrunc.match(regex).map(h => b58dec(h))
  let sfc32 = (a, b, c, d) => {
    return () => {
      a |= 0; b |= 0; c |= 0; d |= 0
      var t = (a + b | 0) + d | 0
      d = d + 1 | 0
      a = b ^ b >>> 9
      b = c + (c << 3) | 0
      c = c << 21 | c >>> 11
      c = c + t | 0
      return (t >>> 0) / 4294967296
    }
  }
  var fxrand = sfc32(...hashes)
  // true if preview mode active, false otherwise
  // you can append preview=1 to the URL to simulate preview active
  var isFxpreview = new URLSearchParams(window.location.search).get('preview') === "1"
  // call this method to trigger the preview
  function fxpreview() {
    console.log("fxhash: TRIGGER PREVIEW")
  }
  //---- /do not edit the following code
</script>



<script type="text/javascript">  //my javascript start

// using some global variables now! I  use all the time now! and I can tune

// gets current browser window size
var win_w=window.innerWidth;
var win_h=window.innerHeight;


// !!!you can change this when starting something new!!!

var cversion="pixeldrop_"; // title of the page, also name of save file!
document.title =cversion;

var show_fps =        true;//  false;  // put this on wen testing!

//- my image / canvas / animation screen-pixel size now-
var im_w = 800;  // image - canvas width 
var im_h = 800;  // image - canvas height







// globals used for my colorlines 
var myco_num = 0;

var myco_x1 = new Array();
var myco_y1 = new Array();
var myco_x2 = new Array();
var myco_y2 = new Array(); 

var myco_xspeed = new Array();
var myco_yspeed = new Array();

var myco_direction = new Array();

var myco_r1 = new Array();
var myco_g1 = new Array();
var myco_b1 = new Array();

var myco_istep = new Array();
var myco_jstep = new Array();

var myco_fade = new Array();
var myco_mode2 = new Array();



// for my palette
var pallet_num=0;
var pallet_r = new Array();
var pallet_g = new Array();
var pallet_b = new Array();


//-----------------------------------tech--------------------------------------------------------

// rgb pixel buffer  
var pix_r = new Uint8ClampedArray(im_w*im_h);
var pix_g = new Uint8ClampedArray(im_w*im_h);
var pix_b = new Uint8ClampedArray(im_w*im_h);



// globals animation
var animation_part=0;
var anim_loop=0;
var do_once=0;

var my_pause=false; // pause anim
var save_image=false;

//----------- show fps------------
var my_timer=setInterval(function(){timer_fps()},1000);//1000
var data_fps=0;
var counter_fps=0;
var timeCurrent, timeLast = Date.now(); 
var test=""; // for testing  !! gets used in fps-counter!

//----------- window events --- 
//----------legacy code, from the internet (not mine)- tech------------------------------------
// sets the animation at 60 fps
if ( !window.requestAnimationFrame ) 
{
    window.requestAnimationFrame = ( function() {
        return window.webkitRequestAnimationFrame ||
        window.mozRequestAnimationFrame ||
        window.oRequestAnimationFrame ||
        window.msRequestAnimationFrame ||
        function(callback, element ) {window.setTimeout( callback, 1000 / 60 );};
    } )();
}

// wen the page is loaded, jump here! - tech -
window.addEventListener('load',init_mywindow, false ); 

// ------------tech next: keys, mouse and windows handling --------------------
document.addEventListener('keyup', function(event)
{
    // saving is now handled in the draw() function!
    if (event.code == 'KeyS') // s key save in the draw() function!
    {  
        save_image=true;
    }
    if (event.code == 'Space') // spacebar key gets paused in  the draw() function!
    {  
        if(my_pause==false){my_pause=true;}else {my_pause=false;}
    }   

}); 

// init  - tech -
function init_mywindow() 
{
    // hide info text block when showfps is  false
    if(show_fps==false){document.getElementById('infoblock').style.visibility = "hidden";}
    else {document.getElementById('infoblock').style.visibility = "visible";}

    //---------------------------windows check on resize
    win_w=window.innerWidth;
    win_h=window.innerHeight;

    // window resize? do this.  
    window.addEventListener( 'resize', onWindowResize, false );

    // set the size of the canvas
    document.getElementById('my_canvas').style.width = win_w+'px'; 
    document.getElementById('my_canvas').style.height= win_h+'px';  
    document.getElementById('my_canvas').style.left= 0+'px';
    document.getElementById('my_canvas').style.top = 0+'px';

    animate(); // !!!____Init__ and trigger-start the animation
} 

//---window stuff
function onWindowResize() 
{
    win_w=window.innerWidth;
    win_h=window.innerHeight;

    // scale / sets the size of the canvas
    document.getElementById('my_canvas').style.width = win_w+'px'; 
    document.getElementById('my_canvas').style.height= win_h+'px';  
    document.getElementById('my_canvas').style.left= 0+'px';
    document.getElementById('my_canvas').style.top = 0+'px';    
}

// html - set text; and dump the html/text in a div
function set_msg(div, msg){document.getElementById(div).innerHTML = msg;}
function go_msg(div, msg) {document.getElementById(div).innerHTML += msg;} // add text


// legacy code from the internet - quick and dirty fps counter!
function timer_fps() // dirty fps counter 
{
    timeCurrent = Date.now();
    if (show_fps==true)
    {
        var fpsThisFrame = 1000 / (timeCurrent - timeLast);
        if(timeCurrent > timeLast) 
        {
            set_msg('infoblock', 'fps:' + counter_fps+test);
            timeLast = timeCurrent;
            counter_fps=0;
        }
    }   
}


 //--- my random using fxrand()------------

function my_random_int(nummer){return ( ((fxrand()*nummer) << 0) );} //int 

function my_random_dub(nummer){return ( fxrand()*nummer );} //float

function my_random_int_minplus(nummer){return  (  ( (fxrand() * (nummer*2)) - nummer) << 0 );} 
//returns int:  between -num +num
function my_random_dub_minplus(nummer){return  ( (fxrand() * (nummer*2)) - nummer)  ;} 
//returns float:  between -num +num

//-------------------------------------------------------------------------------
function animate() 
{
    requestAnimationFrame( animate );
    if (show_fps==true){counter_fps++;}
    draw();
}

// the animation-drawing set at 60fps frames per second atm
function draw()
{

    if(my_pause==false) // check if the animation is not paused with spacebar
    {
        my_animation();
    }

    //now blit-bomb the data to the screen
    var c = document.getElementById("my_canvas"); // select canvas: 'my_canvas'!
    var ctx=c.getContext("2d"); 
    c.width = im_w; // set my canvas to my im_w and im_h size!
    c.height = im_h;

    // dump the rgb buffer to the screen
    var img1 = ctx.createImageData(im_w, im_h); // browser tech - create a new image: width, height 
    for (var p=0, j = 0; j < im_h*im_w; j++) // draw those pixels on the screen!
    {           
            var grey = Math.floor(Math.random() * 256); // get a random grey color
            img1.data[p++] = pix_r[j];  // red
            img1.data[p++] = pix_g[j];  // green
            img1.data[p++] = pix_b[j];  // blue
            img1.data[p++] = 255;   // alpha channel; not used atm
    }
    ctx.putImageData(img1, 0, 0);   // and draw the data image to the canvas!

    // legacy code and trick from the interwebz 
    if (save_image==true) // save image 
    {
        var imagename= cversion+'_'+fxhash+'_'+'.png'; // I also save the fxhashkey!
        var my_download = document.createElement('a');
        my_download.setAttribute('download', imagename);

        var mcanvas = document.getElementById('my_canvas');
        mcanvas.toBlob(function(blob) {
                        var url = URL.createObjectURL(blob);
                        my_download.setAttribute('href', url);
                        my_download.click();    
                        });                         
        save_image=false;
    }



}
//---------------------------end tech--------------------
// you can use and learn from the tech

// the creative part and fine-tuning, you should do yourself !HF!

// !-------------- --- next the creative part -----------!


function init_my_palette()
{
    var palet_data=[
    200,20,20,   205, 205, 205 // r1 g1 b1 r2 g2 b2
    ];
    // I will use this later to collect my favourite palettes 
    // - put fps on to see the rgb numbers
    pallet_num=0;

    palet_data[0]=my_random_int(255); // now just give 2 random colors
    palet_data[1]=my_random_int(255);
    palet_data[2]=my_random_int(255);

    palet_data[3]=my_random_int(255);
    palet_data[4]=my_random_int(255);
    palet_data[5]=my_random_int(255);

    // outputs text to the fps-info
    test="<hr><hr>----rgb----rgb---<hr>     " + "<b><span style='color:rgb("+palet_data[0]+","+palet_data[1]+","+palet_data[2]+");'>"+palet_data[0]+","+palet_data[1]+","+palet_data[2]+","+"</span>"+"<span style='color:rgb("+palet_data[3]+","+palet_data[4]+","+palet_data[5]+");'>"+palet_data[3]+","+palet_data[4]+","+palet_data[5]+", "+"</span></b><hr><hr>"   
    // you can either use " or ' 

    for (var i = 0; i <  6; i++) // fade to dark   rgb 1
    {
        pallet_r[pallet_num]= palet_data[0] - (i*12);
        pallet_g[pallet_num]= palet_data[1] - (i*12);
        pallet_b[pallet_num]= palet_data[2] - (i*12);
        pallet_num++;
    }
    for (var i = 0; i <  6; i++) // fade to dark   rgb 2
    {
        pallet_r[pallet_num]= palet_data[3] - (i*12);
        pallet_g[pallet_num]= palet_data[4] - (i*12);
        pallet_b[pallet_num]= palet_data[5] - (i*12);
        pallet_num++;
    }
    for (var i = 0; i <  6; i++) // fade to dark   grey 
    {
        pallet_r[pallet_num]= ((palet_data[0]+palet_data[1]+palet_data[2])/2) - (i*12)<<0;
        pallet_g[pallet_num]= pallet_r[pallet_num];
        pallet_b[pallet_num]= pallet_r[pallet_num];
        pallet_num++;
    }

    // little error check for
    for (var i = 0; i <  pallet_num; i++)
    {
        if(pallet_r[i]<0){pallet_r[i]=0;}
        if(pallet_g[i]<0){pallet_g[i]=0;}
        if(pallet_b[i]<0){pallet_b[i]=0;}
    }

}


function my_animation()
{
    // start init animation!
    if (animation_part==0)
    {
        init_my_palette();

        var grey=my_random_int(255); // just a grey screen  now     

        //clear screen! 
        for (var j = 0; j < im_h; j++) // y
        {
            var p1=j*im_w;
            for (var i = 0; i <  im_w; i++) // x
            {
                var p2=p1+i; // pixel position!
                pix_r[p2]=grey;
                pix_g[p2]=grey;
                pix_b[p2]=grey;
            }   
        }   


        animation_part++; //// go next!
    }


    // init --animation anim--
    else if (animation_part==1)
    {
        init_my_palette();
        myco_num = 0;


        var myran= 20 + my_random_int(20); // number of lines?
        for (var i = 0; i < myran; i++)
        {       
            myco_x1[myco_num] = my_random_int(im_w)-120;
            myco_y1[myco_num] = my_random_int(im_h);
            myco_x2[myco_num] = myco_x1[myco_num]+my_random_int(im_w);
            myco_y2[myco_num] = myco_y1[myco_num] + 1 + my_random_int(30);

            if(myco_x1[myco_num]<0){myco_x1[myco_num]=0;} // little out of bounds check
            if(myco_x1[myco_num]>im_w){myco_x1[myco_num]=im_w;}


            myco_xspeed[myco_num] = 0.2 + my_random_dub(2);
            myco_yspeed[myco_num] = 0.1 + my_random_dub(2);

            myco_direction[myco_num] = my_random_int(2);

            var col= my_random_int(pallet_num);         
            myco_r1[myco_num]=pallet_r[col];
            myco_g1[myco_num]=pallet_g[col];
            myco_b1[myco_num]=pallet_b[col];

            myco_istep[myco_num] = 1;//  + my_random_int(7);
            myco_jstep[myco_num] = 1;//  + my_random_int(7);
            if(my_random_int(10)==0)
            {
                myco_istep[myco_num] = 1  + my_random_int(7);
                myco_jstep[myco_num] = 1   + my_random_int(7);

            }
            myco_fade[myco_num]= 1 + my_random_int(31);

            myco_mode2[myco_num]=   my_random_int(2);

            myco_num++; // !next particle-part
        }

        anim_loop=0;
        animation_part++;
    }

    // draw and animate horizontal lines
    else if (animation_part==2)
    {


        // alert(myco_num);
        for (var zi = 0; zi < myco_num; zi++) // number of horizontal block lines
        {

            var x1= myco_x1[zi]<<0;
            var y1= myco_y1[zi]<<0;
            var x2= myco_x2[zi]<<0;
            var y2= myco_y2[zi]<<0;

            if(x1<0){x1=0;} // check out of bounds!
            if(y1<0){y1=0;}
            if(x2<0){x2=0;}
            if(y2<0){y2=0;}

            if(x1>im_w){x1=im_w;}
            if(y1>im_h){y1=im_h;}
            if(x2>im_w){x2=im_w;}
            if(y2>im_h){y2=im_h;}

            var r= myco_r1[zi];
            var g= myco_g1[zi];
            var b= myco_b1[zi];

            if(my_random_int(29999)==0)  //  new random palette!
            {
                init_my_palette(); // reset palette

                for (var zii = 0; zii < myco_num; zii++) // reset all colors
                {
                    var col= my_random_int(pallet_num);         
                    myco_r1[zii]=pallet_r[col];
                    myco_g1[zii]=pallet_g[col];
                    myco_b1[zii]=pallet_b[col];
                }
            }

            var istep= myco_istep[zi] ;// do extra step on x or y
            var jstep= myco_jstep[zi] ;

            var num=myco_fade[zi] ;
            var deel=num+1;

            var mode2=myco_mode2[zi];   
            if(mode2==0)    // blend        
            {
                for (var j = y1; j < y2; j=j+jstep) // y
                {
                    var p1=j*im_w;
                    for (var i = x1; i <  x2; i=i+istep) // x
                    {

                        var p2=p1+i; // pixel position!                 
                        pix_r[p2]= (r + (pix_r[p2]*num))/deel <<0;
                        pix_g[p2]= (g + (pix_g[p2]*num))/deel <<0;
                        pix_b[p2]= (b + (pix_b[p2]*num))/deel <<0;
                    }   
                }       
            }
            else if(mode2==1)   // draw - darken        
            {
                for (var j = y1; j < y2; j=j+jstep) // y
                {
                    var p1=j*im_w;
                    for (var i = x1; i <  x2; i=i+istep) // x
                    {
                        var p2=p1+i; // pixel position!                 
                        pix_r[p2]--;
                        pix_g[p2]--;
                        pix_b[p2]--;
                    }   
                }       
            }

            // new movement
            if(myco_direction[zi]==0)           
            {

                myco_y1[zi]+=myco_yspeed[zi];
                myco_y2[zi]+=myco_yspeed[zi];

                if(myco_y1[zi]>im_h+150) // check out of screen - reset block
                {

                    myco_y1[myco_num] = im_h + my_random_int(2);             
                    myco_y2[myco_num] = myco_y1[myco_num]+1  + my_random_int(31);

                    myco_direction[zi]=1;

                    myco_yspeed[zi] = 0.1 + my_random_dub(1.1);
                    myco_fade[zi]= 1 + my_random_int(31);

                    var col= my_random_int(pallet_num); 
                    myco_r1[zi] = pallet_r[col];
                    myco_g1[zi] = pallet_g[col];
                    myco_b1[zi] = pallet_b[col];

                    myco_istep[zi] = 1;
                    myco_jstep[zi] = 1;
                    if(my_random_int(7)==0)
                    {
                        myco_istep[zi] = 1  + my_random_int(7);
                        myco_jstep[zi] = 1  + my_random_int(7);
                    }       
                    myco_mode2[zi]=   my_random_int(2);                 
                }
            }
            else if(myco_direction[zi]==1)          
            {
                myco_y1[zi]-=myco_yspeed[zi];
                myco_y2[zi]-=myco_yspeed[zi];

                if(myco_y2[zi]< -150) //check out of screen - reset block
                {
                    myco_y1[myco_num] =0 - my_random_int(31);            
                    myco_y2[myco_num] = 0;


                    myco_direction[zi]=0;

                    myco_yspeed[zi] = 0.1 + my_random_dub(1.1);
                    myco_fade[zi]= 1 + my_random_int(31);

                    var col= my_random_int(pallet_num); 
                    myco_r1[zi] = pallet_r[col];
                    myco_g1[zi] = pallet_g[col];
                    myco_b1[zi] = pallet_b[col];

                    myco_istep[zi] = 1;
                    myco_jstep[zi] = 1;

                    if(my_random_int(7)==0)
                    {
                        myco_istep[zi] = 1  + my_random_int(7);
                        myco_jstep[zi] = 1  + my_random_int(7);
                    }   
                    myco_mode2[zi]=   my_random_int(2);     
                }
            }


        }

        anim_loop++;
        if(anim_loop==100 && do_once==0) // do fxpreview after 100 drawings
        {
            fxpreview(); // now make the fxhash thumbnail - preview image
            do_once=1; // and do this only at the start
        }


    }

    // ------------------- end of animation 

}


// javascript end
</script>
</head>

<body>

<div class="info_css" id="infoblock">0__.</div>

<canvas class="canvas_css" id="my_canvas">-__-</canvas>

</body>
</html>

So what's in it?

  • favicon and css
  • the fxhash snippet - using fxrandom and fxpreview -> name: canvas#my_canvas
  • window management - on resize-rescale
  • s - save key
  • spacebar - pause animation
  • fps-counter: show_fps = false; // to hide the fps-counter

a slightly different version you can check here: https://www.fxhash.xyz/generative/24719



comtemplate v.01

!!! Note: These examples use an older fxhash-snippet! Always use the latest one, when you want to test and upload it on fxhash !!!

<!doctype html>
<html>
<head>

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

<title>0__.</title>

<!--a favicon 16x16 .png -  created at www.base64-image.de -->
<link rel="icon" type="image/png" sizes="16x16" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH5wILEDkP6ElmoAAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAAAfUlEQVQ4y52SwQ2AIAxFf12IGRyhiRu5DgkjsIJOohvgxUND+Nj6TxB4r4EWIMlAy0DDR4TBdr+Re0MBq8ok4oFnEvHCTCIReCSRKNxLFvxMUr1+P2FXvd/lEf5EC4fb2MNnKat7kEawe5QZTAVWMoOnAtsqBnv7XZNqZecPngE+Zg1jiGkAAAAASUVORK5CYII=" />


 <!-- css stylesheet -->
<style type="text/css">
body
{
    background-color: #111; margin: 0;padding: 0;   
}

.css_background /*for color fader*/
{
    background-color: rgb(0, 0, 0);
    top: 0px;left: 0px;  width:100%; height:100%;
    z-index:11; border-width:0px; position: fixed;
}

.info_css
{
    color: rgb(220, 220, 220); 
    font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px;
    background-color: rgb(100, 100, 120); z-index:21;
    position: fixed; top:0px;left:0px; border-style:none; border-width:4px;
    margin:0px 0px 0px 0px; padding:2px 2px 2px 2px;
}

.canvas_css
{
    z-index:20; position: absolute;
    border-style:solid; border-width:0px; margin:0px 0px 0px 0px; padding:0px 0px 0px 0px;

    /*- no pixel blurring by the browser!! - old legacy code from the internet */
    image-rendering:optimizeSpeed;             /* Legal fallback */ 
    image-rendering:-moz-crisp-edges;          /* Firefox        */ 
    image-rendering:-o-crisp-edges;            /* Opera          */ 
    image-rendering:-webkit-optimize-contrast; /* Safari         */ 
    image-rendering:optimize-contrast;         /* CSS3 Proposed  */ 
    image-rendering:crisp-edges;               /* CSS4 Proposed  */ 
    image-rendering:pixelated;                 /* CSS4 Proposed  * 
    -ms-interpolation-mode:nearest-neighbor;   /* IE8+           */
}
</style>

<script id="fxhash-snippet">
  //-- do not edit the following code (you can indent as you wish) fxpreview -> canvas#my_canvas
  let alphabet = "123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ"
  var fxhash = "oo" + Array(49).fill(0).map(_=>alphabet[(Math.random()*alphabet.length)|0]).join('')
  let b58dec = str=>[...str].reduce((p,c)=>p*alphabet.length+alphabet.indexOf(c)|0, 0)
  let fxhashTrunc = fxhash.slice(2)
  let regex = new RegExp(".{" + ((fxhashTrunc.length/4)|0) + "}", 'g')
  let hashes = fxhashTrunc.match(regex).map(h => b58dec(h))
  let sfc32 = (a, b, c, d) => {
    return () => {
      a |= 0; b |= 0; c |= 0; d |= 0
      var t = (a + b | 0) + d | 0
      d = d + 1 | 0
      a = b ^ b >>> 9
      b = c + (c << 3) | 0
      c = c << 21 | c >>> 11
      c = c + t | 0
      return (t >>> 0) / 4294967296
    }
  }
  var fxrand = sfc32(...hashes)
  // true if preview mode active, false otherwise
  // you can append preview=1 to the URL to simulate preview active
  var isFxpreview = new URLSearchParams(window.location.search).get('preview') === "1"
  // call this method to trigger the preview
  function fxpreview() {
    console.log("fxhash: TRIGGER PREVIEW")
  }
  //--do not edit the following code ^____^
</script>


<script type="text/javascript">  //my javascript start

// using some global variables now! I  use all the time now! and I can tune
// !!!you can change this when starting something new!!!

var cversion="comtemplate_v01"; // title of the page, also name of save file!

var show_fps = false;  // fps counter and info: put this on-true wen testing! also f-key

var random_palette =   true; // false; // - 3 random palette  colors?
var random_palette_grey =  false; // also add some grey to our palette

// css - use now a crosshair when your mouse is over the image
var my_crosshair="crosshair"; // none / default  / crosshair / 

//- my image / canvas / animation screen-pixel size now-
var im_w = 4096;  // image - canvas width !!!!
var im_h = 4096;  // image - canvas height!!!!

var aspi = my_random_int(3); //random aspect ratio!
if(aspi==0)
{
    im_h=5120;
    im_w=5120;
}
else if(aspi==1)
{
    im_w=4096;
    im_h=6144;
}
else if(aspi==2)
{
    im_w=6144;
    im_h=4096;
}




//-------------------tech: setting up screen--------------------    
// gets current browser window size
var win_w=window.innerWidth;
var win_h=window.innerHeight;

// for my palette
var pallet_num=0;
var pallet_r = new Array();
var pallet_g = new Array();
var pallet_b = new Array();
var palette_name;

//globals for css bacrgroundchange
var css_bgchange =  false;
var css_bgchange_count = 0;
var css_bgchange_rgb = new Array();

// rgb pixel buffer  
var pix_r = new Uint8ClampedArray(im_w*im_h);
var pix_g = new Uint8ClampedArray(im_w*im_h);
var pix_b = new Uint8ClampedArray(im_w*im_h);

var pix_z = new Array(); // depth - z 

// screen rendering!
var show_buff=1;

// screen scaled image
var pix_screen_r = new Uint8ClampedArray(); 
var pix_screen_g = new Uint8ClampedArray(); 
var pix_screen_b = new Uint8ClampedArray();

var pix_screen_w = 0;
var pix_screen_h = 0;
var pix_screen_top=0;
var pix_screen_left=0;

var pix_screen_hor=false;
var pix_screen_ver=false;

var render_complete=false;

// highres to low screen rendering
var x_step = new Array();
var y_step = new Array();
var renderstepper=0;
var yline_pos=0;

var c_timesrendered=0;

 // mouse
 var mx, my; // mouse x and y position

// globals animation
var animation_part=0;
var anim_loop=0;
var do_once=0; // for fxpreview

var global_anim_frame=0;

var my_pause=false; // pause anim
var save_image=false;


// legacy code = technical code-snippets from tutorials found on the internet once 
// do not know the orginal author!
// mostly for the legacy code I kept variable names the same
// incase you find org. author:  apple-pie for both!

//----------- show fps------------some legacy code
var my_timer=setInterval(function(){timer_fps()},1000);//1000
var data_fps=0;
var counter_fps=0;
var timeCurrent, timeLast = Date.now(); 
var test=""; // for testing  !! gets used in fps-counter!


// pre-calculated y-table-  y*image_width  
var ytable_im_w = new Array(im_h);

// a pre-calculated random buffer   
var rnd_bufsize=1000;
var rnd_buf = new Array();
var rnd_pos=0;
var rnd_step=1;

// pre-calculated sin cos buffer
var sincos=4096; // make this bigger; if you want bigger circle data
var my_cos=new Array();  
var my_sin=new Array(); 

//----------- window events --- 

// sets the animation at 60 fps - -legacy code
if ( !window.requestAnimationFrame ) 
{
    window.requestAnimationFrame = ( function() {
        return window.webkitRequestAnimationFrame ||
        window.mozRequestAnimationFrame ||
        window.oRequestAnimationFrame ||
        window.msRequestAnimationFrame ||
        function(callback, element ) {window.setTimeout( callback, 1000 / 60 );};
    } )();
}

// wen the page is loaded, jump here! - tech -
window.addEventListener('load',init_mywindow, false ); 

// page  init here!  - tech -
function init_mywindow() 
{
    document.title =cversion;// set html page title

    document.getElementById('my_canvas').style.cursor=my_crosshair; //crosshair; // none

    // precalculated: y table for (y * image_width) 
    for (var j= 0; j< im_h; j++){  ytable_im_w[j] = (j*im_w);}  

    //sets mouse mx and mouse my to middle of screen
    mx = im_w/2;
    my = im_h/2;

    //for the css background color fader
    for (var j= 0; j<6; j++){   css_bgchange_rgb[j]=0;} 

    // hide info-fps text block when showfps is  false
    if(show_fps==false){document.getElementById('infoblock').style.visibility = "hidden";}
    else {document.getElementById('infoblock').style.visibility = "visible";}

    // ------------tech next: keys, mouse and windows handling --------------------
    document.addEventListener('keyup', function(event)
    {
        // saving is now handled in the draw() function!
        if (event.code == 'KeyS') // s key save 
        {  
            save_image=true;
        }
        if (event.code == 'Space') // spacebar  pause 
        {  
            if(my_pause==false){my_pause=true;}else {my_pause=false;}
        }   
        if (event.code == 'KeyF') // f-key show hide fps
        {  
            if(show_fps==false){show_fps=true;}else {show_fps=false;}
            if(show_fps==false){document.getElementById('infoblock').style.visibility = "hidden";}
            else {document.getElementById('infoblock').style.visibility = "visible";}
        }
        if (event.code == 'KeyP') // random palette? // palette gets set at start animation-drawing
        {  
            if(random_palette==false){random_palette=true;}else {random_palette=false;}
        }
    });     

    //---mouse check and input
    var c=document.getElementById('my_canvas'); 
    c.addEventListener("mousemove", function (evt) 
    {
        if(show_buff==0) // big image with scrollbars
        {
            xOffset=Math.max(document.documentElement.scrollLeft,document.body.scrollLeft);
            yOffset=Math.max(document.documentElement.scrollTop,document.body.scrollTop);
            mx= Math.round((evt.clientX +xOffset ));    
            my= Math.round((evt.clientY +yOffset ));    
        }
        else if(show_buff==1) // screen scaled image
        {
            mx=Math.round( (im_w/pix_screen_w) * (evt.clientX - pix_screen_left) );
            my=Math.round( (im_h/pix_screen_h) * (evt.clientY - pix_screen_top)  );
        }
        else if(show_buff==2) // mouse zoom
        {
            mx= Math.round((evt.clientX));// could use better calculation, now just window mouse position
            my= Math.round((evt.clientY));  
        }
        //test="mouse - mx: "+mx+"   my: "+my;  
    }, false);

    c.addEventListener("mouseup", function (evt) 
    {   
        //show the screen scaled image or zoomed in
        show_buff++;
        if(show_buff>2){show_buff=1;}

        if(show_buff==0) // big image with scrollbars
        {
            xOffset=Math.max(document.documentElement.scrollLeft,document.body.scrollLeft);
            yOffset=Math.max(document.documentElement.scrollTop,document.body.scrollTop);
            mx= Math.round((evt.clientX +xOffset ));    
            my= Math.round((evt.clientY +yOffset ));    
        }
        else if(show_buff==1) // screen scaled image
        {
            mx=Math.round( (im_w/pix_screen_w) * (evt.clientX - pix_screen_left) );
            my=Math.round( (im_h/pix_screen_h) * (evt.clientY - pix_screen_top)  );
        }
        else if(show_buff==2) // mouse zoom
        {
            mx= Math.round((evt.clientX));  
            my= Math.round((evt.clientY));  
        }
    }, false);

    c.addEventListener("mousedown", function (evt) 
    {
        // mouse_pressed=true;
    }, false);

    // touch event .. phone etc finger movement 'mouse position'
    c.addEventListener("touchmove", function (evt)   // 'touchstart' 'touchmove' 'touchend'
    {
        var touch = evt.touches[0] || evt.changedTouches[0];

        var tx = touch.pageX;
        var ty = touch.pageY;

        if(tx>0 && ty>0)  // check if there screen is touched.. if not tx/ty is undefined
        {
            if(show_buff==0) // big image with scrollbars
            {
                xOffset=Math.max(document.documentElement.scrollLeft,document.body.scrollLeft);
                yOffset=Math.max(document.documentElement.scrollTop,document.body.scrollTop);
                mx= Math.round((tx +xOffset )); 
                my= Math.round((ty +yOffset ));
            }
            else if(show_buff==1) // screen scaled image
            {
                mx=Math.round( (im_w/pix_screen_w) * (tx - pix_screen_left) );
                my=Math.round( (im_h/pix_screen_h) * (ty - pix_screen_top)  );
            }
            else if(show_buff==2) // mouse zoom
            {
                mx= Math.round(tx); 
                my= Math.round(ty); 
            }   
            // anim         
        }
        evt.preventDefault();// disable unwanted page scrolling; if you touch/swipe
    },{ passive: false },  false);  // found passive:false fixes a scroll bug now

    //---------------------------windows check on resize
    win_w=window.innerWidth;
    win_h=window.innerHeight;

    // window resize? do this.  
    window.addEventListener( 'resize', onWindowResize, false );

    windows_reset_screenimage();

    animate(); // !!!____Init__ and trigger-start the animation
} 

//---window stuff
function onWindowResize() 
{
    windows_reset_screenimage();    
}

// do when resize window!
function windows_reset_screenimage()
{
    win_w=window.innerWidth;
    win_h=window.innerHeight;

    renderstepper=0; // refresh the render lines
    css_bgchange=true;

    //center screen image based on aspect-ratio 
    var img_ratio=im_w/im_h;
    var win_ratio=win_w/win_h;

    //center screen image based on aspect-ratio 
    var newratio=0; 
    pix_screen_w=win_w;
    newratio= (win_w/im_w);
    pix_screen_h = (im_h * newratio)<<0;            
    if (pix_screen_h > win_h)
    {
        pix_screen_h = win_h;
        newratio=(win_h/im_h);
        pix_screen_top=0;
        pix_screen_w=(im_w * newratio)<<0;
        pix_screen_left=((win_w - pix_screen_w)/2) <<0;
        pix_screen_hor=false;
        pix_screen_ver=true;
    }
    else
    {
        pix_screen_left=0;
        pix_screen_top=((win_h - pix_screen_h)/2) <<0;
        pix_screen_hor=true;
        pix_screen_ver=false;
    }

    pix_screen_r = new Uint8ClampedArray(pix_screen_w*pix_screen_h); 
    pix_screen_g = new Uint8ClampedArray(pix_screen_w*pix_screen_h); 
    pix_screen_b = new Uint8ClampedArray(pix_screen_w*pix_screen_h);
}

// html - set text; and dump the html/text in a div
function set_msg(div, msg){document.getElementById(div).innerHTML = msg;}
function go_msg(div, msg) {document.getElementById(div).innerHTML += msg;} // add text

// legacy code from the internet - quick and dirty fps counter!
function timer_fps() // dirty fps counter 
{
    timeCurrent = Date.now();
    if (show_fps==true)
    {
        var fpsThisFrame = 1000 / (timeCurrent - timeLast);
        if(timeCurrent > timeLast) 
        {
            set_msg('infoblock', 'fps:' + counter_fps+test);
            timeLast = timeCurrent;
            counter_fps=0;
        }
    }   
}

//-------------------------------------------------------------------------------
function animate() 
{
    requestAnimationFrame( animate );
    if (show_fps==true){counter_fps++;}
    draw();
}

// the animation-drawing set at 60fps frames per second atm
function draw()
{
    if(my_pause==false) // check if the animation is not paused with spacebar
    {
        my_animation(); //  draw!       
    }

    // calculate smoothed scaled image; in little steps
    toscreen_render();

    //the backround css color fader
    if(css_bgchange==true){css_background_change(200);} // fade in 200 steps

    if(show_buff==0)
    //render the big image (with scollbars) 
    //not really used at the moment- moved it: at save the big image
    {
        var c=document.getElementById('my_canvas');
        var ctx=c.getContext("2d");
        c.width = im_w; 
        c.height = im_h;
        document.getElementById('my_canvas').style.left='0px';
        document.getElementById('my_canvas').style.top='0px';
        //update image buffer - screen
        var img1 = ctx.createImageData(im_w, im_h); //var
        for (var p=0, j = 0; j < im_h*im_w; j++)
        {               
            img1.data[p++] = pix_r[j];  // r
            img1.data[p++] = pix_g[j];  // g
            img1.data[p++] = pix_b[j];  // b
            img1.data[p++] = 255;       // alpha
        }   
        ctx.putImageData(img1, 0, 0);   
    }

    // -------------render to screen - screen scaled image-------------------
    else if(show_buff==1)
    {
        var c=document.getElementById('my_canvas');
        var ctx=c.getContext("2d");
        c.width = pix_screen_w; 
        c.height = pix_screen_h;

        document.getElementById('my_canvas').style.left=pix_screen_left+'px';
        document.getElementById('my_canvas').style.top=pix_screen_top+'px';

        //update image buffer
        var img1 = ctx.createImageData(pix_screen_w, pix_screen_h); //var
        for (var p=0, j = 0; j < pix_screen_w*pix_screen_h; j++)
        {       
            img1.data[p++] =  pix_screen_r[j]; // red
            img1.data[p++] =  pix_screen_g[j]; // green
            img1.data[p++] =  pix_screen_b[j]; // blue
            img1.data[p++] =  255; // alpha not used atm
        }
        ctx.putImageData(img1, 0, 0);
    }

    //----------------mouse zoomed image!----------------
    else if(show_buff==2)
    {   
        var c=document.getElementById('my_canvas');
        var ctx=c.getContext("2d");
        c.width = win_w; 
        c.height = win_h;
        document.getElementById('my_canvas').style.left='0px';
        document.getElementById('my_canvas').style.top='0px';   

        // -200 make it smaller so you have a noscroll zone around borders
        var tratiox=(im_w-win_w)/(win_w-200);
        var tratioy=(im_h-win_h)/(win_h-200);
        var scrollx=((mx-100)*tratiox)<<0;
        var scrolly=((my-100)*tratioy)<<0;
        if(scrollx<0){scrollx=0;}
        if(scrolly<0){scrolly=0;}
        if(scrollx>im_w-win_w){scrollx=im_w-win_w;}
        if(scrolly>im_h-win_h){scrolly=im_h-win_h;}

        //update image buffer - screen
        var img1 = ctx.createImageData(win_w,win_h);

        if(im_w<win_w || im_h<win_h)// --my drawing-image is smaller then the screensize
        {
            var starw=win_w;
            var starh=win_h;
            var starx=0;
            var stary=0;

            if (im_w<win_w)
            {
                starx=((win_w-im_w)/2)<<0;
                starw=(im_w+starx)<<0;
                scrollx = -starx;
            }
            if (im_h<win_h)
            {
                stary=((win_h-im_h)/2)<<0;
                starh=(im_h+stary)<<0;
                scrolly = -stary;
            }

            for (var p=0,j = stary; j < starh; j++)
            {               
                    for (var i = starx; i < starw; i++)
                    {   
                        var p2=((j+scrolly)*im_w)+(i+scrollx);  //  scrolly = -stary;               
                        var p1=((j*4)*win_w)+((i)*4);                   
                        img1.data[p1]   = pix_r[p2];    // r
                        img1.data[p1+1] = pix_g[p2];    // g
                        img1.data[p1+2] =  pix_b[p2];   // b
                        img1.data[p1+3] = 255;      // alpha not used atm
                    }
            }
            ctx.putImageData(img1, 0, 0);   
        }
        else // --my drawing-image is larger then the screen--
        {
            for (var p=0,j = 0; j < win_h; j++)
            {               
                for (var i = 0; i < win_w; i++)
                {   
                    var p2=((j+scrolly)*im_w)+(i+scrollx);              
                    img1.data[p++] = pix_r[p2];     // r
                    img1.data[p++] = pix_g[p2];     // g
                    img1.data[p++] =  pix_b[p2];    // b
                    img1.data[p++] = 255;           // alpha not used atm
                }
            }       
            ctx.putImageData(img1, 0, 0);   
        }

    }

    // save part some legacy code
    if (save_image==true && render_complete==true) // save image 
    {   
        // first draw the image 'big'
        var c=document.getElementById('my_canvas');
        var ctx=c.getContext("2d");
        c.width = im_w; 
        c.height = im_h;
        document.getElementById('my_canvas').style.left='0px';
        document.getElementById('my_canvas').style.top='0px';           

        var img1 = ctx.createImageData(im_w, im_h); //var
        for (var p=0, j = 0; j < im_h*im_w; j++)
        {               
            img1.data[p++] = pix_r[j];  // r
            img1.data[p++] = pix_g[j];  // g
            img1.data[p++] = pix_b[j];  // b
            img1.data[p++] = 255;       // alpha
        }   
        ctx.putImageData(img1, 0, 0);
        // then save the image!
        var imagename= cversion+'_'+fxhash+'_'+'.png'; // I also save the fxhashkey!
        var my_download = document.createElement('a');
        my_download.setAttribute('download', imagename);            
        var mcanvas = document.getElementById('my_canvas');
        mcanvas.toBlob(function(blob) {
                        var url = URL.createObjectURL(blob);
                        my_download.setAttribute('href', url);
                        my_download.click();    
                        });                         
        save_image=false;
    }

}

//------------- css tricks -----------------------
// change - fade background-color of my css backdrop 
function css_background_change(steps)
{
    var r1,g1,b1;       
    if(css_bgchange_count<steps)
    {
        var cstep1=steps-css_bgchange_count;
        var cstep2=steps-cstep1;
        r1 = (((css_bgchange_rgb[3] *cstep1) +  (css_bgchange_rgb[0]*cstep2))/steps)<<0;
        g1 = (((css_bgchange_rgb[4] *cstep1) +  (css_bgchange_rgb[1]*cstep2))/steps)<<0;
        b1 = (((css_bgchange_rgb[5] *cstep1) +  (css_bgchange_rgb[2]*cstep2))/steps)<<0;        
        css_bgchange_count++;
    }
    else //done fading
    {
        r1= css_bgchange_rgb[0];
        g1= css_bgchange_rgb[1];
        b1= css_bgchange_rgb[2];
        css_bgchange_rgb[3] = r1;    
        css_bgchange_rgb[4] = g1;   
        css_bgchange_rgb[5] = b1;
        css_bgchange=false;
    }

    // make the borders a bit darker!
    var r3 = (r1/7)<<0; var g3 = (g1/7)<<0; var b3 = (b1/7)<<0; 

    var fadedirection='to top';
    if(pix_screen_ver==true){fadedirection='to right';}

    document.getElementById('backgroundblock').style.backgroundImage = 
        'linear-gradient('+fadedirection+', rgb('+r3+','+g3+','+b3+'), rgb('+r1+','+g1+','+b1+'),rgb('+r3+','+g3+','+b3+') )'; 
    //radial-gradient 

}

function toscreen_render()
{   
    if(renderstepper==0)
    {
        var stepr_x =(im_w / pix_screen_w);  
        var stepr_y =(im_h / pix_screen_h);

        //sampling org texture
        x_step = new Array(pix_screen_w*pix_screen_h);
        y_step = new Array(pix_screen_w*pix_screen_h);

        for (var j = 0; j < pix_screen_h; j++)  
        {
            for (var i = 0; i <pix_screen_w; i++) 
            {
                var p1=(j*pix_screen_w)+i;
                var ii =(i*stepr_x)<<0;
                var ii2=((i+1)*stepr_x)<<0;
                var jj=(j*stepr_y)<<0;
                var jj2=((j+1)*stepr_y)<<0;
                x_step[p1] = ii2-ii;
                y_step[p1] = jj2-jj;    
            }
        }
        renderstepper=1;
    }   
    if(renderstepper==1)
    {   
        render_complete=false;  

        var stepr_x =(im_w/pix_screen_w);
        var stepr_y =(im_h/pix_screen_h);

        var newy=yline_pos + 32; // render parts: now in steps of 32 !! you can change this faster-slower!
        var lastlines=false;
        if( newy > pix_screen_h-1)
        {
            newy = pix_screen_h;
            lastlines=true;
        }           
        for (var j = yline_pos; j < newy; j++) // 
        {
            for (var i = 0; i < pix_screen_w; i++) 
            {
                    var p0=(j*pix_screen_w)+i; // step buff                         
                    var ii=(i*stepr_x)<<0;
                    var jj=(j*stepr_y)<<0;
                    var p2=(jj*im_w)+ii;

                    var r1=pix_r[p2];
                    var g1=pix_g[p2];
                    var b1=pix_b[p2];
                    var dc=1;

                    for (var cj = 0; cj < (y_step[p0]); cj++) 
                    {               
                        for (var ci = 0; ci < (x_step[p0]); ci++) 
                        {
                            var tpos=(p2+ci) +ytable_im_w[cj]; 
                            r1 += pix_r[tpos];
                            g1 += pix_g[tpos];
                            b1 += pix_b[tpos];
                            dc++;
                        }
                    }
                    pix_screen_r[p0]= (r1/dc)<<0;
                    pix_screen_g[p0]= (g1/dc)<<0;
                    pix_screen_b[p0]= (b1/dc)<<0;
            }
        } 
        if(lastlines==true) 
        {
            render_complete=true; // for save check!
            yline_pos=0;
            c_timesrendered++;
            //test='pages rendered: '+c_timesrendered
        }
        else{yline_pos=newy;}               
    }
}

// pre-calculated random noise buffer 0-255 int
function math_init_random_0_255(buf)
{   
    for (var i=0; i < rnd_bufsize; i++)
    {
        buf[i]=(fxrand()*256)<<0;
    }
}
// get the random number from my buffer
function math_get_random_0_255()
{
  rnd_pos=rnd_pos+rnd_step;
  if (rnd_pos>=rnd_bufsize)
  {
    rnd_step=((fxrand()*20)<<0)+1; // shuffle  the step and starting position
    rnd_pos=(fxrand()*20)<<0;
  }
  return (rnd_buf[rnd_pos]); // returns a random color between 0 and 255
}

// set up a cos/sin buffer (circles waves etc.)
function set_cossinbuffer(nsize,mcos,msin)
{
    for(var i=0; i<nsize; i++) 
    {
        mcos[i]=( Math.cos ( i*360/nsize * Math.PI / 180)); // note: this can change in time !!
        msin[i]=( Math.sin ( i*360/nsize * Math.PI / 180)); // depending on browser - cpu
    }
}

//clear array-screen with a value
function fill_array(buf,size,value)
{   
    for (var i=0; i < size; i++)
    {
        buf[i]=value;
    }
}

 //--- my random using fxrand()------------
function my_random_int(nummer){return ( ((fxrand()*nummer) << 0) );} //int 

function my_random_dub(nummer){return ( fxrand()*nummer );} //float

function my_random_int_minplus(nummer){return  (  ( (fxrand() * (nummer*2)) - nummer) << 0 );} 
//returns int:  between -num +num
function my_random_dub_minplus(nummer){return  ( (fxrand() * (nummer*2)) - nummer)  ;} 
//returns float:  between -num +num

//---------------------------end tech--------------------

// !-------------- --- next the creative part -----------!

// --- palette.js----
function init_my_palette()
{
    // you can store and collect your favourite palette's here
    var palet_data=[
    "red 'n grey", 220,10,10,   125,10,10,  200,200,200, //
    "green orange cyanish", 124,225,245,   219,127,59,    112,175,145,
    "orange-greenish", 245,97,56,   162,183,157,    72,195,57,

    "yellow cyanish",255, 255, 0,   0,  255,255,   200,200,200 ]; //  // last one without , !   

    var numpalettes=palet_data.length / 10; // how many palettes i got now?

    var randompalette=my_random_int(numpalettes)

    var whatpalette = randompalette * 10; // rgb position


    // - put fps on to see the rgb numbers  
    test="<hr>-rgb-rgb-rgb-<hr> "
    if (random_palette ==  false)
    {
        test+= "palette: " +palet_data[whatpalette+0];
        palette_name=palet_data[whatpalette+0];
    }
    else
    {
        test+= "random palette";
        palette_name="random palette";
    }
    test+="<hr>"

    palet_data[0]=palet_data[whatpalette+1]; // get colors from my palette
    palet_data[1]=palet_data[whatpalette+2];
    palet_data[2]=palet_data[whatpalette+3];

    palet_data[3]=palet_data[whatpalette+4];
    palet_data[4]=palet_data[whatpalette+5];
    palet_data[5]=palet_data[whatpalette+6];

    palet_data[6]=palet_data[whatpalette+7];
    palet_data[7]=palet_data[whatpalette+8];
    palet_data[8]=palet_data[whatpalette+9];

    if(random_palette==true)
    {
        palet_data[0]=55+my_random_int(200); // 3 random rgb colors
        palet_data[1]=55+my_random_int(200);
        palet_data[2]=55+my_random_int(200);

        palet_data[3]=55+my_random_int(200);
        palet_data[4]=55+my_random_int(200);
        palet_data[5]=55+my_random_int(200);

        palet_data[6]=55+my_random_int(200);
        palet_data[7]=55+my_random_int(200);
        palet_data[8]=55+my_random_int(200);    
    }   

    // outputs rgb - text to the fps-info // you can either use " or ' 
    test+="<b><span style='color:rgb("+palet_data[0]+","+palet_data[1]+","+palet_data[2]+");'>"+palet_data[0]+","+palet_data[1]+","+palet_data[2]+","+"</span>&nbsp;&nbsp;&nbsp;<span style='color:rgb("+palet_data[3]+","+palet_data[4]+","+palet_data[5]+");'>"+palet_data[3]+","+palet_data[4]+","+palet_data[5]+", "+"</span>&nbsp;&nbsp;&nbsp;<span style='color:rgb("+palet_data[6]+","+palet_data[7]+","+palet_data[8]+");'>"+palet_data[6]+","+palet_data[7]+","+palet_data[8]+","+"</span></b><hr><hr>";

    // !!!! you can change and fine-tune the shades of your palette here. like number and steps to darker
    var numplay=32; // for every palette rgb, make 32 shades 
    var darkstep=7; // shades to darker step

    pallet_num=0;   // start with 0 colors
    for (var i = 0; i <  numplay; i++) //6 fade to dark   palette rgb 1
    {
        pallet_r[pallet_num]= palet_data[0] - (i*darkstep);
        pallet_g[pallet_num]= palet_data[1] - (i*darkstep);
        pallet_b[pallet_num]= palet_data[2] - (i*darkstep);
        pallet_num++; // add this color to the palette buffer
    }
    for (var i = 0; i <  numplay; i++) // fade to dark    palette rgb 2
    {
        pallet_r[pallet_num]= palet_data[3] - (i*darkstep)<<0;
        pallet_g[pallet_num]= palet_data[4] - (i*darkstep)<<0;
        pallet_b[pallet_num]= palet_data[5] - (i*darkstep)<<0;
        pallet_num++;
    }
    for (var i = 0; i <  numplay; i++) // fade to dark    palette rgb 3
    {
        pallet_r[pallet_num]= palet_data[6] - (i*darkstep)<<0;
        pallet_g[pallet_num]= palet_data[7] - (i*darkstep)<<0;
        pallet_b[pallet_num]= palet_data[8] - (i*darkstep)<<0;
        pallet_num++;
    }
    if(random_palette_grey==true)
    {
        for (var i = 0; i <  numplay; i++) // fade to dark  extra  palette grey 
        {
            pallet_r[pallet_num]= ((palet_data[0]+palet_data[1]+palet_data[2])/3) - (i*7) <<0;
            pallet_g[pallet_num]= pallet_r[pallet_num];
            pallet_b[pallet_num]= pallet_r[pallet_num];
            pallet_num++;
        }   
    }

    // little error check else funky -colors!
    for (var i = 0; i <  pallet_num; i++)
    {
        if(pallet_r[i]<0){pallet_r[i]=0;}
        if(pallet_g[i]<0){pallet_g[i]=0;}
        if(pallet_b[i]<0){pallet_b[i]=0;}
    }

    for (var i = 0; i <  pallet_num; i++)
    {
        test+="<span style='background-color:rgb("+pallet_r[i]+","+pallet_g[i]+","+pallet_b[i]+");>&nbsp;</span>"
    }
    test+="<hr>";

}

//----------------------------  xxx.js 
// !now the drawing starts!
function my_animation()
{
    global_anim_frame++; // global frame counter  

    if (animation_part==0) // start init animation!
    {
        // create a new (random) palette
        init_my_palette();

        //clear screen! 
        var col= my_random_int(pallet_num); 
        var r1=pallet_r[col];
        var g1=pallet_g[col];
        var b1=pallet_b[col];
        fill_array(pix_r,im_w*im_h,r1);
        fill_array(pix_g,im_w*im_h,g1);
        fill_array(pix_b,im_w*im_h,b1);

        //change the css_background - color fader
        css_bgchange=true;  css_bgchange_count=0;
        css_bgchange_rgb[0] = r1; css_bgchange_rgb[1] = g1; css_bgchange_rgb[2] = b1;

        animation_part=1; // and go next!        
    }

    // init -- draw random lines
    else if (animation_part==1)
    {   
        anim_loop=0;
        animation_part++; // go next
    }

    // draw random lines
    else if (animation_part==2)
    {   
        var col= my_random_int(pallet_num); // get a random color from my palette
        var r = pallet_r[col];
        var g = pallet_g[col];
        var b = pallet_b[col];

        var x1= my_random_int(im_w);//get random x and y
        var y1= my_random_int(im_h); 

        for (var i = 0; i < 20000; i++) //draw a line of 20000 points 
        {
            var pos= (y1*im_w)+ x1 ; // pixel position
            if(pos>-1 && pos<im_w*im_h) // never draw outside your pixel buffer!
            {               
                pix_r[pos]= r; // draw pixel
                pix_g[pos]= g;
                pix_b[pos]= b;

                x1+= my_random_int(2); // new random position
                y1+= my_random_int(2);

                if(x1>im_w-1){x1=im_w-x1;} // out of bounds - screen check 
                if(y1>im_h-1){y1=im_h-y1;} // check image width and height
                if(x1<0){x1=im_w+x1;}
                if(y1<0){y1=im_h+y1;}
            }
            else {alert('out of bounds - never draw outside the buffer - memory!');}    
        }   

        anim_loop++;
        if(anim_loop>700) // draw 700 lines then jump to end
        {
            anim_loop=0; // reset loop again
            animation_part=100; // jump to end
        }

    }// end animation_part 2

    // end of animation - do fxpreview - and wait a bit
    else if (animation_part==100)
    {
        // do fxpreview after x drawings
        if( anim_loop > 200 && render_complete==true && do_once==0) 
        {

            if (random_palette ==  false)
            {
                window.$fxhashFeatures = 
                {
                    "palette":  palette_name
                }
            }
            fxpreview(); // now make the fxhash thumbnail - preview image
            do_once=1; // and do this only 1 time!
        }

        anim_loop++;
        if(anim_loop>700) // wait 700 times
        {
            anim_loop=0;
            animation_part=101; // then jump to end
        }
    }
    else if (animation_part==101)
    {
        animation_part=0; // reset; restart with a new image // or just wait here
    }

}   // ------------------- end of animation 

// javascript end
</script>
</head>

<body>

<div id="backgroundblock" class="css_background"></div>

<div class="info_css" id="infoblock">0__.</div>

<canvas class="canvas_css" id="my_canvas">-__-</canvas>

</body>
</html>

See also my recent fxhash release. See it working here: https://elout.home.xs4all.nl/drawz/comtemplate/comtemplate01/

!!! Note: These examples use an older fxhash-snippet! Always use the latest one, when you want to test and upload it on fxhash !!!

I open Developer tools in chrome (F12 on windows); check google how to open it; incase you are on a different platform. There you can save the file as well. I use the Developer tools as well, for bug-checking.

So what's in it? - It's drawing a big image of like 4096x4096 - scale it down to the screen

  • Handles screen and windows scaling
  • (mouse)-click - zoom in/out - mouse look
  • s - save image
  • f - fps on/off shows info
  • space-bar - pause image
  • using and creating palettes
  • fxhash random support - using fxpreview() for the thumbnail

I want to concentrate on this template next, for creative coding; in a new article