【问题标题】:D3 - adding grid to simple line chartD3 - 向简单折线图添加网格
【发布时间】:2017-04-07 13:49:01
【问题描述】:

在下面的简单折线图中,我想在 x 和 y 轴上添加网格。有人可以帮我吗?

片段:

<html>

<head>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.12/angular.min.js"></script> 
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script> 
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.3.0/d3.min.js"></script>

</head> 

<body ng-app="myApp" ng-controller="myCtrl"> 

    <svg></svg>

    <script>

        //module declaration 
        var app = angular.module('myApp',[]);

        //Controller declaration
        app.controller('myCtrl',function($scope){

            $scope.svgWidth = 800;//svg Width
            $scope.svgHeight = 500;//svg Height 

            //Data in proper format 
            var data = [
                  {"letter": "A","frequency": "5.01"},
                  {"letter": "B","frequency": "7.80"},
                  {"letter": "C","frequency": "15.35"},
                  {"letter": "D","frequency": "22.70"},
                  {"letter": "E","frequency": "34.25"},
                  {"letter": "F","frequency": "10.21"},
                  {"letter": "G","frequency": "7.68"},
            ];

                //removing prior svg elements ie clean up svg 
                d3.select('svg').selectAll("*").remove();

                //resetting svg height and width in current svg 
                d3.select("svg").attr("width", $scope.svgWidth).attr("height", $scope.svgHeight);

                //Setting up of our svg with proper calculations 
                var svg = d3.select("svg");
                var margin = {top: 20, right: 20, bottom: 30, left: 40};
                var width = svg.attr("width") - margin.left - margin.right;
                var height = svg.attr("height") - margin.top - margin.bottom;

                //Plotting our base area in svg in which chart will be shown 
                var g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");

                //X and Y scaling 
                var x = d3.scaleBand().rangeRound([0, width]).padding(0.4);
                var y = d3.scaleLinear().rangeRound([height, 0]);

                x.domain(data.map(function(d) { return d.letter; }));
                y.domain([0, d3.max(data, function(d) { return +d.frequency; })]);

                //Final Plotting 

                //for x axis 
                g.append("g")
                    .call(d3.axisBottom(x))
                    .attr("transform", "translate(0," + height + ")");

                //for y axis 
                g.append("g")
                    .call(d3.axisLeft(y))
                    .append("text").attr("transform", "rotate(-90)").attr("text-anchor", "end");

                //the line function for path 
                var lineFunction = d3.line()
                    .x(function(d) {return x(d.letter); })
                    .y(function(d) { return y(d.frequency); })
                    .curve(d3.curveLinear);

                //defining the lines
                var path = g.append("path");

                //plotting lines
                path
                    .attr("d", lineFunction(data))
                    .attr("stroke", "blue")
                    .attr("stroke-width", 2)
                    .attr("fill", "none");

        });

    </script> 

</body> 

</html> 

结果:

请帮我找出如何在 x 和 y 轴上向图表添加网格。

【问题讨论】:

    标签: javascript d3.js svg charts linechart


    【解决方案1】:

    创建网格线有两种主要方法,其中一种是将innerTickSize 设置为负数(参见other answer)。这种方法的问题是你失去了向外的刻度。所以,我将解释第二种方式:

    首先,为两个轴设置一个类:

    //for x axis 
    g.append("g")
         .attr("class", "xAxis")
         .call(d3.axisBottom(x))
         .attr("transform", "translate(0," + height + ")");
    
     //for y axis 
     g.append("g")
         .attr("class", "yAxis")
         .call(d3.axisLeft(y))
         .append("text").attr("transform", "rotate(-90)").attr("text-anchor", "end");
    

    然后,使用这些类,追加以下行:

    d3.selectAll("g.yAxis g.tick")
        .append("line")
        .attr("class", "gridline")
        .attr("x1", 0)
        .attr("y1", 0)
        .attr("x2", width)
        .attr("y2", 0);
    
    d3.selectAll("g.xAxis g.tick")
        .append("line")
        .attr("class", "gridline")
        .attr("x1", 0)
        .attr("y1", -height)
        .attr("x2", 0)
        .attr("y2", 0);
    

    这是一个演示:

    //Data in proper format 
                var data = [
                      {"letter": "A","frequency": "5.01"},
                      {"letter": "B","frequency": "7.80"},
                      {"letter": "C","frequency": "15.35"},
                      {"letter": "D","frequency": "22.70"},
                      {"letter": "E","frequency": "34.25"},
                      {"letter": "F","frequency": "10.21"},
                      {"letter": "G","frequency": "7.68"},
                ];
    						
    						var width = 500, height = 300;
    
                    //removing prior svg elements ie clean up svg 
                    d3.select('svg').selectAll("*").remove();
    
                    //resetting svg height and width in current svg 
                    d3.select("svg").attr("width", width).attr("height", height);
    
                    //Setting up of our svg with proper calculations 
                    var svg = d3.select("svg");
                    var margin = {top: 20, right: 20, bottom: 30, left: 40};
                    var width = svg.attr("width") - margin.left - margin.right;
                    var height = svg.attr("height") - margin.top - margin.bottom;
    
                    //Plotting our base area in svg in which chart will be shown 
                    var g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");
    
                    //X and Y scaling 
                    var x = d3.scaleBand().rangeRound([0, width]).padding(0.4);
                    var y = d3.scaleLinear().rangeRound([height, 0]);
    
                    x.domain(data.map(function(d) { return d.letter; }));
                    y.domain([0, d3.max(data, function(d) { return +d.frequency; })]);
    
                    //Final Plotting 
    
                    //for x axis 
                    g.append("g")
    								.attr("class", "xAxis")
                        .call(d3.axisBottom(x))
                        .attr("transform", "translate(0," + height + ")");
    
                    //for y axis 
                    g.append("g")
    								.attr("class", "yAxis")
                        .call(d3.axisLeft(y))
                        .append("text").attr("transform", "rotate(-90)").attr("text-anchor", "end");
    										
    										 d3.selectAll("g.yAxis g.tick") 
            .append("line") 
                .attr("class", "gridline")
                .attr("x1", 0) 
                .attr("y1", 0)
                .attr("x2", width)
                .attr("y2", 0);
                
             d3.selectAll("g.xAxis g.tick") 
            .append("line") 
                .attr("class", "gridline")
                .attr("x1", 0) 
                .attr("y1", -height)
                .attr("x2", 0)
                .attr("y2", 0);
    
                    //the line function for path 
                    var lineFunction = d3.line()
                        .x(function(d) {return x(d.letter); })
                        .y(function(d) { return y(d.frequency); })
                        .curve(d3.curveLinear);
    
                    //defining the lines
                    var path = g.append("path");
    
                    //plotting lines
                    path
                        .attr("d", lineFunction(data))
                        .attr("stroke", "blue")
                        .attr("stroke-width", 2)
                        .attr("fill", "none");
    .gridline{
    stroke: black;
    shape-rendering: crispEdges;
    stroke-opacity: .2;
    }
    <script src="https://d3js.org/d3.v4.min.js"></script>
    <svg></svg>

    【讨论】:

      【解决方案2】:

      可以通过在 XY 轴定义中添加 .innerTickSize(-height) .innerTickSize(-width).axis path,.axis line css 样式来实现


      var xAxis = d3.svg.axis()
          .scale(xScale)
          .orient("bottom")
          .innerTickSize(-height)
          .outerTickSize(0)
          .tickPadding(10);
      
      var yAxis = d3.svg.axis()
          .scale(yScale)
          .orient("left")
          .innerTickSize(-width)
          .outerTickSize(0)
          .tickPadding(10);
      
      svg.append("g")
          .attr("class", "y axis")
          .call(yAxis);
      
      svg.append("g")
          .attr("class", "x axis")
          .attr("transform", "translate(0," + height + ")")
          .call(xAxis);
      

      .axis path,
      .axis line {
        fill: none;
        stroke: grey;
        stroke-width: 1;
        shape-rendering: crispEdges;
      }
      
      .axis path,
      .axis line {
        fill: none;
        stroke: black;
        opacity: 0.2;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-08-29
        • 2013-09-28
        • 1970-01-01
        • 1970-01-01
        • 2021-09-29
        • 2014-03-12
        相关资源
        最近更新 更多