Defining SVG Viewer Window in Global / Root Coordinates

The content visible inside an SVG element depends on its aspect ratio, its viewBox and its preserveAspectRatio .

For example, the same size of an SVG element with the same viewBox value (red dotted bottom) may have different viewports (shown in blue below) depending on preserveAspectRatio :

pictoral examples of varying preserveAspectRatio settings and the resulting viewboxes

  • Chrome has a viewport property, but for my purposes it is always an empty (all 0-digit) SVGRect. Firefox does not implement this property.

  • The svg.getBBox() method returns the value of viewBox , not the actual visible content of the viewport.

Given the link to the SVG element, how can I most easily determine the visible content (viewport) expressed in user coordinates in the root of the SVG (the same coordinates as the viewBox )?

+6
source share
1 answer

Here's a feature that works for Chrome, Safari, and Firefox. See the test page here:

Testing page: http://phrogz.net/SVG/CalculateSVGViewport.html

 // Given an <svg> element, returns an object with the visible bounds // expressed in local viewBox units, eg // { x:-50, y:-50, width:100, height:100 } function calculateViewport(svg){ // http://phrogz.net/JS/_ReuseLicense.txt var style = getComputedStyle(svg), owidth = parseInt(style.width,10), oheight = parseInt(style.height,10), aspect = svg.preserveAspectRatio.baseVal, viewBox = svg.viewBox.baseVal, width = viewBox && viewBox.width || owidth, height = viewBox && viewBox.height || oheight, x = viewBox ? viewBox.x : 0, y = viewBox ? viewBox.y : 0; if (!width || !height || !owidth || !oheight) return; if (aspect.align==aspect.SVG_PRESERVEASPECTRATIO_NONE || !viewBox || !viewBox.height){ return {x:x,y:y,width:width,height:height}; }else{ var inRatio = viewBox.width / viewBox.height, outRatio = owidth / oheight; var meetFlag = aspect.meetOrSlice != aspect.SVG_MEETORSLICE_SLICE; var fillAxis = outRatio>inRatio ? (meetFlag?'y':'x') : (meetFlag?'x':'y'); if (fillAxis=='x'){ height = width/outRatio; var diff = viewBox.height - height; switch (aspect.align){ case aspect.SVG_PRESERVEASPECTRATIO_UNKNOWN: case aspect.SVG_PRESERVEASPECTRATIO_XMINYMID: case aspect.SVG_PRESERVEASPECTRATIO_XMIDYMID: case aspect.SVG_PRESERVEASPECTRATIO_XMAXYMID: y += diff/2; break; case aspect.SVG_PRESERVEASPECTRATIO_XMINYMAX: case aspect.SVG_PRESERVEASPECTRATIO_XMIDYMAX: case aspect.SVG_PRESERVEASPECTRATIO_XMAXYMAX: y += diff; break; } } else{ width = height*outRatio; var diff = viewBox.width - width; switch (aspect.align){ case aspect.SVG_PRESERVEASPECTRATIO_UNKNOWN: case aspect.SVG_PRESERVEASPECTRATIO_XMIDYMIN: case aspect.SVG_PRESERVEASPECTRATIO_XMIDYMID: case aspect.SVG_PRESERVEASPECTRATIO_XMIDYMAX: x += diff/2; break; case aspect.SVG_PRESERVEASPECTRATIO_XMAXYMID: case aspect.SVG_PRESERVEASPECTRATIO_XMAXYMIN: case aspect.SVG_PRESERVEASPECTRATIO_XMAXYMAX: x += diff; break; } } return {x:x,y:y,width:width,height:height}; } } 
+4
source

All Articles