为什么旋转元件会反弹?

时间:2017-09-05 16:58:37

标签: javascript d3.js

我有一个svg元素,我正在为它添加一个简单的旋转属性。 问题是,我希望元素相对于自身的中心旋转,而不是整个svg,所以我指定旋转的x和y,但它有一个奇怪的弹性效果。

let currentAngle = 0;

function rotate() {
  d3.select('.group1')
  .transition()
  .attr('transform', function() {
    let bb = this.getBBox();
    let rx = bb.x + bb.width / 2;
    let ry = bb.y + bb.height / 2;
    
    currentAngle += 90;
    
    return `rotate(${currentAngle}, ${rx}, ${ry})`;
    
  });
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<svg viewbox="0 0 1600 1600" width="500" height="500">
  <g class="group1" onclick="rotate()">
    <rect x="250" y="250" width="100" height="100" />
    <circle cx="420" cy="300" r="50" />
  </g>
</svg>

作为替代方案,我尝试在css上添加transform-origin,类似于transform-origin: 800px 800px;(但当然有效中心px),虽然它在Chrome中有效但在IE和Safari中无效

为什么在旋转时提供x和y使我的元素反弹?

2 个答案:

答案 0 :(得分:2)

这个问题涉及到一些问题。这是解释一下发生了什么的问题:D3.js animate rotation

Mike Bostock在这里做的方式:https://bl.ocks.org/mbostock/3305854是将对象放在<g>中,然后转换到你想要的位置然后旋转。这可能是获得精彩动画的最简单方法。例如:

&#13;
&#13;
let currentAngle = 0;

function rotate() {
  d3.select('rect')
  .transition()
  .attr('transform', function() {
    let bb = this.getBBox();
    let rx = bb.x + bb.width / 2;
    let ry = bb.y + bb.height / 2;
    
    currentAngle += 45;
    
    return `rotate(${currentAngle}, ${rx}, ${ry})`;
    
  });
} 
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<svg viewbox="0 0 1600 1600" width="500" height="500">
<g transform="translate(250, 250)">
  <rect x="-50", y="-50" width="100" height="100" onclick="rotate()" />
</g>
</svg>
&#13;
&#13;
&#13;

答案 1 :(得分:1)

看看这个不同的

如果select idclassrotate慢慢地,你会看到中间旋转的红点一点一点地移动,但是{{1} } select我认为它更稳定而不像id select更强大地弹跳

&#13;
&#13;
class
&#13;
let currentAngle = 0;
let currentAngle2 = 0;

function rotate() {

  d3.select('#aa')
  
  .transition()
  .duration(300)
  .attr('transform', function() {
    let bb = this.getBBox();
    let rx = bb.x + bb.width / 2;
    let ry = bb.y + bb.height / 2;
         d3.select(this).append('circle')
    .attr('cx',rx)
    .attr('cy',ry)
    .attr('r',20)
    .attr('fill','red')
    currentAngle += 10;
    return `rotate(${currentAngle}, ${rx}, ${ry})`;
    
  });
}

function rotate2() {
  d3.selectAll('.aa')
  .transition()
  .attr('transform', function() {
    let bb = this.getBBox();
    let rx = bb.x + bb.width / 2;
    let ry = bb.y + bb.height / 2;
             d3.select(this).append('circle')
    .attr('cx',rx)
    .attr('cy',ry)
    .attr('r',20)
    .attr('fill','red')
    currentAngle2 += 10;
    return `rotate(${currentAngle2}, ${rx}, ${ry})`;
    
  });
}
&#13;
&#13;
&#13;

然后,如果你用苛刻的价值(大值)反弹,你会看到红点反弹,但再次<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <svg viewbox="0 0 1600 1600" width="500" height="500"> <g id ='aa' onclick="rotate()"> <rect x="100", y="100" width="100" height="100" /> <circle cx="250" cy="150" r="50"/> </g> <g class ='aa' onclick="rotate2()"> <rect x="600", y="100" width="100" height="100" /> <circle cx="750" cy="150" r="50" /> </g> </svg> select做得更稳定

&#13;
&#13;
id
&#13;
let currentAngle = 0;
let currentAngle2 = 0;

function rotate() {

  d3.select('#aa')
  
  .transition()
  .duration(300)
  .attr('transform', function() {
    let bb = this.getBBox();
    let rx = bb.x + bb.width / 2;
    let ry = bb.y + bb.height / 2;
         d3.select(this).append('circle')
    .attr('cx',rx)
    .attr('cy',ry)
    .attr('r',20)
    .attr('fill','red')
    currentAngle += 90;
    return `rotate(${currentAngle}, ${rx}, ${ry})`;
    
  });
}

function rotate2() {
  d3.selectAll('.aa')
  .transition()
  .attr('transform', function() {
    let bb = this.getBBox();
    let rx = bb.x + bb.width / 2;
    let ry = bb.y + bb.height / 2;
             d3.select(this).append('circle')
    .attr('cx',rx)
    .attr('cy',ry)
    .attr('r',20)
    .attr('fill','red')
    currentAngle2 += 90;
    return `rotate(${currentAngle2}, ${rx}, ${ry})`;
    
  });
}
&#13;
&#13;
&#13;

解决方案

  

你必须慢慢地旋转到终点,你可以做补间   使用<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <svg viewbox="0 0 1600 1600" width="500" height="500"> <g id ='aa' onclick="rotate()"> <rect x="100", y="100" width="100" height="100" /> <circle cx="250" cy="150" r="50"/> </g> <g class ='aa' onclick="rotate2()"> <rect x="600", y="100" width="100" height="100" /> <circle cx="750" cy="150" r="50" /> </g> </svg>,然后繁荣......它完全按d3.interpolate或者{。}旋转   id

&#13;
&#13;
class
&#13;
let currentAngle = 0;
let currentAngle2 = 0;

function rotate() {

  d3.select('#aa')
  
  .transition()
  .duration(300)
  .attrTween("transform", tween);
  /*
  .attr('transform', function() {
    let bb = this.getBBox();
    let rx = bb.x + bb.width / 2;
    let ry = bb.y + bb.height / 2;
         d3.select(this).append('circle')
    .attr('cx',rx)
    .attr('cy',ry)
    .attr('r',20)
    .attr('fill','red')
    currentAngle += 10;
   // console.log(rx,ry,currentAngle)
   
    return `rotate(${currentAngle}, ${rx}, ${ry})`;
    
  });
  */

    function tween(d, i, a) {
        let bb = this.getBBox();
    let rx = bb.x + bb.width / 2;
    let ry = bb.y + bb.height / 2;
         d3.select(this).append('circle')
    .attr('cx',rx)
    .attr('cy',ry)
    .attr('r',20)
    .attr('fill','red')
    var e = `rotate(${currentAngle}, ${rx}, ${ry})`
    currentAngle += 90;
    var o = `rotate(${currentAngle}, ${rx}, ${ry})`
      return d3.interpolateString(e,o);
    }

  

}

function rotate2() {

  d3.selectAll('.aa')
  .transition()
  .duration(300)
  .attrTween("transform", tween);
  /*
  .attr('transform', function() {
    let bb = this.getBBox();
    let rx = bb.x + bb.width / 2;
    let ry = bb.y + bb.height / 2;
             d3.select(this).append('circle')
    .attr('cx',rx)
    .attr('cy',ry)
    .attr('r',20)
    .attr('fill','red')
    currentAngle2 += 10;
   // console.log(rx,ry,currentAngle)
   
    return `rotate(${currentAngle2}, ${rx}, ${ry})`;
    
  });
  */
  
  function tween(d, i, a) {
        let bb = this.getBBox();
    let rx = bb.x + bb.width / 2;
    let ry = bb.y + bb.height / 2;
         d3.select(this).append('circle')
    .attr('cx',rx)
    .attr('cy',ry)
    .attr('r',20)
    .attr('fill','red')
    var e = `rotate(${currentAngle2}, ${rx}, ${ry})`
    currentAngle2 += 90;
    var o = `rotate(${currentAngle2}, ${rx}, ${ry})`
      return d3.interpolateString(e,o);
    }

}
&#13;
&#13;
&#13;