D3.js网格和刻度问题

时间:2016-01-13 11:23:39

标签: javascript css d3.js

我使用D3.js创建了一个图形,并且遇到了x轴网格线的问题。

var data = [{
    x: '12-May-12',
    y: 5
  }, {
    x: '30-Apr-12',
    y: 28
  }, {
    x: '27-Apr-12',
    y: 58
  }, {
    x: '26-Apr-12',
    y: 93
  }, {
    x: '25-Apr-12',
    y: 8
  }, {
    x: '24-Apr-12',
    y: 48
  }, {
    x: '23-Apr-12',
    y: 28
  }, {
    x: '20-Apr-12',
    y: 68
  }, {
    x: '19-Apr-12',
    y: 8
  }, {
    x: '18-May-12',
    y: 58
  }, {
    x: '17-Apr-12',
    y: 5
  }, {
    x: '16-Apr-12',
    y: 80
  }, {
    x: '13-Apr-12',
    y: 38
  }

];

var margin = {
    top: 30,
    right: 20,
    bottom: 35,
    left: 50
  },

  width = 1200 - (margin.left + margin.right),
  height = 360 - 2 * (margin.top + margin.bottom);

// Parse the date / time
var parseDate = d3.time.format("%d-%b-%y");
var xScale = d3.time.scale().range([0, width])
  .domain(d3.extent(data, function(d) {
    return parseDate.parse(d.x);
  }))
  .nice();

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

d3.select("#d3-chart")
  .style("width", width + margin.left + margin.right + "px")
  .style("height", height + 2 * (margin.top + margin.bottom) + 100 + "px");

d3.select("#d3-chart").select('.d3_charts').append("p")
  .attr("class", "chart-header")
  .text("D3 Line Chart");

// Adds the div for tooltips
var div = d3.select("#d3-chart").append("div")
  .attr("id", "tooltip")
  .attr("class", "hidden");

div.append("p").append("span").attr("class", "value");
div.append("p").append("span").attr("class", "date");

var svg = d3.select("#d3-chart").select('.d3_charts')
  .append("svg")
  .attr("width", width + margin.left + margin.right)
  .attr("height", height + margin.top + margin.bottom)
  .attr("class", "bg-color")
  .append("g")
  .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

svg.selectAll("line.x")
  .data(xScale.ticks(10))
  .enter().append("line")
  .attr("class", " x_minor minor")
  .attr("x1", xScale)
  .attr("x2", xScale)
  .attr("y1", 0)
  .attr("y2", height);

// Draw Y-axis grid lines
svg.selectAll("line.y")
  .data(yScale.ticks(10))
  .enter().append("line")
  .attr("class", "y_minor minor")
  .attr("x1", 0)
  .attr("x2", width)
  .attr("y1", yScale)
  .attr("y2", yScale);

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

var yAxis = d3.svg.axis().scale(yScale).orient("left").ticks(5).tickSize(0).outerTickSize(0);

data.sort(function(a, b) {
  return parseDate.parse(a.x) - parseDate.parse(b.x);
});

svg.append('g')
  .attr("class", "axis")
  .attr("transform", "translate(0," + height + ")")
  .call(xAxis);

svg.append('g')
  .attr("class", "axis")
  .call(yAxis);

// Define the line
var lineGen = d3.svg.line()
  .interpolate("monotone")
  .x(function(d) {
    return xScale(parseDate.parse(d.x));
  })
  .y(function(d) {
    return yScale(d.y);
  });

svg.append('path')
  .attr("class", "line")
  .style("stroke", "blue")
  .attr('d', lineGen(data));

var focus = svg.append("g")
  .attr("class", "focus")
  .style("display", "none");
text {
  font-size: 40px
}
text.inner-circle {
  font-weight: 400;
  font-size: 12px;
  text-transform: uppercase;
}
text.inner-text {
  font-weight: 400;
  font-size: 36px;
  font-family: 'Metric Regular', 'Metric';
  text-align: center;
  font-style: normal;
  text-transform: uppercase;
}
path {
  stroke: steelblue;
  stroke-width: 2;
  fill: none;
}
.axis path,
.axis line {
  fill: none;
  stroke: grey;
  stroke-width: 2;
  shape-rendering: crispEdges;
}
.grid .tick {
  stroke: lightgrey;
  stroke-opacity: 0.7;
  shape-rendering: crispEdges;
}
.grid path {
  stroke-width: 0;
}
.area {
  fill: lightsteelblue;
}
#tooltip {
  position: absolute;
  width: 100px;
  height: auto;
  padding: 10px;
  background-color: white;
  border: 1px solid black;
  text-align: center;
  pointer-events: none;
}
#tooltip.hidden {
  display: none;
}
#tooltip p {
  margin: 0;
  font-family: sans-serif;
  font-size: 14px;
  line-height: 12px;
  vertical-align: middle;
  .value {
    font-weight: 700;
  }
  .date {
    font-size: 10px;
  }
}
.line {
  fill: none;
  stroke: steelblue;
  stroke-width: 2px;
  shape-rendering: crispEdges;
}
.overlay {
  fill: none;
  pointer-events: all;
}
.focus circle {
  fill: none;
  stroke: steelblue;
}
.focus text {
  font: 10px sans-serif;
}
d3-bars {
  margin: 10px;
  padding-top: 20px;
}
svg {
  display: block;
  margin: auto;
}
div.d3_charts,
.charts_top {
  background-color: white;
  /*  padding-top: 45px;*/
}
.chart-header {
  font-weight: 400;
  font-style: normal;
  font-size: 20px;
  color: #666666;
  font-family: "Metric-Regular";
  padding-top: 5px;
  margin-bottom: 0px !important;
  margin-right: 20px;
  margin-left: 20px;
}
.default-title-class {
  text-align: left;
}
.lengend-action-header,
.lengend-action-buttons {
  float: left;
  margin-right: 15px;
}
.lengend-action-header {
  margin-left: 10px;
  font-weight: normal;
  font-size: 1.2em;
  Font-Family: Metric-Regular;
  Color: #666666;
}
.d3_charts_footer {
  label {
    font-weight: normal;
    font-size: 1.2em;
    Font-Family: Metric-Regular;
    Color: #666666;
    display: block;
    cursor: pointer;
  }
  [type="radio"] {
    border: 0;
    clip: rect(0 0 0 0);
    height: 1px;
    margin: -1px;
    overflow: hidden;
    padding: 0;
    position: absolute;
    width: 1px;
  }
  [type="radio"] + span:before {
    content: '';
    display: inline-block;
    width: 1.1em;
    height: 1.1em;
    vertical-align: -0.25em;
    border-radius: 1em;
    border: 0.35em solid #fff;
    box-shadow: 0 0 0 0.10em #36B18D;
    margin-right: 0.75em;
    transition: 0.5s ease all;
  }
  [type="radio"]:checked + span:before {
    background: #36B18D;
    box-shadow: 0 0 0 0.10em #36B18D;
  }
  [type="radio"]:focus + span::after {
    font-size: 1.2em;
    line-height: 1;
    vertical-align: -0.125em;
  }
  .my-legend {
    margin-top: 5px;
  }
  .my-legend .legend-title {
    text-align: left;
    margin-bottom: 5px;
    font-weight: bold;
    font-size: 90%;
  }
  .my-legend .legend-scale ul {
    margin: 0;
    margin-bottom: 5px;
    padding: 0;
    float: left;
    list-style: none;
  }
  .my-legend .legend-scale ul li {
    display: inline-block;
    font-size: 80%;
    list-style: none;
    line-height: 18px;
    vertical-align: text-top;
  }
  .my-legend ul.legend-labels li span {
    display: inline-block;
    height: 16px;
    width: 20px;
    margin-right: 5px;
    margin-left: 10px;
    border: 1px solid #999;
  }
  .my-legend a {
    color: #777;
  }
  .legend-labels li:nth-child(even) {
    margin-right: 15px;
  }
}
svg.bg-color {
  background-color: white;
}
.axis text {
  font: 10px sans-serif;
}
.axis path {
  fill: none;
  stroke: #ccc;
  stroke-width: 1px;
  shape-rendering: crispEdges;
}
.axis line {
  fill: none;
  stroke: #ccc;
  stroke-width: 1px;
}
.x_minor {
  stroke: #cccccc;
  stroke-width: 1px;
}
.y_minor:nth-child(even) {
  stroke: #cccccc;
}
.y_minor:nth-child(odd) {
  stroke: #f6f6f6;
}
.tick text {
  Font-Family: Metric-Regular;
  Font-Size: 12px;
  Color: #666666;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id="d3-chart">
  <div class="d3_charts"></div>
</div>

enter image description here

我的问题是如何在x轴上格式化网格,所以它看起来像图片中显示的网格而不管数据是什么?

此外,如何在x和y轴线与刻度值之间添加空格。

1 个答案:

答案 0 :(得分:1)

  • 网格线

我假设你想要每个可见滴答的网格线而不是每个计算的滴答。这可以通过明确地使用innerTickSize轴设置来实现:

var xAxis = d3.svg.axis().scale(xScale)
 .orient("bottom")
 .ticks(5)
 .tickSize(0)
.innerTickSize(-height) // set this value to be the size of the chart area
.outerTickSize(0);


var yAxis = d3.svg.axis().scale(yScale)
 .orient("left")
 .ticks(5)
 .tickSize(0)
 .innerTickSize(-width)
 .outerTickSize(0);  
  • 在轴线和刻度值之间添加空格:

      svg.append('g')
       .attr("class", "x axis")
       .attr("transform", "translate(0," + height + ")")
      .call(xAxis)
      .selectAll("text") 
      // select the tick value and adjust its position after axis gets called
      .attr("y", 10) 
      .attr("x", 6)
    
      svg.append('g')
        .attr("class", "y axis")
        .call(yAxis)
        .selectAll("text")  
         .attr("y", 3)
         .attr("x", -10)
    

根据评论更新:

第一个垂直网格线更接近y轴的原因是,在轴设置中,指定ticks(5),而源数据中的日期不是连续数据。

我想说取决于实现目标,以下方法可能是合适的:

  • 删除ticks(5)设置,让d3执行勾选计算工作,例如在此plunkr
  • 使用固定的刻度值生成指定的刻度,例如:

    var xAxis = d3.svg.axis().scale(xScale)
    .orient("bottom")
    .tickValues([
      parseDate.parse('30-Apr-12'),
      parseDate.parse('25-Apr-12'),
      parseDate.parse('23-Apr-12'),
      parseDate.parse('17-Apr-12'),
     ])
      .innerTickSize(-height)
      .outerTickSize(0);
    
  • 或者您可以预处理源数据,以便日期是连续的,这意味着更均匀的分布式滴答