c3
Version:
D3-based reusable chart library
193 lines (184 loc) • 5.23 kB
text/typescript
import CLASS from './class'
import { ChartInternal } from './core'
import { getBBox, isValue, isWithinBox } from './util'
ChartInternal.prototype.initBar = function() {
var $$ = this
$$.main
.select('.' + CLASS.chart)
.append('g')
.attr('class', CLASS.chartBars)
}
ChartInternal.prototype.updateTargetsForBar = function(targets) {
var $$ = this,
config = $$.config,
mainBars,
mainBarEnter,
classChartBar = $$.classChartBar.bind($$),
classBars = $$.classBars.bind($$),
classFocus = $$.classFocus.bind($$)
mainBars = $$.main
.select('.' + CLASS.chartBars)
.selectAll('.' + CLASS.chartBar)
.data(targets)
.attr('class', function(d) {
return classChartBar(d) + classFocus(d)
})
mainBarEnter = mainBars
.enter()
.append('g')
.attr('class', classChartBar)
.style('pointer-events', 'none')
// Bars for each data
mainBarEnter
.append('g')
.attr('class', classBars)
.style('cursor', function(d) {
return config.data_selection_isselectable(d) ? 'pointer' : null
})
}
ChartInternal.prototype.updateBar = function(durationForExit) {
var $$ = this,
barData = $$.barData.bind($$),
classBar = $$.classBar.bind($$),
initialOpacity = $$.initialOpacity.bind($$),
color = function(d) {
return $$.color(d.id)
}
var mainBar = $$.main
.selectAll('.' + CLASS.bars)
.selectAll('.' + CLASS.bar)
.data(barData)
var mainBarEnter = mainBar
.enter()
.append('path')
.attr('class', classBar)
.style('stroke', color)
.style('fill', color)
$$.mainBar = mainBarEnter.merge(mainBar).style('opacity', initialOpacity)
mainBar
.exit()
.transition()
.duration(durationForExit)
.style('opacity', 0)
}
ChartInternal.prototype.redrawBar = function(
drawBar,
withTransition,
transition
) {
const $$ = this
return [
(withTransition ? this.mainBar.transition(transition) : this.mainBar)
.attr('d', drawBar)
.style('stroke', this.color)
.style('fill', this.color)
.style('opacity', d => ($$.isTargetToShow(d.id) ? 1 : 0))
]
}
ChartInternal.prototype.getBarW = function(axis, barTargetsNum) {
var $$ = this,
config = $$.config,
w =
typeof config.bar_width === 'number'
? config.bar_width
: barTargetsNum
? (axis.tickInterval() * config.bar_width_ratio) / barTargetsNum
: 0
return config.bar_width_max && w > config.bar_width_max
? config.bar_width_max
: w
}
ChartInternal.prototype.getBars = function(i, id) {
var $$ = this
return (id
? $$.main.selectAll('.' + CLASS.bars + $$.getTargetSelectorSuffix(id))
: $$.main
).selectAll('.' + CLASS.bar + (isValue(i) ? '-' + i : ''))
}
ChartInternal.prototype.expandBars = function(i, id, reset) {
var $$ = this
if (reset) {
$$.unexpandBars()
}
$$.getBars(i, id).classed(CLASS.EXPANDED, true)
}
ChartInternal.prototype.unexpandBars = function(i) {
var $$ = this
$$.getBars(i).classed(CLASS.EXPANDED, false)
}
ChartInternal.prototype.generateDrawBar = function(barIndices, isSub) {
var $$ = this,
config = $$.config,
getPoints = $$.generateGetBarPoints(barIndices, isSub)
return function(d, i) {
// 4 points that make a bar
var points = getPoints(d, i)
// switch points if axis is rotated, not applicable for sub chart
var indexX = config.axis_rotated ? 1 : 0
var indexY = config.axis_rotated ? 0 : 1
var path =
'M ' +
points[0][indexX] +
',' +
points[0][indexY] +
' ' +
'L' +
points[1][indexX] +
',' +
points[1][indexY] +
' ' +
'L' +
points[2][indexX] +
',' +
points[2][indexY] +
' ' +
'L' +
points[3][indexX] +
',' +
points[3][indexY] +
' ' +
'z'
return path
}
}
ChartInternal.prototype.generateGetBarPoints = function(barIndices, isSub) {
var $$ = this,
axis = isSub ? $$.subXAxis : $$.xAxis,
barTargetsNum = barIndices.__max__ + 1,
barW = $$.getBarW(axis, barTargetsNum),
barX = $$.getShapeX(barW, barTargetsNum, barIndices, !!isSub),
barY = $$.getShapeY(!!isSub),
barOffset = $$.getShapeOffset($$.isBarType, barIndices, !!isSub),
barSpaceOffset = barW * ($$.config.bar_space / 2),
yScale = isSub ? $$.getSubYScale : $$.getYScale
return function(d, i) {
var y0 = yScale.call($$, d.id)(0),
offset = barOffset(d, i) || y0, // offset is for stacked bar chart
posX = barX(d),
posY = barY(d)
// fix posY not to overflow opposite quadrant
if ($$.config.axis_rotated) {
if ((0 < d.value && posY < y0) || (d.value < 0 && y0 < posY)) {
posY = y0
}
}
posY -= y0 - offset
// 4 points that make a bar
return [
[posX + barSpaceOffset, offset],
[posX + barSpaceOffset, posY],
[posX + barW - barSpaceOffset, posY],
[posX + barW - barSpaceOffset, offset]
]
}
}
/**
* Returns whether the data point is within the given bar shape.
*
* @param mouse
* @param barShape
* @return {boolean}
*/
ChartInternal.prototype.isWithinBar = function(mouse, barShape) {
return isWithinBox(mouse, getBBox(barShape), 2)
}