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> |