在SVG中进行“缩放”时如何保持视口框��中?

7

通常我使用viewBox属性来“缩放”SVG元素。当然,通过使用较低的widthheight值来设置viewBox属性实现缩放 - 但是对于保持场景居中,xy值有点棘手。

下面是一个片段,其中viewBox="0 0 100 100"( x y width height )这是我的起点。场景按比例缩放并从左上角开始。

<head>
  <link rel="stylesheet" href="https://codepen.io/basement/pen/oepKxY.css">
</head>

<body> 
  <iframe src="https://s.codepen.io/basement/debug/zdpVyV/PNAvYLZmJRQr"
          id="grid"
  ></iframe>

  <div class="wrp">   
  
    <!-- SVG relevant code below-->
    <svg xmlns="http://www.w3.org/2000/svg"
         viewBox="0 0 100 100"
         width="100" height="100"
         class="canvas"
    > 
      <defs>   
        <style type="text/css"> 

          circle {
            fill: #0ff;
            fill-opacity: 0.25;
            stroke-width: 0.25;
            stroke: #0ee;
          }

        </style>       
      </defs>

      <circle cx="37.5" cy="50" r="25" />
      <circle cx="62.5" cy="50" r="25" />
      <circle cx="50" cy="71.65" r="25" />    
    </svg>
    
  </div>
</body>

(可以在完整页面中查看。代码片段具有响应性)

缩放

viewBox中的宽度(width)高度(height)值更改为50,即可将场景缩放。但是,我不得不同时调整xy的值,使其都为viewBox的一半尺寸:25,以保持图形居中。

viewBox="25 25 50 50"

<head>
  <link rel="stylesheet" href="https://codepen.io/basement/pen/oepKxY.css">
</head>

<body> 
  <iframe src="https://s.codepen.io/basement/debug/zdpVyV/PNAvYLZmJRQr"
          id="grid"
  ></iframe>

  <div class="wrp">   
  
    <!-- SVG relevant code below-->
    <svg xmlns="http://www.w3.org/2000/svg"
         viewBox="25 25 50 50"
         width="100" height="100"
         class="canvas"
    > 
      <defs>   
        <style type="text/css"> 

          circle {
            fill: #0ff;
            fill-opacity: 0.25;
            stroke-width: 0.25;
            stroke: #0ee;
          }

        </style>       
      </defs>

      <circle cx="37.5" cy="50" r="25" />
      <circle cx="62.5" cy="50" r="25" />
      <circle cx="50" cy="71.65" r="25" />    
    </svg>
    
  </div>
</body>

减半宽度和高度不一致

按照减半宽度高度的模式来居中场景:

viewBox="12.5 12.5 25 25" 应继续缩放并保持居中。但它并没有保持居中。我的问题是SVG使用了什么公式或技术,我可以始终数学计算出要在viewBox中居中特定宽度高度值所需的xy值。

注意:我知道有像Snap.svgRaphaël这样的库。为了理解基本原理,我避免使用库。

还有一件事:如果你已经在viewBox中有一个宽度高度值,如何找到场景的中心坐标。反之亦然。

外部样式表是为视觉认知而包含的。这个问题唯一相关的代码与SVG元素有关。

2个回答

10

你的计算有误。如果viewBox的宽度和高度变小,那么xy的值需要变大。

Initial viewBox:  0 0 100 100
Zoom X2:          25 25 50 50
Zoom X4:          37.5 37.5 25 25

要获取x或y值,需要从上一个(或原始的)viewBox的中心点减去新宽度或高度的一半。
Zoom X2:  centre - newWidth/2
          = (100/2) - (50/2) = 25
Zoom X4:  (100/2) - (25/2) = 37.5, or
          (25 + 50/2) - (25/2) = 37.5

另一种计算方法是将原始宽度减去当前宽度并除以二。
Zoom X4:  (100 - 25) / 2 = 37.5

<head>
  <link rel="stylesheet" href="https://codepen.io/basement/pen/oepKxY.css">
</head>

<body> 
  <iframe src="https://s.codepen.io/basement/debug/zdpVyV/PNAvYLZmJRQr"
          id="grid"
  ></iframe>

  <div class="wrp">   
  
    <!-- SVG relevant code below-->
    <svg xmlns="http://www.w3.org/2000/svg"
         viewBox="37.5 37.5 25 25"
         width="100" height="100"
         class="canvas"
    > 
      <defs>   
        <style type="text/css"> 

          circle {
            fill: #0ff;
            fill-opacity: 0.25;
            stroke-width: 0.25;
            stroke: #0ee;
          }

        </style>       
      </defs>

      <circle cx="37.5" cy="50" r="25" />
      <circle cx="62.5" cy="50" r="25" />
      <circle cx="50" cy="71.65" r="25" />    
    </svg>
    
  </div>
</body>


谢谢您的回答,对我的目的很有效:在保持SVG元素的中心点时进行缩放。但是,如果我首先有一个聚焦点,例如(35,67)和一个缩放级别,例如2X 50 50在这种情况下,如何调整此公式,然后得出X和Y坐标以使该点(35,67)保持在viewBox的中心?这里有一个关于此问题的完整未解答(并最近已编辑)的问题:https://stackoverflow.com/questions/45892233/centering-on-specific-points-when-zooming-using-svg-viewbox?noredirect=1&lq=1 - basement
我进行了更多的测试,发现它只是偏离中心,因为我错误地将网格的实际尺寸误认为是viewBox。你的解决方案很可靠,在这种情况下再次起作用。谢谢! - basement
太棒了!我已经为此苦苦挣扎了将近两个小时。 - Krishna sagar

3

由于代码片段已过期,我不得不思考如何实现它,因此我想让其他人免去这个思考,发布一个有效的代码片段。

var svg = document.querySelector('svg');
var viewBox = svg.viewBox.baseVal;

function zoomIn(){
    viewBox.x = viewBox.x + viewBox.width / 4;
    viewBox.y = viewBox.y + viewBox.height / 4;
    viewBox.width = viewBox.width / 2;
    viewBox.height = viewBox.height / 2;
}

function zoomOut(){
    viewBox.x = viewBox.x - viewBox.width / 2;
    viewBox.y = viewBox.y - viewBox.height / 2;
    viewBox.width = viewBox.width * 2;
    viewBox.height = viewBox.height * 2;
}

如果您实现了平移功能,它也将在没有任何修改的情况下正常工作。

当我想要将缩放比例从2倍改为1.5倍时,如何保持居中?当我将2替换为1.5时,它不再居中。 - Caleb Taylor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接