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
If we drag on main SVG, it goes to opposite direction and sometimes also got stuck.
Is there any way to drag main SVG smooth like we do from minimap ?