SVG和D3.js在翻译后发出正确的旋转问题

时间:2015-07-09 18:48:54

标签: d3.js svg

在我做以下事情之后,我一直在努力争取如何获得正确的旋转中心点:

1)将盒子拖到靠近屏幕中心的位置

2)按下测试按钮将盒子旋转90度

3)将盒子拖到另一个位置

4)再次按下测试按钮再旋转90度(180)

5)关闭所产生的旋转和平移。如果我将其旋转到0度并拖动框然后点击测试按钮它正确旋转它工作正常。 请看我的代码:

enter code here https://jsfiddle.net/1ctqckhL/3/

1 个答案:

答案 0 :(得分:0)

如果您选择正确的组元素以启用旋转,则更容易。假设你希望它围绕svg元素的中心旋转(即在十字线周围),你可以这样做......

要点

  • 变换container2所以(0,0)在旋转原点上 这意味着翻译和轮换是分离的
  • 仅更改move_path
  • 中的轮播
  • 仅更改zoomed
  • 中的翻译
  • 使用d3.transform管理转换元素
  • 使用模运算符(%
  • 简化轮换计数器
  • 将偏移量添加到rect的初始位置以进行概括

工作代码



var container2;
  var last_scale = 1;
  var last_rotation = [0, 0, 0];
  var last_translate = [0, 0];
  var zoom;
  w = window.innerWidth;
  h = window.innerHeight;
  var offsetx = w / 4;
  var offsety = h / 4;

  d3.select("#container3").attr("transform", function() {
    var tr = d3.transform(d3.select(this).attr("transform"));
    return (tr.translate = [offsetx, offsety], tr.toString())
  });

  //  document.getElementById("mid_x").style.top = h / 2 + 'px';
  //  document.getElementById("mid_y").style.left = w / 2 + 'px';
  d3.select("#test_btn").style({
    top: h - 50 + "px",
    left: "10%"
  });
  zoom = d3.behavior.zoom()
    .center([w / 2, h / 2])
    .scaleExtent([1, 10])
    .on("zoom", zoomed);

  var svg = d3.select("#svg_main")
    .attr("width", w)
    .attr("height", h);
  svg.append("path").attr("d", "M" + [w / 2, 0] + "L" + [w / 2, h]).style({
    stroke: "red"
  })
  svg.append("path").attr("d", "M" + [0, h / 2] + "L" + [w, h / 2]).style({
    stroke: "red"
  });

  var container2 = d3.select("#container2")
    .attr("transform", "translate(" + zoom.center() + ")")
  .call(zoom),

    //////////////////////////////////////////////////////////////////////////////////////////////////
    //include scaling and fix text just for demo...
    container3 = container2.select("#container3").attr("transform", function() {
      var tr = d3.transform(d3.select(this).attr("transform"));
      return (tr.scale = [h / 955, h / 955], tr.toString())
    });
  container3.selectAll("text").style("font-size", (12 * 955 / h) + "px").attr("dy", "0.35em");
  //////////////////////////////////////////////////////////////////////////////////////////////////

  var trans2 = d3.transform(container2.attr("transform"));
  container2.select("#container3").attr("transform", function() {
    var tr = d3.transform(d3.select(this).attr("transform"));
    return (tr.translate = [offsetx - trans2.translate[0], offsety - trans2.translate[1]], tr.toString())
  })
  d3.selectAll("#test_btn").on("click", move_path);

  function move_path() {

    last_rotation[0] = (last_rotation[0] += 90) % 360;

    container2.attr("transform", function() {
      var tr = d3.transform(d3.select(this).attr("transform"));
      return (tr.rotate = last_rotation, tr.toString())
    });

  }

  function zoomed() {

    d3.select(this).selectAll("g").attr("transform", function() {
      var trf = d3.transform(d3.select(this).attr("transform")),
        trn = d3.event.translate;
      return (trf.translate = [offsetx - trans2.translate[0] + trn[0], offsety - trans2.translate[1] + trn[1]], trf.toString())
    })
  }

svg {
  display: block;
  overflow: visible;
  background: #9F0;
  outline: 1px solid red;
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div style="width:100%;height:100%;border:1px solid blue;position:absolute;left:0px;top:0px;overflow:hidden;">
  <div id="map_div" style="position:relative;left:0px;top:0px;border:0px solid red;width:100%;height:100%;overflow:hidden;">
    <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="svg_main" style="border:1px solid red;">
      <g id="container1">
        <g id="container2">zoom and rotate
          <g id="container3"> offset, drag and global scale
            <rect y="0" x="0" fill="#00AEEF" stroke="#000000" width="300" height="300" />
            <text transform="matrix(1 0 0 1 90 8.167)" font-family="'MyriadPro-Regular'" font-size="12">top</text>
          </g>
        </g>
      </g>
    </svg>
    <!--<div id="mid_x" style="height:1px;background:red;width:100%;position:absolute;top:500px;left:0px;"></div>-->
    <!--<div id="mid_y" style="height:100%;background:red;width:1px;position:absolute;top:0px;"></div>-->
  </div>
</div>
<div id="map_holder" style="display:none;"></div>
<input id="test_btn" type="button" style="position:absolute;top:500px;left:100px;" value="rotate">
&#13;
&#13;
&#13;