Skip to content

Instantly share code, notes, and snippets.

@drfloob
Forked from azundo/flag.svg
Last active December 19, 2015 10:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save drfloob/5938266 to your computer and use it in GitHub Desktop.
Save drfloob/5938266 to your computer and use it in GitHub Desktop.
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
<!doctype html>
<html>
<head>
<title>The Pirate Puzzle></title>
<style>
.island {
stroke: blue;
stroke-width: 3;
fill: transparent;
}
.tree {
stroke: green;
fill: green;
}
.grave {
stroke: black;
fill: black;
}
.flag {
stroke: red;
fill: red;
}
.treasure {
stroke: yellow;
fill: yellow;
}
.flag-path {
stroke: black;
fill: none;
}
</style>
</head>
<body>
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script type="text/javascript">
(function (){
var width = 960,
height = 600,
// our svg container
svg = d3.select('body').append('svg')
.attr('width', width)
.attr('height', height),
// a group within our container that will hold our map features
features = svg.append('g'),
// a group within our features group that will hold some paths to explain the geometries
geometries = features.append('g'),
islandRadius = 300,
featureLength = 30,
treeOffset = 210,
trees = [
{
x: treeOffset,
y: treeOffset
},
{
x: islandRadius - treeOffset,
y: treeOffset+120
}],
grave = {x: islandRadius, y: islandRadius},
// helper function for generating path values for lines
line = d3.svg.line()
.x(function(d) { return d.x; })
.y(function(d) { return d.y; });
// create a mask to keep features from displaying off of the island
svg.append('g')
.append('clipPath')
.attr('id','island-mask')
.append('circle')
.attr('r', islandRadius)
.attr('cx', islandRadius)
.attr('cy', islandRadius);
// apply it to the features group
features.attr('clip-path', 'url(#island-mask)');
// create the island on top of everything. If we draw our features "over top"
// of the island then they will interfere with our event handling
svg.append('circle')
.attr('r', islandRadius)
.attr('cx', islandRadius)
.attr('cy', islandRadius)
.classed('island', true);
// create the trees - these are static so only draw them once
features.selectAll('.tree')
.data(trees)
.enter().append('image')
.attr('xlink:href', 'tree.svg')
.attr('width', featureLength)
.attr('height', featureLength)
.attr('x', getX)
.attr('y', getY)
.classed('tree', true);
// dynamic draw function for things that react to moving the grave position
function draw() {
// calculate positions
var flags = getFlagPositions(trees, grave),
treasure = getTreasurePosition(flags),
paths = getPathPoints(trees, flags, grave);
// draw the grave
features.selectAll('.grave')
.data([grave])
.attr('x', getX)
.attr('y', getY)
.enter().append('image')
.attr('xlink:href', 'grave.svg')
.classed('grave', true)
.attr('height', featureLength)
.attr('width', featureLength)
.attr('x', getX)
.attr('y', getY);
// draw the flags
features.selectAll('.flag')
.data(flags)
.attr('x', getX)
.attr('y', getY)
.enter().append('image')
.attr('xlink:href', 'flag.svg')
.classed('flag', true)
.attr('height', featureLength)
.attr('width', featureLength)
.attr('x', getX)
.attr('y', getY);
// draw the treasure location
features.selectAll('.treasure')
.data([treasure])
.attr('x', getX)
.attr('y', getY)
.enter().append('image')
.attr('xlink:href', 'treasure_chest.svg')
.classed('treasure', true)
.attr('height', featureLength)
.attr('width', featureLength)
.attr('x', getX)
.attr('y', getY);
// draw triangles showing the flag calculations
// these are in the geometries group so they appear underneath the other features
geometries.selectAll('.flag-path')
.data(paths)
.attr('d', line)
.enter().append('path')
.classed('flag-path', true)
.attr('d', line);
}
// move grave location to wherever the mouse is
svg.select('.island')
.on('mousemove', function() {
// 15 is a magic number to make things look nice, on my screen at least.
var mousePosition = d3.mouse(this);
grave.x = mousePosition[0] - 5;
grave.y = mousePosition[1] - 5;
draw();
});
// calculate the positions of the flags
function getFlagPositions(treePositions, gravePosition) {
var leftTree, rightTree, rise, run, leftFlag, rightFlag,
flagPositions, leftTreeIdx, rightTreeIdx;
// XXX assume grave position is either above or below both,
// i.e. y positions are equal for both trees
// this code determines which tree is "left" and which is "right" based
// on the location of the grave
if (
(treePositions[0].x < treePositions[1].x && treePositions[0].y < grave.y) ||
(treePositions[0].x > treePositions[1].x && treePositions[0].y > grave.y)
) {
leftTreeIdx = 0;
rightTreeIdx = 1;
} else {
leftTreeIdx = 1;
rightTreeIdx = 0;
}
leftTree = treePositions[leftTreeIdx];
rightTree = treePositions[rightTreeIdx];
// get left flag position
rise = gravePosition.y - leftTree.y;
run = gravePosition.x - leftTree.x;
// turn 90 to the left
leftFlag = {
x: leftTree.x - rise,
y: leftTree.y + run
};
// get right flag position
rise = gravePosition.y - rightTree.y;
run = gravePosition.x - rightTree.x;
// turn 90 to the right
rightFlag = {
x: rightTree.x + rise,
y: rightTree.y - run
};
flagPositions = [];
// use these indexes to keep the order of our flags consistent with the order
// of our trees in the trees array
flagPositions[leftTreeIdx] = leftFlag;
flagPositions[rightTreeIdx] = rightFlag;
return flagPositions;
}
function getTreasurePosition(flagPositions) {
// averages the x and y values of the two flag positions
return {
x: (flagPositions[0].x + flagPositions[1].x) / 2,
y: (flagPositions[0].y + flagPositions[1].y) / 2
}
}
function getPathPoints(treePositions, flagPositions, grave) {
// create two lines, grave -> tree -> flag -> grave for each tree
return [
[
grave,
treePositions[0],
flagPositions[0],
grave
],
[
grave,
treePositions[1],
flagPositions[1],
grave
]
]
}
// helper functions for positioning
function getX(d) {
return d.x - featureLength/2;
}
function getY(d) {
return d.y - featureLength/2;
}
})();
</script>
</body>
</html>
Display the source blob
Display the rendered blob
Raw
<!-- http://thenounproject.com/noun/chest/#icon-No7173 Victor N. Escorsin da silva from The Noun Project -->
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Layer_1" x="0px" y="0px" width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
<g>
<path fill-rule="evenodd" clip-rule="evenodd" d="M99.204,54.544c-1.188,0.19-2.377,0.364-3.563,0.566 c-5.327,0.917-10.656,1.845-15.984,2.764c-6.347,1.096-12.693,2.191-19.04,3.285c-5.854,1.01-11.707,2.017-17.56,3.026 c-3.082,0.531-6.162,1.061-9.242,1.596c-0.093,0.014-0.182,0.043-0.321,0.08c0.066,10.295,0.133,20.597,0.2,30.96 c0.869-0.188,1.701-0.362,2.531-0.545c12.892-2.85,25.781-5.702,38.673-8.554c7.376-1.631,14.75-3.262,22.129-4.883 c0.307-0.068,0.395-0.177,0.41-0.457c0.204-3.361,0.419-6.721,0.633-10.08c0.241-3.783,0.488-7.566,0.726-11.348 c0.111-1.762,0.212-3.522,0.321-5.282c0.014-0.202,0.057-0.401,0.088-0.602C99.204,54.895,99.204,54.721,99.204,54.544z"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M69.921,3.255c-0.669,0.055-1.335,0.125-2.008,0.161 c-4.975,0.279-9.951,0.546-14.928,0.825c-5.961,0.333-11.922,0.679-17.883,1.014c-4.445,0.25-8.888,0.489-13.334,0.734 c-2.644,0.145-5.289,0.292-7.935,0.441c-0.167,0.009-0.334,0.036-0.605,0.068c0.238,0.115,0.384,0.188,0.533,0.259 c1.2,0.566,2.188,1.354,2.913,2.414c0.129,0.188,0.244,0.288,0.516,0.271c4.052-0.236,8.104-0.457,12.158-0.685 c4.96-0.278,9.92-0.563,14.88-0.839c3.896-0.218,7.794-0.426,11.69-0.644c4.443-0.247,8.889-0.5,13.33-0.751 c1.535-0.086,3.067-0.171,4.601-0.259c0.092-0.006,0.183-0.024,0.368-0.048c-0.174-0.282-0.304-0.539-0.478-0.766 c-0.718-0.925-1.694-1.544-2.796-2.013c-0.123-0.053-0.24-0.121-0.362-0.182C70.359,3.255,70.142,3.255,69.921,3.255z"/>
<path style="fill: yellow; stroke: yellow;" fill-rule="evenodd" clip-rule="evenodd" d="M8.297,48.493c3.664,2.063,7.323,4.126,10.983,6.186 c4.197,2.362,8.393,4.729,12.598,7.076c0.215,0.12,0.531,0.175,0.777,0.134c5.492-0.91,10.979-1.839,16.468-2.762 c6.508-1.096,13.013-2.186,19.521-3.283c5.967-1.004,11.931-2.018,17.896-3.022c2.884-0.486,5.767-0.969,8.676-1.541 c-10.389-3.275-20.781-6.55-31.221-9.84c3.271-9.43,6.533-22.854,9.82-32.333c-0.864,0.046-1.67,0.084-2.472,0.133 c-3.146,0.192-6.29,0.391-9.435,0.585c-3.599,0.222-7.195,0.442-10.794,0.664c-3.051,0.187-6.103,0.374-9.152,0.561 c-3.583,0.219-7.166,0.442-10.748,0.661c-3.114,0.19-6.228,0.377-9.341,0.566c-1.47,0.089-2.939,0.191-4.412,0.258 c-0.329,0.016-0.381,0.186-0.438,0.401c-0.57,2.075-1.137,4.149-1.708,6.223c-2.277,8.281-4.555,20.584-6.835,28.864 C8.441,48.172,8.369,48.315,8.297,48.493z"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.033,50.637c0.07,2.424,0.14,4.766,0.207,7.108 c0.082,2.783,0.159,5.564,0.244,8.348c0.105,3.524,0.217,7.049,0.318,10.575c0.009,0.296,0.118,0.505,0.359,0.707 c7.352,6.177,14.697,12.358,22.044,18.539c0.146,0.123,0.301,0.237,0.517,0.407c0-0.682,0.006-1.286,0-1.89 c-0.04-3.733-0.08-7.464-0.125-11.196c-0.061-5.086-0.124-10.175-0.19-15.261c-0.012-0.992-0.057-1.981-0.051-2.972 c0.001-0.315-0.107-0.49-0.393-0.66c-5.499-3.283-10.993-6.574-16.487-9.865c-2.042-1.224-4.083-2.446-6.125-3.668 C6.275,50.764,6.194,50.723,6.033,50.637z"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.175,47.03c0.369-1.322,0.717-2.57,1.061-3.818 c2.413-8.744,4.823-21.511,7.234-30.256c0.171-0.621,0.354-1.239,0.507-1.864c0.033-0.135,0.023-0.342-0.065-0.431 c-1.147-1.153-2.422-2.124-4.172-2.347C8.521,8.159,7.532,8.6,6.699,9.391c-0.895,0.849-1.411,1.919-1.931,2.979 c-2.5,5.088-3.764,10.423-3.611,16.025c0.136,5.026,1.422,13.815,3.811,18.327C5.012,46.806,5.078,46.883,5.175,47.03z"/>
</g>
</svg>
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment