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.
277 lines
11 KiB
277 lines
11 KiB
import CLASS from './class'; |
|
import { c3_chart_internal_fn } from './core'; |
|
import { isValue } from './util'; |
|
|
|
c3_chart_internal_fn.initGrid = function () { |
|
var $$ = this, config = $$.config, d3 = $$.d3; |
|
$$.grid = $$.main.append('g') |
|
.attr("clip-path", $$.clipPathForGrid) |
|
.attr('class', CLASS.grid); |
|
if (config.grid_x_show) { |
|
$$.grid.append("g").attr("class", CLASS.xgrids); |
|
} |
|
if (config.grid_y_show) { |
|
$$.grid.append('g').attr('class', CLASS.ygrids); |
|
} |
|
if (config.grid_focus_show) { |
|
$$.grid.append('g') |
|
.attr("class", CLASS.xgridFocus) |
|
.append('line') |
|
.attr('class', CLASS.xgridFocus); |
|
} |
|
$$.xgrid = d3.selectAll([]); |
|
if (!config.grid_lines_front) { $$.initGridLines(); } |
|
}; |
|
c3_chart_internal_fn.initGridLines = function () { |
|
var $$ = this, d3 = $$.d3; |
|
$$.gridLines = $$.main.append('g') |
|
.attr("clip-path", $$.clipPathForGrid) |
|
.attr('class', CLASS.grid + ' ' + CLASS.gridLines); |
|
$$.gridLines.append('g').attr("class", CLASS.xgridLines); |
|
$$.gridLines.append('g').attr('class', CLASS.ygridLines); |
|
$$.xgridLines = d3.selectAll([]); |
|
}; |
|
c3_chart_internal_fn.updateXGrid = function (withoutUpdate) { |
|
var $$ = this, config = $$.config, d3 = $$.d3, |
|
xgridData = $$.generateGridData(config.grid_x_type, $$.x), |
|
tickOffset = $$.isCategorized() ? $$.xAxis.tickOffset() : 0; |
|
|
|
$$.xgridAttr = config.axis_rotated ? { |
|
'x1': 0, |
|
'x2': $$.width, |
|
'y1': function (d) { return $$.x(d) - tickOffset; }, |
|
'y2': function (d) { return $$.x(d) - tickOffset; } |
|
} : { |
|
'x1': function (d) { return $$.x(d) + tickOffset; }, |
|
'x2': function (d) { return $$.x(d) + tickOffset; }, |
|
'y1': 0, |
|
'y2': $$.height |
|
}; |
|
$$.xgridAttr.opacity = function () { |
|
var pos = +d3.select(this).attr(config.axis_rotated ? 'y1' : 'x1'); |
|
return pos === (config.axis_rotated ? $$.height : 0) ? 0 : 1; |
|
}; |
|
|
|
var xgrid = $$.main.select('.' + CLASS.xgrids).selectAll('.' + CLASS.xgrid) |
|
.data(xgridData); |
|
var xgridEnter = xgrid.enter().append('line') |
|
.attr("class", CLASS.xgrid) |
|
.attr('x1', $$.xgridAttr.x1) |
|
.attr('x2', $$.xgridAttr.x2) |
|
.attr('y1', $$.xgridAttr.y1) |
|
.attr('y2', $$.xgridAttr.y2) |
|
.style("opacity", 0); |
|
$$.xgrid = xgridEnter.merge(xgrid); |
|
if (!withoutUpdate) { |
|
$$.xgrid |
|
.attr('x1', $$.xgridAttr.x1) |
|
.attr('x2', $$.xgridAttr.x2) |
|
.attr('y1', $$.xgridAttr.y1) |
|
.attr('y2', $$.xgridAttr.y2) |
|
.style("opacity", $$.xgridAttr.opacity); |
|
} |
|
xgrid.exit().remove(); |
|
}; |
|
|
|
c3_chart_internal_fn.updateYGrid = function () { |
|
var $$ = this, config = $$.config, |
|
gridValues = $$.yAxis.tickValues() || $$.y.ticks(config.grid_y_ticks); |
|
var ygrid = $$.main.select('.' + CLASS.ygrids).selectAll('.' + CLASS.ygrid) |
|
.data(gridValues); |
|
var ygridEnter = ygrid.enter().append('line') |
|
// TODO: x1, x2, y1, y2, opacity need to be set here maybe |
|
.attr('class', CLASS.ygrid); |
|
$$.ygrid = ygridEnter.merge(ygrid); |
|
$$.ygrid |
|
.attr("x1", config.axis_rotated ? $$.y : 0) |
|
.attr("x2", config.axis_rotated ? $$.y : $$.width) |
|
.attr("y1", config.axis_rotated ? 0 : $$.y) |
|
.attr("y2", config.axis_rotated ? $$.height : $$.y); |
|
ygrid.exit().remove(); |
|
$$.smoothLines($$.ygrid, 'grid'); |
|
}; |
|
|
|
c3_chart_internal_fn.gridTextAnchor = function (d) { |
|
return d.position ? d.position : "end"; |
|
}; |
|
c3_chart_internal_fn.gridTextDx = function (d) { |
|
return d.position === 'start' ? 4 : d.position === 'middle' ? 0 : -4; |
|
}; |
|
c3_chart_internal_fn.xGridTextX = function (d) { |
|
return d.position === 'start' ? -this.height : d.position === 'middle' ? -this.height / 2 : 0; |
|
}; |
|
c3_chart_internal_fn.yGridTextX = function (d) { |
|
return d.position === 'start' ? 0 : d.position === 'middle' ? this.width / 2 : this.width; |
|
}; |
|
c3_chart_internal_fn.updateGrid = function (duration) { |
|
var $$ = this, main = $$.main, config = $$.config, |
|
xgridLine, xgridLineEnter, ygridLine, ygridLineEnter, |
|
xv = $$.xv.bind($$), yv = $$.yv.bind($$), |
|
xGridTextX = $$.xGridTextX.bind($$), yGridTextX = $$.yGridTextX.bind($$); |
|
|
|
// hide if arc type |
|
$$.grid.style('visibility', $$.hasArcType() ? 'hidden' : 'visible'); |
|
|
|
main.select('line.' + CLASS.xgridFocus).style("visibility", "hidden"); |
|
if (config.grid_x_show) { |
|
$$.updateXGrid(); |
|
} |
|
xgridLine = main.select('.' + CLASS.xgridLines).selectAll('.' + CLASS.xgridLine) |
|
.data(config.grid_x_lines); |
|
// enter |
|
xgridLineEnter = xgridLine.enter().append('g') |
|
.attr("class", function (d) { return CLASS.xgridLine + (d['class'] ? ' ' + d['class'] : ''); }); |
|
xgridLineEnter.append('line') |
|
.attr("x1", config.axis_rotated ? 0 : xv) |
|
.attr("x2", config.axis_rotated ? $$.width : xv) |
|
.attr("y1", config.axis_rotated ? xv : 0) |
|
.attr("y2", config.axis_rotated ? xv : $$.height) |
|
.style("opacity", 0); |
|
xgridLineEnter.append('text') |
|
.attr("text-anchor", $$.gridTextAnchor) |
|
.attr("transform", config.axis_rotated ? "" : "rotate(-90)") |
|
.attr("x", config.axis_rotated ? yGridTextX : xGridTextX) |
|
.attr("y", xv) |
|
.attr('dx', $$.gridTextDx) |
|
.attr('dy', -5) |
|
.style("opacity", 0); |
|
// udpate |
|
$$.xgridLines = xgridLineEnter.merge(xgridLine); |
|
// done in d3.transition() of the end of this function |
|
// exit |
|
xgridLine.exit().transition().duration(duration) |
|
.style("opacity", 0) |
|
.remove(); |
|
|
|
// Y-Grid |
|
if (config.grid_y_show) { |
|
$$.updateYGrid(); |
|
} |
|
ygridLine = main.select('.' + CLASS.ygridLines).selectAll('.' + CLASS.ygridLine) |
|
.data(config.grid_y_lines); |
|
// enter |
|
ygridLineEnter = ygridLine.enter().append('g') |
|
.attr("class", function (d) { return CLASS.ygridLine + (d['class'] ? ' ' + d['class'] : ''); }); |
|
ygridLineEnter.append('line') |
|
.attr("x1", config.axis_rotated ? yv : 0) |
|
.attr("x2", config.axis_rotated ? yv : $$.width) |
|
.attr("y1", config.axis_rotated ? 0 : yv) |
|
.attr("y2", config.axis_rotated ? $$.height : yv) |
|
.style("opacity", 0); |
|
ygridLineEnter.append('text') |
|
.attr("text-anchor", $$.gridTextAnchor) |
|
.attr("transform", config.axis_rotated ? "rotate(-90)" : "") |
|
.attr("x", config.axis_rotated ? xGridTextX : yGridTextX) |
|
.attr("y", yv) |
|
.attr('dx', $$.gridTextDx) |
|
.attr('dy', -5) |
|
.style("opacity", 0); |
|
// update |
|
$$.ygridLines = ygridLineEnter.merge(ygridLine); |
|
$$.ygridLines.select('line') |
|
.transition().duration(duration) |
|
.attr("x1", config.axis_rotated ? yv : 0) |
|
.attr("x2", config.axis_rotated ? yv : $$.width) |
|
.attr("y1", config.axis_rotated ? 0 : yv) |
|
.attr("y2", config.axis_rotated ? $$.height : yv) |
|
.style("opacity", 1); |
|
$$.ygridLines.select('text') |
|
.transition().duration(duration) |
|
.attr("x", config.axis_rotated ? $$.xGridTextX.bind($$) : $$.yGridTextX.bind($$)) |
|
.attr("y", yv) |
|
.text(function (d) { return d.text; }) |
|
.style("opacity", 1); |
|
// exit |
|
ygridLine.exit().transition().duration(duration) |
|
.style("opacity", 0) |
|
.remove(); |
|
}; |
|
c3_chart_internal_fn.redrawGrid = function (withTransition, transition) { |
|
var $$ = this, config = $$.config, xv = $$.xv.bind($$), |
|
lines = $$.xgridLines.select('line'), |
|
texts = $$.xgridLines.select('text'); |
|
return [ |
|
(withTransition ? lines.transition(transition) : lines) |
|
.attr("x1", config.axis_rotated ? 0 : xv) |
|
.attr("x2", config.axis_rotated ? $$.width : xv) |
|
.attr("y1", config.axis_rotated ? xv : 0) |
|
.attr("y2", config.axis_rotated ? xv : $$.height) |
|
.style("opacity", 1), |
|
(withTransition ? texts.transition(transition) : texts) |
|
.attr("x", config.axis_rotated ? $$.yGridTextX.bind($$) : $$.xGridTextX.bind($$)) |
|
.attr("y", xv) |
|
.text(function (d) { return d.text; }) |
|
.style("opacity", 1) |
|
]; |
|
}; |
|
c3_chart_internal_fn.showXGridFocus = function (selectedData) { |
|
var $$ = this, config = $$.config, |
|
dataToShow = selectedData.filter(function (d) { return d && isValue(d.value); }), |
|
focusEl = $$.main.selectAll('line.' + CLASS.xgridFocus), |
|
xx = $$.xx.bind($$); |
|
if (! config.tooltip_show) { return; } |
|
// Hide when scatter plot exists |
|
if ($$.hasType('scatter') || $$.hasArcType()) { return; } |
|
focusEl |
|
.style("visibility", "visible") |
|
.data([dataToShow[0]]) |
|
.attr(config.axis_rotated ? 'y1' : 'x1', xx) |
|
.attr(config.axis_rotated ? 'y2' : 'x2', xx); |
|
$$.smoothLines(focusEl, 'grid'); |
|
}; |
|
c3_chart_internal_fn.hideXGridFocus = function () { |
|
this.main.select('line.' + CLASS.xgridFocus).style("visibility", "hidden"); |
|
}; |
|
c3_chart_internal_fn.updateXgridFocus = function () { |
|
var $$ = this, config = $$.config; |
|
$$.main.select('line.' + CLASS.xgridFocus) |
|
.attr("x1", config.axis_rotated ? 0 : -10) |
|
.attr("x2", config.axis_rotated ? $$.width : -10) |
|
.attr("y1", config.axis_rotated ? -10 : 0) |
|
.attr("y2", config.axis_rotated ? -10 : $$.height); |
|
}; |
|
c3_chart_internal_fn.generateGridData = function (type, scale) { |
|
var $$ = this, |
|
gridData = [], xDomain, firstYear, lastYear, i, |
|
tickNum = $$.main.select("." + CLASS.axisX).selectAll('.tick').size(); |
|
if (type === 'year') { |
|
xDomain = $$.getXDomain(); |
|
firstYear = xDomain[0].getFullYear(); |
|
lastYear = xDomain[1].getFullYear(); |
|
for (i = firstYear; i <= lastYear; i++) { |
|
gridData.push(new Date(i + '-01-01 00:00:00')); |
|
} |
|
} else { |
|
gridData = scale.ticks(10); |
|
if (gridData.length > tickNum) { // use only int |
|
gridData = gridData.filter(function (d) { return ("" + d).indexOf('.') < 0; }); |
|
} |
|
} |
|
return gridData; |
|
}; |
|
c3_chart_internal_fn.getGridFilterToRemove = function (params) { |
|
return params ? function (line) { |
|
var found = false; |
|
[].concat(params).forEach(function (param) { |
|
if ((('value' in param && line.value === param.value) || ('class' in param && line['class'] === param['class']))) { |
|
found = true; |
|
} |
|
}); |
|
return found; |
|
} : function () { return true; }; |
|
}; |
|
c3_chart_internal_fn.removeGridLines = function (params, forX) { |
|
var $$ = this, config = $$.config, |
|
toRemove = $$.getGridFilterToRemove(params), |
|
toShow = function (line) { return !toRemove(line); }, |
|
classLines = forX ? CLASS.xgridLines : CLASS.ygridLines, |
|
classLine = forX ? CLASS.xgridLine : CLASS.ygridLine; |
|
$$.main.select('.' + classLines).selectAll('.' + classLine).filter(toRemove) |
|
.transition().duration(config.transition_duration) |
|
.style('opacity', 0).remove(); |
|
if (forX) { |
|
config.grid_x_lines = config.grid_x_lines.filter(toShow); |
|
} else { |
|
config.grid_y_lines = config.grid_y_lines.filter(toShow); |
|
} |
|
};
|
|
|