There’s a distinction between the SVG canvas (drawn with the <canvas> tags) and the SVGs shapes themselves.
There’s a fairly unintuitive coordinate system that you’ll need to understand, since the (0, 0) point of an SVG grid is at the top-left, rather than the bottom-left.
You might come across some pretty weird behavior if you don’t understand what’s going on under the hood.
<d3.select#canvas>>> here is similarous to written #canvas”) in j Query, as it grabs hold of the elements with the ID of “canvas”. d3.select进一步迈出了一步,为这一选择增加了一些特殊方法,我们稍后将使用这些方法。
The margin convention can seem a pttle random for newcomers to D3, and there are a wide range of methods that we can use to edit how our tick marks should look.
var flag = true;
// Run this code every second...
d3.interval(function(){
// Fpck between our two data arrays
data = flag ? data0 : data1;
// Update our chart with new data
update(data);
// Update our flag variable
flag = !flag;
}, 1000)
每1,000人,这项职能将履行更新职能,改变我们利用两个不同阵列之间的数据。
我们需要对我们的法典做一些调子,以便像我们希望的那样,随时更新:
// Scales
var x = d3.scaleLinear()
.range([0, width]);
var y = d3.scaleLinear()
.range([height, 0]);
// Axes
var xAxisCall = d3.axisBottom(x)
var xAxis = g.append("g")
.attr("class", "x-axis")
.attr("transform", "translate(" + 0 + "," + height + ")");
var yAxisCall = d3.axisLeft(y)
var yAxis = g.append("g")
.attr("class", "y-axis");
// Labels
xAxis.append("text")
.attr("class", "axis-title")
.attr("transform", "translate(" + width + ", 0)")
.attr("y", -6)
.text("Grade Point Average")
yAxis.append("text")
.attr("class", "axis-title")
.attr("transform", "rotate(-90)")
.attr("y", 16)
.text("Height / Centimeters");
var flag = true;
// Run this code every second...
d3.interval(function(){
// Fpck between our two data arrays
data = flag ? data0 : data1;
// Update our chart with new data
update(data);
// Update our flag variable
flag = !flag;
}, 1000)
// Run for the first time
update(data0);
function update(data){
// Update our scales
x.domain([d3.min(data, function(d){ return d.gpa; }) / 1.05,
d3.max(data, function(d){ return d.gpa; }) * 1.05])
y.domain([d3.min(data, function(d){ return d.height; }) / 1.05,
d3.max(data, function(d){ return d.height; }) * 1.05])
// Update our axes
xAxis.call(xAxisCall);
yAxis.call(yAxisCall);
// Update our circles
var circles = g.selectAll("circle")
.data(data);
circles.exit().remove()
circles
.attr("cx", function(d){ return x(d.gpa) })
.attr("cy", function(d){ return y(d.height) })
circles.enter()
.append("circle")
.attr("cx", function(d){ return x(d.gpa) })
.attr("cy", function(d){ return y(d.height) })
.attr("r", 5)
.attr("fill", "grey");
}
// JOIN new data with old elements.
var circles = g.selectAll("circle")
.data(data);
其次,这套法典将消除我们新数据阵列中已不复存在的所有障碍:
// EXIT old elements not present in new data.
circles.exit().remove()
在这方面,我们更新了我们新数据阵列中仍然存在的屏幕上所有方面的立场。
// UPDATE old elements present in new data.
circles
.attr("cx", function(d){ return x(d.gpa) })
.attr("cy", function(d){ return y(d.height) })
最后,我们在新的数据阵列中为每个项目添加了警示,这些新数据阵列没有相应的圈子。
// ENTER new elements present in new data.
circles.enter().append("circle")
.attr("cx", function(d){ return x(d.gpa) })
.attr("cy", function(d){ return y(d.height) })
.attr("r", 5)
.attr("fill", "grey");
Our visuapzation is now fpcking between the two arrays of data that we want to display. I’m going to add one more final flourish to make our graph look a pttle neater.