mirror of https://github.com/masayuki0812/c3.git
Quite good looking graph derived from d3.js
http://c3js.org
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
224 lines
8.4 KiB
224 lines
8.4 KiB
import { CLASS } from './class'; |
|
import { isFunction } from './util'; |
|
|
|
const initBrush = function () { |
|
let $$ = this, d3 = $$.d3; |
|
$$.brush = d3.svg.brush().on('brush', () => { $$.redrawForBrush(); }); |
|
$$.brush.update = function () { |
|
if ($$.context) { $$.context.select('.' + CLASS.brush).call(this); } |
|
return this; |
|
}; |
|
$$.brush.scale = function (scale) { |
|
return $$.config.axis_rotated ? this.y(scale) : this.x(scale); |
|
}; |
|
}; |
|
const initSubchart = function () { |
|
let $$ = this, config = $$.config, |
|
context = $$.context = $$.svg.append('g').attr('transform', $$.getTranslate('context')), |
|
visibility = config.subchart_show ? 'visible' : 'hidden'; |
|
|
|
context.style('visibility', visibility); |
|
|
|
// Define g for chart area |
|
context.append('g') |
|
.attr('clip-path', $$.clipPathForSubchart) |
|
.attr('class', CLASS.chart); |
|
|
|
// Define g for bar chart area |
|
context.select('.' + CLASS.chart).append('g') |
|
.attr('class', CLASS.chartBars); |
|
|
|
// Define g for line chart area |
|
context.select('.' + CLASS.chart).append('g') |
|
.attr('class', CLASS.chartLines); |
|
|
|
// Add extent rect for Brush |
|
context.append('g') |
|
.attr('clip-path', $$.clipPath) |
|
.attr('class', CLASS.brush) |
|
.call($$.brush); |
|
|
|
// ATTENTION: This must be called AFTER chart added |
|
// Add Axis |
|
$$.axes.subx = context.append('g') |
|
.attr('class', CLASS.axisX) |
|
.attr('transform', $$.getTranslate('subx')) |
|
.attr('clip-path', config.axis_rotated ? '' : $$.clipPathForXAxis) |
|
.style('visibility', config.subchart_axis_x_show ? visibility : 'hidden'); |
|
}; |
|
const updateTargetsForSubchart = function (targets) { |
|
let $$ = this, context = $$.context, config = $$.config, |
|
contextLineEnter, contextLineUpdate, contextBarEnter, contextBarUpdate, |
|
classChartBar = $$.classChartBar.bind($$), |
|
classBars = $$.classBars.bind($$), |
|
classChartLine = $$.classChartLine.bind($$), |
|
classLines = $$.classLines.bind($$), |
|
classAreas = $$.classAreas.bind($$); |
|
|
|
if (config.subchart_show) { |
|
// -- Bar --// |
|
contextBarUpdate = context.select('.' + CLASS.chartBars).selectAll('.' + CLASS.chartBar) |
|
.data(targets) |
|
.attr('class', classChartBar); |
|
contextBarEnter = contextBarUpdate.enter().append('g') |
|
.style('opacity', 0) |
|
.attr('class', classChartBar); |
|
// Bars for each data |
|
contextBarEnter.append('g') |
|
.attr('class', classBars); |
|
|
|
// -- Line --// |
|
contextLineUpdate = context.select('.' + CLASS.chartLines).selectAll('.' + CLASS.chartLine) |
|
.data(targets) |
|
.attr('class', classChartLine); |
|
contextLineEnter = contextLineUpdate.enter().append('g') |
|
.style('opacity', 0) |
|
.attr('class', classChartLine); |
|
// Lines for each data |
|
contextLineEnter.append('g') |
|
.attr('class', classLines); |
|
// Area |
|
contextLineEnter.append('g') |
|
.attr('class', classAreas); |
|
|
|
// -- Brush --// |
|
context.selectAll('.' + CLASS.brush + ' rect') |
|
.attr(config.axis_rotated ? 'width' : 'height', config.axis_rotated ? $$.width2 : $$.height2); |
|
} |
|
}; |
|
const updateBarForSubchart = function (durationForExit) { |
|
const $$ = this; |
|
$$.contextBar = $$.context.selectAll('.' + CLASS.bars).selectAll('.' + CLASS.bar) |
|
.data($$.barData.bind($$)); |
|
$$.contextBar.enter().append('path') |
|
.attr('class', $$.classBar.bind($$)) |
|
.style('stroke', 'none') |
|
.style('fill', $$.color); |
|
$$.contextBar |
|
.style('opacity', $$.initialOpacity.bind($$)); |
|
$$.contextBar.exit().transition().duration(durationForExit) |
|
.style('opacity', 0) |
|
.remove(); |
|
}; |
|
const redrawBarForSubchart = function (drawBarOnSub, withTransition, duration) { |
|
(withTransition ? this.contextBar.transition(Math.random().toString()).duration(duration) : this.contextBar) |
|
.attr('d', drawBarOnSub) |
|
.style('opacity', 1); |
|
}; |
|
const updateLineForSubchart = function (durationForExit) { |
|
const $$ = this; |
|
$$.contextLine = $$.context.selectAll('.' + CLASS.lines).selectAll('.' + CLASS.line) |
|
.data($$.lineData.bind($$)); |
|
$$.contextLine.enter().append('path') |
|
.attr('class', $$.classLine.bind($$)) |
|
.style('stroke', $$.color); |
|
$$.contextLine |
|
.style('opacity', $$.initialOpacity.bind($$)); |
|
$$.contextLine.exit().transition().duration(durationForExit) |
|
.style('opacity', 0) |
|
.remove(); |
|
}; |
|
const redrawLineForSubchart = function (drawLineOnSub, withTransition, duration) { |
|
(withTransition ? this.contextLine.transition(Math.random().toString()).duration(duration) : this.contextLine) |
|
.attr('d', drawLineOnSub) |
|
.style('opacity', 1); |
|
}; |
|
const updateAreaForSubchart = function (durationForExit) { |
|
let $$ = this, d3 = $$.d3; |
|
$$.contextArea = $$.context.selectAll('.' + CLASS.areas).selectAll('.' + CLASS.area) |
|
.data($$.lineData.bind($$)); |
|
$$.contextArea.enter().append('path') |
|
.attr('class', $$.classArea.bind($$)) |
|
.style('fill', $$.color) |
|
.style('opacity', function () { $$.orgAreaOpacity = +d3.select(this).style('opacity'); return 0; }); |
|
$$.contextArea |
|
.style('opacity', 0); |
|
$$.contextArea.exit().transition().duration(durationForExit) |
|
.style('opacity', 0) |
|
.remove(); |
|
}; |
|
const redrawAreaForSubchart = function (drawAreaOnSub, withTransition, duration) { |
|
(withTransition ? this.contextArea.transition(Math.random().toString()).duration(duration) : this.contextArea) |
|
.attr('d', drawAreaOnSub) |
|
.style('fill', this.color) |
|
.style('opacity', this.orgAreaOpacity); |
|
}; |
|
const redrawSubchart = function (withSubchart, transitions, duration, durationForExit, areaIndices, barIndices, lineIndices) { |
|
let $$ = this, d3 = $$.d3, config = $$.config, |
|
drawAreaOnSub, drawBarOnSub, drawLineOnSub; |
|
|
|
$$.context.style('visibility', config.subchart_show ? 'visible' : 'hidden'); |
|
|
|
// subchart |
|
if (config.subchart_show) { |
|
// reflect main chart to extent on subchart if zoomed |
|
if (d3.event && d3.event.type === 'zoom') { |
|
$$.brush.extent($$.x.orgDomain()).update(); |
|
} |
|
// update subchart elements if needed |
|
if (withSubchart) { |
|
// extent rect |
|
if (!$$.brush.empty()) { |
|
$$.brush.extent($$.x.orgDomain()).update(); |
|
} |
|
// setup drawer - MEMO: this must be called after axis updated |
|
drawAreaOnSub = $$.generateDrawArea(areaIndices, true); |
|
drawBarOnSub = $$.generateDrawBar(barIndices, true); |
|
drawLineOnSub = $$.generateDrawLine(lineIndices, true); |
|
|
|
$$.updateBarForSubchart(duration); |
|
$$.updateLineForSubchart(duration); |
|
$$.updateAreaForSubchart(duration); |
|
|
|
$$.redrawBarForSubchart(drawBarOnSub, duration, duration); |
|
$$.redrawLineForSubchart(drawLineOnSub, duration, duration); |
|
$$.redrawAreaForSubchart(drawAreaOnSub, duration, duration); |
|
} |
|
} |
|
}; |
|
const redrawForBrush = function () { |
|
let $$ = this, x = $$.x; |
|
$$.redraw({ |
|
withTransition: false, |
|
withY: $$.config.zoom_rescale, |
|
withSubchart: false, |
|
withUpdateXDomain: true, |
|
withDimension: false, |
|
}); |
|
$$.config.subchart_onbrush.call($$.api, x.orgDomain()); |
|
}; |
|
const transformContext = function (withTransition, transitions) { |
|
let $$ = this, subXAxis; |
|
if (transitions && transitions.axisSubX) { |
|
subXAxis = transitions.axisSubX; |
|
} else { |
|
subXAxis = $$.context.select('.' + CLASS.axisX); |
|
if (withTransition) { subXAxis = subXAxis.transition(); } |
|
} |
|
$$.context.attr('transform', $$.getTranslate('context')); |
|
subXAxis.attr('transform', $$.getTranslate('subx')); |
|
}; |
|
const getDefaultExtent = function () { |
|
let $$ = this, config = $$.config, |
|
extent = isFunction(config.axis_x_extent) ? config.axis_x_extent($$.getXDomain($$.data.targets)) : config.axis_x_extent; |
|
if ($$.isTimeSeries()) { |
|
extent = [$$.parseDate(extent[0]), $$.parseDate(extent[1])]; |
|
} |
|
return extent; |
|
}; |
|
|
|
export { |
|
initBrush, |
|
initSubchart, |
|
updateTargetsForSubchart, |
|
updateBarForSubchart, |
|
redrawBarForSubchart, |
|
updateLineForSubchart, |
|
redrawLineForSubchart, |
|
updateAreaForSubchart, |
|
redrawAreaForSubchart, |
|
redrawSubchart, |
|
redrawForBrush, |
|
transformContext, |
|
getDefaultExtent, |
|
};
|
|
|