Notes
-
There are two separate SVG elements on the page:
- main (for the main SVG)
- mini (for the minimap)
-
Each SVG lies within a div, named after its purpose (
div#mainanddiv#mini) -
The main SVG is nested within another SVG (svg.aperture)
- This allows us to have a "magnifying glass"
- The layout is then something like this:
- section.vis -> div#main -> svg.aperture -> svg#butterfly
- section.vis -> div#mini -> svg
-
Use CSS to size the SVGs appropriately on the page
- Here I'm using flexbox, and setting the main SVG to be 3 times the size of the minimap
-
About widths and heights:
- The butterfly SVG from Bill White's examples has
widthandheightattributes- I've rounded those up to round integer values in
svg#butterfly - These values are copied into the containing SVG (
svg.aperture), so that the viewport of that main svg is defined.- This holds the aspect ratio of
svg.apertureconstant on the page, while itsviewBoxstring changes (this method uses that viewBox string to zoom and translate). - CSS is additionally used to size the SVG itself to fit on the screen with a 3:1 ratio vs the minimap
- Using
flex-grow: 3for the main SVG andflex-grow: 1for the minimap will ensure that the main is 3 times as large as the minimap on screen. The two SVGs might still have identical width and height attributes.
- Using
- This holds the aspect ratio of
- The rounded up width and height are used to define the
viewBoxattribute the magnifying SVG (svg.aperture)viewBoxis the string of the form"<min-x> <min-y> width height"so we get"0 0 400 250"
- The same
viewBoxis also applied to the minimap SVG
- I've rounded those up to round integer values in
- The magnifying glass effect on
svg.apertureis due to itspreserveAspectRatioattribute beingnone- This attribute value means that
svg#butterfly(which is contained withinsvg.aperture) will stretch to fit its parent (svg.aperture), regardless of width:height ratio
- This attribute value means that
- The butterfly SVG from Bill White's examples has
-
Rendering the SVG twice
- The butterfly svg has an
idattribute. This is required for this technique to work. - The minimap svg re-renders the main svg via the
<use xlink:href="#butterfly">- This means that whatever dynamic behaviour your main SVG has will reflect in the minimap
- see the Josquin ribbon for a working example
- This means that whatever dynamic behaviour your main SVG has will reflect in the minimap
- The butterfly svg has an
-
Zoom behavior
- a single d3.zoom object is applied to both:
svg.apertureand the minimap SVG.- The minimap's zoom callback calls the main svg's zoom callback, which then:
- calculates the new viewBox values based on the zoom.transform's
x,yandkvalues- x and y are the initial coordinates and the initial viewBox lengths are multiplied by the k-value
- sends the viewbox dimensions as extents for brush.move()
- manually sets the
__zoomproperty on the minimap.
- calculates the new viewBox values based on the zoom.transform's
- The minimap's zoom callback calls the main svg's zoom callback, which then:
- d3.brush is applied to the minimap SVG.
- It doesn't call any of the zoom callbacks. Instead it:
- sets the
__zoomproperty for the main and minimap SVGs - sets the main SVGs viewBox based on the brush.extent()
- sets the
- It doesn't call any of the zoom callbacks. Instead it:
- Thus, mouse wheel events on either SVG leads to zoom
- By storing the
__zoomproperty on each, we ensure that both SVGs have the same zoom values at all times.
- By storing the
- a single d3.zoom object is applied to both:
Links
- Bill White's original work
- His update using d3v4 (also works in v5)
- and the ensuing discussion
- A most important primer on SVG coordinate systems
Built with blockbuilder.org
forked from seemantk's block: "Minimap" Zoom/Pan with viewBox
@ShreyasBhargavaNV, oh my gosh, I didn't receive a notification of your comment. I noticed that as well -- the mouse direction changes. it nagged me until the last minute, but I could never figure out the math, so i will try again.
as to your second question: do you mean, you'd like to click and drag the main SVG itself?