经过几个小时的尝试,我自己放弃了。我来这里寻求帮助。
我试图沿着通往基本路径特定部分的路径为对象设置动画。我想使用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;
如果可能的话,可以执行此操作的方法会考虑可能的屏幕大小调整。 非常感谢任何帮助。