Browse Source

Show legend as new line when overflow - #15 #64

pull/80/head
Masayuki Tanaka 11 years ago
parent
commit
45ba2dbefe
  1. 180
      c3.js
  2. 4
      c3.min.js

180
c3.js

@ -68,7 +68,6 @@
__data_selection_isselectable = getConfig(['data', 'selection', 'isselectable'], function () { return true; }),
__data_selection_multiple = getConfig(['data', 'selection', 'multiple'], true);
// subchart
var __subchart_show = getConfig(['subchart', 'show'], false),
__subchart_size_height = __subchart_show ? getConfig(['subchart', 'size', 'height'], 60) : 0;
@ -221,6 +220,7 @@
};
var isLegendRight = __legend_position === 'right';
var legendStep = 0, legendItemWidth = 0, legendItemHeight = 0;
/*-- Define Functions --*/
@ -365,12 +365,20 @@
maxDataCount = getMaxDataCount();
return maxDataCount > 1 ? (base * ratio) / (maxDataCount - 1) : base;
}
function updateLegndStep(step) {
legendStep = step;
}
function updateLegendItemWidth(w) {
legendItemWidth = w;
}
function updateLegendItemHeight(h) {
legendItemHeight = h;
}
function getLegendWidth() {
// TODO: legend width should be an option
return __legend_show ? isLegendRight ? 150 : currentWidth : 0;
return __legend_show ? isLegendRight ? legendItemWidth * (legendStep + 1) : currentWidth : 0;
}
function getLegendHeight() {
return __legend_show ? isLegendRight ? currentHeight : 40 : 0;
return __legend_show ? isLegendRight ? currentHeight : legendItemHeight * (legendStep + 1) : 0;
}
function getLegendPaddingTop() {
var xAxisLabelPositon = getXAxisLabelPosition();
@ -1963,17 +1971,11 @@
.attr("clip-path", __axis_rotated ? getClipPath("yaxis-clip") : "");
}
/*-- Legend Region --*/
if (__legend_show) {
updateLegend(c3.data.targets);
}
// Set targets
updateTargets(c3.data.targets);
// Draw with targets
redraw({withTransform: true, withUpdateXDomain: true});
redraw({withTransform: true, withUpdateXDomain: true, withLegend: true});
// Show tooltip if needed
if (__tooltip_init_show) {
@ -1997,7 +1999,9 @@
window.onresize = generateResize();
}
if (window.onresize.add) {
window.onresize.add(updateAndRedraw);
window.onresize.add(function () {
updateAndRedraw({withTransition: false, withLegend: true});
});
}
}
@ -2271,7 +2275,7 @@
var mainCircle, mainBar, mainRegion, mainText, contextBar, eventRectUpdate;
var barIndices = getBarIndices(), maxDataCountTarget;
var rectX, rectW;
var withY, withSubchart, withTransition, withTransform, withUpdateXDomain, withUpdateOrgXDomain;
var withY, withSubchart, withTransition, withTransform, withUpdateXDomain, withUpdateOrgXDomain, withLegend;
var hideAxis = hasArcType(c3.data.targets);
var drawBar, drawBarOnSub, xForText, yForText;
var duration, durationForExit;
@ -2283,10 +2287,17 @@
withTransform = isDefined(options.withTransform) ? options.withTransform : false;
withUpdateXDomain = isDefined(options.withUpdateXDomain) ? options.withUpdateXDomain : false;
withUpdateOrgXDomain = isDefined(options.withUpdateOrgXDomain) ? options.withUpdateOrgXDomain : false;
withLegend = isDefined(options.withLegend) ? options.withLegend : false;
duration = withTransition ? __transition_duration : 0;
durationForExit = isDefined(options.durationForExit) ? options.durationForExit : duration;
// update legend
if (withLegend && __legend_show) {
updateLegend(c3.data.targets, options);
return; // call in updateLegend again with same options
}
if (withUpdateOrgXDomain) {
x.domain(d3.extent(getXDomain(c3.data.targets)));
orgXDomain = x.domain();
@ -2640,11 +2651,6 @@
.style("fill-opacity", 0)
.remove();
// update legend
if (__legend_show) {
updateLegend(c3.data.targets, {withTransition: withTransition});
}
// update fadein condition
getTargetIds().forEach(function (id) {
withoutFadeIn[id] = true;
@ -2690,10 +2696,11 @@
return callResizeFunctions;
}
function updateAndRedraw(options) {
var withTransition, withTransform;
var withTransition, withTransform, withLegend;
options = isDefined(options) ? options : {};
withTransition = isDefined(options.withTransition) ? options.withTransition : false;
withTransition = isDefined(options.withTransition) ? options.withTransition : true;
withTransform = isDefined(options.withTransform) ? options.withTransform : false;
withLegend = isDefined(options.withLegend) ? options.withLegend : false;
// Update sizes and scales
updateSizes();
updateScales();
@ -2713,7 +2720,8 @@
withTransition: withTransition,
withUpdateXDomain: true,
withTransform: withTransform,
durationForExit: 0
durationForExit: 0,
withLegend: withLegend
});
}
@ -2846,12 +2854,6 @@
.style("stroke", function (d) { return color(d.id); });
}
/*-- Legend --*/
if (__legend_show) {
updateLegend(targets);
}
/*-- Show --*/
// Fade-in each chart
@ -2877,7 +2879,7 @@
updateTargets(c3.data.targets);
// Redraw with new targets
redraw({withUpdateOrgXDomain: true, withUpdateXDomain: true});
redraw({withUpdateOrgXDomain: true, withUpdateXDomain: true, withLegend: true});
done();
}
@ -2907,58 +2909,74 @@
function updateLegend(targets, options) {
var ids = getTargetIds(targets), l;
var xForLegend, xForLegendText, xForLegendRect, yForLegend, yForLegendText, yForLegendRect;
var paddingTop = 4, paddingRight = 30, margin;
var totalLength = 0, offsets = {}, widths = {}, heights = {};
var paddingTop = 4, paddingRight = 26, maxWidth, maxHeight, posMin = 10;
var totalLength = 0, offsets = {}, widths = {}, heights = {}, margins = {}, steps = {}, step = 0;
var withTransition;
options = isUndefined(options) ? {} : options;
withTransition = isDefined(options.withTransition) ? options.withTransition : true;
function getXOffset(id, i) {
return __legend_equally ? widths[id] * i : offsets[id];
}
function getYOffset(id, i) {
return __legend_equally ? heights[id] * i : offsets[id];
}
function updatePositions(textElement, id) {
function updatePositions(textElement, id, reset) {
var box = textElement.getBBox(),
width = Math.ceil((box.width + paddingRight) / 10) * 10,
height = Math.ceil((box.height + paddingTop) / 10) * 10,
length = isLegendRight ? height : width,
itemWidth = Math.ceil((box.width + paddingRight) / 10) * 10,
itemHeight = Math.ceil((box.height + paddingTop) / 10) * 10,
itemLength = isLegendRight ? itemHeight : itemWidth,
areaLength = isLegendRight ? legendHeight : legendWidth,
maxWidth, maxHeight;
margin, maxLength;
// MEMO: care about condifion of step, totalLength
function updateValues(id, withoutStep) {
if (!withoutStep) {
margin = (areaLength - totalLength - itemLength) / 2;
if (margin < posMin) {
margin = (areaLength - itemLength) / 2;
totalLength = 0;
step++;
}
}
steps[id] = step;
margins[step] = margin;
offsets[id] = totalLength;
totalLength += itemLength;
}
widths[id] = width;
heights[id] = height;
if (reset) {
totalLength = 0;
step = 0;
maxWidth = 0;
maxHeight = 0;
}
widths[id] = itemWidth;
heights[id] = itemHeight;
if (!maxWidth || itemWidth >= maxWidth) { maxWidth = itemWidth; }
if (!maxHeight || itemHeight >= maxHeight) { maxHeight = itemHeight; }
maxLength = isLegendRight ? maxHeight : maxWidth;
if (__legend_equally) {
maxWidth = d3.max(Object.keys(widths).map(function (key) { return widths[key]; }));
maxHeight = d3.max(Object.keys(heights).map(function (key) { return heights[key]; }));
if (width >= maxWidth) {
Object.keys(widths).forEach(function (key) { widths[key] = width; });
if (! isLegendRight) {
margin = (legendWidth - width * Object.keys(targets).length) / 2;
}
Object.keys(widths).forEach(function (id) { widths[id] = maxWidth; });
Object.keys(heights).forEach(function (id) { heights[id] = maxHeight; });
margin = (areaLength - maxLength * ids.length) / 2;
if (margin < posMin) {
totalLength = 0;
step = 0;
ids.forEach(function (id) { updateValues(id); });
}
if (height >= maxHeight) {
Object.keys(heights).forEach(function (key) { heights[key] = height; });
if (isLegendRight) {
margin = (legendHeight - height * Object.keys(targets).length) / 2;
}
else {
updateValues(id, true);
}
} else {
offsets[id] = totalLength;
totalLength += length;
margin = (areaLength - totalLength) / 2;
updateValues(id);
}
}
if (isLegendRight) {
xForLegend = function () { return legendWidth * 0.2; };
yForLegend = function (id, i) { return margin + getYOffset(id, i); };
xForLegend = function (id) { return maxWidth * (0.2 + steps[id]); };
yForLegend = function (id) { return margins[steps[id]] + offsets[id]; };
} else {
xForLegend = function (id, i) { return margin + getXOffset(id, i); };
yForLegend = function () { return legendHeight * 0.2; };
xForLegend = function (id) { return margins[steps[id]] + offsets[id]; };
yForLegend = function (id) { return maxHeight * (0.2 + steps[id]); };
}
xForLegendText = function (id, i) { return xForLegend(id, i) + 14; };
yForLegendText = function (id, i) { return yForLegend(id, i) + 9; };
@ -2984,10 +3002,10 @@
});
l.append('text')
.text(function (id) { return isDefined(__data_names[id]) ? __data_names[id] : id; })
.each(function (id) { updatePositions(this, id); })
.each(function (id, i) { updatePositions(this, id, i === 0); })
.style("pointer-events", "none")
.attr('x', isLegendRight ? xForLegendText : -200)
.attr('y', isLegendRight ? -200 : yForLegend);
.attr('y', isLegendRight ? -200 : yForLegendText);
l.append('rect')
.attr("class", "legend-item-event")
.style('fill-opacity', 0)
@ -3000,13 +3018,13 @@
.style("pointer-events", "none")
.style('fill', function (id) { return color(id); })
.attr('x', isLegendRight ? xForLegendText : -200)
.attr('y', isLegendRight ? -200 : yForLegendText)
.attr('y', isLegendRight ? -200 : yForLegend)
.attr('width', 10)
.attr('height', 10);
legend.selectAll('text')
.data(ids)
.each(function (id) { updatePositions(this, id); })
.each(function (id, i) { updatePositions(this, id, i === 0); })
.transition().duration(withTransition ? 250 : 0)
.attr('x', xForLegendText)
.attr('y', yForLegendText);
@ -3023,6 +3041,15 @@
.attr('x', xForLegend)
.attr('y', yForLegend);
// Update all to reflect change of legend
updateLegendItemWidth(maxWidth);
updateLegendItemHeight(maxHeight);
updateLegndStep(step);
updateSizes();
updateScales();
transformAll(false);
options.withLegend = false;
redraw(options);
}
/*-- Event Handling --*/
@ -3160,11 +3187,10 @@
if (__legend_show) {
svg.selectAll('.legend-item' + getTargetSelectorSuffix(targetId)).remove();
updateLegend(c3.data.targets);
}
if (c3.data.targets.length > 0) {
redraw({withUpdateOrgXDomain: true, withUpdateXDomain: true});
redraw({withUpdateOrgXDomain: true, withUpdateXDomain: true, withLegend: true});
}
};
@ -3210,42 +3236,42 @@
c3.toLine = function (targets) {
setTargetType(targets, 'line');
updateAndRedraw({withTransition: true});
updateAndRedraw();
};
c3.toSpline = function (targets) {
setTargetType(targets, 'spline');
updateAndRedraw({withTransition: true});
updateAndRedraw();
};
c3.toBar = function (targets) {
setTargetType(targets, 'bar');
updateAndRedraw({withTransition: true});
updateAndRedraw();
};
c3.toScatter = function (targets) {
setTargetType(targets, 'scatter');
updateAndRedraw({withTransition: true});
updateAndRedraw();
};
c3.toArea = function (targets) {
setTargetType(targets, 'area');
updateAndRedraw({withTransition: true});
updateAndRedraw();
};
c3.toAreaSpline = function (targets) {
setTargetType(targets, 'area-spline');
updateAndRedraw({withTransition: true});
updateAndRedraw();
};
c3.toPie = function (targets) {
setTargetType(targets, 'pie');
updateAndRedraw({withTransition: true, withTransform: true});
updateAndRedraw({withTransform: true});
};
c3.toDonut = function (targets) {
setTargetType(targets, 'donut');
updateAndRedraw({withTransition: true, withTransform: true});
updateAndRedraw({withTransform: true});
};
c3.groups = function (groups) {
@ -3325,7 +3351,7 @@
c3.resize = function (size) {
__size_width = size ? size.width : null;
__size_height = size ? size.height : null;
updateAndRedraw();
updateAndRedraw({withLegend: true, withTransition: false});
};
c3.destroy = function () {

4
c3.min.js vendored

File diff suppressed because one or more lines are too long
Loading…
Cancel
Save