I'm trying to customize a stacked bar chart, and having some trouble figuring out the right way to inject some text into each bar. This is what I currently have, and it does inject a span element, but its not actually getting visibly displayed. Not sure if its just that I'm not setting the height and width of the span or what. Anyone have any idea what I'm missing?
var chart = Chartist.Bar(this.getDOMNode(), chartData, chartOptions).on("draw", function (data) {
if (data.type === "bar") {
var label = new Chartist.Svg("span");
label.addClass("ct-label ct-horizontal");
label.text("Test");
data.element.append(label);
data.element.attr({
style: "stroke-width: 35px"
});
}
});
I think the problem is that you can't use spans in SVG. But there is a text element. You can read more about it here: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/text
Yeah, I came up with a solution for this...and it was to use the text element as you suggested. For anyone who might need to do something similar in the future, here's what I came up with:
Handle the draw event of the chart with a function that looks something like this:
onDraw: function (data) {
if (data.type === "bar") {
var label, labelText, barLength, labelWidth, barClasses,
barWidth = 40,
barHorizontalCenter = (data.x1 + (data.element.width() * .5)),
barVerticalCenter = (data.y1 + (barWidth * .12)),
classLabelMap = {
cardinal: "Scared",
flamingo: "Confused",
sunglow: "Indifferent",
pistachio: "Confident",
grass: "Secure"
};
// set the width of the bar
data.element.attr({
style: "stroke-width: " + barWidth + "px"
});
// need to grab the CSS classes that were applied to the bar
barClasses = data.element.parent().classes();
// typically each bar gets two classes, ct-series and ct-series-<color>
// (cardinal, flamingo, etc)
barClasses.forEach(className => {
// eliminate the basic series class...we can't do anything with that
var color = className.replace("ct-series", "");
// once that is stripped off, if there's anything left, then we have
// the class that specifies the color of the bar...
if (color.length) {
// strip off the remaining leading dash
color = color.substr(1, color.length);
// use the color class to map to the text we want to display in
// the custom label for the bar
labelText = classLabelMap[color];
}
});
// add the custom label text as an attribute to the bar for use by a tooltip
data.element.attr({ label: labelText }, "ct:series");
// create a custom label element to insert into the bar
label = new Chartist.Svg("text");
label.text(labelText);
label.attr({
x: barHorizontalCenter,
y: barVerticalCenter,
"text-anchor": "middle",
style: "font-family: 'proxima-nova-alt', Helvetica, Arial, sans-serif; font-size: 12px; fill: white"
});
// add the new custom text label to the bar
data.group.append(label);
// only *now* that its been added to the bar and written to the DOM
// can we measure it to see if it actually fits in the bar
barLength = data.element.width(); // get the width of the bar itself
labelWidth = label._node.clientWidth; // now get the width of the custom label
// if the padded width of the label is larger than the bar...
if ((labelWidth + 20) >= barLength) {
// don't show it
label.remove();
}
}
}
And the result ends up looking something like this:

I'm open to suggestion if anyone has any ideas for how the above could be done better. Personally, key'ing off the class names of the parent feels a bit hackish, but it was the only thing I could find that uniquely identified each of the stacked bars. If there is something that would be better, please let me know.
That looks quite nice, and I'm glad you worked it out!
Awesome @ryexley ! If you like you can make a pull request and add this as an example on the Chartist example page. Just checkout the stack, create an example JS file here: https://github.com/gionkunz/chartist-js/tree/develop/site/examples
... and insert an example entry into the markdown file here: https://github.com/gionkunz/chartist-js/blob/develop/site/data/pages/examples.yml#L159
Cool work!
This is fantastic, it would be great if you were able to add this to Chartist main code! Great job!
Most helpful comment
Yeah, I came up with a solution for this...and it was to use the
textelement as you suggested. For anyone who might need to do something similar in the future, here's what I came up with:Handle the
drawevent of the chart with a function that looks something like this:And the result ends up looking something like this:
I'm open to suggestion if anyone has any ideas for how the above could be done better. Personally, key'ing off the class names of the parent feels a bit hackish, but it was the only thing I could find that uniquely identified each of the stacked bars. If there is something that would be better, please let me know.