Make Multiple Line With Animation From The Last Position To The New Positions
Solution 1:
Is it something like this that your are looking for?
There is a variable that stores the last data points for each series (if it exists, or create a new entry in the lastData array if there is no last data point for this series) and starts the new paths from these values. So even if you add new series of data, this should take care of creating a new line automatically.
Note: this uses D3.v4 (and not D3.v3 as in your example), since v3 is not maintained anymore.
var svg = d3.select('svg');
var backLayer = svg.append("g");
//variable to store last data points the paths will have to start fromlet lastData = []
//color scaleconst colorScale = d3.scaleOrdinal()
.domain([0, 1, 2])
.range(["blue", "red", "green"])
//line generatorlet lineGenerator = d3.line()
.x(function(d) {
return d.corriente
})
.y(function(d) {
return d.voltaje
})
.curve(d3.curveBasis)
functionextractLastPoint(data){
let lastDataPoint = []
data.forEach(d => {
lastDataPoint.push(d[d.length-1])
})
return lastDataPoint
}
functiondisplayLine(data) {
//adjust lastData array if discrepency of sizeif (lastData.length<data.length) {
let diffSize = data.length - lastData.lengthlet firstPos = data.length - diffSize
for (let i=firstPos; i<data.length; i++){
lastData.push(data[i][0])
}
}
//add a path for each series and animate it
data.forEach((d, i) => {
d.unshift(lastData[i])
let line = backLayer.append("path")
.datum(d)
.attr("d", p =>lineGenerator(p))
.attr("class", `line${i}`)
.attr("fill", "none")
.attr("stroke", colorScale(i))
.attr("stroke-width", "3px")
let totalLength = line.node().getTotalLength();
line
.attr("stroke-dasharray", totalLength + " " + totalLength)
.attr("stroke-dashoffset", totalLength)
.transition()
.duration(2000)
.ease(d3.easeLinear)
.attr("stroke-dashoffset", 0);
})
//save new last points of data to start next path from it
lastData = extractLastPoint(data)
}
//initial linelet dataSet=[
[
{ "voltaje": Math.random() * 200 + 10, "corriente": Math.random() * 550 + 10},
{ "voltaje": Math.random() * 200 + 10, "corriente": Math.random() * 550 + 10},
{ "voltaje": Math.random() * 200 + 10, "corriente": Math.random() * 550 + 10}
],
[
{ "voltaje": Math.random() * 200 + 10, "corriente": Math.random() * 550 + 10},
{ "voltaje": Math.random() * 200 + 10, "corriente": Math.random() * 550 + 10},
{ "voltaje": Math.random() * 200 + 10, "corriente": Math.random() * 550 + 10},
{ "voltaje": Math.random() * 200 + 10, "corriente": Math.random() * 550 + 10}
]
]
displayLine(dataSet)
//add new data every 3 sec
d3.interval(function() {
let dataSet=[
[
{ "voltaje": Math.random() * 200 + 10, "corriente": Math.random() * 550 + 10},
{ "voltaje": Math.random() * 200 + 10, "corriente": Math.random() * 550 + 10},
{ "voltaje": Math.random() * 200 + 10, "corriente": Math.random() * 550 + 10}
],
[
{ "voltaje": Math.random() * 200 + 10, "corriente": Math.random() * 550 + 10},
{ "voltaje": Math.random() * 200 + 10, "corriente": Math.random() * 550 + 10},
{ "voltaje": Math.random() * 200 + 10, "corriente": Math.random() * 550 + 10},
{ "voltaje": Math.random() * 200 + 10, "corriente": Math.random() * 550 + 10}
]
]
displayLine(dataSet)
}, 3000)
* {
margin: 0;
padding: 0;
border: 0;
}
body {
background: #ffd;
}
<scriptsrc="https://d3js.org/d3.v4.min.js"></script><svgwidth="800"height="800"></svg>
Solution 2:
first the example without your data the data is
dataSet = [{x,y},{x,y}]
newData = [last x and y, new data]
you want to change to
var dataSet=[
[
{ "voltaje": 10, "corriente": Math.random() * 130 + 10},
{ "voltaje": 40, "corriente": Math.random() * 130 + 10},
{ "voltaje": 70, "corriente": Math.random() * 130 + 10}
],
[
{ "voltaje": 100, "corriente": Math.random() * 130 + 10},
{ "voltaje": 130, "corriente": Math.random() * 130 + 10},
{ "voltaje": 160, "corriente": Math.random() * 130 + 10},
{ "voltaje": 190, "corriente": Math.random() * 130 + 10}
]
];
newData = [last voltaje and corriente, new data]
create new data holder like dataSet1
, push
all new variable there, when redraw set the parameter to point on your data, you can use index, then draw it
var svg = d3.select('svg');
var backLayer = svg.append("g");
var frontLayer = svg.append("g");
var dataSet=[
[
{ "voltaje": 10, "corriente": Math.random() * 130 + 10},
{ "voltaje": 40, "corriente": Math.random() * 130 + 10},
{ "voltaje": 70, "corriente": 30}
],
[
{ "voltaje": 70, "corriente": 30},
{ "voltaje": 130, "corriente": Math.random() * 130 + 10},
{ "voltaje": 160, "corriente": Math.random() * 130 + 10},
{ "voltaje": 190, "corriente": 30}
],
[
{ "voltaje": 190, "corriente": 30},
{ "voltaje": 160, "corriente": Math.random() * 130 + 10},
{ "voltaje": 200, "corriente": 30}
],
[
{ "voltaje": 200, "corriente":30},
{ "voltaje": 130, "corriente": Math.random() * 130 + 10},
{ "voltaje": 160, "corriente": Math.random() * 130 + 10},
{ "voltaje": 190, "corriente": Math.random() * 130 + 10}
]
];
var dataSet1=[]
console.log(dataSet[1][1])
/*
var dataSet = d3.range(1).map(function(d) {
return {
x: d * 30 + 10,
y: Math.random() * 130 + 10
}
});
*/var lineGenerator = d3.svg.line()
.x(function(d) {
return d.voltaje
})
.y(function(d) {
return d.corriente
})
.interpolate("monotone")
functiondisplayLine(data) {
var line = backLayer.selectAll(null)
.data(data)
.enter()
.append("path")
.attr({
d: lineGenerator(data),
fill: 'none',
stroke: "red",
"stroke-width": "3px"
});
var totalLength = line.node().getTotalLength();
line.attr("stroke-dasharray", totalLength + " " + totalLength)
.attr("stroke-dashoffset", totalLength)
.transition()
.duration(2000)
.ease("linear")
.attr("stroke-dashoffset", 0);
}
dataSet1.push(dataSet[0])
displayLine(dataSet[0])
var i =0var l = dataSet.lengthconsole.log(i)
setTimeout(function() {
setInterval(function() {
i++
if (i<l){
var newData = dataSet[i];
}else{
var newData = [{ 'voltaje': Math.random() * 30 + 10, 'corriente': Math.random() * 130 + 10 }]
}
console.log(i,newData,dataSet1,dataSet1[i-1] )
newData.unshift(dataSet1[i-1][dataSet1[i-1].length - 1])
displayLine(newData);;
dataSet1.push(newData);
}, 2000);
}, 2000);
* {
margin: 0;
padding: 0;
border: 0;
}
body {
background: #ffd;
}
<scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script><svgwidth="800"height="800"></svg>
Solution 3:
maybe this, you must simple it i make it not simple cos i want you understand, it can make with single svg if you know the min max value of axis, but i doing on 3 svg i hope you can learn and make it what you want
var dataSet=[
[
{ "voltaje": 10, "corriente": Math.random() * 130 + 10},
{ "voltaje": 40, "corriente": Math.random() * 130 + 10}
],
[
{ "voltaje": 10, "corriente": Math.random() * 130 + 10},
{ "voltaje": 40, "corriente": Math.random() * 130 + 10},
{ "voltaje": 50, "corriente": 30}
],
[
{ "voltaje": 10, "corriente": Math.random() * 130 + 10}
],
];
dataSet.forEach(function(d,i){
var svg = d3.select('#dataset'+(i+1));
var backLayer = svg.append("g").attr('id','back'+i);
var frontLayer = svg.append("g").attr('id','front'+i);
})
var dataSet1=[]
var dataSet2=[]
var dataSet3=[]
console.log(dataSet[1][1])
/*
var dataSet = d3.range(1).map(function(d) {
return {
x: d * 30 + 10,
y: Math.random() * 130 + 10
}
});
*/functiondisplayLine(data,svg,i) {
var lineGenerator = d3.svg.line()
.x(function(d) {
return d.voltaje
})
.y(function(d) {
return d.corriente
})
.interpolate("monotone")
var line = d3.select('#back'+i).selectAll(null)
.data(data)
.enter()
.append("path")
.attr({
d: lineGenerator(data),
fill: 'none',
stroke: "red",
"stroke-width": "3px"
});
var totalLength = line.node().getTotalLength();
line.attr("stroke-dasharray", totalLength + " " + totalLength)
.attr("stroke-dashoffset", totalLength)
.transition()
.duration(2000)
.ease("linear")
.attr("stroke-dashoffset", 0);
}
dataSet.forEach(function(d,i){
if (i==0){
var data = dataSet1
}elseif(i==1){
var data = dataSet2
}else{
var data = dataSet3
}
var svg = d3.select('#dataset'+(i+1));
data.push(dataSet[i])
displayLine(dataSet[i],svg,i)
})
var i1=(-1)
var i2=(-1)
var i3=(-1)
var t = 1setTimeout(function() {
setInterval(function() {
t++
dataSet.forEach(function(d,i){
var newData = [{ 'voltaje': 10 + 50*t + 100, 'corriente': Math.random() * 130 + 10*1 }]
if (i==0){
i1++
var data = dataSet1
newData.unshift(data[i1][data[i1].length - 1])
console.log(i,data[i])
}elseif(i==1){
i2++
var data = dataSet2
newData.unshift(data[i2][data[i2].length - 1])
console.log(i,data[i])
}else{
i3++
var data = dataSet3
newData.unshift(data[i3][data[i3].length - 1])
console.log(i,data[i])
}
var svg = d3.select('#dataset'+(i+1));
displayLine(newData,svg,i);
data.push(newData);
})
}, 2000);
}, 2000);
* {
margin: 0;
padding: 0;
border: 0;
}
svg{
display:block;
}
body {
background: #ffd;
}
<scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script><svgwidth="500"height="200"id='dataset1'></svg><svgwidth="500"height="200"id='dataset2'></svg><svgwidth="500"height="200"id='dataset3'></svg>
Post a Comment for "Make Multiple Line With Animation From The Last Position To The New Positions"