阻止D3图表缩放

时间:2017-07-31 21:34:06

标签: javascript d3.js

我正在使用this作为我的基础项目,它可以在x轴和y轴上滚动和缩放。我已将其修改为只能在x轴上滚动和缩放。现在,我想防止它可伸缩(即x-scale不应该改变),同时保持它可滚动(即点击图形并拖动它向左或向右滑动)

我尝试过scale(1)进行转换以保持规模不变,但这并没有帮助。以下是该片段:

g.append("svg:rect")
              .attr("class", "zoom x box")
              .attr("width", width - margin.left - margin.right)
              .attr("height", height - margin.top - margin.bottom)
              .attr("transform", "translate(" + 0 + "," + 0 + ")")
              .style("visibility", "hidden")
              .attr("pointer-events", "all")
              .call( d3.behavior.zoom().on("zoom", function(){
                  g.attr("transform", "translate(" + d3.event.translate + ") scale(1)")
              }) ).append("g");

这里是完整的代码:



<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.10/d3.min.js"></script>
<!DOCTYPE html>
<html>
  <head>
    <title>Simpe Single Axis Zoom</title>
    <script src="http://d3js.org/d3.v3.min.js"></script>
    <style>
    .axis path, .axis line {
        fill: none;
        stroke: #000;
        shape-rendering: crispEdges;
    }
    </style>
  </head>
  <body>
    <div id="chart"></div>
    <script>
      var ex_chart = example().zoom(true);

      var data = [];
      for (var i = 0; i < 100; i++) {
        data.push([Math.random(), Math.random()]);
      }
      d3.select('#chart')
      .append("svg").attr("width", window.innerWidth).attr("height",window.innerHeight)
      .datum(data).call(ex_chart);

      function example() {
        var svg;
        var margin = {
          top: 60,
          bottom: 80,
          left: 60,
          right: 0
        };
        var width = 500;
        var height = 400;
        var xaxis = d3.svg.axis();
        var yaxis = d3.svg.axis();
        var xscale = d3.scale.linear();
        var yscale = d3.scale.linear();
        var zoomable = true;

        var xzoom = d3.behavior.zoom()
          .x(xscale)
          .on("zoom", zoomable ? draw : null);

        function chart(selection) {
          selection.each(function(data) {
            svg = d3.select(this).selectAll('svg').data([data]);
            svg.enter().append('svg');
            var g = svg.append('g')
              .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

            g.append("defs").append("clipPath")
              .attr("id", "clip")
              .append("rect")
              .attr("width", width - margin.left - margin.right)
              .attr("height", height - margin.top - margin.bottom);

            g.append("svg:rect")
              .attr("class", "border")
              .attr("width", width - margin.left - margin.right)
              .attr("height", height - margin.top - margin.bottom)
              .style("stroke", "black")
              .style("fill", "none");

            g.append("g").attr("class", "x axis")
              .attr("transform", "translate(" + 0 + "," + (height - margin.top - margin.bottom) + ")");

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

            g.append("g")
              .attr("class", "scatter")
              .attr("clip-path", "url(#clip)");


            g
              .append("svg:rect")
              .attr("class", "zoom x box")
              .attr("width", width - margin.left - margin.right)
              .attr("height", height - margin.top - margin.bottom)
              .attr("transform", "translate(" + 0 + "," + 0 + ")")
              .style("visibility", "hidden")
              .attr("pointer-events", "all")
              .call( d3.behavior.zoom().on("zoom", function(){
                  g.attr("transform", "translate(" + d3.event.translate + ") scale(1)")
              }) ).append("g");

            // Update the x-axis
            xscale.domain(d3.extent(data, function(d) {
              return d[0];
            }))
              .range([0, width - margin.left - margin.right]);

            xaxis.scale(xscale)
              .orient('bottom')
              .tickPadding(10);

            svg.select('g.x.axis').call(xaxis);

            // Update the y-scale.
            yscale.domain(d3.extent(data, function(d) {
              return d[1];
            }))
              .range([height - margin.top - margin.bottom, 0]);

            yaxis.scale(yscale)
              .orient('left')
              .tickPadding(10);

            svg.select('g.y.axis').call(yaxis);

            draw();
          });

          return chart;
        }

        function update() {
          var gs = svg.select("g.scatter");

          var circle = gs.selectAll("circle")
            .data(function(d) {
              return d;
            });

          circle.enter().append("svg:circle")
            .attr("class", "points")
            .style("fill", "steelblue")
            .attr("cx", function(d) {
              return X(d);
            })
            .attr("cy", function(d) {
              return Y(d);
            })
            .attr("r", 4);

          circle.attr("cx", function(d) {
            return X(d);
          })
            .attr("cy", function(d) {
              return Y(d);
            });

          circle.exit().remove();
        }

        function zoom_update() {

          xzoom = d3.behavior.zoom()
            .x(xscale)
            .on("zoom", zoomable ? draw : null);

          svg.select('rect.zoom.x.box').call(xzoom);
        }

        function draw() {
          svg.select('g.x.axis').call(xaxis);
          //svg.select('g.y.axis').call(yaxis);

          update();
          zoom_update();
        };

        // X value to scale

        function X(d) {
          return xscale(d[0]);
        }

        // Y value to scale

        function Y(d) {
          return yscale(d[1]);
        }

        chart.zoom = function (_){
          if (!arguments.length) return zoomable;
          zoomable = _;
          return chart;
        }

        return chart;
      }
    </script>
  </body>
</html>
&#13;
&#13;
&#13;

非常感谢任何形式的帮助。感谢。

1 个答案:

答案 0 :(得分:0)

我发现有一个简单的解决方法。在d3.behaviour.zoom()函数中,我需要添加的是.scaleExtent([1,1]),它不会扩展超过1的任何值,因此会阻止缩放。

示例:https://jsfiddle.net/x97k4snj/1/

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.10/d3.min.js"></script>
<!DOCTYPE html>
<html>
  <head>
    <title>Simpe Single Axis Zoom</title>
    <script src="http://d3js.org/d3.v3.min.js"></script>
    <style>
    .axis path, .axis line {
        fill: none;
        stroke: #000;
        shape-rendering: crispEdges;
    }
    </style>
  </head>
  <body>
    <div id="chart"></div>
    <script>
      var ex_chart = example().zoom(true);

      var data = [];
      for (var i = 0; i < 100; i++) {
        data.push([Math.random(), Math.random()]);
      }
      d3.select('#chart')
      .append("svg").attr("width", window.innerWidth).attr("height",window.innerHeight)
      .datum(data).call(ex_chart);

      function example() {
        var svg;
        var margin = {
          top: 60,
          bottom: 80,
          left: 60,
          right: 0
        };
        var width = 500;
        var height = 400;
        var xaxis = d3.svg.axis();
        var yaxis = d3.svg.axis();
        var xscale = d3.scale.linear();
        var yscale = d3.scale.linear();
        var zoomable = true;

        var xzoom = d3.behavior.zoom()
          .scaleExtent([1,1])
          .x(xscale)
          .on("zoom", zoomable ? draw : null);

        function chart(selection) {
          selection.each(function(data) {
            svg = d3.select(this).selectAll('svg').data([data]);
            svg.enter().append('svg');
            var g = svg.append('g')
              .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

            g.append("defs").append("clipPath")
              .attr("id", "clip")
              .append("rect")
              .attr("width", width - margin.left - margin.right)
              .attr("height", height - margin.top - margin.bottom);

            g.append("svg:rect")
              .attr("class", "border")
              .attr("width", width - margin.left - margin.right)
              .attr("height", height - margin.top - margin.bottom)
              .style("stroke", "black")
              .style("fill", "none");

            g.append("g").attr("class", "x axis")
              .attr("transform", "translate(" + 0 + "," + (height - margin.top - margin.bottom) + ")");

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

            g.append("g")
              .attr("class", "scatter")
              .attr("clip-path", "url(#clip)");


            g
              .append("svg:rect")
              .attr("class", "zoom x box")
              .attr("width", width - margin.left - margin.right)
              .attr("height", height - margin.top - margin.bottom)
              .attr("transform", "translate(" + 0 + "," + 0 + ")")
              .style("visibility", "hidden")
              .attr("pointer-events", "all")
              .call( d3.behavior.zoom().on("zoom", function(){
                  g.attr("transform", "translate(" + d3.event.translate + ") scale(1)")
              }) ).append("g");

            // Update the x-axis
            xscale.domain(d3.extent(data, function(d) {
              return d[0];
            }))
              .range([0, width - margin.left - margin.right]);

            xaxis.scale(xscale)
              .orient('bottom')
              .tickPadding(10);

            svg.select('g.x.axis').call(xaxis);

            // Update the y-scale.
            yscale.domain(d3.extent(data, function(d) {
              return d[1];
            }))
              .range([height - margin.top - margin.bottom, 0]);

            yaxis.scale(yscale)
              .orient('left')
              .tickPadding(10);

            svg.select('g.y.axis').call(yaxis);

            draw();
          });

          return chart;
        }

        function update() {
          var gs = svg.select("g.scatter");

          var circle = gs.selectAll("circle")
            .data(function(d) {
              return d;
            });

          circle.enter().append("svg:circle")
            .attr("class", "points")
            .style("fill", "steelblue")
            .attr("cx", function(d) {
              return X(d);
            })
            .attr("cy", function(d) {
              return Y(d);
            })
            .attr("r", 4);

          circle.attr("cx", function(d) {
            return X(d);
          })
            .attr("cy", function(d) {
              return Y(d);
            });

          circle.exit().remove();
        }

        function zoom_update() {

          xzoom = d3.behavior.zoom()
            .scaleExtent([1,1])
            .x(xscale)
            .on("zoom", zoomable ? draw : null);

          svg.select('rect.zoom.x.box').call(xzoom);
        }

        function draw() {
          svg.select('g.x.axis').call(xaxis);
          //svg.select('g.y.axis').call(yaxis);

          update();
          zoom_update();
        };

        // X value to scale

        function X(d) {
          return xscale(d[0]);
        }

        // Y value to scale

        function Y(d) {
          return yscale(d[1]);
        }

        chart.zoom = function (_){
          if (!arguments.length) return zoomable;
          zoomable = _;
          return chart;
        }

        return chart;
      }
    </script>
  </body>
</html>