d3 v4中的可缩放区域无法正常工作

时间:2017-06-15 23:17:48

标签: d3.js zoom

我正在尝试关注此https://bl.ocks.org/mbostock/34f08d5e11952a80609169b7917d4172

这是我的小提琴:https://jsfiddle.net/q0xece4k/17/'

<!DOCTYPE html>
<meta charset="utf-8">
<title>Plotting a Trendline with D3.js</title>
<style>
    .line {
        stroke: blue;
        fill:none;
        stroke-width: 3;
    }

    .axis path,
    .axis line {
        fill: none;
        stroke: black;
        shape-rendering: crispEdges;
    }

    .axis text {
        font-size: 10px;
        font-family: sans-serif;
    }

    .text-label {
        font-size: 10px;
        font-family: sans-serif;
    }

    .zoom {
  cursor: move;
  fill: none;
  pointer-events: all;
}

</style>
<div>
    <div id="container"></div>
</div>
<body>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>

<script>
    var height = 300;
    var width = 600;
    var margin = {top: 10, right:20, bottom: 50, left: 40};

    // formatters for axis and labels
    var rateFormat = d3.format("0.1f");
 var trendDataArr = [
     {
     date: "2017-01-29",
     value: 87.1
     },
     {
     date: "2017-02-06",
     value: 88
     },
     {
     date: "2017-02-13",
     value: 86.8
     },
     {
     date: "2017-02-20",
     value: 86.8
     },
     {
     date: "2017-02-27",
     value: 87.1
        },
     {
     date: "2017-03-05",
     value: 85.8
     },
     {
     date: "2017-03-12",
     value: 85.5
     },
        {
        date: "2017-03-19",
        value: 87.1
        },
        {
        date: "2017-03-26",
        value: 88
        },
        {
        date: "2017-04-02",
        value: 87.4
        },
        {
        date: "2017-04-09",
        value: 86.8
        },
        {
        date: "2017-04-16",
        value: 87.1
        },
        {
        date: "2017-04-23",
        value: 87.4
        },
        {
        date: "2017-04-30",
        value: 85.8
        },
        {
        date: "2017-05-07",
        value: 86.5
        },
        {
        date: "2017-05-14",
        value: 87.1
        },
        {
        date: "2017-05-21",
        value: 86.9
        },
        {
        date: "2017-05-28",
        value: 87.7
        },
        {
        date: "2017-06-04",
        value: 87.8
        }
];



var zoom = d3.zoom()
    .scaleExtent([1, Infinity])
    .translateExtent([[0, 0], [width, height]])
    .extent([[0, 0], [width, height]])
    .on("zoom", zoomed);

    var svg = d3.select('#container')
        .append("svg")
        .attr("pointer-events", "all")
        .attr("width", 1000 + margin.left + margin.right)
        .attr("height", height + margin.top + margin.bottom)
        .attr("transform", "translate(" + margin.left + "," + margin.top + ")")
        .append("g");


        svg.append("rect")
                    .attr("class", "zoom")
                    .attr("width", width)
                    .attr("height", height)
                    .attr("transform", "translate(" + margin.left + "," + margin.top + ")")
                    .call(zoom);


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

    svg.append("g")
        .attr("class", "x axis");


         function getDate(d) {
             return moment(d["date"],"YYYY-MM-DD").toDate();
         }

             function removeDuplicates(xLabels){
                var result = [];
                             xLabels.forEach(function(item) {
                                     if(result.indexOf(item) < 0) {
                                             result.push(item);
                                     }
                             return result;
                     });
             }


      var minDate = getDate(trendDataArr[0]),
      maxDate = getDate(trendDataArr[trendDataArr.length-1]);


      var xScale = d3.scaleTime()
           // .rangeBands([margin.left, width-100], .1);
                   .domain([minDate, maxDate])
                     .range([margin.left, width])
                    // .nice(trendDataArr.length);

      var yScale = d3.scaleLinear()
        .range([height, 0]);

      var xAxis = d3.axisBottom(xScale)
                            .tickFormat(d3.timeFormat('%d %b %y'));

      var yAxis = d3.axisLeft(yScale);
        var xLabels = trendDataArr.map(function (d) { return getDate(d); });

        xScale.domain(d3.extent(xLabels));
        yScale.domain([Math.round(d3.min(trendDataArr, function(d) { return parseFloat(d['value']); }))-5, Math.round(d3.max(trendDataArr, function(d) { return parseFloat(d['value']); }))+5]);

        var line = d3.line()
            .x(function(d) { return xScale(getDate(d)); })
            .y(function(d) { return yScale(d['value']); })
            .curve(d3.curveCardinal);


   svg.append("path")
     .datum(trendDataArr)
     .attr('fill','none')
         .attr("d", line(trendDataArr.filter(function(d) {

                                     return d;
      }
                 )
               )
             )

             .attr('stroke', "steelblue")
             .attr('stroke-width', 2);


        svg.select(".x.axis")
            .attr("transform", "translate(0," + (height+5) + ")")
            .call(xAxis.tickFormat(d3.timeFormat("%d %b %y")))
            .selectAll("text")
            .style("text-anchor","end")
            .attr("transform", function(d) {
                return "rotate(-45) ";
            });

        svg.select(".y.axis")
            .attr("transform", "translate(" + (margin.left) + ",0)")
            .call(yAxis.tickFormat(rateFormat));

        // chart title
        svg.append("text")
            .attr("x", (width + (margin.left + margin.right) )/ 2 -200)
            .attr("y", 0 + margin.top -20)
            .attr("text-anchor", "middle")
            .style("font-size", "16px")
            .style("font-family", "sans-serif")
            .text("Zoomable chart");

            //y axis  label
        svg.append("text")
        .attr("transform", "rotate(-90)")
        .attr("y", -20)
        .attr("x",0 - (height / 2))
        .attr("dy", "1em")
        .style("text-anchor", "middle")
        .text("Rate");

        function zoomed() {
                var t = d3.event.transform;
            xScale.domain(t.rescaleX(xScale).domain());
        }

</script>
</body>

有人可以帮我调整轴上的放大/缩小,以便我可以钻进每一天或缩小到几年吗?

2 个答案:

答案 0 :(得分:0)

我得到了它的工作: 这是更新的小提琴: https://jsfiddle.net/q0xece4k/17/

var height = 300;
    var width = 600;
    var margin = {top: 10, right:20, bottom: 50, left: 40};

    // formatters for axis and labels
    var rateFormat = d3.format("0.1f");
 var trendDataArr = [
     {
     date: "2017-01-29",
     value: 87.1
     },
     {
     date: "2017-02-06",
     value: 88
     },
     {
     date: "2017-02-13",
     value: 86.8
     },
     {
     date: "2017-02-20",
     value: 86.8
     },
     {
     date: "2017-02-27",
     value: 87.1
        },
     {
     date: "2017-03-05",
     value: 85.8
     },
     {
     date: "2017-03-12",
     value: 85.5
     },
        {
        date: "2017-03-19",
        value: 87.1
        },
        {
        date: "2017-03-26",
        value: 88
        },
        {
        date: "2017-04-02",
        value: 87.4
        },
        {
        date: "2017-04-09",
        value: 86.8
        },
        {
        date: "2017-04-16",
        value: 87.1
        },
        {
        date: "2017-04-23",
        value: 87.4
        },
        {
        date: "2017-04-30",
        value: 85.8
        },
        {
        date: "2017-05-07",
        value: 86.5
        },
        {
        date: "2017-05-14",
        value: 87.1
        },
        {
        date: "2017-05-21",
        value: 86.9
        },
        {
        date: "2017-05-28",
        value: 87.7
        },
        {
        date: "2017-06-04",
        value: 87.8
        }
];



var zoom = d3.zoom()
    .scaleExtent([1, Infinity])
    .translateExtent([[0, 0], [width, height]])
    .extent([[0, 0], [width, height]])
    .on("zoom", zoomed);

    var svg = d3.select('#container')
        .append("svg")
        .attr("pointer-events", "all")
        .attr("width", 1000 + margin.left + margin.right)
        .attr("height", height + margin.top + margin.bottom)
        .attr("transform", "translate(" + margin.left + "," + margin.top + ")")
        .append("g");


        svg.append("rect")
                    .attr("class", "zoom")
                    .attr("width", width)
                    .attr("height", height)
                    .attr("transform", "translate(" + margin.left + "," + margin.top + ")")
                    .call(zoom);


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

    svg.append("g")
        .attr("class", "x axis");


         function getDate(d) {
             return moment(d["date"],"YYYY-MM-DD").toDate();
         }

             function removeDuplicates(xLabels){
                var result = [];
                             xLabels.forEach(function(item) {
                                     if(result.indexOf(item) < 0) {
                                             result.push(item);
                                     }
                             return result;
                     });
             }


      var minDate = getDate(trendDataArr[0]),
      maxDate = getDate(trendDataArr[trendDataArr.length-1]);


      var xScale = d3.scaleTime()
           // .rangeBands([margin.left, width-100], .1);
                   .domain([minDate, maxDate])
                     .range([margin.left, width])
                    // .nice(trendDataArr.length);

      var yScale = d3.scaleLinear()
        .range([height, 0]);

      var xAxis = d3.axisBottom(xScale)
                            .tickFormat(d3.timeFormat('%d %b %y'));

      var yAxis = d3.axisLeft(yScale);
        var xLabels = trendDataArr.map(function (d) { return getDate(d); });

        xScale.domain(d3.extent(xLabels));
        yScale.domain([Math.round(d3.min(trendDataArr, function(d) { return parseFloat(d['value']); }))-5, Math.round(d3.max(trendDataArr, function(d) { return parseFloat(d['value']); }))+5]);

        var line = d3.line()
            .x(function(d) { return xScale(getDate(d)); })
            .y(function(d) { return yScale(d['value']); })
            .curve(d3.curveCardinal);


   svg.append("path")
     .datum(trendDataArr)
     .attr('fill','none')
         .attr("d", line(trendDataArr.filter(function(d) {

                                     return d;
      }
                 )
               )
             )

             .attr('stroke', "steelblue")
             .attr('stroke-width', 2);


        svg.select(".x.axis")
            .attr("transform", "translate(0," + (height+5) + ")")
            .call(xAxis.tickFormat(d3.timeFormat("%d %b %y")))
            .selectAll("text")
            .style("text-anchor","end")
            .attr("transform", function(d) {
                return "rotate(-45) ";
            });

        svg.select(".y.axis")
            .attr("transform", "translate(" + (margin.left) + ",0)")
            .call(yAxis.tickFormat(rateFormat));

        // chart title
        svg.append("text")
            .attr("x", (width + (margin.left + margin.right) )/ 2 -200)
            .attr("y", 0 + margin.top -20)
            .attr("text-anchor", "middle")
            .style("font-size", "16px")
            .style("font-family", "sans-serif")
            .text("Zoomable chart");

            //y axis  label
        svg.append("text")
        .attr("transform", "rotate(-90)")
        .attr("y", -20)
        .attr("x",0 - (height / 2))
        .attr("dy", "1em")
        .style("text-anchor", "middle")
        .text("Rate");

        function zoomed() {
                var t = d3.event.transform;
            xScale.domain(t.rescaleX(xScale).domain());
        }

答案 1 :(得分:0)

您需要再次拨打xAxis。

function zoomed() {
  console.info('zoom called');
  var t = d3.event.transform;
  xScale.domain(t.rescaleX(xScale).domain());
  svg.select(".x.axis")
 .call(xAxis.tickFormat(d3.timeFormat("%d %b %y")));
}

这不是完整的解决方案,因为它只是放大xAxis而不是绘图,但它也可以帮助你缩放绘图。

或者您可能想参考:https://bl.ocks.org/deristnochda/1ffe16ccf8bed2035ea5091ab9bb53fb