Last active
August 29, 2015 14:02
-
-
Save rusanu/c3513049293770330511 to your computer and use it in GitHub Desktop.
This file contains hidden or 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> | |
.brush .extent { | |
stroke: #fff; | |
fill-opacity: .125; | |
shape-rendering: crispEdges; | |
} | |
.land { | |
fill: #ddd; | |
stroke: #fff; | |
stroke-width: 0.25px; | |
} | |
.map-big { | |
z-index: 1; | |
} | |
.map-mini { | |
position: absolute; | |
z-index: 10; | |
border: 1px solid #ddd; | |
top: 71%; | |
left: 72.5%; | |
background: #fff; | |
} | |
</style> | |
<body> | |
<script src="http://d3js.org/d3.v3.min.js"></script> | |
<script src="http://d3js.org/queue.v1.min.js"></script> | |
<script> | |
var bigMap = { | |
width: 960, | |
height: 480 | |
}; | |
var miniMap = { | |
width: bigMap.width * 1/4, | |
height: bigMap.height * 1/4 | |
}; | |
d3.json('ne-countries-50m.json',function(error, world) { | |
if (error) { | |
console.log(error); | |
return; | |
} | |
bigMap.svg = d3.select("body").append('svg') | |
.attr('class', 'map map-big') | |
.attr('width', bigMap.width) | |
.attr('height', bigMap.height) | |
miniMap.svg = d3.select("body").append('svg') | |
.attr('class', 'map map-mini brush') | |
.attr('width', miniMap.width) | |
.attr('height', miniMap.height); | |
drawLand = function(target, features) { | |
target.scale = .95 * target.width/2/Math.PI; | |
target.projection = d3.geo.mercator() | |
.translate([target.width/2, target.height/2]) | |
.scale(target.scale); | |
target.path = d3.geo.path().projection(target.projection); | |
target.land_g = target.svg.append("g"); | |
target.land_g.selectAll('path') | |
.data(features) | |
.enter() | |
.append('path') | |
.attr('class', 'land') | |
.attr('d', target.path); | |
} | |
drawLand(bigMap, world.features); | |
drawLand(miniMap, world.features); | |
var originalAspectRatio = bigMap.width / bigMap.height; | |
var enforceAspectRatio = function(extent) { | |
var ew = extent[1][0]-extent[0][0]; | |
var eh = extent[1][1]-extent[0][1]; | |
var newAspectRatio = ew/eh; | |
var changed = false; | |
if (newAspectRatio > (originalAspectRatio * 1.05)) { | |
var neh = miniMap.height * (ew/miniMap.width); | |
extent[0][1] -= (neh-eh)/2; | |
extent[1][1] += (neh-eh)/2; | |
changed = true; | |
} | |
else if (newAspectRatio < (originalAspectRatio * .95)) { | |
var newh = miniMap.width * (eh/miniMap.height); | |
extent[0][0] -= (newh-ew)/2; | |
extent[1][0] += (newh-ew)/2; | |
changed = true; | |
} | |
return changed; | |
}; | |
var brushX = d3.scale.linear() | |
.range([0, miniMap.width]) | |
.domain([0, bigMap.width]); | |
var brushY = d3.scale.linear() | |
.range([0, miniMap.height]) | |
.domain([0, bigMap.height]); | |
var zoom; | |
var brush = d3.svg.brush() | |
.x(brushX) | |
.y(brushY) | |
.on('brush', function() { | |
var extent = brush.extent(); | |
if (!extent) return; | |
enforceAspectRatio(extent); | |
var s = bigMap.width / (extent[1][0] - extent[0][0]); | |
var t = [ | |
-extent[0][0] * s, | |
-extent[0][1] * s | |
]; | |
var transform = 'translate(' + t[0] + ',' + t[1] + ')scale(' + (s) + ')'; | |
bigMap.land_g | |
.style("stroke-width", 1/s) | |
.attr('transform', transform); | |
bigMap.data_g | |
.attr('transform', transform); | |
// Reset the big map zoom to this t and s | |
// This way the big map zoom and the mini-map brush are always in sync | |
zoom.scale(s).translate(t); | |
}) | |
.on('brushend', function() { | |
if (!d3.event.sourceEvent) return; | |
var extent = brush.extent(); | |
if (!extent) return; | |
if (enforceAspectRatio(extent)) { | |
miniMap.svg.transition() | |
.call(brush.extent(extent)) | |
.call(brush.event); | |
} | |
}); | |
miniMap.svg.call(brush); | |
zoom = d3.behavior.zoom() | |
.on('zoom', function() { | |
var t = d3.event.translate; | |
var s = d3.event.scale; | |
var extent = [ | |
[-t[0]/s,-t[1]/s], | |
[-t[0]/s + bigMap.width/s, -t[1]/s + bigMap.height/s] | |
]; | |
// Resize the mini-map brush extent to this zoom t and s | |
// Trigger brush.event to redraw the big-map | |
miniMap.svg | |
.call(brush.extent(extent)) | |
.call(brush.event); | |
}); | |
bigMap.svg.call(zoom); | |
}); | |
</script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi, Found your Gist I am trying to achieve a minimap effect on a D3 visualization... I can't seem to find your minimap here.