Skip to content

Instantly share code, notes, and snippets.

@rusanu
Last active August 29, 2015 14:02
Show Gist options
  • Save rusanu/c3513049293770330511 to your computer and use it in GitHub Desktop.
Save rusanu/c3513049293770330511 to your computer and use it in GitHub Desktop.
<!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>
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
@webmutation
Copy link

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment