D3.js 轴缩放

D3.js zooming with axis

我有一个项目,我需要在 3 个轴上独立缩放。我正在使用滚动条来完成此操作,但发生缩放时轴不会重绘。

此外,剪辑路径似乎没有按预期工作。

最终我也想为图表添加平移功能,但我不确定从哪里开始。

http://jsfiddle.net/yo4mwLpj/

在此先感谢您的帮助。

// cases vs deaths of a disease over time
var data = [
{"year": "1960", "cases":"887",   "deaths": "199"},
{"year": "1965", "cases":"218",   "deaths": "55"},
{"year": "1993", "cases":"37046", "deaths": "931"},
{"year": "1994", "cases":"38735", "deaths": "118"},
{"year": "1995", "cases":"19903", "deaths": "624"},
{"year": "1997", "cases":"4170",  "deaths": "125"},
{"year": "1998", "cases":"10000", "deaths": "0"}
];
data.forEach(function (d) {
   d.year   = d3.time.format("%Y").parse(d.year.toString());
   d.cases  = +d.cases;
   d.deaths = +d.deaths;
});

var margin = { top: 30, right: 40, bottom: 30, left: 50 },
   width = 500 - margin.left - margin.right,
   height = 270 - margin.top - margin.bottom;

var xScale = d3.time.scale()
   .domain(d3.extent(data, function (d) { return d.year; }))
   .range([0, width]);

var yScaleLeft = d3.scale.linear()
   .domain([0, d3.max(data, function (d) { return d.cases; })])
   .range([height, 0]);

var yScaleRight = d3.scale.linear()
   .domain([0, d3.max(data, function (d) { return d.deaths; })])
   .range([height, 0]);

var xAxis = d3.svg.axis()
   .scale(xScale)
   .orient("bottom").ticks(5);

var yAxisLeft = d3.svg.axis()
   .scale(yScaleLeft)
   .orient("left").ticks(5);

var yAxisRight = d3.svg.axis()
   .scale(yScaleRight)
   .orient("right").ticks(5);

var lineCases = d3.svg.line()
   .x(function (d) { return xScale(d.year); })
   .y(function (d) { return yScaleLeft(d.cases); });

var lineDeaths = d3.svg.line()
   .x(function (d) { return xScale(d.year); })
   .y(function (d) { return yScaleRight(d.deaths); });

var svg = d3.select("#chart").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("g")
   .attr("class", "x axis")
   .attr("transform", "translate(0," + height + ")")
   .call(xAxis);

svg.append("g")
   .attr("class", "y axis yleft")
   .call(yAxisLeft);

svg.append("g")
   .attr("class", "y axis yright")
   .call(yAxisRight)
   .attr('transform', 'translate(' + width + ',0)');

svg.append("path")
   .datum(data)
   .attr("class", "line lineLeft")
   .style("stroke", "red")
   .attr("d", lineCases(data))
   .attr("clip", "url(#clip)");

svg.append("path")
   .datum(data)
   .attr("class", "line lineRight")
   .attr("d", lineDeaths(data))
   .attr("clip", "url(#clip)");

svg.append("clipPath")
   .attr("id", "clip")
   .append("rect")
   .attr("width", width)
   .attr("height", height);

$("#slider-x").slider({
   orientation: "horizontal",
   range: "min",
   min: 1000,
   max: 10000, // make max be (maxDate-minDate).Days*1000, so you can zoom to one day
   value: 1000,
   slide: function( event, ui ) {
      zoomXWithSlider(ui.value/1000);
   }
});

$( "#slider-y-left" ).slider({
   orientation: "vertical",
   range: "min",
   min: 1000,
   max: 10000,
   value: 1000,
   slide: function( event, ui ) {
      zoomLeftWithSlider(ui.value/1000);
   }
});

$("#slider-y-right").slider({
   orientation: "vertical",
   range: "min",
   min: 1000,
   max: 10000,
   value: 1000,
   slide: function( event, ui ) {
      zoomRightWithSlider(ui.value/1000);
   }
});

function zoomXWithSlider(scale) {
   // Note: works only on the <g> element and not on the <svg> element
     // which is a common mistake
   svg.selectAll("path.line").attr("transform", "scale("+scale+", 1)");
   svg.select(".x.axis").call(xAxis);
}

function zoomLeftWithSlider(scale) {
   svg.select("path.line.lineLeft").attr("transform", "scale(1, "+scale+")");
   svg.select(".y.axis.yleft").call(yAxisLeft);
}

function zoomRightWithSlider(scale) {
   svg.select("path.line.lineRight").attr("transform", "scale(1, "+scale+")");
   svg.select(".y.axis.yright").call(yAxisRight);
}

http://jsfiddle.net/8oo3ocfs/

    var zoom = d3.behavior.zoom() //zoomYAxis
   .x(xScale)
   .y(yScaleLeft)
   .on("zoom", function(){
      // don't let double-click or scroll wheel do anything
      if (d3.event.sourceEvent == null || d3.event.sourceEvent.type == "wheel"){
         zoom.scale(previousScale);
         zoom.translate(previousTranslate);
         zoomRight.scale(previousScale);
         zoomRight.translate(previousTranslate);
         return;
      }

      // set previous scale for future use
      previousScale = zoom.scale();
      previousTranslate = zoom.translate();

      //zoom.translate(panLimit());
      //zoomRight.translate(zoom.translate());

      // update the right side scale
      zoomRight.scale(previousScale);
      zoomRight.translate(previousTranslate);

      // redraw lines
      svg.select("path.line.lineLeft").attr("d", lineCases(data));
      svg.select("path.line.lineRight").attr("d", lineDeaths(data));

      // redraw axes
      svg.select(".x.axis").call(xAxis);
      svg.select(".y.axis.yleft").call(yAxisLeft);
      svg.select(".y.axis.yright").call(yAxisRight);
   });

我最终成功了。我不需要剪辑路径在 jsfiddle 中工作,因为它在我们的实际项目中工作。此外,我最终没有限制平移功能,因为它在数学上变得非常复杂。所以我只是在上面放了一个重置​​按钮。