wireservice / leather

Python charting for 80% of humans.
https://leather.readthedocs.io
MIT License
330 stars 30 forks source link

Stacked (filled) lines #95

Closed wdoekes closed 4 years ago

wdoekes commented 4 years ago

Here's a quick and dirty implementation of stacked lines, by subclassing Line and hacking the data:

class Filled(Line):
    def to_svg(self, width, height, x_scale, y_scale, series, palette):
        group = super().to_svg(
            width=width, height=height, x_scale=x_scale, y_scale=y_scale,
            series=series, palette=palette)

        path = group[0]
        path_d = path.get('d').split(' ')

        # Go down to Y 0.
        path_d.extend(['V', six.text_type(y_scale.project(0, height, 0))])
        # Go back to t0 X.
        path_d.extend(['H', path_d[1]])
        # Close path.
        path_d.extend(['Z'])

        # Set fill to stroke and stroke to none. And update 'd'.
        path.set('fill', path.get('stroke'))
        path.set('stroke', 'none')
        path.set('d', ' '.join(path_d))

        return group

Data:

  1. Make sure you accumulate y-values of all lines, so the "top" lines have the Y-values of all the lines below them.

  2. Then, instead of add_line, add the Filled line from above. Make sure you add in reverse order. (The highest Y-value should be drawn first.)

    
            if stacked:
                chart.add_series(
                    Series(data=lines[idx], name=labels[idx]),
                    Filled(stroke_color=colors[idx]))
            else:
                chart.add_line(
                    data=lines[idx], name=labels[idx],
                    stroke_color=color[idx])
jpmckinney commented 4 years ago

Thanks! leather is basically in "essential maintenance" mode, so not adding any new features. That said, users might find this issue and copy your code.