我根据d3.js中随机生成的数据绘制了动态波。我使用“dot”(svg.selectAll(“dot”))元素来表示波浪上的数据点(x和y轴)。基于setinterval方法,我的数据每200ms更新一次,我将数据从右向左转换。但是我添加到波浪中的数据点(点)不随波浪一起移动,它们是固定的(不移动),只有波浪移动。
这是代码: https://jsfiddle.net/rajatmehta/tm5166e1/4/
function updateData() {
var newData = GenData(N,lastUpdateTime);
lastUpdateTime = newData[newData.length-1].timestamp;
var newData2 = GenData2(N,lastUpdateTimeNew);
lastUpdateTimeNew = newData2[newData2.length-1].timestamp;
for (var i=0; i<newData.length; i++){
console.log(globalData.length);
if(globalData.length>99){
globalData.shift();
}
globalData.push(newData[i]);
}
for (var i=0; i<newData2.length; i++){
console.log(globalDataNew.length);
if(globalDataNew.length>99){
globalDataNew.shift();
}
globalDataNew.push(newData2[i]);
}
//code for transition start
x1 = newData[0].timestamp;
x2 = newData[newData.length - 1].timestamp;
dx = dx + (x(x1) - x(x2)); // dx needs to be cummulative
x1New = newData2[0].timestamp;
x2New = newData2[newData2.length - 1].timestamp;
dxNew = dxNew + (x(x1New) - x(x2New)); // dx needs to be cummulative
d3.select("path#path1")
.datum(globalData)
.attr("class", "line")
.attr("d", valueline(globalData))
.transition()
.ease("linear")
.attr("transform", "translate(" + String(dx) + ")");
d3.select("path#path2")
.datum(globalDataNew)
.attr("class", "line")
.attr("d", valueline2(globalDataNew))
.transition()
.ease("linear")
.attr("transform", "translate(" + String(dxNew) + ")");
svg.select(".x.axis").call(xAxis);
}
我是d3.js的新手,所以对此并不太了解。
答案 0 :(得分:1)
两个问题:
您没有正确添加圈子:无法将<circle>
元素附加到<path>
元素。您必须使用“输入”选项,将它们附加到SVG(或组元素):
chartBody.selectAll(null)
.data(globalData)
.enter()
.append("circle")
.attr("class", "dot1")
.attr("r", 3)
.attr("cx", function(d) {
console.log(d)
return x(d.timestamp);
})
.attr("cy", function(d) {
return y(d.value);
});
在更新功能中,按类:
选择这些圈子d3.selectAll(".dot1")
.data(globalData)
.transition()
.ease("linear")
.attr("transform", "translate(" + String(dx) + ")");
以下是包含这些更改的代码:
var lastUpdateTime = +new Date();
var lastUpdateTimeNew = +new Date();
var GenData = function(N, lastTime) {
var output = [];
for (var i = 0; i < N; i++) {
output.push({
value: Math.random() * 10,
timestamp: lastTime
});
lastTime = lastTime + 1000;
}
return output;
}
var GenData2 = function(N, lastTime) {
var output = [];
for (var i = 0; i < N; i++) {
output.push({
value: Math.random() * 20,
timestamp: lastTime
});
lastTime = lastTime + 1000;
}
return output;
}
var globalData;
var globalDataNew;
// plot the original data by retrieving everything from time 0
data = GenData(50, lastUpdateTime);
dataNew = GenData2(50, lastUpdateTimeNew);
lastUpdateTime = data[data.length - 1].timestamp;
lastUpdateTimeNew = dataNew[dataNew.length - 1].timestamp;
globalData = data;
globalDataNew = dataNew;
// Define the div for the tooltip
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
var margin = {
top: 30,
right: 20,
bottom: 30,
left: 50
},
width = 800 - margin.left - margin.right,
height = 350 - margin.top - margin.bottom;
var x = d3.time.scale()
.range([0, width]);
var y = d3.scale.linear()
.range([height, 0]);
x.domain(d3.extent(globalDataNew, function(d) {
return d.timestamp;
}));
y.domain(d3.extent(globalDataNew, function(d) {
return d.value;
}));
var xAxis = d3.svg.axis().scale(x)
.orient("bottom")
.ticks(d3.time.seconds, 20)
.tickFormat(d3.time.format('%X'))
.tickSize(5)
.tickPadding(8);
var xAxisTop = d3.svg.axis().scale(x)
.orient("bottom").tickFormat("").tickSize(0);
var yAxis = d3.svg.axis().scale(y)
.orient("left").ticks(5);
var yAxisRight = d3.svg.axis().scale(y)
.orient("right").tickFormat("").tickSize(0);
var valueline = d3.svg.line()
.x(function(d) {
return x(d.timestamp);
})
.y(function(d) {
return y(d.value);
});
var valueline2 = d3.svg.line()
.x(function(d) {
return x(d.timestamp);
})
.y(function(d) {
return y(d.value);
});
var svg = d3.select("body")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
svg.append("rect")
.attr("width", width)
.attr("height", height)
.attr("class", "plot");
var clip = svg.append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("x", 0)
.attr("y", 0)
.attr("width", width)
.attr("height", height);
var chartBody = svg.append("g")
.attr("clip-path", "url(#clip)");
/* .on("mouseover", function(d) {
div.transition()
.duration(200)
.style("opacity", .9);
div .html(formatTime(d.timestamp) + "<br/>" + d.close)
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY - 28) + "px");
})
.on("mouseout", function(d) {
div.transition()
.duration(500)
.style("opacity", 0);
})*/
chartBody.append("path") // Add the valueline path
.datum(globalData)
.attr("id", "path1")
.attr("class", "line")
.attr("d", valueline);
chartBody.selectAll(null)
.data(globalData)
.enter()
.append("circle")
.attr("class", "dot1")
.attr("r", 3)
.attr("cx", function(d) {
return x(d.timestamp);
})
.attr("cy", function(d) {
return y(d.value);
});
chartBody.selectAll(null)
.data(globalDataNew)
.enter()
.append("circle")
.attr("class", "dot2")
.attr("r", 3)
.attr("cx", function(d) {
return x(d.timestamp);
})
.attr("cy", function(d) {
return y(d.value);
});
chartBody.append("path") // Add the valueline path
.datum(globalDataNew)
.attr("id", "path2")
.attr("class", "line")
.attr("d", valueline2);
svg.append("g") // Add the X Axis
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g") // Add the Y Axis
.attr("class", "y axis")
.call(yAxis);
svg.append("g")
.attr("class", "y axis")
.attr("transform", "translate(" + width + ",0)")
.call(yAxisRight);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + String(0) + ")")
.call(xAxisTop);
svg.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 0 - margin.left)
.attr("x", (0 - (height / 2)))
.attr("dy", "1em")
.style("text-anchor", "middle")
.style("font-weight", "bold")
.text("Return (%)");
var inter = setInterval(function() {
updateData();
}, 1000);
//////////////////////////////////////////////////////////////
var N = 3;
var dx = 0;
var dxNew = 0;
function updateData() {
var newData = GenData(N, lastUpdateTime);
lastUpdateTime = newData[newData.length - 1].timestamp;
var newData2 = GenData2(N, lastUpdateTimeNew);
lastUpdateTimeNew = newData2[newData2.length - 1].timestamp;
for (var i = 0; i < newData.length; i++) {
if (globalData.length > 99) {
globalData.shift();
}
globalData.push(newData[i]);
}
for (var i = 0; i < newData2.length; i++) {
if (globalDataNew.length > 99) {
globalDataNew.shift();
}
globalDataNew.push(newData2[i]);
}
//code for transition start
x1 = newData[0].timestamp;
x2 = newData[newData.length - 1].timestamp;
dx = dx + (x(x1) - x(x2)); // dx needs to be cummulative
x1New = newData2[0].timestamp;
x2New = newData2[newData2.length - 1].timestamp;
dxNew = dxNew + (x(x1New) - x(x2New)); // dx needs to be cummulative
d3.select("path#path1")
.datum(globalData)
.attr("class", "line")
.attr("d", valueline(globalData))
.transition()
.ease("linear")
.attr("transform", "translate(" + String(dx) + ")");
d3.select("path#path2")
.datum(globalDataNew)
.attr("class", "line")
.attr("d", valueline2(globalDataNew))
.transition()
.ease("linear")
.attr("transform", "translate(" + String(dxNew) + ")");
d3.selectAll(".dot1")
.data(globalData)
.transition()
.ease("linear")
.attr("transform", "translate(" + String(dx) + ")");
d3.selectAll(".dot2")
.data(globalDataNew)
.transition()
.ease("linear")
.attr("transform", "translate(" + String(dx) + ")");
svg.select(".x.axis").call(xAxis);
}
body {
font: 12px Arial;
}
path {
stroke: black;
stroke-width: 1;
fill: none;
}
.axis path,
.axis line {
fill: none;
stroke: black;
stroke-width: 2;
shape-rendering: crispEdges;
}
text {
fill: black;
}
rect {
fill: #add8e6;
}
<script src="https://d3js.org/d3.v3.min.js"></script>
PS:当线条向左移动时,你必须添加新的圆圈。但是,这是另一个问题。