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
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