问题描述
SVG元素内部实际可见的内容取决于其宽高比,
//给定< svg> element,返回一个具有可见边界的对象
//以本地viewBox单位表示,例如
// {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;
休息;
case aspect.SVG_PRESERVEASPECTRATIO_XMINYMAX:
case aspect.SVG_PRESERVEASPECTRATIO_XMIDYMAX:
case aspect.SVG_PRESERVEASPECTRATIO_XMAXYMAX:
y + = diff;
休息;
}
}
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;
休息;
case aspect.SVG_PRESERVEASPECTRATIO_XMAXYMID:
case aspect.SVG_PRESERVEASPECTRATIO_XMAXYMIN:
case aspect.SVG_PRESERVEASPECTRATIO_XMAXYMAX:
x + = diff;
休息;
}
}
返回{x:x,y:y,width:width,height:height};
}
}
The content actually visible inside an SVG element depends on its aspect ratio, its viewBox
value, and its preserveAspectRatio
value.
For example, the same SVG element size with the same viewBox
value (dotted red below) can have different viewports (shown in blue below) depending on the preserveAspectRatio
:
Chrome has a
viewport
property, but in my uses it's always an empty (all 0-valued) SVGRect. Firefox does not implement this property.The
svg.getBBox()
method returns the value of theviewBox
, not the actual visible viewport content.
Given a reference to a SVG element, how can I most easily determine the visible content (the viewport), expressed in the user coordinates at the root of the SVG (the same coordinates as the viewBox
)?
Here's a function that works for Chrome, Safari, and Firefox. See the test page here:
Test Page: http://phrogz.net/SVG/CalculateSVGViewport.html
// Given an <svg> element, returns an object with the visible bounds
// expressed in local viewBox units, e.g.
// { 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};
}
}
这篇关于在全局/根坐标中确定SVG视口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!