如何在 SVG 中 "zooming" 时保持 viewBox 居中?

How to keep viewBox centered when "zooming" in SVGs?

我经常将 viewBox 属性用于 "zoom" SVG 元素。缩放当然是通过为 viewBox 属性使用较低的 widthheight 值来实现的——但是 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 中将 widthheight 值更改为 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 使用什么公式或技术,我总能从数学上算出什么 xy 值我需要将特定 [= viewBox?

中的 63=]width 和 height

注意:我知道像 Snap.svg and Raphaël 这样的库。我正在避开图书馆以努力了解基础知识。

还有一件事:我想问您是否已经在 widthheight 值=13=] 如何找到场景的中心坐标。反之则不然。

包含用于视觉认知的外部样式表。与此问题唯一相关的代码与 SVG 元素有关。

你的计算有误。如果 viewBox 的宽度和高度变小,则 x 和 y 值需要变大。

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>

由于代码片段已过期,我不得不考虑如何实现它,我想我会避免其他人这样做,post 一个有效的代码片段。

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;
}

如果您实现了平移功能,它也无需任何修改即可使用。