Browse Source

extra label and round edges on bar chart

pull/1333/head
Oren Griffin 10 years ago
parent
commit
e04c0f4d7b
  1. 1
      .gitignore
  2. 12
      c3.css
  3. 78
      c3.js
  4. 10
      c3.min.js
  5. 2
      src/config.js
  6. 9
      src/core.js
  7. 9
      src/data.js
  8. 17
      src/format.js
  9. 12
      src/shape.bar.js
  10. 29
      src/text.js

1
.gitignore vendored

@ -6,3 +6,4 @@ d3.min.js
components
build
.sass-cache
.idea

12
c3.css

@ -1,7 +1,7 @@
/*-- Chart --*/
.c3 svg {
font: 10px sans-serif;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0); }
-webkit-tap-highlight-color: transparent; }
.c3 path, .c3 line {
fill: none;
@ -12,7 +12,11 @@
-moz-user-select: none;
user-select: none; }
.c3-legend-item-tile, .c3-xgrid-focus, .c3-ygrid, .c3-event-rect, .c3-bars path {
.c3-legend-item-tile,
.c3-xgrid-focus,
.c3-ygrid,
.c3-event-rect,
.c3-bars path {
shape-rendering: crispEdges; }
.c3-chart-arc path {
@ -71,11 +75,11 @@
/*-- Region --*/
.c3-region {
fill: steelblue;
fill-opacity: 0.1; }
fill-opacity: .1; }
/*-- Brush --*/
.c3-brush .extent {
fill-opacity: 0.1; }
fill-opacity: .1; }
/*-- Select - Drag --*/
/*-- Legend --*/

78
c3.js

@ -561,7 +561,7 @@
// setup drawer - MEMO: these must be called after axis updated
drawArea = $$.generateDrawArea ? $$.generateDrawArea(areaIndices, false) : undefined;
drawBar = $$.generateDrawBar ? $$.generateDrawBar(barIndices) : undefined;
drawBar = $$.generateDrawBar ? $$.generateDrawBar(barIndices, null, config.bar_radius) : undefined;
drawLine = $$.generateDrawLine ? $$.generateDrawLine(lineIndices, false) : undefined;
xForText = $$.generateXYForText(areaIndices, barIndices, lineIndices, true);
yForText = $$.generateXYForText(areaIndices, barIndices, lineIndices, false);
@ -602,6 +602,11 @@
$$.updateText(durationForExit);
}
// text
if ($$.hasSecondDataLabel()) {
$$.updateSecondText(durationForExit);
}
// title
if ($$.redrawTitle) { $$.redrawTitle(); }
@ -660,6 +665,7 @@
$$.redrawArea(drawArea, true),
$$.redrawCircle(cx, cy, true),
$$.redrawText(xForText, yForText, options.flow, true),
$$.redrawSecondText(xForText, yForText, options.flow, true),
$$.redrawRegion(true),
$$.redrawGrid(true),
].forEach(function (transitions) {
@ -689,6 +695,7 @@
$$.redrawArea(drawArea);
$$.redrawCircle(cx, cy);
$$.redrawText(xForText, yForText, options.flow);
$$.redrawSecondText(xForText, yForText, options.flow, true);
$$.redrawRegion();
$$.redrawGrid();
if (config.onrendered) {
@ -1101,6 +1108,7 @@
data_type: undefined,
data_types: {},
data_labels: {},
data_secondLabel: {},
data_order: 'desc',
data_regions: {},
data_color: undefined,
@ -1222,6 +1230,7 @@
line_connectNull: false,
line_step_type: 'step',
// bar
bar_radius: 0,
bar_width: undefined,
bar_width_ratio: 0.6,
bar_width_max: undefined,
@ -1906,6 +1915,15 @@
}
return false;
};
c3_chart_internal_fn.hasSecondDataLabel = function () {
var config = this.config;
if (typeof config.data_secondLabel === 'boolean' && config.data_secondLabel) {
return true;
} else if (typeof config.data_secondLabel === 'object' && notEmpty(config.data_secondLabel)) {
return true;
}
return false;
};
c3_chart_internal_fn.getDataLabelLength = function (min, max, key) {
var $$ = this,
lengths = [0, 0], paddingCoef = 1.3;
@ -3290,7 +3308,7 @@
var $$ = this;
$$.getBars(i).classed(CLASS.EXPANDED, false);
};
c3_chart_internal_fn.generateDrawBar = function (barIndices, isSub) {
c3_chart_internal_fn.generateDrawBar = function (barIndices, isSub, r) {
var $$ = this, config = $$.config,
getPoints = $$.generateGetBarPoints(barIndices, isSub);
return function (d, i) {
@ -3301,13 +3319,21 @@
var indexX = config.axis_rotated ? 1 : 0;
var indexY = config.axis_rotated ? 0 : 1;
var pathWithRoundEdges = 'M ' + points[0][indexX] + ',' + points[0][indexY] + ' ' +
'v' +(-1 * (points[0][indexY]-points[1][indexY]-r) )+ ' ' +
'a ' + r + ',' + r + ' 1 0 1 ' + r + ',' + (-r) + ' ' +
'h' + (points[2][indexX] - points[0][indexX] - 2 * r) + ' ' +
'a ' + r + ',' + r + ' 1 0 1 ' + (r) + ',' + r + ' ' +
'v' + ((points[0][indexY]-points[1][indexY]-r))+ ' ' + 'z';
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;
return r ? pathWithRoundEdges : path;
};
};
c3_chart_internal_fn.generateGetBarPoints = function (barIndices, isSub) {
@ -3350,6 +3376,7 @@
$$.main.select('.' + CLASS.chart).append("g")
.attr("class", CLASS.chartTexts);
$$.mainText = $$.d3.selectAll([]);
$$.mainText2 = $$.d3.selectAll([]);
};
c3_chart_internal_fn.updateTargetsForText = function (targets) {
var $$ = this, mainTextUpdate, mainTextEnter,
@ -3385,6 +3412,25 @@
.style('fill-opacity', 0)
.remove();
};
c3_chart_internal_fn.updateSecondText = function (durationForExit) {
var $$ = this, config = $$.config,
barOrLineData = $$.barOrLineData.bind($$),
classText = $$.classText.bind($$);
$$.mainText2 = $$.main.selectAll('.' + CLASS.texts).selectAll('.' + CLASS.text + '2')
.data(barOrLineData);
$$.mainText2.enter().append('text')
.attr("class", function () {return 'second-label ' + classText.apply(this, arguments); })
.attr('text-anchor', function (d) { return config.axis_rotated ? (d.value < 0 ? 'end' : 'start') : 'middle'; })
.style("stroke", 'none')
.style("fill", function (d) { return $$.color(d); })
.style("fill-opacity", 0);
$$.mainText2
.text(function (d, i, j) { return $$.dataSecondLabelFormat(d.id)(d.value, d.id, i, j); });
$$.mainText2.exit()
.transition().duration(durationForExit)
.style('fill-opacity', 0)
.remove();
};
c3_chart_internal_fn.redrawText = function (xForText, yForText, forFlow, withTransition) {
return [
(withTransition ? this.mainText.transition() : this.mainText)
@ -3394,6 +3440,15 @@
.style("fill-opacity", forFlow ? 0 : this.opacityForText.bind(this))
];
};
c3_chart_internal_fn.redrawSecondText = function (xForText, yForText, forFlow, withTransition) {
return [
(withTransition ? this.mainText2.transition() : this.mainText2)
.attr('x', xForText)
.attr('y', function () {return 16 + yForText.apply(this, arguments);})
.style("fill", this.color)
.style("fill-opacity", forFlow ? 0 : this.opacityForText.bind(this))
];
};
c3_chart_internal_fn.getTextRect = function (text, cls, element) {
var dummy = this.d3.select('body').append('div').classed('c3', true),
svg = dummy.append("svg").style('visibility', 'hidden').style('position', 'fixed').style('top', 0).style('left', 0),
@ -5772,6 +5827,23 @@
}
return format;
};
c3_chart_internal_fn.dataSecondLabelFormat = function (targetId) {
var $$ = this, data_secondLabel = $$.config.data_secondLabel,
format, defaultFormat = function (v) { return isValue(v) ? +v : ""; };
// find format according to axis id
if (typeof data_secondLabel.format === 'function') {
format = data_secondLabel.format;
} else if (typeof data_secondLabel.format === 'object') {
if (data_secondLabel.format[targetId]) {
format = data_secondLabel.format[targetId] === true ? defaultFormat : data_secondLabel.format[targetId];
} else {
format = function () { return ''; };
}
} else {
format = defaultFormat;
}
return format;
};
c3_chart_internal_fn.hasCaches = function (ids) {
for (var i = 0; i < ids.length; i++) {

10
c3.min.js vendored

File diff suppressed because one or more lines are too long

2
src/config.js

@ -38,6 +38,7 @@ c3_chart_internal_fn.getDefaultConfig = function () {
data_type: undefined,
data_types: {},
data_labels: {},
data_secondLabel: {},
data_order: 'desc',
data_regions: {},
data_color: undefined,
@ -159,6 +160,7 @@ c3_chart_internal_fn.getDefaultConfig = function () {
line_connectNull: false,
line_step_type: 'step',
// bar
bar_radius: 0,
bar_width: undefined,
bar_width_ratio: 0.6,
bar_width_max: undefined,

9
src/core.js

@ -556,7 +556,7 @@ c3_chart_internal_fn.redraw = function (options, transitions) {
// setup drawer - MEMO: these must be called after axis updated
drawArea = $$.generateDrawArea ? $$.generateDrawArea(areaIndices, false) : undefined;
drawBar = $$.generateDrawBar ? $$.generateDrawBar(barIndices) : undefined;
drawBar = $$.generateDrawBar ? $$.generateDrawBar(barIndices, null, config.bar_radius) : undefined;
drawLine = $$.generateDrawLine ? $$.generateDrawLine(lineIndices, false) : undefined;
xForText = $$.generateXYForText(areaIndices, barIndices, lineIndices, true);
yForText = $$.generateXYForText(areaIndices, barIndices, lineIndices, false);
@ -597,6 +597,11 @@ c3_chart_internal_fn.redraw = function (options, transitions) {
$$.updateText(durationForExit);
}
// text
if ($$.hasSecondDataLabel()) {
$$.updateSecondText(durationForExit);
}
// title
if ($$.redrawTitle) { $$.redrawTitle(); }
@ -655,6 +660,7 @@ c3_chart_internal_fn.redraw = function (options, transitions) {
$$.redrawArea(drawArea, true),
$$.redrawCircle(cx, cy, true),
$$.redrawText(xForText, yForText, options.flow, true),
$$.redrawSecondText(xForText, yForText, options.flow, true),
$$.redrawRegion(true),
$$.redrawGrid(true),
].forEach(function (transitions) {
@ -684,6 +690,7 @@ c3_chart_internal_fn.redraw = function (options, transitions) {
$$.redrawArea(drawArea);
$$.redrawCircle(cx, cy);
$$.redrawText(xForText, yForText, options.flow);
$$.redrawSecondText(xForText, yForText, options.flow, true);
$$.redrawRegion();
$$.redrawGrid();
if (config.onrendered) {

9
src/data.js

@ -262,6 +262,15 @@ c3_chart_internal_fn.hasDataLabel = function () {
}
return false;
};
c3_chart_internal_fn.hasSecondDataLabel = function () {
var config = this.config;
if (typeof config.data_secondLabel === 'boolean' && config.data_secondLabel) {
return true;
} else if (typeof config.data_secondLabel === 'object' && notEmpty(config.data_secondLabel)) {
return true;
}
return false;
};
c3_chart_internal_fn.getDataLabelLength = function (min, max, key) {
var $$ = this,
lengths = [0, 0], paddingCoef = 1.3;

17
src/format.js

@ -40,3 +40,20 @@ c3_chart_internal_fn.dataLabelFormat = function (targetId) {
}
return format;
};
c3_chart_internal_fn.dataSecondLabelFormat = function (targetId) {
var $$ = this, data_secondLabel = $$.config.data_secondLabel,
format, defaultFormat = function (v) { return isValue(v) ? +v : ""; };
// find format according to axis id
if (typeof data_secondLabel.format === 'function') {
format = data_secondLabel.format;
} else if (typeof data_secondLabel.format === 'object') {
if (data_secondLabel.format[targetId]) {
format = data_secondLabel.format[targetId] === true ? defaultFormat : data_secondLabel.format[targetId];
} else {
format = function () { return ''; };
}
} else {
format = defaultFormat;
}
return format;
};

12
src/shape.bar.js

@ -66,7 +66,7 @@ c3_chart_internal_fn.unexpandBars = function (i) {
var $$ = this;
$$.getBars(i).classed(CLASS.EXPANDED, false);
};
c3_chart_internal_fn.generateDrawBar = function (barIndices, isSub) {
c3_chart_internal_fn.generateDrawBar = function (barIndices, isSub, r) {
var $$ = this, config = $$.config,
getPoints = $$.generateGetBarPoints(barIndices, isSub);
return function (d, i) {
@ -77,13 +77,21 @@ c3_chart_internal_fn.generateDrawBar = function (barIndices, isSub) {
var indexX = config.axis_rotated ? 1 : 0;
var indexY = config.axis_rotated ? 0 : 1;
var pathWithRoundEdges = 'M ' + points[0][indexX] + ',' + points[0][indexY] + ' ' +
'v' +(-1 * (points[0][indexY]-points[1][indexY]-r) )+ ' ' +
'a ' + r + ',' + r + ' 1 0 1 ' + r + ',' + (-r) + ' ' +
'h' + (points[2][indexX] - points[0][indexX] - 2 * r) + ' ' +
'a ' + r + ',' + r + ' 1 0 1 ' + (r) + ',' + r + ' ' +
'v' + ((points[0][indexY]-points[1][indexY]-r))+ ' ' + 'z';
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;
return r ? pathWithRoundEdges : path;
};
};
c3_chart_internal_fn.generateGetBarPoints = function (barIndices, isSub) {

29
src/text.js

@ -3,6 +3,7 @@ c3_chart_internal_fn.initText = function () {
$$.main.select('.' + CLASS.chart).append("g")
.attr("class", CLASS.chartTexts);
$$.mainText = $$.d3.selectAll([]);
$$.mainText2 = $$.d3.selectAll([]);
};
c3_chart_internal_fn.updateTargetsForText = function (targets) {
var $$ = this, mainTextUpdate, mainTextEnter,
@ -38,6 +39,25 @@ c3_chart_internal_fn.updateText = function (durationForExit) {
.style('fill-opacity', 0)
.remove();
};
c3_chart_internal_fn.updateSecondText = function (durationForExit) {
var $$ = this, config = $$.config,
barOrLineData = $$.barOrLineData.bind($$),
classText = $$.classText.bind($$);
$$.mainText2 = $$.main.selectAll('.' + CLASS.texts).selectAll('.' + CLASS.text + '2')
.data(barOrLineData);
$$.mainText2.enter().append('text')
.attr("class", function () {return 'second-label ' + classText.apply(this, arguments); })
.attr('text-anchor', function (d) { return config.axis_rotated ? (d.value < 0 ? 'end' : 'start') : 'middle'; })
.style("stroke", 'none')
.style("fill", function (d) { return $$.color(d); })
.style("fill-opacity", 0);
$$.mainText2
.text(function (d, i, j) { return $$.dataSecondLabelFormat(d.id)(d.value, d.id, i, j); });
$$.mainText2.exit()
.transition().duration(durationForExit)
.style('fill-opacity', 0)
.remove();
};
c3_chart_internal_fn.redrawText = function (xForText, yForText, forFlow, withTransition) {
return [
(withTransition ? this.mainText.transition() : this.mainText)
@ -47,6 +67,15 @@ c3_chart_internal_fn.redrawText = function (xForText, yForText, forFlow, withTra
.style("fill-opacity", forFlow ? 0 : this.opacityForText.bind(this))
];
};
c3_chart_internal_fn.redrawSecondText = function (xForText, yForText, forFlow, withTransition) {
return [
(withTransition ? this.mainText2.transition() : this.mainText2)
.attr('x', xForText)
.attr('y', function () {return 16 + yForText.apply(this, arguments);})
.style("fill", this.color)
.style("fill-opacity", forFlow ? 0 : this.opacityForText.bind(this))
];
};
c3_chart_internal_fn.getTextRect = function (text, cls, element) {
var dummy = this.d3.select('body').append('div').classed('c3', true),
svg = dummy.append("svg").style('visibility', 'hidden').style('position', 'fixed').style('top', 0).style('left', 0),

Loading…
Cancel
Save