Plotly.js: bar: avoid line between stacked bars

Created on 16 Sep 2019  路  7Comments  路  Source: plotly/plotly.js

Because of antialiasing, we produce subpixel artifacts between stacked bars which appear as white lines. This is shown in this Codepen

This has been discussed in this Stack Overflow thread and in https://github.com/plotly/plotly.js/issues/4149. Because bars are rectangles, I wonder if we shouldn't set shape-rendering="crispEdges" on them :thinking:

cc @alexcjohnson

bug

All 7 comments

huh, why doesn't that example get crispEdges? Normal stacked bars DO, eg https://rreusser.github.io/plotly-mock-viewer/#bar_stackto1
Screen Shot 2019-09-16 at 6 27 25 PM

I seem to recall some cases where we thought it should be avoided, but I don't remember what those were. Anyway even if there are such cases, your example is not one of them, it should be crisp.

huh, why doesn't that example get crispEdges? Normal stacked bars DO, eg

Very nice! I see that it does the right thing: there:https://github.com/plotly/plotly.js/blob/832590bb9f2c837058e96c2777d27e5f504921a0/src/traces/bar/style.js#L31-L39

Turns out that in my example the layout.bargap defaults to 0.2 because the barmode is group (see bar/layout_defaults.js for details). Anyway, setting the layout.bargap to zero fixed the issue.

I think this is satisfactory and I'm not sure this qualifies as a bug anymore. I would be OK with closing this issue if you agree of course.

Ah right, single, non-stacked bars with gaps are better with crisp off. But in this case, even though it's just one trace, there's still self-stacking. Ideal would be if we can figure out when there is self-stacking like this and have that effectively count as barcount > 1 (line 35 ^^) - I think it'd be worth trying this before closing, esp. since we've recently changed our algorithms to create more self-stacking - and we have px encouraging that use case.

Too bad browsers don't have separate x/y crisp modes, that would really be the ideal. One can sort of do this by precisely rounding the bar edges and disabling crispEdges, but that falls apart if the user zooms their browser.

I think it'd be worth trying this before closing, esp. since we've recently changed our algorithms to create more self-stacking - and we have px encouraging that use case.

Correct, this became the default behaviour after https://github.com/plotly/plotly.js/pull/3680

Here are a few cases where we don't set crispEdges and arguably we should:

Case 1

Plotly.newPlot(gd, [{
  type: 'bar',
  y: [1, 2],
  marker: {color: 'blue'}
}, {
  type: 'bar',
  y: [2, 1],
  marker: {color: 'blue'}
}], {
  showlegend: false
})

looks like

image

Note that setting both trace to same marker.color makes the artifact easier to spot. Adding bargroup:0 to the layout gets us crispEdges.

Case 2

Plotly.newPlot(gd, [{
  type: 'bar',
  x: [0, 0],
  y: [1, 2],
}])

image

just a more minimal example to the one from the codepen in the issue header.

Case 3

Plotly.newPlot(gd, [{
  type: 'bar',
  x: [0, 0],
  y: [1, 1],
  base: [0, 1]
}], {
  barmode: 'overlay'
})

image



Now a few questions:

  • Should we try to turn crispEdges every time two bars touch?
  • Or should we be more selective, and turn on cripsEdges when things look _really_ bad otherwise?
  • How much of a (perf) penalty do we pay by setting crispEdges?
  • Should we try to find alternatives to crispEdges similar to we what currently do here:

https://github.com/plotly/plotly.js/blob/1dee68b7fdd768c5dbc4b3644d4bcbd15f8e591a/src/traces/bar/plot.js#L196-L210

Should we try to turn crispEdges every time two bars touch?

That would be super tough to figure out

Or should we be more selective, and turn on cripsEdges when things look really bad otherwise?

I might even go the other way: what are the situations when crispEdges looks bad and we need to NOT enable it? Frankly the only one that occurs to me is narrow bars/gaps. If bars - OR the gaps between them - are, for example, somewhere between 2 and 3 px wide, crisp will make some of them 2px and others 3px, which looks junky, particularly if there are gaps. Even worse, if the bars or gaps are between 0 and 1 px, they can alternate between visible and completely gone.

How much of a (perf) penalty do we pay by setting crispEdges?

I'd assume the opposite, crispEdges disables antialiasing, and the extra blending it entails, so should be faster than leaving it off.

Should we try to find alternatives to crispEdges similar to we what currently do here:

Note that that solution fails with CSS transforms that scale the bars. Of course all hell breaks loose if you have a CSS rotation (that's not a multiple of 90 degrees)...

Was this page helpful?
0 / 5 - 0 ratings