【问题标题】:scale an SVG group element to have a path centered in viewport dynamically on click缩放 SVG 组元素以在单击时动态地在视口中居中路径
【发布时间】:2017-05-29 12:16:10
【问题描述】:

我想缩放一个 SVG 组元素,以便它缩放并转换到路径所在的点。这意味着,当我单击路径时,组必须以路径适合视口的高度或宽度的方式缩放并以路径为中心。我真的尝试了很多方法,比如使用getBBox() 来获取路径的高度、宽度、x 和 y,并从视口偏移中减去它们。我还尝试了 d3.js 来操纵它。但是,我找不到好的方法。

这是包含 SVG 的 HTML:

<div style="width: 700px; height:600px; border:1px solid #d0d0d0; background: #e8e8e8; margin: 0 auto;">
    <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
         viewBox="0 0 255.1 170.1" style="enable-background:new 0 0 255.1 170.1;" xml:space="preserve" width="100%" height="100%">

        <g id="floorplan">
            <path fill="#ED1C24" d="M35.8,51.8h36.3c1.6,0,2.8-1.3,2.8-2.8V22.1c0-1.6-1.3-2.8-2.8-2.8H35.8c-1.6,0-2.8,1.3-2.8,2.8v26.8
                C33,50.5,34.3,51.8,35.8,51.8z"/>
            <path fill="#4A68B1" d="M209.8,114.3h36.3c1.6,0,2.8-1.3,2.8-2.8V84.6c0-1.6-1.3-2.8-2.8-2.8h-36.3c-1.6,0-2.8,1.3-2.8,2.8v26.8
                C207,113,208.3,114.3,209.8,114.3z"/>
            <path fill="#F8991D" d="M134.3,158.8h36.3c1.6,0,2.8-1.3,2.8-2.8v-26.8c0-1.6-1.3-2.8-2.8-2.8h-36.3c-1.6,0-2.8,1.3-2.8,2.8v26.8
                C131.5,157.5,132.8,158.8,134.3,158.8z"/>
            <path fill="#ed2590" d="M13.1,124.3h36.3c1.6,0,2.8-1.3,2.8-2.8V94.6c0-1.6-1.3-2.8-2.8-2.8H13.1c-1.6,0-2.8,1.3-2.8,2.8v26.8
                C10.2,123,11.5,124.3,13.1,124.3z"/>
            <path fill="#356732" d="M161.1,42.5h36.3c1.6,0,2.8-1.3,2.8-2.8V12.8c0-1.6-1.3-2.8-2.8-2.8h-36.3c-1.6,0-2.8,1.3-2.8,2.8v26.8
                C158.2,41.2,159.5,42.5,161.1,42.5z"/>
        </g>
    </svg>
</div>

这就是它的样子:

这就是我点击红色路径后想要的:

【问题讨论】:

    标签: javascript jquery html d3.js svg


    【解决方案1】:

    @Alexander,打败我了,但这里有一个更多的 d3 实现:

    <!DOCTYPE html>
    <html>
    
    <head>
      <script data-require="d3@4.0.0" data-semver="4.0.0" src="https://d3js.org/d3.v4.min.js"></script>
    </head>
    
    <body>
      <div style="width: 700px; height:600px; border:1px solid #d0d0d0; background: #e8e8e8; margin: 0 auto;">
        <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 255.1 170.1" style="enable-background:new 0 0 255.1 170.1;" xml:space="preserve" width="100%" height="100%">
          <g id="floorplan">
            <path fill="#ED1C24" d="M35.8,51.8h36.3c1.6,0,2.8-1.3,2.8-2.8V22.1c0-1.6-1.3-2.8-2.8-2.8H35.8c-1.6,0-2.8,1.3-2.8,2.8v26.8
                    C33,50.5,34.3,51.8,35.8,51.8z"></path>
            <path fill="#4A68B1" d="M209.8,114.3h36.3c1.6,0,2.8-1.3,2.8-2.8V84.6c0-1.6-1.3-2.8-2.8-2.8h-36.3c-1.6,0-2.8,1.3-2.8,2.8v26.8
                    C207,113,208.3,114.3,209.8,114.3z"></path>
            <path fill="#F8991D" d="M134.3,158.8h36.3c1.6,0,2.8-1.3,2.8-2.8v-26.8c0-1.6-1.3-2.8-2.8-2.8h-36.3c-1.6,0-2.8,1.3-2.8,2.8v26.8
                    C131.5,157.5,132.8,158.8,134.3,158.8z"></path>
            <path fill="#ed2590" d="M13.1,124.3h36.3c1.6,0,2.8-1.3,2.8-2.8V94.6c0-1.6-1.3-2.8-2.8-2.8H13.1c-1.6,0-2.8,1.3-2.8,2.8v26.8
                    C10.2,123,11.5,124.3,13.1,124.3z"></path>
            <path fill="#356732" d="M161.1,42.5h36.3c1.6,0,2.8-1.3,2.8-2.8V12.8c0-1.6-1.3-2.8-2.8-2.8h-36.3c-1.6,0-2.8,1.3-2.8,2.8v26.8
                    C158.2,41.2,159.5,42.5,161.1,42.5z"></path>
          </g>
        </svg>
      </div>
    
      <script>
    
        var svg = d3.select("svg"),
            g = svg.select("g");
            
        var v = svg.attr("viewBox").split(" "),
            width = v[2],
            height = v[3];
        
        svg.on("click", function(d){
          g.attr("transform", "translate(" + [0,0] + ")scale(" + 1 + ")");
        });
    
        d3.selectAll("path")
          .on("click", function() {
            var bbox = this.getBBox(),
                dx = bbox.width - bbox.x,
                dy = bbox.height - bbox.y,
                x = (bbox.x + (bbox.x + bbox.width)) / 2,
                y = (bbox.y + (bbox.y + bbox.height)) / 2,
                scale = Math.min(height / bbox.height, width / bbox.width),
                translate = [width / 2 - scale * x, height / 2 - scale * y];
              
              g.attr("transform", "translate(" + translate + ")scale(" + scale + ")");
              
              d3.event.stopPropagation();
          });
      </script>
    
    </body>
    
    </html>

    【讨论】:

    • 哦,是的!我的解决方案并不优雅,因为我没有使用 d3,而只使用了 jQuery。我会考虑你的经验,@Mark。
    • 你救了我。谢谢
    【解决方案2】:

    使用单击的path 元素的transform attribute 来缩放和平移实体。在下面的示例中,我使用了 svg 元素的高度和宽度的常量,但它可以帮助您入门。

    $("#floorplan path").click(function() {
      if ($(this).attr("transform")) {
        $(this).removeAttr("transform");
        $("#floorplan path:not([transform])").show();
      } else {
        var objRect = this.getBoundingClientRect();
        var svgRect = $("#Layer_1")[0].getBoundingClientRect();
        var scaleX = svgRect.width / 255.1;
        var scaleY = svgRect.height / 170.1;
        var newX = (svgRect.left - objRect.left) / scaleX;
        var newY = (svgRect.top - objRect.top) / scaleY;
        var xScale = svgRect.width / objRect.width;
        var yScale = svgRect.height / objRect.height;
        $(this).attr("transform", "matrix(" + xScale + " 0 0 " + yScale + " " + newX * xScale + " " + newY * yScale + ")");
        $("#floorplan path:not([transform])").hide();
      }
    });
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <div style="width: 700px; height:600px; border:1px solid #d0d0d0; background: #e8e8e8; margin: 0 auto;">
      <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 255.1 170.1" xml:space="preserve">
            <g id="floorplan">
                <path fill="#ED1C24" d="M35.8,51.8h36.3c1.6,0,2.8-1.3,2.8-2.8V22.1c0-1.6-1.3-2.8-2.8-2.8H35.8c-1.6,0-2.8,1.3-2.8,2.8v26.8
                    C33,50.5,34.3,51.8,35.8,51.8z"/>
                <path fill="#4A68B1" d="M209.8,114.3h36.3c1.6,0,2.8-1.3,2.8-2.8V84.6c0-1.6-1.3-2.8-2.8-2.8h-36.3c-1.6,0-2.8,1.3-2.8,2.8v26.8
                    C207,113,208.3,114.3,209.8,114.3z"/>
                <path fill="#F8991D" d="M134.3,158.8h36.3c1.6,0,2.8-1.3,2.8-2.8v-26.8c0-1.6-1.3-2.8-2.8-2.8h-36.3c-1.6,0-2.8,1.3-2.8,2.8v26.8
                    C131.5,157.5,132.8,158.8,134.3,158.8z"/>
                <path fill="#ed2590" d="M13.1,124.3h36.3c1.6,0,2.8-1.3,2.8-2.8V94.6c0-1.6-1.3-2.8-2.8-2.8H13.1c-1.6,0-2.8,1.3-2.8,2.8v26.8
                    C10.2,123,11.5,124.3,13.1,124.3z"/>
                <path fill="#356732" d="M161.1,42.5h36.3c1.6,0,2.8-1.3,2.8-2.8V12.8c0-1.6-1.3-2.8-2.8-2.8h-36.3c-1.6,0-2.8,1.3-2.8,2.8v26.8
                    C158.2,41.2,159.5,42.5,161.1,42.5z"/>
            </g>
        </svg>
    </div>

    您可以更正thansformation matrix 以与预期结果完全匹配。

    【讨论】:

    • 感谢您的努力和帮助
    猜你喜欢
    • 2018-08-20
    • 2021-09-30
    • 2021-12-01
    • 2023-03-27
    • 2012-04-22
    • 2022-01-12
    • 2020-10-12
    • 2020-04-08
    • 2023-03-03
    相关资源
    最近更新 更多