D3沿路径停止并重新启动过渡,以允许单击进入地理数据坐标 [英] D3 stop and restart transition along path to allow click through to geo data coordinates
问题描述
我正在尝试使用D3暂停和恢复沿此示例所示路径的标记的过渡 D3沿路径段过渡,并在坐标值处暂停.我通过单击标记来开始转换,并且希望能够停止它,然后在单击它时重新启动它-此时它会暂停一段时间然后再启动.
Hi I’m trying to use D3 to pause and resume a transition of a marker along a path like this example D3 tween - pause and resume controls plus stop the marker's transition on a particular data point like this D3 transition along segments of path and pause at coordinate values. I am starting the transition by clicking on the marker and would like to be able to stop it and then restart it when it is clicked – at the moment it pauses for a period and then starts.
我希望能够完全停止标记,因此我可以处理该点,即根据其json数据单击特定链接的点的xlink:href,然后离开页面-然后返回标记过渡,并从停止的同一点恢复过渡.
I’d like to be able to stop the marker completely so I can do something with the point ie click through to xlink:href for a particular clicked point based on its json data and so leave the page - and then return to the marker transition and resume the transition from the same point it stopped.
我认为我需要将pauseValues传递到转换函数中,但根本不了解如何执行此操作.
I think I need to pass the pauseValues into the transition function but just can’t understand how to do this.
这是我的代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<style type="text/css">
body {
font-family: "Helvetica Neue", Helvetica, sans-serif;
color: red;
}
circle {
fill: steelblue;
stroke: steelblue;
stroke-width: 3px;
}
.point {
fill: green;
}
.line {
fill: none;
stroke: red;
stroke-width: 4;
stroke-dasharray: 4px, 8px;
}
</style>
<body>
<script>
var width = 960,
height = 500;
var data = [
[610.4199794444444, 243.7191682432953], //Paris
[480, 200],
[580, 400],
[680, 100],
[780, 300],
[180, 300],
[280, 100],
[380, 400]
];
var duration = 20000/data.length,
pauseTime = 2000;
var line = d3.line()
.x(function(d) {
return (d)[0];
})
.y(function(d) {
return (d)[1];
});
var svg = d3.select("body")
.append("svg")
.attr("width", width)
.attr("height", height);
//path to animate - marker transitions along this path
var path = svg.append("path")
.data([data])
.attr("d", line)
.attr('class', 'line')
.attr("d", function(d) {
return line(d)
});
//Want to activate circles when marker paused on them - intention is to have on click to href and stop marker while href is displayed
svg.selectAll("circle")
.data(data)
.enter()
.append("circle")
.attr("class", "point")
.attr("r", 10)
.attr("transform", function(d) {
return "translate(" + d + ")";
})
.on('click', function(d, i) {
d3.select(this)
.style("fill", "pink")
//sample - data will be for each point and based on the geojson in real example
.append("a")
.attr("xlink:href", "http://collections.anmm.gov.au/en/objects/details/11429/")
pausePoints.push(i);
console.log("pausePoints_push_i: " +pausePoints.push(i));
console.log("pausePoints: " + pausePoints);
if (pausePoints.length === 1)
transition();
});
var marker = svg.append("circle")
.attr("r", 19)
.attr("transform", "translate(" + (data[0]) + ")")
.on('click', function(d, i) {
d3.select(this)
.style("fill", "pink")
pausePoints.push(i);
if (pausePoints.length === 1)
setTimeout(function() {
pauseValues.lastTime = pauseValues.currentTime;
}, 100);
transition();
});
var pauseValues = {
lastTime: 0,
currentTime: 0
};
var pausePoints = [],
iter = 0,
transData = data.slice();
function transition() {
marker.transition()
.ease(d3.easeLinear)
.duration(duration - (duration * pauseValues.lastTime))
.attrTween("transform", function(){
var p0 = transData.shift(),
p1 = transData[0];
m = (p0[1] - p1[1]) / (p0[0] - p1[0]),
b = p0[1] - (m * p0[0]),
i = d3.interpolateNumber(p0[0], p1[0]);
return function(t){
//console.log("T: " +t);
var x = i(t),
y = m*x + b;
return "translate(" + x + "," + y + ")";
}
})
.on("end", function(){
if (transData.length <= 1) return;
iter++;
setTimeout(transition, pausePoints.indexOf(iter) !== -1 ? pauseTime : 0);
});
};
</script>
</body>
推荐答案
我为您解决了最后一个问题.从我编写的代码中,您引入了此变量pauseValues
,它打算做什么?据我所知,它尝试根据先前的暂停来调整持续时间;只有在所有路径上进行长时间过渡时,才需要此功能.我的代码将每个分支作为单个过渡运行.如果您想暂停并继续点击,这里有一个简单的重构方法:
I helped you with your last question. From the code I wrote, you introduced this variable pauseValues
, what is it intended to do? From what I can tell, it attempts to adjust the duration based on previous pauses; you only needed this when you were running one long transition across all the paths. My code runs each leg as a single transition. If you want to pause and resume on click here's a simple refactor:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<style type="text/css">
body {
font-family: "Helvetica Neue", Helvetica, sans-serif;
color: red;
}
circle {
fill: steelblue;
stroke: steelblue;
stroke-width: 3px;
}
.point {
fill: green;
}
.line {
fill: none;
stroke: red;
stroke-width: 4;
stroke-dasharray: 4px, 8px;
}
</style>
<body>
<script>
var width = 960,
height = 500;
var data = [
[610.4199794444444, 243.7191682432953], //Paris
[480, 200],
[580, 400],
[680, 100],
[780, 300],
[180, 300],
[280, 100],
[380, 400]
];
var duration = 20000 / data.length,
pauseTime = 2000;
var line = d3.line()
.x(function(d) {
return (d)[0];
})
.y(function(d) {
return (d)[1];
});
var svg = d3.select("body")
.append("svg")
.attr("width", width)
.attr("height", height);
//path to animate - marker transitions along this path
var path = svg.append("path")
.data([data])
.attr("d", line)
.attr('class', 'line')
.attr("d", function(d) {
return line(d)
});
//Want to activate circles when marker paused on them - intention is to have on click to href and stop marker while href is displayed
svg.selectAll("circle")
.data(data)
.enter()
.append("circle")
.attr("class", "point")
.attr("r", 10)
.attr("transform", function(d) {
return "translate(" + d + ")";
})
.on('click', function(d, i) {
d3.select(this)
.style("fill", "pink")
//sample - data will be for each point and based on the geojson in real example
.append("a")
.attr("xlink:href", "http://collections.anmm.gov.au/en/objects/details/11429/")
pausePoints.push(i);
if (pausePoints.length === 1)
transition();
});
var marker = svg.append("circle")
.attr("r", 19)
.attr("transform", "translate(" + (data[0]) + ")")
.on('click', function(d, i) {
transition();
});
var pausePoints = [],
iter = 0;
transData = data.slice();
function transition() {
marker.transition()
.ease(d3.easeLinear)
.duration(duration)
.attrTween("transform", function() {
var p0 = transData.shift(),
p1 = transData[0],
m = (p0[1] - p1[1]) / (p0[0] - p1[0]),
b = p0[1] - (m * p0[0]),
interp = d3.interpolateNumber(p0[0], p1[0]);
return function(t) {
var x = interp(t),
y = m * x + b;
return "translate(" + x + "," + y + ")";
}
})
.on("end", function() {
iter++;
if (
transData.length <= 1 || // out of points
pausePoints.indexOf(iter) !== -1) // on a clicked point
{
return;
}
transition();
});
};
</script>
</body>
这篇关于D3沿路径停止并重新启动过渡,以允许单击进入地理数据坐标的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!