我正在使用D3构建一个[bar]图表,除了一点点之外我还能正常工作:
当我放大时,图表会改变,但X轴不会。
根据我的理解,我需要放大我的'svg'元素,因为我希望所有附加的内容都可以缩放 - 如果我将缩放功能附加到嵌套的'g'元素,我只会在我缩放时缩放在附加到'g'元素的图元素上...而不是。之间的空白区域。
(其次,我如何让缩放功能在光标位置操作,而不是它当前似乎在“附近”)
当前页面位于http://lucas.ucs.ed.ac.uk/test/stacked_area_ian.html
(我已经把它放在了jfiddle上,但我无法弄清楚如何使URL数据加载工作,并且不想在javascript中添加8,000行数据结构:))
并且javascript代码是
/* The size of the chart
* The whole thing sits in a 'frame' - $body_width wide, 500px high
* "margin" is the space between the SVG 'frame' and the actual graph
* "width" and "height" are derived from the actual space of the SVG 'frame'
* Note there are two graphs, therefore two margins & two heights
*/
var margin = {top: 10, right: 80, bottom: 350, left: 80},
body_width = parseInt(d3.select('body').style('width').replace('px','')),
width = body_width - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
// Routine for parsing a string into a date object
var parseDate = d3.time.format("%M %H %d %m %Y").parse;
/* "x" and "y" scales.
* "x" is time, "y" is a count.
* .range() is the length of the scale
* .domain() [done later] is the actual range of the values
* Note that "width" is [0,nnn] whilst "height" is [nnn,0] as the
* origin in a web page is top left, but the graph is bottom-left
* see http://www.jeromecukier.net/blog/2011/08/11/d3-scales-and-color/
*/
var x = d3.time.scale().range([0, width])
.rangeRound([0, width], .1),
y = d3.scale.linear().range([height, 0]);
/* The "xAxis" and "yAxis" are the actual axis lines
* The scales come from the "scales" above
* We automatically have tick-marks
* Axis labels are provided
*/
var xAxis = d3.svg.axis().scale(x).orient("bottom"),
yAxis = d3.svg.axis().scale(y).orient("left");
var make_x_axis = function () {
console.log("make_x_axis called");
return d3.svg.axis()
.scale(x)
.orient("bottom");
};
/* The zoom trigger - which is centered on the cursor, and zooms just the
* x scale
*/
var zoom = d3.behavior.zoom()
.x(x)
.on("zoom", zoomed);
/* Now we set up some areas on the canvas
* "svg" is our Scalar Vector Graphics element in the xhtml DOM
* This is placed inside an element identified by an 'id' attribute,
* and this element needs to appear in the xhtml *before* this j'script
*/
var svg = d3.select("#for_svg").append("svg")
.attr("class", "chart")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.call(zoom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var clip = svg.append("svg:clipPath")
.attr("id", "clip")
.append("svg:rect")
.attr("x", 0)
.attr("y", 0)
.attr("width", width)
.attr("height", height);
var chartBody = svg.append("g")
.attr("clip-path", "url(#clip)");
/* Having got everything set up, we can pull in our data
* d3.csv automagically knows how to read .csv files & convert them
* into JSON data for the function to use.
* It also knows to take the first line as the
*
* The 'clean' function modifies the data as its read in
*/
d3.csv("http://lucas.ucs.ed.ac.uk/test/area_ingest.csv", clean, function(data) {
/* We can now set the xAxis domain, based on what's come in.
* d3.extent returns the lower & upper values of everything in the array
* passed in
* d3.max just returns the largest number
*
* Also note that, whilst the *SCALE* goes [max,0] the domain is going 0
* to max.
* Again, refer to the Jerome Cukier page
*/
x.domain(d3.extent(data.map(function(d) { return d.date; })));
y.domain([0, d3.max(data.map(function(d) { return d.count; }))]);
/* Add the X & Y axis
* This has to happen in here, otherwise we don't know the values for
* the xAxis properly
*/
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.append("text")
.attr("transform", "translate(" + (width / 2) + ")")
.attr("dy", "3em")
.text("Time");
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 0 - 40)
.attr("x",0 - (height / 2))
.attr("dy", "1em")
.style("text-anchor", "middle")
.text("Total Deposits at time");
/* And finally, the bars */
chartBody.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", "bar")
.attr("x", function (d) { return (x(d.date)); })
.attr("width", (width/data.length)*0.8)
.attr("y", function(d) { return y(d.count); })
.attr("height", function(d) { return height - y(d.count); });
});
function zoomed() {
svg.selectAll(".bar")
.attr("transform", "translate(" + d3.event.translate[0] + ",0)scale(" + d3.event.scale + ", 1)");
svg.call(make_x_axis);
}
/* A function to clean the data
* - date gets parsed into a date format
* - count gets thrown into a numberic context
*/
function clean(d) {
d.date = parseDate(d.date);
d.count = +d.count;
return d;
};