Playing with order influence between CSS::transform::rotation/translate/scale
- D3.js (v3.5.5)
- blockbuilder.org
- dat.gui (v0.5.1)
| license: mit |
Playing with order influence between CSS::transform::rotation/translate/scale
| <!DOCTYPE html> | |
| <head> | |
| <meta charset="utf-8"> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.5.1/dat.gui.min.js"></script> | |
| <style> | |
| body { | |
| margin:0; | |
| position:fixed; | |
| top:0; | |
| right:0; | |
| bottom:0; | |
| left:0; | |
| background-color: black; | |
| } | |
| svg { | |
| width:100%; | |
| height: 100%; | |
| } | |
| .iris .spark .ray { | |
| fill: none; | |
| stroke: aqua; | |
| // stroke-width: 10; | |
| // stroke-opacity: 0.05; | |
| stroke-linejoin: round; | |
| stroke-linecap: round; | |
| } | |
| .eyelid { | |
| // stroke: white; | |
| stroke-width: 10; | |
| stroke-opacity: 0.5; | |
| } | |
| .terminator { | |
| fill: darkred; | |
| stroke: darkred; | |
| stroke-width: 4; | |
| stroke-opacity: 0.5; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <script> | |
| var svgWidth = 960, | |
| svgHeight = 500; | |
| var requester = {USER: 0, RANDOM: 1}; | |
| var controlsSettings = { | |
| pupil: { | |
| random: function() { updatePupil(requester.USER); }, | |
| round: function() { roundPupil(requester.USER); }, | |
| alien: function() { alienPupil(requester.USER); }, | |
| cardioide: function() { cardioidePupil(requester.USER); }, | |
| radioactive: function() { radioactive(requester.USER); } | |
| }, | |
| blinkEyelids: function() { blinkEyelids(requester.USER); }, | |
| terminator: function() { terminator(requester.USER); } | |
| }; | |
| var controls = new dat.GUI({width: 200}); | |
| controls.close(); | |
| var pupilControls = controls.addFolder("Pupil"); | |
| pupilControls.open(); | |
| pupilControls.add(controlsSettings.pupil, "random"); | |
| pupilControls.add(controlsSettings.pupil, "round"); | |
| pupilControls.add(controlsSettings.pupil, "alien"); | |
| pupilControls.add(controlsSettings.pupil, "cardioide"); | |
| pupilControls.add(controlsSettings.pupil, "radioactive"); | |
| controls.add(controlsSettings, "blinkEyelids"); | |
| controls.add(controlsSettings, "terminator"); | |
| var minIrisRadius = svgHeight/8, | |
| maxIrisRadius = 4*minIrisRadius; | |
| var raysPerSpark = 3, | |
| rayNoise = 20; | |
| var sparkCount = 360/raysPerSpark, | |
| sparkRadianIncrement = 2*Math.PI/sparkCount, | |
| sparkDegreeIncrement = 360/sparkCount | |
| rayDegreeIncrement = sparkDegreeIncrement/raysPerSpark; | |
| var pupilVelocity = 2000, | |
| pupilAverageUpdateDelay = 2000; | |
| var blinkVelocity = 750, | |
| averageBlinkDelay = 10000; // 10s | |
| var terminatorVelocity = 1000, | |
| terminatorAverageDelay = 40000; // 40s | |
| var radioactiveVelocity = 1000, | |
| radioactiveAverageDelay = 40000; // 40s | |
| var irisScale = d3.scale.linear() | |
| .domain([1,4]) | |
| .range([minIrisRadius, 4*minIrisRadius]); | |
| var sparks = []; | |
| var sparkNum, rayNum, rays, rayWidth; | |
| for (sparkNum=0; sparkNum<sparkCount; sparkNum++) { | |
| rays = []; | |
| for (rayNum=0; rayNum<raysPerSpark; rayNum++) { | |
| rayWidth = 2+8*Math.random(); | |
| rays.push({ | |
| width: rayWidth, | |
| opacity: 0.3/rayWidth, | |
| path: [[irisScale(1), 0], | |
| [irisScale(1+Math.random()), 0.5*rayNoise*(Math.random()-0.5)], | |
| [irisScale(2-Math.random()/2), 0.5*rayNoise*(Math.random()-0.5)], | |
| [irisScale(2+Math.random()/2), 0.5*rayNoise*(Math.random()-0.5)], | |
| [irisScale(3-Math.random()/2), rayNoise*(Math.random()-0.5)], | |
| [irisScale(3+Math.random()/8), rayNoise*(Math.random()-0.5)] | |
| ] | |
| }); | |
| }; | |
| sparks.push(rays); | |
| }; | |
| var upperEyelid = {opened: [ | |
| [-svgWidth/2, -svgHeight/2], | |
| [-svgWidth/2, 0], | |
| [-minIrisRadius, -svgHeight/2], | |
| [minIrisRadius, -svgHeight/2], | |
| [svgWidth/2, 0], | |
| [svgWidth/2, -svgHeight/2] | |
| ], | |
| closed: [ | |
| [-svgWidth/2, -svgHeight/2], | |
| [-svgWidth/2, 0], | |
| [-minIrisRadius, 0], | |
| [minIrisRadius, 0], | |
| [svgWidth/2, 0], | |
| [svgWidth/2, -svgHeight/2] | |
| ]} | |
| var lowerEyelid = {opened: [ | |
| [-svgWidth/2, svgHeight/2], | |
| [-svgWidth/2, 0], | |
| [-minIrisRadius, svgHeight/2], | |
| [minIrisRadius, svgHeight/2], | |
| [svgWidth/2, 0], | |
| [svgWidth/2, svgHeight/2] | |
| ], | |
| closed: [ | |
| [-svgWidth/2, svgHeight/2], | |
| [-svgWidth/2, 0], | |
| [-minIrisRadius, 0], | |
| [minIrisRadius, 0], | |
| [svgWidth/2, 0], | |
| [svgWidth/2, svgHeight/2] | |
| ]}; | |
| var rayLine = d3.svg.line().interpolate("cardinal"); | |
| var eyelidLine = d3.svg.line().interpolate("basis"); | |
| var svg = d3.select("body").append("svg").append("g").attr("transform", "translate("+[svgWidth/2, svgHeight/2]+")"); | |
| var drawnIris = svg.append("g") | |
| .classed("iris", true); | |
| var drawnSparks = drawnIris.selectAll(".spark") | |
| .data(sparks); | |
| drawnSparks.enter() | |
| .append("g") | |
| .classed("spark", true) | |
| .attr("transform", function(d, i) { return "rotate("+((i-0.5)*sparkDegreeIncrement)+")"; }); | |
| drawnSparks.selectAll(".ray") | |
| .data(function(d) { return d; }) | |
| .enter() | |
| .append("path") | |
| .classed("ray", true) | |
| .attr({ | |
| d: function(d, i) { return rayLine(d.path); }, | |
| transform: function(d, i) { return "rotate("+(i*rayDegreeIncrement)+")"; } | |
| }) | |
| .style({ | |
| 'stroke-opacity': function(d, i){ return d.opacity; }, | |
| 'stroke-width': function(d, i){ return d.width} | |
| }); | |
| var drawnEyelids = svg.append("g").classed("eyelids", true); | |
| drawnEyelids = drawnEyelids.selectAll(".eyelid") | |
| .data([upperEyelid, lowerEyelid]); | |
| drawnEyelids.enter() | |
| .append("path") | |
| .classed("eyelid", true) | |
| .attr({ | |
| id: function(d,i) { return (i===1)? "upper-eyelid" : "lower-eyelid"; }, | |
| d: function (d) { return eyelidLine(d.opened); } | |
| }); | |
| var drawnTerminator = svg.insert("circle", ".eyelids") | |
| .classed("terminator", true) | |
| .attr("r", 0); | |
| updatePupil(requester.RANDOM); | |
| blinkEyelids(requester.RANDOM); | |
| terminator(requester.RANDOM); | |
| function updatePupil (currentRequester) { | |
| var chooser = Math.random()*100; | |
| if (chooser < 70) { roundPupil(currentRequester); } | |
| else if (chooser < 80) { alienPupil(currentRequester); } | |
| else if (chooser < 90) { cardioidePupil(currentRequester); } | |
| else { radioactive(requester.RANDOM); } | |
| } | |
| function roundPupil (currentRequester) { | |
| var updateDelay = pupilAverageUpdateDelay*(0.5+Math.random()) // 1s->3s | |
| var pupilRadius = minIrisRadius*(1+(1.5*Math.random()-0.2)); // in [0.8, 2.3] | |
| var sparkTranslation = pupilRadius-minIrisRadius; | |
| var sparkScalling = maxIrisRadius/(maxIrisRadius+sparkTranslation); | |
| if (currentRequester === requester.USER) { updateDelay=0; }; | |
| drawnSparks.transition() | |
| .delay(updateDelay) | |
| .duration(pupilVelocity*(0.5+Math.random())) | |
| .attr("transform", function(d,i) { return "rotate("+((i-0.5)*sparkDegreeIncrement)+"),translate("+sparkTranslation+"),scale("+sparkScalling+")";}) | |
| .each("end", function(d,i) { | |
| if (i===0) { updatePupil(requester.RANDOM); } | |
| }); | |
| }; | |
| function alienPupil (currentRequester) { | |
| var updateDelay = pupilAverageUpdateDelay*(0.5+Math.random()) // 2s->3s | |
| var horizontalPupilRadius = minIrisRadius*(1+(1.5*Math.random()-0.2)); // in [0.8, 2.3] | |
| var verticalPupilRadius = minIrisRadius*(1+(1.5*Math.random()-0.2)); // in [0.8, 2.3] | |
| var horizontalPupilSymetry = 1; | |
| var verticalPupilSymetry = 1; | |
| while ( horizontalPupilSymetry===1 && | |
| verticalPupilSymetry===1) { | |
| horizontalPupilSymetry = Math.round(2*Math.random())+1; | |
| verticalPupilSymetry = Math.round(2*Math.random())+1; | |
| } | |
| if (currentRequester === requester.USER) { updateDelay=0; }; | |
| drawnSparks.transition() | |
| .delay(updateDelay) | |
| .duration(pupilVelocity*(0.5+Math.random())) | |
| .attr("transform", function(d,i) { | |
| var radian = (i-0.5)*sparkRadianIncrement; | |
| var sparkTranslation = Math.sqrt(Math.pow(Math.cos(horizontalPupilSymetry*radian)*horizontalPupilRadius,2) + Math.pow(Math.sin(verticalPupilSymetry*radian)*verticalPupilRadius,2))-minIrisRadius; | |
| var sparkScalling = maxIrisRadius/(maxIrisRadius+sparkTranslation); | |
| return "rotate("+((i-0.5)*sparkDegreeIncrement)+"),translate("+sparkTranslation+"),scale("+sparkScalling+")";}) | |
| .each("end", function(d,i) { | |
| if (i===0) { updatePupil(requester.RANDOM); } | |
| }); | |
| }; | |
| function cardioidePupil (currentRequester) { | |
| //cf. http://mathworld.wolfram.com/HeartCurve.html, 6th curve | |
| var updateDelay = pupilAverageUpdateDelay*(0.5+Math.random()) // 2s->3s | |
| var pupilRadius = minIrisRadius*(1+(1.5*Math.random()-0.2)); // in [0.8, 2.3] | |
| if (currentRequester === requester.USER) { updateDelay=0; }; | |
| drawnSparks.transition() | |
| .delay(updateDelay) | |
| .duration(pupilVelocity*(0.5+Math.random())) | |
| .attr("transform", function(d,i) { | |
| var pRadian = (i-0.5)*sparkRadianIncrement+Math.PI/2; //parametric radian | |
| var x = 16*Math.pow(Math.sin(pRadian),3); | |
| var y = -(13*Math.cos(pRadian) - 5*Math.cos(2*pRadian) - 2*Math.cos(3*pRadian) - Math.cos(4*pRadian)); | |
| var degree = Math.atan2(y, x)*180/Math.PI; | |
| var sparkTranslation = Math.sqrt(x*x+y*y)*pupilRadius/16 - minIrisRadius; | |
| var sparkScalling = maxIrisRadius/(maxIrisRadius+sparkTranslation); | |
| return "rotate("+degree+"),translate("+sparkTranslation+"),scale("+sparkScalling+")";}) | |
| .each("end", function(d,i) { | |
| if (i===0) { updatePupil(requester.RANDOM); } | |
| }); | |
| }; | |
| function radioactive(currentRequester) { | |
| var updateDelay = radioactiveAverageDelay*(0.5+Math.random()) // 1s->3s | |
| if (currentRequester === requester.USER) { updateDelay=0; }; | |
| drawnSparks.transition() | |
| .delay(updateDelay) | |
| .duration(radioactiveVelocity*(0.5+Math.random())) | |
| .attr("transform", function(d,i) { | |
| var refAngle = Math.floor((i*sparkDegreeIncrement)/120)*120; // within [0,120,240] | |
| var newAngle = refAngle + (i*sparkDegreeIncrement - refAngle)/2; | |
| return "rotate("+(newAngle)+"),translate(0),scale(1)";} | |
| ) | |
| .each("end", function(d,i) { | |
| if (i===0) { updatePupil(requester.RANDOM); } | |
| }); | |
| }; | |
| function blinkEyelids (currentRequester) { | |
| var updateDelay = averageBlinkDelay*(0.5+Math.random()); // 5s>15s | |
| var blinkDuration = blinkVelocity*(0.5+Math.random())/2; | |
| var verticalBlink = (Math.random()*100 < 10); | |
| if (currentRequester === requester.USER) { updateDelay=0; }; | |
| drawnEyelids.attr("transform", (verticalBlink)? "rotate(90)" : "" ) | |
| drawnEyelids.transition() | |
| .delay(updateDelay) | |
| .duration(blinkDuration) | |
| .attr("d", function(d,i) { return eyelidLine(d.closed); }) | |
| .each("end", function(d,i) { | |
| d3.select(this).transition() | |
| .duration(blinkDuration) | |
| .attr("d", function(d,i) { return eyelidLine(d.opened); }) | |
| .each("end", function(d,i) { | |
| if(i===0) { blinkEyelids(requester.RANDOM); } | |
| }) | |
| }); | |
| }; | |
| function terminator (currentRequester) { | |
| var updateDelay = terminatorAverageDelay*(0.5+Math.random()) // 20s->60s | |
| if (currentRequester === requester.USER) { updateDelay=0; }; | |
| drawnTerminator.transition() | |
| .delay(updateDelay) | |
| .duration(terminatorVelocity) | |
| .attr("r", 2) | |
| .transition() | |
| .duration(terminatorVelocity/3) | |
| .attr("r", 8) | |
| .transition() | |
| .duration(2*terminatorVelocity/3) | |
| .attr("r", 0) | |
| .each("end", function(d,i) { | |
| terminator(requester.RANDOM); | |
| }) | |
| }; | |
| </script> | |
| </body> |