I might be a little too excited for the next season.
House of Cards Flag
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<meta charset="utf-8"> | |
<style> | |
body { | |
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; | |
width: 960px; | |
height: 500px; | |
position: relative; | |
} | |
div { | |
position: absolute; | |
top: 1em; | |
left: 1em; | |
} | |
svg { | |
background-color: #121212; | |
} | |
rect.union { | |
fill: #0F2690; | |
} | |
</style> | |
<script src="http://d3js.org/d3.v3.min.js"></script> | |
<body> | |
<div> | |
<button id="veil">Veil</button> | |
<button id="unveil">Unveil</button> | |
<button id="rightway">Correct Display</button> | |
<button id="wrongway">Incorrect Display</button> | |
</div> | |
</body> | |
<script> | |
var red = "#AF1600"; | |
var white = "#FFF"; | |
var blue = "#0F2690"; | |
var background = "#131313"; | |
var flagRatio = 1.9; | |
var stripeDuration = 250; //ms | |
var stripeDelay = 80; //ms | |
var flipDuration = 500; //ms | |
var width = 960; | |
var height = 500; | |
var flagHeight = height/2; | |
var flagWidth = width/2; | |
if ((flagWidth / flagHeight) < flagRatio) { | |
flagHeight = flagWidth / 1.9; | |
} else { | |
flagWidth = flagHeight * 1.9; | |
} | |
var stripeHeight = flagHeight / 13; | |
var flagDatum = { upsideDown: true, backwards: true }; | |
var stripeData = []; | |
for (var i = 0; i < 13; i++) { stripeData.push({}); } | |
function flagTransform(upsideUp,leftToRight) { | |
// If we want to see a commonly recognized american flag, we're looking for | |
// upsideup=true and leftToRight=true. (This is slightly confused by | |
// the fact that the natural orientation the code creates is false,false) | |
// This transform is broken into a translation and scaling. The scaling | |
// should be thought of as a vehicle for mirroring. (If we scale an axis | |
// to -1, that causes a mirroring over that axis) | |
var upperLeftCornerX = (width / 2) - (flagWidth / 2); | |
var upperLeftCornerY = (height / 2) - (flagHeight / 2); | |
var scaleX = upsideUp ? -1 : 1; | |
var scaleY = leftToRight ? -1 : 1; | |
// If we're flipping things around, that will change the position of the | |
// flag, so we have to account for that. | |
upperLeftCornerX += (scaleX == -1) ? flagWidth : 0; | |
upperLeftCornerY += (scaleY == -1) ? flagHeight : 0; | |
return "translate("+upperLeftCornerX+","+upperLeftCornerY+")scale("+scaleX+","+scaleY+")"; | |
} | |
function flagTransformTween(d,i,a) { | |
var targetTransform = flagTransform(d.upsideUp, d.leftToRight); | |
return d3.interpolateString(a, targetTransform); | |
} | |
var svg = d3.select("body").append("svg") | |
.attr("width", width) | |
.attr("height", height); | |
var flag = svg.append("g") | |
.datum(flagDatum) | |
.attr("transform",flagTransform(false,false)); | |
flag.selectAll("rect.stripe").data(stripeData) | |
.enter().append("rect") | |
.attr("x", 0) | |
.attr("y", function(d,i) { return i * stripeHeight; }) | |
.attr("height", stripeHeight) | |
.attr("width", 0) | |
.classed("stripe",true) | |
.style("fill", function(d,i) { return (i % 2) ? white : red }); | |
flag.append("rect") | |
.attr("x", flagWidth * 0.6) | |
.attr("y", 6 * stripeHeight) | |
.attr("width", 0) | |
.attr("height", 7 * stripeHeight) | |
.classed("union", true); | |
function unveil() { | |
flag.selectAll("rect.stripe") | |
.transition() | |
.delay(function(d,i) { return i * stripeDelay }) | |
.duration(stripeDuration) | |
.ease("cubic-out") | |
.attr("width", function(d,i) { return (i < 6) ? flagWidth : (0.6 * flagWidth); }); | |
flag.select("rect.union") | |
.transition() | |
.delay(13 * stripeDelay + stripeDuration) | |
.duration(stripeDuration) | |
.ease("cubic-out") | |
.attr("width", flagWidth * 0.4); | |
} | |
function veil() { | |
flag.selectAll("rect.stripe") | |
.transition() | |
.delay(0) | |
.duration(stripeDuration) | |
.ease("cubic-out") | |
.attr("width", 0); | |
flag.select("rect.union") | |
.transition() | |
.delay(0) | |
.duration(stripeDuration) | |
.ease("cubic-out") | |
.attr("width", 0); | |
} | |
function flipTo(upsideUp, leftToRight) { | |
flagDatum.upsideUp = upsideUp; | |
flagDatum.leftToRight = leftToRight; | |
flag | |
.transition() | |
.duration(flipDuration) | |
.attrTween("transform", flagTransformTween); | |
} | |
function toCorrectDisplay() { flipTo(true, true); } | |
function toHalfWay() { flipTo(true, false); } | |
function toHouseOfCards() { flipTo(false, false); } | |
window.setTimeout(unveil, 500); | |
d3.select('#veil').on('click', veil); | |
d3.select('#unveil').on('click', unveil); | |
d3.select('#rightway').on('click', function() { | |
if (!flagDatum.upsideUp || !flagDatum.leftToRight) { | |
toHalfWay(); | |
window.setTimeout(toCorrectDisplay, flipDuration); | |
} | |
}); | |
d3.select('#wrongway').on('click', function() { | |
if (flagDatum.upsideUp || flagDatum.leftToRight) { | |
toHalfWay(); | |
window.setTimeout(toHouseOfCards, flipDuration); | |
} | |
}); | |
</script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment