Skip to content

Instantly share code, notes, and snippets.

@Kcnarf
Last active December 3, 2018 08:32
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Kcnarf/72259aabaf92904432eb to your computer and use it in GitHub Desktop.
Save Kcnarf/72259aabaf92904432eb to your computer and use it in GitHub Desktop.
Iris
license: mit

Playing with order influence between CSS::transform::rotation/translate/scale

Acknowledgments to:

<!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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment