D3将对象设置为路径上特定点的动画

时间:2016-12-28 20:52:37

标签: javascript animation d3.js svg path

经过几个小时的尝试,我自己放弃了。我来这里寻求帮助。

我试图沿着通往基本路径特定部分的路径为对象设置动画。我想使用D3,所以我也可以放松动画。

为了说明动画本身,我已经包含了一个基础路径(单击GO按钮以查看此动画)我希望对象的动画就像覆盖路径一样(所以它是这条路径的尖端&# 39;结束。)

能够调用一个函数说moveTo(from,to){}为该段的路径设置动画,这将是我需要的。我不希望它移动到一个点,但是例如如果它在拐角曲线之前,它应该遵循该曲线,就像整个动画过渡()它没有。如果可能的话,不要突然停止,而是在停止时放松。



/* D3.JS CODE */

// TODO: MOVE TO SPECIFIC PART ON THE PATH
// TODO: CENTER OBJ ON PATH

var width = 436,
  height = 245;

var svg = d3.select("#svg");

var path = d3.select("#base");

var circle = svg.append("rect")
  .attr("width", 20)
  .attr("height", 20)
  .attr("fill", "#FFF")
  .attr("transform", "translate(-10,-10)");

function transition() {
  circle.transition()
    .duration(2000)
    .attrTween("transform", translateAlong(path.node()));
}

// WAIT UNTIL PATH IS DRAWN
setTimeout(function(){
	transition();
}, 2000);

// Returns an attrTween for translating along the specified path element.
var to = 20;
var from = 0;

function translateAlong(path) {
  var t0 = from;
  var t = from;
  var l = path.getTotalLength();
  return function(d, i, a) {
    return function(t) {
      var p0 = path.getPointAtLength(t0 * l); //previous point
      var p = path.getPointAtLength(t * l); ////current point
      var angle = Math.atan2(p.y - p0.y, p.x - p0.x) * 180 / Math.PI; //angle for tangent
      t0 = t;
      // TRANSFORM
      // BUG: (p.x-10) + "," + (p.y-10) DOES NOT WORK WELL
      return "translate(" + p.x + "," + p.y + ") rotate(" + angle + ")";
    };
  };
}

// ----------------------------------

/* JQUERY CODE THAT CONTROLS THE UNDERLYING PATH */
$path = $('#base').attr('d');
$('.progressPath, .progressPathBlur').attr('d', $path);
var basePath = document.querySelector('.basePath');
var pathLength = basePath.getTotalLength();
var sylCount = 0;
var rowCount = 0; // ROW 1
$('path').css('stroke-dasharray', pathLength).css('stroke-dashoffset', pathLength);
// SIMULATE PAGE LOAD
setTimeout(function() {
  // DONE SETTING UP REMOVE LOADING FROM BODY
  $('path').removeClass('loading').addClass('on');
  $('.basePath').css('stroke-dashoffset', 0);
}, 1000);

// PROGRESS BAR PATH BASED ON SYLLABLES
function animateProgress(row, val) {
  if (row === 2 && val == 7) {
    return false;
  }
  $stop = pathLength;
  max = pathLength;
  corner = pathLength / 100 * 6.25;
  // TODO: COMPRESS MATH TO SINGLE LINES AFTER TESTING
  if (row === 0) {
    // ROW 1
    max = 5;
    rowAdd = corner; // ADD FIRST CORNER
    if (val == max) {
      rowAdd = corner * 2; // PROGRESS A LITTLE FURTHER TO INDICATE LINE CAN BE WRITTEN ON
    }
  }
  if (row === 1) {
    // ROW 2
    max = 7;
    rowAdd = 371.77 + (corner * 2); // + CORNER THAT DONT BELONG TO NEXT ROW
    if (val == max) {
      rowAdd = 371.77 + (corner * 3);
    }
  }
  if (row === 2) {
    // ROW 3
    max = 5;
    rowAdd = (371.77 * 2) + (corner * 3); // + CORNERS THAT DONT BELONG TO NEXT ROW
    if (val == max) {
      rowAdd = (371.77 * 2) + (corner * 4);
    }
  }
  // SET WHERE THE LINE SHOULD ANIMATE TO (STOP)
  if (val <= max) { // ADD AS LONG AS ROW IS NOT COMPLETE
    $stop = rowAdd + (3.71 * (val / max * 100));
    $stop = pathLength - $stop;
  }

  // SPECIAL CIRCUMSTANCE
  if (row === 2 && val === 5) {
    // DON'T OVERSHOOT LAST STEP
    $('.progressPath, .progressPathBlur').removeClass('on'); // TODO: RESET IN OTHER CASES
  } else {
    $('.progressPath, .progressPathBlur').addClass('on');
  }

  // ANIMATE PATH
  $('.progressPath, .progressPathBlur').css('stroke-dashoffset', $stop);
};

$('#go').on('click', function(e) {
  // ADD STEP
  sylCount++;

  if (sylCount == 6 && rowCount == 0) { // FIRST COMPLETED MOVE TO 2ND
    rowCount = 1;
    sylCount = 1;
  }
  if (sylCount == 8 && rowCount == 1) { // ROW TWO COMPLETE GO TO THIRD
    // 
    rowCount = 2;
    sylCount = 1;
  }
  if (sylCount == 6 && rowCount == 2) { // THIRD COMPLETED
    return false;
  }
  animateProgress(rowCount, sylCount);

  e.preventDefault();
  return false
});
//
&#13;
html,
body {
  width: 100%;
  height: 100%;
  overflow: hidden;
  background: radial-gradient(circle at 1.98% 14.97%, #556270, transparent 100%), radial-gradient(circle at 98.02% 52.96%, #FF6B6B, transparent 100%), radial-gradient(circle at 50% 50%, #4a2735, #4a2735 100%);
}

#svg {
  /* | RATIO | 1:0.78 | */
  /* | TRUE SIZE: 354*198PX | */
  /* NOW SCALE BASED ON RATIO & PAGE WIDTH */
  width: 50vw;
  height: 29vw;
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
}

.basePath,
.progressPath,
.progressPathBlur {
  fill: none;
  stroke: inherit;
  stroke-width: 4;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-linejoin: arcs;
  stroke-miterlimit: 20;
  transition: all 2s ease-in-out;
}

.progressPath {
  stroke-width: 5;
  opacity: 0.8;
  filter: blur(2px);
  stroke: rgb(255, 255, 255);
transition: all 2s cubic-bezier(0.68, -0.55, 0.265, 1.55);
}

.progressPathBlur {
  stroke-width: 5;
  z-index: 999;
  filter: url(#blurFilter);
  opacity: 1;
  transition: all 2s cubic-bezier(0.68, -0.55, 0.265, 1.55);
  stroke: rgb(255, 255, 255);
}

.loading {
  transition: all 0s;
}

.basePath.on {
  transition: all 2s ease-in-out;
}

#go {
  padding: 0;
  position: absolute;
  bottom: 5%;
  right: 5%;
  height: 50px;
  width: 50px;
  border-radius: 100%;
  text-align: center;
  background: salmon;
  cursor: pointer;
  z-index: 111;
  opacity: 0.5;
  line-height: 50px;
}
&#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 xmlns="http://www.w3.org/2000/svg" version="1.1" x="0" y="0" width="100%" height="100%" viewBox="0 0 435 245" preserveAspectRatio="xMidYMid meet" id="svg">
    <filter id="blurFilter" x="-20" y="-20" width="30" height="30">
      <feGaussianBlur in="SourceGraphic" stddeviation="8"></feGaussianBlur>
    </filter>
    <path class="basePath loading" id="base" style="stroke:#FC604D" d="M32 2C15.4 2 2 15.3 2 31.9s13.4 29.9 30 29.9l370-.2c16.6 0 30 13.4 30 30s-13.4 30-30 30l-370 .2c-16.6 0-30 13.7-30 30.2s13.4 30.5 30 30.5h370c16.6 0 30 12.9 30 29.5s-13.4 29.5-30 29.5"
    />
    <path class="progressPathBlur loading" d=""
    />
    <path class="progressPath loading" d="" />
  </svg>

<div id="go">
  GO
</div>
&#13;
&#13;
&#13;

如果可能的话,可以执行此操作的方法会考虑可能的屏幕大小调整。 非常感谢任何帮助。

0 个答案:

没有答案