在全局/根坐标中确定SVG视口 [英] Determining the SVG viewport in global/root coordinates

查看:97
本文介绍了在全局/根坐标中确定SVG视口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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 the viewBox, 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视口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆