在d3js缩放期间让X轴重新缩放

时间:2014-04-14 06:17:06

标签: d3.js

我正在使用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;
};

0 个答案:

没有答案