d3条形图,固定条宽和固定间距,以中心轴线对齐

时间:2017-07-31 18:59:54

标签: javascript html css d3.js svg

我知道这有点奇怪,我确实需要有固定宽度的条形图而不是动态宽度处理。这是通过处理xwidth使用以下代码实现的,现在当条数很少时,条之间的间距更大。那么在d3中是否有可能在轴线的中心呈现x轴值和图表,其中条形宽度固定且条形之间的间距固定?

bars.append('rect')
.attr('class', function(d,i) {
    return 'bar';
})
.attr('id', function(d, i) {
    return name+'-bar-'+i;
})
.attr('x', function(d) { 
    return xScale(d.month) + (xScale.rangeBand() - 15)/2;
})
.attr('width', function(){
    return Math.min(xScale.rangeBand()-2, 15);
})
.attr('y', function(d) { return yScale(d.set.count); })
.attr('height', function(d) { return height - yScale(d.set.count); })
.on('click', function(d, i) {
  //
});

fiddle

1 个答案:

答案 0 :(得分:4)

一种简单的方法是动态设置xScale范围:

var xScaleRange = data.length * 30;
var xScale = d3.scale.ordinal()
    .rangeRoundBands([width / 2 - xScaleRange, width / 2 + xScaleRange], 0.2);

这里的幻数30只是条宽的两倍。

以下是您更改的代码:



// container size
var margin = {
    top: 10,
    right: 10,
    bottom: 30,
    left: 30
  },
  width = 600,
  height = 300;

var data = [{
  "month": "DEC",
  "set": {
    "count": 26,
    "id": 1,
    "label": "Set",
    "year": "2016"
  }
}, {
  "month": "JAN",
  "set": {
    "count": 30,
    "id": 1,
    "label": "Set",
    "year": "2017"
  }
}, {
  "month": "FEB",
  "set": {
    "count": 30,
    "id": 1,
    "label": "Set",
    "year": "2017"
  }
}];

var name = 'dashboard';

var xScaleRange = data.length * 30;

// x scale
var xScale = d3.scale.ordinal()
  .rangeRoundBands([width / 2 - xScaleRange, width / 2 + xScaleRange], 0.2);

// set x and y scales
xScale.domain(data.map(function(d) {
  return d.month;
}));

// x axis
var xAxis = d3.svg.axis()
  .scale(xScale)
  .orient('bottom')
  .outerTickSize(0);

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

var ticks = yScale.ticks(),
  lastTick = ticks[ticks.length - 1];
var newLastTick = lastTick + (ticks[1] - ticks[0]);
if (lastTick < yScale.domain()[1]) {
  ticks.push(lastTick + (ticks[1] - ticks[0]));
}

// adjust domain for further value
yScale.domain([yScale.domain()[0], newLastTick]);

// y axis
var yAxis = d3.svg.axis()
  .scale(yScale)
  .orient('left')
  .tickSize(-width, 0, 0)
  .tickFormat(d3.format('d'))
  .tickValues(ticks);

// create svg container
var svg = d3.select('#chart')
  .append('svg')
  .attr('class', 'd3-setup-barchart')
  .attr('width', width + margin.left + margin.right)
  .attr('height', height + margin.top + margin.bottom)
  .append('g')
  .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');

// Horizontal grid (y axis gridline)
svg.append('g')
  .attr('class', 'grid horizontal')
  .attr("transform", "translate(" + (width / 2 - xScaleRange) + ",0)")
  .call(d3.svg.axis()
    .scale(yScale)
    .orient('left')
    .tickSize(-xScaleRange * 2, 0, 0)
    .tickFormat('')
    .tickValues(ticks)
  );

// create bars
var bars = svg.selectAll('.bar')
  .data(data)
  .enter()
  .append('g');

bars.append('rect')
  .attr('class', function(d, i) {
    return 'bar';
  })
  .attr('id', function(d, i) {
    return name + '-bar-' + i;
  })
  .attr('x', function(d) {
    return xScale(d.month) + (xScale.rangeBand() - 15) / 2;
  })
  .attr('width', function() {
    return Math.min(xScale.rangeBand() - 2, 15);
  })
  .attr('y', function(d) {
    return yScale(d.set.count);
  })
  .attr('height', function(d) {
    return height - yScale(d.set.count);
  })
  .on('click', function(d, i) {
    //
  });

// draw x axis
svg.append('g')
  .attr('id', name + '-x-axis')
  .attr('class', 'x axis')
  .attr('transform', 'translate(0,' + height + ')')
  .call(xAxis);

// draw y axis
svg.append('g')
  .attr('class', 'y axis')
  .attr("transform", "translate(" + (width / 2 - xScaleRange) + ",0)")
  .call(yAxis)
  .append('text')
  .attr('transform', 'rotate(-90)')
  .attr('y', 6)
  .attr('dy', '.71em')
  .style('text-anchor', 'end');

// remove 0 in y axis
svg.select('.y')
  .selectAll('.tick')
  .filter(function(d) {
    return d === 0 || d % 1 !== 0;
  }).remove();

svg
  .select('.horizontal')
  .selectAll('.tick')
  .filter(function(d) {
    return d === 0 || d % 1 !== 0;
  }).remove();
&#13;
.d3-setup-barchart {
  background-color: #666666;
}
.d3-setup-barchart .axis path {
  fill: none;
  stroke: #000;
}
.d3-setup-barchart .bar {
  fill: #ccc;
}
.d3-setup-barchart .bar:hover {
  fill: orange;
  cursor: pointer;
}
.d3-setup-barchart .bar.selected {
  fill: orange;
  stroke: #fff;
  stroke-width: 2;
}
.d3-setup-barchart .label-text {
  text-anchor: middle;
  font-size: 12px;
  font-weight: bold;
  fill: orange;
  opacity: 0;
}
.d3-setup-barchart .label-text.selected {
  opacity: 1;
}
.d3-setup-barchart .axis text {
  fill: rgba(255, 255, 255, 0.6);
  font-size: 9px;
}
.d3-setup-barchart .axis-text.selected {
  fill: orange;
}
.d3-setup-barchart .y.axis path {
  display: none;
}
.d3-setup-barchart .y.axis text {
  font-size: 6px;
}
.d3-setup-barchart .x.axis path {
  fill: none;
  stroke: #353C41;
}
.d3-setup-barchart .grid .tick {
  stroke: #fff;
  opacity: .18 !important;
  stroke-width: 0;
}
.d3-setup-barchart .grid .tick line {
  stroke-width: .5 !important;
}
.d3-setup-barchart .grid path {
  stroke-width: 0;
}
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id="chart"></div>
&#13;
&#13;
&#13;