You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Is there any way to add "DataLabels" like Highcharts. That is, to provide above/next to the bar/column the value of the y axis? #2
changed the title [-]Is there any way to add a DataLabel like Highcharts. That is, to provide above/next to the bar/column the value of the y axis? [/-][+]Is there any way to add "DataLabels" like Highcharts. That is, to provide above/next to the bar/column the value of the y axis? [/+]on Feb 22, 2024
If those numbers are drawn (and where) should be styleable self.style gives you the style dictionary. Measuring the content and deciding where to draw it could get tricky, though.
You are on the right track. You can just use the normal draw.* commands here. The ctx is not a canvas.ctx object, but a plot.ctx object, which contains the axes you are drawing on.
Note, that scaling is already set-up when this function is called.
Looks good. You should use relative coordinates to mix canvas units with absolute units: draw.content(rel: (0, offset), to: ((left + right) / 2, y-max))
You should also use add: anchor: "south" to use the south anchor as origin.
Also, the offset and content must come from the style dict.
If we want to add this a functionality to add-bar, we have to consider horizontal bars (check the value of y-axis.horizontal, and if so, either rotate the text or use a different anchor.
I checked the docs on code and pdf but couldn't manage to understand how to call it correctly. The docs don't mention these 'rel' and and 'to' parameters. Am I missing something?
draw.rect((left, y-min), (right, y-max))
if self.style.data-label != none {
let offset = self.data-label.at("offset")
let size = self.data-label.at("text-size")
let data_label = text(size:size)[#y-max]
if y-axis.horizontal {
draw.content((rel: (offset, 0), to: (right, (y-min + y-max) / 2)), anchor:"west", data_label)
} else {
draw.content((rel: (0, offset), to: ((left + right) / 2, y-max)), anchor:"south", data_label)
}
}
It is working for columnchart but not for barchart. I tried to mess up with parameters but the data-labels didn't appeared at all in the barchart case. Don't know what I'm missing.
Also I couldn't understand how to propagate the 'data-label' from:
set-style(
data-label: data-label,
)
To the _draw-rects(self, ctx) function above where I need to use the data-label from style dict.
The only problem that persists that I've noticed is that the style values aren't overriding the defaults, that applies not only for data-label, but for other custom values like "bar-width" and "x-inset".
set-style isn't working for 'x-inset', 'barwidth' and 'data-label'. I suspect the merge of the set-style dict and the bar defaults isn't working properly. Maybe it is a bug?
Nice! You must not use ctx.style directly but styles.resolve(ctx.style, ...) (search for uses or look up the documentation). I would also suggest adding a callback to add-bar that allows returning the content to show as label: this allows for custom formatting.
Do you want to open up a PR with your changes? I can also add some additions myself. If we add this feature I would like to have it more configurable: overriding the content anchor, specifying the side of the bar that is used as anchor etc.
Would it be possible to have a basic version of data-labels for bar charts - i.e. w/o scaling (users usually preview and can manually adjust?) ? Thank you,
Yes. I'll try to add something after refactoring the plot environment to make sub-plots possible.
With cetz:0.4.0 a better implementation is possible, but cetz-plot needs some rework to support than (custom coordinate systems). This is a feature I am planning to implement.
I'd love to see this implemented properly, but for now I am looking for a quick and dirty solution that I can use before my thesis deadline this sunday. So I am currently trying to hack on the codebase trying to get it to work, any pointers?
Very interesting. Is this going to be released soon? I really need it in a report.
Sorry, but I do not think I will have the time to release this soon. The PR is a hack that I do not want to release it. Plan is to do a rewrite of how cetz-plot works internally.
Activity
[-]Is there any way to add a DataLabel like Highcharts. That is, to provide above/next to the bar/column the value of the y axis? [/-][+]Is there any way to add "DataLabels" like Highcharts. That is, to provide above/next to the bar/column the value of the y axis? [/+]johannes-wolf commentedon Feb 22, 2024
This is currently not implemented, no.
rousbound commentedon Feb 22, 2024
If it is a desirable feature, I can look into it and suggest an implementation.
If that's the case, could you @johannes-wolf or someone give me some pointers on how to start thinking about this?
I'm not familiar with CeTZ the source code yet.
johannes-wolf commentedon Feb 22, 2024
Sure. The barchart implementation is here: https://github.com/johannes-wolf/cetz/blob/master/src/lib/plot/bar.typ.
You can do the drawing in the _stroke function: https://github.com/johannes-wolf/cetz/blob/bf3ec2f6894ccd9255243e1fa40d2b56d6ddcd5b/src/lib/plot/bar.typ#L72
If those numbers are drawn (and where) should be styleable
self.stylegives you the style dictionary. Measuring the content and deciding where to draw it could get tricky, though.rousbound commentedon Feb 25, 2024
Well, actually I think that it makes more sense to draw it here while iterating through each bar, doesn't it?
For example:
I couldn't understand how to draw text on that context though.
I'm on the right track?
If that's the case, can you give me some insight into how to draw text in that "if self.data-label" line?
johannes-wolf commentedon Feb 25, 2024
You are on the right track. You can just use the normal
draw.*commands here. Thectxis not acanvas.ctxobject, but aplot.ctxobject, which contains the axes you are drawing on.Note, that scaling is already set-up when this function is called.
rousbound commentedon Feb 25, 2024
Now I got it. I missed the draw.content function.
I arrived on this:
if self.data-label != none { let offset = self.data-label.at("offset") let size = self.data-label.at("text-size") draw.content((((left) + right)/2, y-max+offset), text(size:size)[#y-max]) }Then I pass this to the columnchart parameters:
data-label:(offset: 0.4, text-size: 7pt)
The offset doesn't work in a fixed manner because it scales, so you need to adjust it.
It kinda works for me right now.
If you wish we can see how to exactly make this follow the API style.
Example:
johannes-wolf commentedon Feb 25, 2024
Looks good. You should use relative coordinates to mix canvas units with absolute units:
draw.content(rel: (0, offset), to: ((left + right) / 2, y-max))You should also use add:
anchor: "south"to use the south anchor as origin.Also, the
offsetandcontentmust come from the style dict.If we want to add this a functionality to
add-bar, we have to consider horizontal bars (check the value ofy-axis.horizontal, and if so, either rotate the text or use a different anchor.rousbound commentedon Feb 26, 2024
I tried to follow the draw.content function call that you suggested, but couldn't manage to make it work:
It gives this error:
I checked the docs on code and pdf but couldn't manage to understand how to call it correctly. The docs don't mention these 'rel' and and 'to' parameters. Am I missing something?
johannes-wolf commentedon Feb 26, 2024
You are missing parentheses arround your coordinate. rel: and to: are not arguments to content.
rousbound commentedon Feb 26, 2024
Oh! Right. Now I got it.
What I have now is the following:
draw.rect((left, y-min), (right, y-max)) if self.style.data-label != none { let offset = self.data-label.at("offset") let size = self.data-label.at("text-size") let data_label = text(size:size)[#y-max] if y-axis.horizontal { draw.content((rel: (offset, 0), to: (right, (y-min + y-max) / 2)), anchor:"west", data_label) } else { draw.content((rel: (0, offset), to: ((left + right) / 2, y-max)), anchor:"south", data_label) } }It is working for columnchart but not for barchart. I tried to mess up with parameters but the data-labels didn't appeared at all in the barchart case. Don't know what I'm missing.
Also I couldn't understand how to propagate the 'data-label' from:
To the _draw-rects(self, ctx) function above where I need to use the data-label from style dict.
Can you give more pointers how to continue?
rousbound commentedon Feb 26, 2024
Nevermind! I got it. Found on the source code that you needed to use 'draw.group(ctx => {})'.
draw.rect((left, y-min), (right, y-max)) draw.group(ctx => { if ctx.style.data-label != none { let offset = ctx.style.data-label.at("offset") let size = ctx.style.data-label.at("text-size") let data_label = text(size:size)[#y-max] if y-axis.horizontal { draw.content((rel: (offset, 0), to: (right, (y-min + y-max) / 2)), anchor:"west", data_label) } else { draw.content((rel: (0, offset), to: ((left + right) / 2, y-max)), anchor:"south", data_label) } } })I just need to know why the data-labels aren't appearing on the barchart.
rousbound commentedon Feb 26, 2024
Done!
bar.typ:
draw.group(ctx => { if ctx.style.data-label != none { let offset = ctx.style.data-label.at("offset") let size = ctx.style.data-label.at("text-size") let data_label = text(size:size)[#y-max] let anchor = if y-axis.horizontal {"west"} else {"south"} draw.content((rel: (0, offset), to: ((left + right) / 2, y-max)), anchor:"south", data_label) } })I needed to make some changes to columchart.typ and barchart.typ to include these:
columnchart.typ
barchart.typ
The only problem that persists that I've noticed is that the style values aren't overriding the defaults, that applies not only for data-label, but for other custom values like "bar-width" and "x-inset".
I mean:
canvas({ draw.set-style( x-inset: 0, legend: (fill: white), padding: 1.5pt, data-label: data-label, ) chart.columnchart( data, label-key: 0, value-key: (..range(1, labels.len() + 1)), mode: "clustered", size: size, y-label: smallcaps[Escala de Likert], x-label: smallcaps[Perguntas], y-tick-step: 0.5, y-min: 1, y-max: 5, labels: labels, legend: "legend.north-east", bar-style: p ) } ) }set-style isn't working for 'x-inset', 'barwidth' and 'data-label'. I suspect the merge of the set-style dict and the bar defaults isn't working properly. Maybe it is a bug?
Current state of the charts:
johannes-wolf commentedon Feb 27, 2024
Nice! You must not use
ctx.styledirectly butstyles.resolve(ctx.style, ...)(search for uses or look up the documentation). I would also suggest adding a callback toadd-barthat allows returning the content to show as label: this allows for custom formatting.Do you want to open up a PR with your changes? I can also add some additions myself. If we add this feature I would like to have it more configurable: overriding the content anchor, specifying the side of the bar that is used as anchor etc.
rousbound commentedon Feb 27, 2024
Ok! I've created the PR, take a look!
I looked into using the styles.resolve but couldn't see exactly how to use it. I would need to check which default-style to use inside the draw-rects.
Also the 'add-bar' callback you mentioned I didn't understand how to implement it exactly.
If you need anything just comment on the PR and I can try to help.
6 remaining items
johannes-wolf commentedon Nov 24, 2024
Yes. I'll try to add something after refactoring the plot environment to make sub-plots possible.
LevitatingBusinessMan commentedon Jun 20, 2025
Is there currently any quick way to get this to work? Does the old PR still merge cleanly?
LevitatingBusinessMan commentedon Jun 23, 2025
The code still appears to work although the placement of the labels seems a bit off.
johannes-wolf commentedon Jun 23, 2025
With cetz:0.4.0 a better implementation is possible, but cetz-plot needs some rework to support than (custom coordinate systems). This is a feature I am planning to implement.
LevitatingBusinessMan commentedon Jun 23, 2025
I'd love to see this implemented properly, but for now I am looking for a quick and dirty solution that I can use before my thesis deadline this sunday. So I am currently trying to hack on the codebase trying to get it to work, any pointers?
johannes-wolf commentedon Jun 23, 2025
Maybe I will push a branch later today that helps implementing it.
LevitatingBusinessMan commentedon Jun 24, 2025
Were you able to make some changes?
johannes-wolf commentedon Jun 24, 2025
With this branch:
#135
And this code:
You can place labels:

wlievens commentedon Jun 25, 2025
Very interesting. Is this going to be released soon? I really need it in a report.
johannes-wolf commentedon Jun 25, 2025
Sorry, but I do not think I will have the time to release this soon. The PR is a hack that I do not want to release it. Plan is to do a rewrite of how cetz-plot works internally.
Is using a local checkout a problem?
wlievens commentedon Jun 26, 2025
I could use a local checkout, yes. It's part of an automated flow in a python module so no reason why that would not work. Thanks for the tip.
LevitatingBusinessMan commentedon Jun 29, 2025
I applied the following patch for
src/chart/barchart.typwhich works for my needs.@johannes-wolf I am incredibly thankful that you could cook something up this quickly, this is exactly what I was hoping to be possible.
johannes-wolf commentedon Mar 7, 2026
Link: #170