<!DOCTYPE html>
<!--
Author: Twily 2022
Website: twily.info
-->
<html>
<head>
<title>Twily Void2</title>
<script type="text/javascript">
var $=function(id) { return document.getElementById(id); };
function rndMinMax(min,max) { // min and max included
return Math.floor(Math.random()*(max-min+1)+min);
}
var void1={};
void1.num=6;
void1.degree=360;
void1.range=[-50,50];
void1.points=Math.round(void1.degree/void1.num)+1;
void1.dig=[];
var void2={};
void2.num=9;
void2.degree=360;
void2.range=[100,250];
void2.points=Math.round(void2.degree/void2.num)+1;
void2.dig=[];
var void3={};
void3.num=12;
void3.degree=360;
void3.range=[300,600];
void3.points=Math.round(void3.degree/void3.num)+1;
void3.dig=[];
var hue=[ // R,G,B,IDX,STep,min,max,mix // only uses step/min/max/mix - rest is rndHue
[127,127,127,0,0.5,0,255,35],
[127,127,127,2,0.3,25,230,75],
[127,127,127,4,0.2,0,200,127]
];
//var hueidx=0;
//var hueidx1=2;
//var hueidx2=4;
//
function dechex(dec=0,hmx=-1) {
var rdec=Math.round(dec);
var lhueMix=hueMix;
if(hmx>-1) {
lhueMix=hue[hmx][7];
}
var mdec=rdec;
if(lhueMix>0) {
mdec=Math.round((rdec+lhueMix)/2);
}
var strhex="00";
strhex="0"+mdec.toString(16);
return strhex.substr(strhex.length-2);
}
var huedeg=0;
var huedeg2=0;
var huedeg3=0;
var rndHue=[ // rndHue[0][0-4][0-2] #1 = circle | #2 = from/to/locked(0|1)/order012/12/2 | #3 in from/to/lock = r/g/b
[[0,0,0],[0,0,0],[0,0,0],"012"],
[[0,0,0],[0,0,0],[0,0,0],"012"],
[[0,0,0],[0,0,0],[0,0,0],"012"]
];
//012=idx
//3=0+1
//4=0+2
//5=1+2
var maxHue=255;
var minHue=0;
var hueMix=35;
var deltaT=0;
var lT=0;
function moveHue() {
var lock;
var co="";
for(var i=0;i<rndHue.length;i++) {
lock=false;
co="";
if(rndHue[i][2][0]==0) { // red unlocked
lock=true;
if(rndHue[i][3].length>0) {
//if(rndHue[i][3].indexOf("0")!=-1) {
lock=false;
co=rndHue[i][3].substr(0,1);
if(co=="0" || co=="3" || co=="4") {
if(rndHue[i][1][0]>rndHue[i][0][0]) {
rndHue[i][0][0]+=hue[i][4];
if(Math.round(rndHue[i][0][0])>=rndHue[i][1][0]) lock=true;
} else if(rndHue[i][1][0]<rndHue[i][0][0]) {
rndHue[i][0][0]-=hue[i][4];
if(Math.round(rndHue[i][0][0])<=rndHue[i][1][0]) lock=true;
} else {
lock=true;
}
}
//}
}
if(lock && co!="") {
rndHue[i][2][0]=1;
if(rndHue[i][3].indexOf("4")!=-1) {
rndHue[i][3]=rndHue[i][3].replace("4","2"); // free next
conlog("co="+co+" on i="+i+" locking red");
} else if(rndHue[i][3].indexOf("3")!=-1) {
rndHue[i][3]=rndHue[i][3].replace("3","1"); // free next
conlog("co="+co+" on i="+i+" locking red");
} else if(rndHue[i][3].indexOf("0")!=-1) {
rndHue[i][3]=rndHue[i][3].replace("0",""); // free next
}
}
}
lock=false;
co="";
if(rndHue[i][2][1]==0) { // green unlocked
lock=true;
if(rndHue[i][3].length>0) {
//if(rndHue[i][3].indexOf("1")!=-1) {
lock=false;
var co=rndHue[i][3].substr(0,1);
if(co=="1" || co=="3" || co=="5") {
if(rndHue[i][1][1]>rndHue[i][0][1]) {
rndHue[i][0][1]+=hue[i][4];
if(Math.round(rndHue[i][0][1])>=rndHue[i][1][1]) lock=true;
} else if(rndHue[i][1][1]<rndHue[i][0][1]) {
rndHue[i][0][1]-=hue[i][4];
if(Math.round(rndHue[i][0][1])<=rndHue[i][1][1]) lock=true;
} else {
lock=true;
}
}
//}
}
if(lock && co!="") {
rndHue[i][2][1]=1;
if(rndHue[i][3].indexOf("5")!=-1) {
rndHue[i][3]=rndHue[i][3].replace("5","2"); // free next
conlog("co="+co+" on i="+i+" locking green");
} else if(rndHue[i][3].indexOf("3")!=-1) {
rndHue[i][3]=rndHue[i][3].replace("3","0"); // free next
conlog("co="+co+" on i="+i+" locking green");
} else if(rndHue[i][3].indexOf("1")!=-1) {
rndHue[i][3]=rndHue[i][3].replace("1",""); // free next
}
}
}
lock=false;
co="";
if(rndHue[i][2][2]==0) { // blue unlocked
lock=true;
if(rndHue[i][3].length>0) {
//if(rndHue[i][3].indexOf("2")!=-1) {
lock=false;
var co=rndHue[i][3].substr(0,1);
if(co=="2" || co=="4" || co=="5") {
if(rndHue[i][1][2]>rndHue[i][0][2]) {
rndHue[i][0][2]+=hue[i][4];
if(Math.round(rndHue[i][0][2])>=rndHue[i][1][2]) lock=true;
} else if(rndHue[i][1][2]<rndHue[i][0][2]) {
rndHue[i][0][2]-=hue[i][4];
if(Math.round(rndHue[i][0][2])<=rndHue[i][1][2]) lock=true;
} else {
lock=true;
}
}
//}
}
if(lock && co!="") {
rndHue[i][2][2]=1;
if(rndHue[i][3].indexOf("5")!=-1) {
rndHue[i][3]=rndHue[i][3].replace("5","1"); // free next
conlog("co="+co+" on i="+i+" locking blue");
} else if(rndHue[i][3].indexOf("4")!=-1) {
rndHue[i][3]=rndHue[i][3].replace("4","0"); // free next
conlog("co="+co+" on i="+i+" locking blue");
} else if(rndHue[i][3].indexOf("2")!=-1) {
rndHue[i][3]=rndHue[i][3].replace("2",""); // free next
}
}
}
if(rndHue[i][2][0]==1 && rndHue[i][2][1]==1 && rndHue[i][2][2]==1) {
rndHue[i][0][0]=rndHue[i][1][0];
rndHue[i][0][1]=rndHue[i][1][1];
rndHue[i][0][2]=rndHue[i][1][2];
if(i==0) {
var rndBlack=rndMinMax(0,1);
if(rndBlack==1) {
//var lowest=rndHue[i][0][0];
//if(rndHue[i][0][1]<lowest) lowest=rndHue[i][0][1];
//if(rndHue[i][0][2]<lowest) lowest=rndHue[i][0][2];
//rndHue[i][1][0]=rndHue[i][0][0]-lowest;
//rndHue[i][1][1]=rndHue[i][0][1]-lowest;
//rndHue[i][1][2]=rndHue[i][0][2]-lowest;
rndHue[i][1][0]=0;
rndHue[i][1][1]=0;
rndHue[i][1][2]=0;
} else {
rndHue[i][1][0]=rndMinMax(hue[i][5],hue[i][6]);
rndHue[i][1][1]=rndMinMax(hue[i][5],hue[i][6]);
rndHue[i][1][2]=rndMinMax(hue[i][5],hue[i][6]);
}
} else {
rndHue[i][1][0]=rndMinMax(hue[i][5],hue[i][6]);
rndHue[i][1][1]=rndMinMax(hue[i][5],hue[i][6]);
rndHue[i][1][2]=rndMinMax(hue[i][5],hue[i][6]);
}
var order="";
var comb=[
"012",
"021",
"102",
"120",
"201",
"210",
"32",
"41",
"50",
"05",
"14",
"23"
];
while(order.length<2) {
//var num=rndMinMax(0,2);
//if(order.indexOf(num)==-1) {
// order+=num.toString();
//}
order=comb[rndMinMax(0,comb.length-1)];
}
rndHue[i][3]=order;
rndHue[i][2][0]=0;
rndHue[i][2][1]=0;
rndHue[i][2][2]=0;
}
//switch(hue[i][3]) {
// case 0:
// hue[i][1]+=hue[i][4];
// if(hue[i][1]>=maxHue) {
// hue[i][1]=maxHue;
// hue[i][3]=1;
// }
// break;
// case 1:
// hue[i][0]-=hue[i][4];
// if(hue[i][0]<=minHue) {
// hue[i][0]=minHue;
// hue[i][3]=2;
// }
// break;
// case 2:
// hue[i][2]+=hue[i][4];
// if(hue[i][2]>=maxHue) {
// hue[i][2]=maxHue;
// hue[i][3]=3;
// }
// break;
// case 3:
// hue[i][1]-=hue[i][4];
// if(hue[i][1]<=minHue) {
// hue[i][1]=minHue;
// hue[i][3]=4;
// }
// break;
// case 4:
// hue[i][0]+=hue[i][4];
// if(hue[i][0]>=maxHue) {
// hue[i][0]=maxHue;
// hue[i][3]=5;
// }
// break;
// case 5:
// hue[i][2]-=hue[i][4];
// if(hue[i][2]<=minHue) {
// hue[i][2]=minHue;
// hue[i][3]=0;
// }
// break;
// default:
//}
}
//conlog("hue=[");
//conlog(" ["+hue[0][0]+","+hue[0][1]+","+hue[0][2]+","+hue[0][3]+"],");
//conlog(" ["+hue[1][0]+","+hue[1][1]+","+hue[1][2]+","+hue[1][3]+"],");
//conlog(" ["+hue[2][0]+","+hue[2][1]+","+hue[2][2]+","+hue[2][3]+"],");
//conlog("];");
//huedeg+=10/fps;
//
//if(huedeg>360) huedeg=0;
//if(huedeg<0) huedeg=360;
//ctx1.filter="hue-rotate("+huedeg+"deg)";
//huedeg2+=15/fps;
//
//if(huedeg2>360) huedeg2=0;
//if(huedeg2<0) huedeg2=360;
//ctx2.filter="hue-rotate("+huedeg2+"deg)";
//
//huedeg3+=20/fps;
//
//if(huedeg3>360) huedeg3=0;
//if(huedeg3<0) huedeg3=360;
//ctx3.filter="hue-rotate("+huedeg3+"deg)";
//var mode1="multiply"; // multiply overlay color hue color-dodge
var mode1="color-dodge"; // multiply overlay color hue color-dodge
var mode2="destination-in"; // fade out blacks?
//
//ctx1.clearRect(0,0,$('cvoid1').width,$('cvoid1').height);
//var hexcol1="#"+dechex(hue[0][0])+dechex(hue[0][1])+dechex(hue[0][2]);
var hexcol1="#"+dechex(rndHue[0][0][0],0)+dechex(rndHue[0][0][1],0)+dechex(rndHue[0][0][2],0);
//conlog("hexcol1="+hexcol1);
ctx1.globalAlpha=1.0;
ctx1.drawImage(voidimg,0,0);
ctx1.fillStyle=hexcol1;
ctx1.globalCompositeOperation=mode1;
//conlog('mode1 = '+mode1);
ctx1.fillRect(0,0,$('cvoid1').width,$('cvoid1').height);
//ctx1.globalAlpha=0.5;
ctx1.globalCompositeOperation=mode2;
ctx1.drawImage(voidimg,0,0);
//ctx2.clearRect(0,0,$('cvoid2').width,$('cvoid2').height);
//var hexcol2="#"+dechex(hue[1][0])+dechex(hue[1][1])+dechex(hue[1][2]);
var hexcol2="#"+dechex(rndHue[1][0][0],1)+dechex(rndHue[1][0][1],1)+dechex(rndHue[1][0][2],1);
ctx2.globalAlpha=1.0;
ctx2.drawImage(voidimg,0,0);
ctx2.fillStyle=hexcol2;
ctx2.globalCompositeOperation="multiply";
ctx2.fillRect(0,0,$('cvoid2').width,$('cvoid2').height);
//ctx2.globalAlpha=0.6;
ctx2.globalCompositeOperation=mode2;
ctx2.drawImage(voidimg,0,0);
//ctx3.clearRect(0,0,$('cvoid3').width,$('cvoid3').height);
//var hexcol3="#"+dechex(hue[2][0])+dechex(hue[2][1])+dechex(hue[2][2]);
var hexcol3="#"+dechex(rndHue[2][0][0],2)+dechex(rndHue[2][0][1],2)+dechex(rndHue[2][0][2],2);
ctx3.globalAlpha=1.0;
ctx3.drawImage(voidimg,0,0);
ctx3.fillStyle=hexcol3;
ctx3.globalCompositeOperation="multiply";
ctx3.fillRect(0,0,$('cvoid3').width,$('cvoid3').height);
//ctx3.globalAlpha=0.7;
ctx3.globalCompositeOperation=mode2;
ctx3.drawImage(voidimg,0,0);
var dT=new Date().getTime();
deltaT+=dT-lT;
if(deltaT>=1000) {
//conlog('print'+deltaT);
//condir(rndHue);
//
if(typeof conlog!=="undefined") {
conlog("rndHue=[");
conlog(" [["+Math.round(rndHue[0][0][0])+","+Math.round(rndHue[0][0][1])+","+Math.round(rndHue[0][0][2])+"],["+rndHue[0][1][0]+","+rndHue[0][1][1]+","+rndHue[0][1][2]+"],["+rndHue[0][2][0]+","+rndHue[0][2][1]+","+rndHue[0][2][2]+"],\""+rndHue[0][3]+"\"],");
conlog(" [["+Math.round(rndHue[1][0][0])+","+Math.round(rndHue[1][0][1])+","+Math.round(rndHue[1][0][2])+"],["+rndHue[1][1][0]+","+rndHue[1][1][1]+","+rndHue[1][1][2]+"],["+rndHue[1][2][0]+","+rndHue[1][2][1]+","+rndHue[1][2][2]+"],\""+rndHue[1][3]+"\"],");
conlog(" [["+Math.round(rndHue[2][0][0])+","+Math.round(rndHue[2][0][1])+","+Math.round(rndHue[2][0][2])+"],["+rndHue[2][1][0]+","+rndHue[2][1][1]+","+rndHue[2][1][2]+"],["+rndHue[2][2][0]+","+rndHue[2][2][1]+","+rndHue[2][2][2]+"],\""+rndHue[2][3]+"\"]");
conlog("];");
conlog("hexcol1 = "+hexcol1);
conlog("hexcol2 = "+hexcol2);
conlog("hexcol3 = "+hexcol3);
} //
deltaT=0;
}
lT=dT;
}
let voidimg;
var radian=(Math.PI/180);
function digits() { // place the digits in position
var mylog=[],x,y,cangle,orbit=((void1.range[0]+void1.range[1])/2);
for(var i=0;i<void1.num;i++) {
var rnd=rndMinMax(0,1);
void1.dig[i]={orbit: orbit, dir: rnd};
}
orbit=((void2.range[0]+void2.range[1])/2);
for(var i=0;i<void2.num;i++) {
var rnd=rndMinMax(0,1);
void2.dig[i]={orbit: orbit, dir: rnd};
}
orbit=((void3.range[0]+void3.range[1])/2);
for(var i=0;i<void3.num;i++) {
var rnd=rndMinMax(0,1);
void3.dig[i]={orbit: orbit, dir: rnd};
}
}
var lastupdate=0;
var norb=false;
function clockswap() { // every 5 second switch clock2 num between 61 and 62 and recreate missing
//
}
function clearCanvas(ctx) {
ctx.clearRect(0,0,ww,hh);
}
function drawImage(ctx, image, x, y, scale, rotation){
var ssWD=0;
var ssHD=0;
var ssW=ww*scale;
var ssH=hh*scale;
ssWD=Math.round((ssW-ww)/2);
ssHD=Math.round((ssH-hh)/2);
ctx.setTransform(scale, 0, 0, scale, x-ssWD, y-ssHD); // sets scale and origin
ctx.translate(ww/2,hh/2);
ctx.rotate(rotation);
//ctx.drawImage(image, -image.width / 2, -image.height / 2);
ctx.drawImage(image, 0, 0);
}
//function drawImageCenter(ctx, image, x, y, cx, cy, scale, rotation){
// ctx.setTransform(scale, 0, 0, scale, x, y); // sets scale and origin
// //ctx.translate(ww/2,hh/2);
// ctx.rotate(rotation);
// ctx.drawImage(image, -cx, -cy);
//}
function resetRotation(ctx) {
ctx.setTransform(1,0,0,1,0,0); // faster than save/restore?
//ctx.translate(-(ww/2),-(hh/2));
ctx.translate(0,0);
}
var fps=60;
var spina=90;
var spinb=90;
var spinc=90;
var spindir=0;
function spin() { // loop and spin the digits around CCW/CW
moveHue();
if(spina>360) spina=0;
if(spina<0) spina=360;
if(spinb>360) spinb=0;
if(spinb<0) spinb=360;
if(spinc>360) spinc=0;
if(spinc<0) spinc=360;
spina-=movA;
spinb-=movB;
spinc-=movC;
var ctime=new Date().getTime();
if(ctime-lastupdate>5000) {
clockswap();
lastupdate=ctime;
}
var mylog=[],x,y,orbit,cangle;
clearCanvas(ctxm);
ctxm.fillStyle="#000000";
ctxm.fillRect(0,0,$('cvoidm').width,$('cvoidm').height);
for(var i=0;i<void1.num;i++) {
if(void1.dig[i]) {
cangle=(i*void1.points-spina);
while(cangle>360) cangle-=360;
while(cangle<0) cangle+=360;
orbit=parseFloat(void1.dig[i].orbit);
var lastodir=void1.dig[i].dir;
if(lastodir=="1") {
orbit+=10/fps;
} else {
orbit-=15/fps;
}
if(orbit>=void1.range[1]) {
orbit=void1.range[1];
lastodir="0";
}
if(orbit<=void1.range[0]) {
orbit=void1.range[0];
lastodir="1";
}
void1.dig[i].orbit=orbit;
void1.dig[i].dir=lastodir;
x=Math.round(Math.cos(cangle*radian)*orbit);
y=Math.round(Math.sin(cangle*radian)*orbit);
var rad45=cangle-70;
if(rad45<0) {
rad45=360-Math.abs(rad45);
}
drawImage(ctxm, $('cvoid1'), x, y, ss, rad45*Math.PI/180);
resetRotation(ctxm);
}
}
for(var i=0;i<void2.num;i++) {
if(void2.dig[i]) {
cangle=(i*void2.points-spinb);
while(cangle>360) cangle-=360;
while(cangle<0) cangle+=360;
orbit=parseFloat(void2.dig[i].orbit);
var lastodir=void2.dig[i].dir;
if(lastodir=="1") {
orbit+=30/fps;
} else {
orbit-=20/fps;
}
if(orbit>=void2.range[1]) {
orbit=void2.range[1];
lastodir="0";
}
if(orbit<=void2.range[0]) {
orbit=void2.range[0];
lastodir="1";
}
void2.dig[i].orbit=orbit;
void2.dig[i].dir=lastodir;
x=Math.round(Math.cos(cangle*radian)*orbit);
y=Math.round(Math.sin(cangle*radian)*orbit);
var rad45=cangle-70;
if(rad45<0) {
rad45=360-Math.abs(rad45);
}
var ss2=ss*20/100;
drawImage(ctxm, $('cvoid2'), x, y, ss+ss2, rad45*Math.PI/180);
resetRotation(ctxm);
}
}
for(var i=0;i<void3.num;i++) {
if(void3.dig[i]) {
cangle=(i*void3.points-spinc);
while(cangle>360) cangle-=360;
while(cangle<0) cangle+=360;
orbit=parseFloat(void3.dig[i].orbit);
var lastodir=void3.dig[i].dir;
if(lastodir=="1") {
orbit+=50/fps;
} else {
orbit-=40/fps;
}
if(orbit>=void3.range[1]) {
orbit=void3.range[1];
lastodir="0";
}
if(orbit<=void3.range[0]) {
orbit=void3.range[0];
lastodir="1";
}
void3.dig[i].orbit=orbit;
void3.dig[i].dir=lastodir;
x=Math.round(Math.cos(cangle*radian)*orbit);
y=Math.round(Math.sin(cangle*radian)*orbit);
var rad45=cangle-70;
if(rad45<0) {
rad45=360-Math.abs(rad45);
}
var ss3=ss*40/100;
drawImage(ctxm, $('cvoid3'), x, y, ss+ss3, rad45*Math.PI/180);
resetRotation(ctxm);
}
}
}
var hh,ww,ss=1.0;
function windowRez() {
ww=window.innerWidth;
hh=window.innerHeight;
//ss=1.1;
ss=(((ww+hh)/2)/1500);
// 1920+1080=3000/2=1500 = 1.0
// 1280+720=2000/2=1000 = 0.6666..
ss=Math.min(ww / voidimg.width , hh / voidimg.height);
//alert(ss);
$('cvoidm').width=ww;
$('cvoidm').height=hh;
$('cvoidm').style.width=ww+"px";
$('cvoidm').style.height=hh+"px";
digits();
}
var wrT;
window.onresize=function() {
clearTimeout(wrT);
wrT=setTimeout(function() { windowRez(); },100);
}
var movA=21/fps;
var movB=33/fps;
var movC=38/fps;
var ctx1,ctx2,ctx3;
var ctxm;
var lastupdate=0;
function initvoid() {
voidimg = new Image();
voidimg.onload=function() {
$('cvoid1').width=voidimg.width;
$('cvoid1').height=voidimg.height;
$('cvoid2').width=voidimg.width;
$('cvoid2').height=voidimg.height;
$('cvoid3').width=voidimg.width;
$('cvoid3').height=voidimg.height;
$('cvoid1').style.width=voidimg.width+"px";
$('cvoid1').style.height=voidimg.height+"px";
$('cvoid2').style.width=voidimg.width+"px";
$('cvoid2').style.height=voidimg.height+"px";
$('cvoid3').style.width=voidimg.width+"px";
$('cvoid3').style.height=voidimg.height+"px";
}
voidimg.src="./void.png";
ctxm=$('cvoidm').getContext("2d");
ctx1=$('cvoid1').getContext("2d");
ctx2=$('cvoid2').getContext("2d");
ctx3=$('cvoid3').getContext("2d");
document.body.style.overflow="hidden";
//ctxm.globalAlpha=0.5;
//ctxm.globalCompositeOperation="multiply";
wrT=setTimeout(function() { windowRez(); },500);
var iS,spintoggle=false;
if(!spintoggle) {
lastupdate=new Date().getTime();
iS=setInterval(function() { spin(); },1000/fps);
if(spindir==-1 || spindir==0) spindir=1;
else if(spindir==1) spindir=-1;
} else {
clearInterval(iS);
}
spintoggle=!spintoggle;
}
</script>
</head>
<body>
<div id="voidbg" style="width: 100%; height: 100%; position: fixed; top:0; left:0; background: #000; z-index:9;"></div>
<canvas id="cvoidm" style="width: 100%; height: 100%; position: fixed; top:0; left:0; background: transparent; z-index:10;"></canvas>
<canvas id="cvoid1" style="width: 100%; height: 100%; position: fixed; top:0; left:0; background: transparent; z-index:-1; visibility: hidden;"></canvas>
<canvas id="cvoid2" style="width: 100%; height: 100%; position: fixed; top:0; left:0; background: transparent; z-index:-1; visibility: hidden;"></canvas>
<canvas id="cvoid3" style="width: 100%; height: 100%; position: fixed; top:0; left:0; background: transparent; z-index:-1; visibility: hidden;;"></canvas>
<!--<div style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: transparent; z-index: 13;"></div>-->
<script>
initvoid();
</script>
</body>
</html>
Top