gampleman / elm-visualization

A data visualization library for Elm

Home Page:http://package.elm-lang.org/packages/gampleman/elm-visualization/latest/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Vertical axis labels

pchronz opened this issue · comments

Hi and thanks for providing elm-visualization!

It would be great to be able to rotate the labels on the axes.
As a concrete use case, I'm trying to build a bar chart based on the bar chart example (https://code.gampleman.eu/elm-visualization/BarChart/).

Currently, the labels overlap when they're too long, which makes them unreadable.
elm-visualization-overlapping labels

I've tried to rotate the columns individually in SVG by using the rotate(90) transformation in the browser. However, there are two problems with this approach.

  1. The labels are misaligned
  2. There doesn't seem to be a way to do this using the visualization API.

screen shot 2018-06-25 at 1 10 48 pm

I've also tried to apply the rotation transformation to the .tick class in the example. However, then the translation of individual columns doesn't work anymore. Furthermore, this approach applies the transformation to the x and y axis. Finally, the problem with alignment would remain.

screen shot 2018-06-25 at 1 15 50 pm

As a third approach I've limited the size of the labels. In this case some labels turn out to be duplicates, which leads to errors in the rendering:

screen shot 2018-06-25 at 1 19 01 pm

I'd really appreciate any help on this issue.

Cheers,
Peter

I've got this with modifying the view function in the BarChart example to read like this:

view : List ( Date, Float ) -> Svg msg
view model =
    svg [ width (toString w ++ "px"), height (toString (h + 10) ++ "px") ]
        [ Svg.style [] [ text """
            .column rect { fill: rgba(118, 214, 78, 0.8); }
            .column text { display: none; }
            .column:hover rect { fill: rgb(118, 214, 78); }
            .column:hover text { display: inline; }

            .x-axis .tick text {
              transform: rotate(45deg);
              transform-origin: -4px 33px;
            }
          """ ]
        , g [ transform ("translate(" ++ toString (padding - 1) ++ ", " ++ toString (h - padding) ++ ")"), class "x-axis" ]
            [ xAxis model ]
        , g [ transform ("translate(" ++ toString (padding - 1) ++ ", " ++ toString padding ++ ")") ]
            [ yAxis ]
        , g [ transform ("translate(" ++ toString padding ++ ", " ++ toString padding ++ ")"), class "series" ] <|
            List.map (column (xScale model)) model
        ]

screen shot 2018-06-25 at 12 50 06

Notice the .x-axis .tick text: this allows you to target just the text label and not the tick mark. The transform-origin allows you to pinpoint where the rotation point will be.

Let me know if this solves the issue for you.

Thank you very much for your help.

Using your suggestions I got the following:

screen shot 2018-06-25 at 2 56 59 pm

Here I had to fine-tune the transform-origin setting and I had to increase the padding in y-direction. As long as the maximum length of the labels is fixed this approach seems to be okay. A better approach in the future might be to generate the text in the origin of the SVG group and then to rotate and translate. I imagine that would make it possible to align all labels nicely. Though I have no idea how to do that in SVG.

So, for my purposes the solution is good enough. Feel free to close the issue.

So I think the missing piece here was the text-anchor property:

    transform-origin: 0 9px;
    text-anchor: start;
    transform: rotate(45deg);

should do what you want even with events of different length.

Works perfectly, thank you.