【问题标题】:How to keep viewBox centered when "zooming" in SVGs?在 SVG 中“缩放”时如何保持 viewBox 居中?
【发布时间】:2018-02-04 03:26:36
【问题描述】:

我经常使用viewBox 属性来“缩放” SVG 元素。缩放当然是通过对viewBox 属性使用较低的 widthheight 值来完成的 - 但 xy em> 值很难确定以保持场景居中。

下面是一个sn-p,其中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>

宽度和高度减半不一致

按照将 widthheight 减半的模式使场景居中:

viewBox="12.5 12.5 25 25" 应该继续缩放并保持居中。但它不会保持居中。我的问题是 SVG 使用什么公式或技术,我总能从数学上算出我需要使特定 width 居中的 xy 值是多少viewBox?中的 height 值?

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

还有一件事:我在问你是否在viewBox 中已经有了 widthheight 值,你如何找到中心坐标现场。反之亦然。

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

【问题讨论】:

    标签: html css svg zooming viewbox


    【解决方案1】:

    你的计算是错误的。如果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>

    【讨论】:

    • 感谢您的回答,它对我的​​目的很有效:在将焦点保持在 SVG 元素的中心点的同时进行缩放。但是,如果我首先有一个焦点,我该如何调整这个公式。比如( 35, 67 )和一个缩放级别,比如2X50 50在这种情况下然后想出X和Y坐标来保持那个点( 35, 67 )在viewBox的中心?这里有一个完整的未回答(最近编辑过)的问题:stackoverflow.com/questions/45892233/…
    • 做了更多测试,我发现它只出现在偏离中心的位置,因为我把网格的实际尺寸误认为是viewBox。您的解决方案是可靠的,并且在这种情况下再次有效。谢谢!
    • 很棒的答案!已经为此苦苦挣扎了将近两个小时。
    【解决方案2】:

    由于代码 sn-p 已过期,我不得不考虑如何实现它,我想我会避免其他人这样做并发布一个工作代码 sn-p。

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

    如果你实现了一个平移功能,它也可以在没有任何修改的情况下使用它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-02-09
      • 2020-04-21
      • 2015-01-21
      • 2011-12-25
      • 1970-01-01
      • 1970-01-01
      • 2014-01-17
      相关资源
      最近更新 更多