d3 Minimap Pan and Zoom Demo

2,432 views
Skip to first unread message

Bill White

unread,
Nov 26, 2013, 8:26:13 PM11/26/13
to d3...@googlegroups.com
Just an FYI:  I posted a demo (with source code) showing how to create a d3 container/canvas with a corresponding pan and zoom minimap.  I'm using this design as part of a larger modeling tool, but I figured I'd take a moment to demo how this works and see if anyone has any suggestions for ways to improve on it.  You can see the demo here.

Ian Johnson

unread,
Nov 26, 2013, 8:31:57 PM11/26/13
to d3...@googlegroups.com
this is a pretty sweet demo! i love minimaps...
thanks for sharing :)


On Tue, Nov 26, 2013 at 5:26 PM, Bill White <billd...@gmail.com> wrote:
Just an FYI:  I posted a demo (with source code) showing how to create a d3 container/canvas with a corresponding pan and zoom minimap.  I'm using this design as part of a larger modeling tool, but I figured I'd take a moment to demo how this works and see if anyone has any suggestions for ways to improve on it.  You can see the demo here.

--
You received this message because you are subscribed to the Google Groups "d3-js" group.
To unsubscribe from this group and stop receiving emails from it, send an email to d3-js+un...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.



--
Ian Johnson - 周彦

Joe Martinez

unread,
Nov 27, 2013, 9:27:36 AM11/27/13
to d3...@googlegroups.com
This is really well done. Subscribed to the blog.


On Tue, Nov 26, 2013 at 8:26 PM, Bill White <billd...@gmail.com> wrote:
Just an FYI:  I posted a demo (with source code) showing how to create a d3 container/canvas with a corresponding pan and zoom minimap.  I'm using this design as part of a larger modeling tool, but I figured I'd take a moment to demo how this works and see if anyone has any suggestions for ways to improve on it.  You can see the demo here.

Bill White

unread,
Dec 2, 2013, 1:29:08 PM12/2/13
to d3...@googlegroups.com, j...@joemartinez.name
Thanks!  I just added a followup post here about using this with a force layout.  I'm using these demos to explore the best ways to create usuable d3 components without straying too far from the selection lifecycle that makes d3 so awesome to use.  Any tips on ways to improve it are appreciated.

- Bill

Phyo Arkar Lwin

unread,
Feb 3, 2014, 2:26:12 PM2/3/14
to d3...@googlegroups.com
Very cool! I am also needing minimap.
I have a lot of items so Is that also possible to render only visible part on big map?

Bill White

unread,
Feb 3, 2014, 2:40:35 PM2/3/14
to d3...@googlegroups.com
Rendering only some of the items on the main container is a little problematic for a few reasons:

1. The minimap is drawn based on the content of the main container (see the cloneNode() call in the minimap class), so you would need to rework the logic to render the source content into both places rather than my approach of just rendering into the main container and then updating the minimap based on that container's content.

2.  I've done some visualizations which do not update the positions of items that are positioned outside the viewport, but it takes a pretty specific set of conditions for this to work correctly.   If you have any type of containment in your d3 visualization (i.e. a box within a box within a box) then doing partial rendering gets tricky because you have to know when to update the parent containers of items that are inside the viewport, etc.  I'd say the answer really depends on the type of SVG content you are trying to render.

Bill

Fern of the Andes

unread,
Feb 3, 2014, 3:52:35 PM2/3/14
to d3...@googlegroups.com
Hi Bill,

I am going to abuse of your notorious kindness and good will by asking you a question without spending too much time looking at the code for the force layout mini-map. But I guess this would help me cut through the chase while multitasking (you know the drill): would it be possible to factor out the core part which actually handles the input data and force layout, canvas.addCircles, and plug in another layout like say, a radial tree, without touching too many other parts of the code?

Thanks,
Nivaldo

Bill White

unread,
Feb 3, 2014, 5:50:33 PM2/3/14
to d3...@googlegroups.com
Are you talking about something like this?  All I did here was rip out the .addCircles method and the force layout stuff and just render the tree directly onto the panCanvas.  If you grab the code from this demo and compare it to the force layout demo you should be able to see what I changed.  Hope that helps. 

Bill

Fern of the Andes

unread,
Feb 3, 2014, 6:02:27 PM2/3/14
to d3...@googlegroups.com
Absolutely great! I cannot thank you enough...many times I am dealing with large datasets and this capability will be of much use. Thanks again!!

Nivaldo

Bill White

unread,
Feb 4, 2014, 1:59:14 AM2/4/14
to d3...@googlegroups.com
Glad to help :)

Dan Mendes

unread,
Jul 3, 2014, 10:27:30 AM7/3/14
to d3...@googlegroups.com
Hi Bill,

This looks awesome. Have you worked on this a bit more? I would like to know if there is an easy way to restrain the paint brush to just the borders of the minimap.
I was thinking about doing something like his because I hadn't found anything until I stumbled upon your code. Do you think that it's a god option to render controllers in the SVG or should these be on a different div/layer. I want to add a zoom in and out button similar interface to http://norkart.github.io/Leaflet-MiniMap/example.html

TIA

Robert R. Raiz

unread,
Jul 3, 2014, 10:29:53 AM7/3/14
to d3...@googlegroups.com
This is awesome. I was thinking at a minimap for my display. Will dig into this soon.

Thanks for sharing.

Bill White

unread,
Jul 3, 2014, 4:34:37 PM7/3/14
to d3...@googlegroups.com
I have not really added too much else yet, but the logic to restrict the dragging range of the minimap reticle should not be too hard to write.  I would suggest that you start by adding some logic to keep the drag position within the bounds you want inside the drag handler with something like this:
...
            .on("drag.minimap", function() {
                d3.event.sourceEvent.stopImmediatePropagation();
                frameX += d3.event.dx;
                frameY += d3.event.dy;
// add logic to constrain x/y drag range  (assume leftBoundaryX/Y = 0 and reticleWidth is 300 or whatever size you use for the minimap) 
                frameX = Math.min( (Math.max(frameX, leftBoundaryX), leftBoundaryX+reticleWidth) 
                frameY = Math.min( (Math.max(frameY, topBoundaryX), topBoundaryX+reticleHeight) 
// end constrain logic
                frame.attr("transform", "translate(" + frameX + "," + frameY + ")");
                var translate =  [(-frameX*scale),(-frameY*scale)];
                target.attr("transform", "translate(" + translate + ")scale(" + scale + ")");
                zoom.translate(translate);
            });

I'm just throwing that example out so I'm sure there are some additional details to work out, but maybe that will point you in the right direction.    :)

Bill White

unread,
Jul 3, 2014, 4:44:22 PM7/3/14
to d3...@googlegroups.com
I tried to reply to the other question but it doesn't seem to have shown up.  You can write the controls to be part of the SVG or make them regular dom nodes that use Javascript to trigger action in the svg map/controller.  You can use d3 to create both sets of components if you want.  See my other demo showing containers with flow layouts as an example.  I use an regular dom node "add container" button which in turn adds items to the SVG container which is somewhat similar to what you described.


On Thursday, July 3, 2014 9:27:30 AM UTC-5, Dan Mendes wrote:

Dan Mendes

unread,
Jul 3, 2014, 5:51:38 PM7/3/14
to d3...@googlegroups.com
Thanks for both of your replies. 

Your code is a huge head start for what I want to do. Ill update this thread with a link, when I am done, should take a couple of weeks. (I am doing his as a 20/80 project, I only work on it one day of the week.)

Your code is very clean and easy to read! :) If I get stuck at some point Ill definitely revive this thread!

Bill White

unread,
Jul 4, 2014, 7:06:39 PM7/4/14
to d3...@googlegroups.com
Thanks, glad you like the code. :)

younes barhouni

unread,
Aug 12, 2014, 5:59:31 AM8/12/14
to d3...@googlegroups.com
Hello,
I saw recently that you published on github a jquery plugin to display an svg minimap.
Can you please give us an example or demo to show us how to deal with it?
Regards

Daniel MD

unread,
Aug 12, 2014, 6:19:01 AM8/12/14
to d3...@googlegroups.com
Hi, Ill post a demo soon, I need to clean up the code some more, currently I am handling mouse events in a very inefficient way. You can take the library that is on https://github.com/dan-mendes/jquery-svgminimap the usage is simple just create an html file with the following body 

<body>
<div id="minimap-viewport">
    <div id="minimap-controls">
        <button id="minimap-zoomin">+</button>
        <button id="minimap-zoomout">-</button>
    </div>
    <div id="title">
        <span id="file-title"></span>
    </div>
</div>
<div id="chart-viewport"></div>
<div id="minimap-help">Use mouse or arrow keys to navigate. zoomIn [i] zoomOut[o]</div>
</body>
//This is all going to be removed to be created by the plugin

Then in JS just pass an SVG image into the image and it will do the rest... currently it looks like this http://i.imgur.com/R1tJjt6.png there is no styling or anything its a WIP.

Regards,
Dan




--
You received this message because you are subscribed to a topic in the Google Groups "d3-js" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/d3-js/aaf7vCZaDKc/unsubscribe.
To unsubscribe from this group and all its topics, send an email to d3-js+un...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Emilio Ponce

unread,
Aug 24, 2018, 9:10:14 PM8/24/18
to d3-js
Hi Bill,

Thanks for share this!!! I've added two buttons to zoom in and zoom out, but in the callback of the click event I am doing this:

zoomIn.on("click", function() {
zoom.scaleBy(panCanvas.transition().duration(350), 1.5);
updateCanvasZoomExtents();
});

zoomOut.on("click", function() {
zoom.scaleBy(panCanvas.transition().duration(350), 1/1.5);
    updateCanvasZoomExtents();
})

The issue is that when the user tries to zooming with the mouse after use the zoom control buttons there is a weird jump of the SVG. Do you know if there is another way to trigger instead of zoom.scaleBy

It's like if there are 2 zoom instances.

Bill White

unread,
Aug 29, 2018, 8:27:30 AM8/29/18
to d3-js
The jump is likely because the zoom's are getting out of sync; it is difficult to explain, but read my blog post on this and it might help you figure out the issue... 

Emilio Ponce

unread,
Aug 29, 2018, 10:27:22 AM8/29/18
to d3-js
Hi All, Thanks for your response Bill, at the end I noticed that I was applying the transition to the wrong container so instead of:

zoom.scaleBy(panCanvas.transition().duration(350), 1.5);

I applied the transition to the "innerWrapper" element.

zoom.scaleBy(innerWrapper.transition().duration(350), 1.5);

And that fixed my issue!

Cheers
Reply all
Reply to author
Forward
0 new messages