[英]Line chart axis zoom
I've got some problems with my d3 visualization. d3可视化出现一些问题。 I'm trying to do a line chart that shows a development over 15 years. 我正在尝试制作折线图,以显示15年来的发展。
First problem is that the x-axis does't scale depending on the zoom. 第一个问题是x轴不会根据缩放比例缩放。 I've used this to get started: http://bl.ocks.org/mbostock/4dc8736fb1ce9799c6d6 But I don't know why my axis doesn't zoom. 我已经开始使用它了: http : //bl.ocks.org/mbostock/4dc8736fb1ce9799c6d6但是我不知道为什么我的轴不能缩放。
Second, the axis labeling is wrong, it should be the week and the year (eg01-2016) 其次,轴标签错误,应该是星期和年份(例如,01-2016)
And the last: What opportunities do I have, if there is some data missing, for example the data for the year 2013? 最后一点:如果缺少某些数据(例如2013年的数据),我有什么机会? Can I have a break in the chart, so that there is just a white space for this year? 我可以在图表中休息一下,以便今年只有空白吗?
Here is the HTML 这是HTML
<!doctype html>
<html>
<head>
<link rel="stylesheet" href="main.css">
<script src="//d3js.org/d3.v3.min.js"></script>
<title>Test Tool</title>
</head>
<body>
<!--MAIN-->
<main>
<!--LINE CHART -->
<script>
// Set the dimensions of the canvas / graph
var margin = {top: 10, right: 20, bottom: 30, left: 50},
width = 1000 - margin.left - margin.right,
height = 570 - margin.top - margin.bottom;
// Set the ranges
var x = d3.time.scale().domain([-width / 2, width / 2])
.range([0, width]);
var y = d3.scale.linear().domain([-height / 2, height / 2])
.range([height, 0]);
// Define the axes
var xAxis = d3.svg.axis().scale(x)
.orient("bottom").ticks(10);
var yAxis = d3.svg.axis().scale(y)
.orient("left").ticks(5);
var zoom = d3.behavior.zoom()
.x(x)
.y(y)
.scaleExtent([1, 10])
.on("zoom", zoomed);
var drag = d3.behavior.drag()
.origin(function(d) { return d; })
.on("dragstart", dragstarted)
.on("drag", dragged)
.on("dragend", dragended);
var area = d3.svg.area()
.x(function(d) { return x(d.meldewoche); })
.y0(height)
.y1(function(d) { return y(d.faelle); })
.interpolate("basis");
var areaflip = d3.svg.area()
.x(function(d) { return x(d.meldewoche); })
.y0(height)
.y1(function(d) { return y(-d.faelle); })
.interpolate("basis");
// Define the line
var valueline = d3.svg.line()
.x(function(d) { return x(d.meldewoche); })
.y(function(d) { return y(d.faelle); })
.interpolate("basis");
var valuelineflip = d3.svg.line()
.x(function(d) { return x(d.meldewoche); })
.y(function(d) { return y(-d.faelle); })
.interpolate("basis");
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 + ")")
.call(zoom);
var container = svg.append("g");
var rect = svg.append("rect")
.attr("width", width)
.attr("height", height)
.style("fill", "none")
.style("pointer-events", "all");
// Add the X Axis
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
// Add the Y Axis
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
// Get the data
d3.csv("data-hanta-gesamt.csv", function(error, data) {
data.forEach(function(d) {
// Parse the date / time
var parseDate = d3.time.format("%W-%Y").parse;
d.meldewoche = parseDate(d.meldewoche);
d.faelle = +d.faelle;
});
// Scale the range of the data
x.domain(d3.extent(data, function(d) { return d.meldewoche; }));
y.domain([0, d3.max(data, function(d) { return d.faelle+550; })]);
// Add the valueline path.
container.append("path")
.attr("class", "line")
.attr("d", valueline(data))
.attr("transform", "translate(0,-265)");
container.append("path")
.attr("class", "lineflip")
.attr("d", valuelineflip(data))
.attr("transform", "translate(0,-265)");
container.append("path")
.datum(data)
.attr("class", "area")
.attr("d", area)
.attr("transform", "translate(0,-265)");
container.append("path")
.datum(data)
.attr("class", "areaflip")
.attr("d", areaflip)
.attr("transform", "translate(0,-265)");
});
//ZOOM
function zoomed() {
container.select(".x axis").call(xAxis);
container.select(".y axis").call(yAxis);
//svg.selectAll('.line').attr('d', line)
container.attr("transform", "translate(" + d3.event.translate[0] + ",0)scale(" + d3.event.scale + ",1)");
}
function dragstarted(d) {
d3.event.sourceEvent.stopPropagation();
d3.select(this).classed("dragging", true);
}
function dragged(d) {
d3.select(this)
.attr("cx", d.x = d3.event.x)
.attr("cy", d.y = d3.event.y);
}
function dragended(d) {
d3.select(this).classed("dragging", false);
}
</script>
</main>
</body>
</html>
And the CSS: 和CSS:
body {
background: #E1E2DD;
color: #333;
font: 1em/1em "Helvetica Neue";
}
#main {
float: left;
padding: 3em;
width: 65%;
}
#footer {
padding: 1em;
text-align: right;
width:65%;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
stroke-width: 1;
shape-rendering: crispEdges;
}
.x.axis path {
display: none;
}
.line {
fill: none;
stroke: steelblue;
stroke-width: 1.5px;
}
.lineflip {
fill: none;
stroke: steelblue;
stroke-width: 1.5px;
}
.area {
fill: lightsteelblue;
stroke-width: 0;
fill-opacity: .67;
}
.areaflip {
fill: lightsteelblue;
stroke-width: 0;
fill-opacity: .67;
}
The csv looks like this: csv看起来像这样:
meldewoche,faelle
01-2001,2
03-2001,1
04-2001,2
05-2001,2
07-2001,1
08-2001,6
09-2001,1
...
You just need to small changes to fix the issues you mentioned. 您只需要进行少量更改即可解决您提到的问题。
Issue 1: the x-axis doesn't scale in response to the zoom. 问题1:x轴无法响应缩放。 The problem you're having comes from how you are updating the x- and y-axes in zoomed
. 您遇到的问题来自于您是如何更新的x和y轴zoomed
。 In particular, your current code tries to select the axes from container
: 特别是,您当前的代码尝试从container
选择轴:
container.select(".x axis").call(xAxis); container.select(".y axis").call(yAxis);
However, the axes are not children of container
. 但是,轴不是container
子代。 Furthermore, you replaced the .
此外,您还替换了.
required to select the axes by the class "axis" with a space. 需要在带有空格的“轴”类中选择轴。 If instead you select the axes as children of the svg
and setting the class selector properly, then your zoom behavior will work: 相反,如果您选择轴作为svg
子代并正确设置类选择器,则缩放行为将起作用:
svg.select(".x.axis").call(xAxis); svg.select(".y.axis").call(yAxis);
Issue 2: The x-axis labeling is wrong. 问题2:x轴标签错误。 This problem stems from the fact that you are adding the x-axis before loading your data. 此问题源于您在加载数据之前添加x轴的事实。 Thus, the domain of the x-axis hasn't been set using the dates of your data. 因此,尚未使用数据日期设置x轴的域。
The solution to this problem is to move all of the code that relies on the x-axis into your d3.csv
. 解决此问题的方法是将所有依赖x轴的代码移到d3.csv
。 This way, when you add the axis or even when you zoom, the domain of the scale x
for the x-axis has already been set properly. 这样,当您添加轴或什至缩放时,已经正确设置了x轴的比例x
的域。 Here's the updated Javascript that's working for me. 这是为我工作的更新的Javascript。
// Set the dimensions of the canvas / graph var margin = { top: 10, right: 20, bottom: 30, left: 50 }, width = 1000 - margin.left - margin.right, height = 570 - margin.top - margin.bottom; //设置画布/图形的尺寸var margin = {顶部:10,右侧:20,底部:30,左侧:50},宽度= 1000-margin.left-margin.right,高度= 570-margin.top -margin.bottom;
// Set the ranges
var x = d3.time.scale().domain([-width / 2, width / 2])
.range([0, width]);
var y = d3.scale.linear().domain([-height / 2, height / 2])
.range([height, 0]);
// Define the axes
var xAxis = d3.svg.axis().scale(x)
.orient("bottom").ticks(10);
var yAxis = d3.svg.axis().scale(y)
.orient("left").ticks(5);
// Get the data
d3.csv("data-hanta-gesamt.csv", function(error, data) {
data.forEach(function(d) {
// Parse the date / time
var parseDate = d3.time.format("%W-%Y").parse;
d.meldewoche = parseDate(d.meldewoche);
d.faelle = +d.faelle;
});
var drag = d3.behavior.drag()
.origin(function(d) {
return d;
})
.on("dragstart", dragstarted)
.on("drag", dragged)
.on("dragend", dragended);
var area = d3.svg.area()
.x(function(d) {
return x(d.meldewoche);
})
.y0(height)
.y1(function(d) {
return y(d.faelle);
})
.interpolate("basis");
var areaflip = d3.svg.area()
.x(function(d) {
return x(d.meldewoche);
})
.y0(height)
.y1(function(d) {
return y(-d.faelle);
})
.interpolate("basis");
// Define the line
var valueline = d3.svg.line()
.x(function(d) {
return x(d.meldewoche);
})
.y(function(d) {
return y(d.faelle);
})
.interpolate("basis");
var valuelineflip = d3.svg.line()
.x(function(d) {
return x(d.meldewoche);
})
.y(function(d) {
return y(-d.faelle);
})
.interpolate("basis");
// Scale the range of the data
x.domain(d3.extent(data, function(d) {
return d.meldewoche;
}));
y.domain([0, d3.max(data, function(d) {
return d.faelle + 550;
})]);
var zoom = d3.behavior.zoom()
.x(x)
.y(y)
.scaleExtent([1, 10])
.on("zoom", zoomed);
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 + ")")
.call(zoom);
var container = svg.append("g");
var rect = svg.append("rect")
.attr("width", width)
.attr("height", height)
.style("fill", "none")
.style("pointer-events", "all");
// Add the Y Axis
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
// Add the X Axis
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
// Add the valueline path.
container.append("path")
.attr("class", "line")
.attr("d", valueline(data))
.attr("transform", "translate(0,-265)");
container.append("path")
.attr("class", "lineflip")
.attr("d", valuelineflip(data))
.attr("transform", "translate(0,-265)");
container.append("path")
.datum(data)
.attr("class", "area")
.attr("d", area)
.attr("transform", "translate(0,-265)");
container.append("path")
.datum(data)
.attr("class", "areaflip")
.attr("d", areaflip)
.attr("transform", "translate(0,-265)");
//ZOOM
function zoomed() {
svg.select(".x.axis").call(xAxis);
svg.select(".y.axis").call(yAxis);
//svg.selectAll('.line').attr('d', line)
container.attr("transform", "translate(" + d3.event.translate[0] + ",0)scale(" + d3.event.scale + ",1)");
}
function dragstarted(d) {
d3.event.sourceEvent.stopPropagation();
d3.select(this).classed("dragging", true);
}
function dragged(d) {
d3.select(this)
.attr("cx", d.x = d3.event.x)
.attr("cy", d.y = d3.event.y);
}
function dragended(d) {
d3.select(this).classed("dragging", false);
}
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.