Learning Highcharts 4
上QQ阅读APP看书,第一时间看更新

Understanding Highcharts' layout

Before we start to learn how Highcharts layout works, it is imperative that we understand some basic concepts first. To do that, let's first recall the chart example used in Chapter 1, Web Charts, and set a couple of borders to be visible. First, set a border around the plot area. To do that we can set the options of plotBorderWidth and plotBorderColor in the chart section, as follows:

        chart: {
                renderTo: 'container',
                type: 'spline',
                plotBorderWidth: 1,
                plotBorderColor: '#3F4044'
        },

The second border is set around the Highcharts container. Next, we extend the preceding chart section with additional settings:

        chart: {
                renderTo: 'container',
                ....
                borderColor: '#a1a1a1',
                borderWidth: 2,
                borderRadius: 3
        },

This sets the container border color with a width of 2 pixels and corner radius of 3 pixels.

As we can see, there is a border around the container and this is the boundary that the Highcharts display cannot exceed:

Understanding Highcharts' layout

By default, Highcharts displays have three different areas: spacing, labeling, and plot area. The plot area is the area inside the inner rectangle that contains all the plot graphics. The labeling area is the area where labels such as title, subtitle, axis title, legend, and credits go, around the plot area, so that it is between the edge of the plot area and the inner edge of the spacing area. The spacing area is the area between the container border and the outer edge of the labeling area.

The following screenshot shows three different kinds of areas. A gray dotted line is inserted to illustrate the boundary between the spacing and labeling areas.

Understanding Highcharts' layout

Each chart label position can be operated in one of the following two layouts:

  • Automatic layout: Highcharts automatically adjusts the plot area size based on the labels' positions in the labeling area, so the plot area does not overlap with the label element at all. Automatic layout is the simplest way to configure, but has less control. This is the default way of positioning the chart elements.
  • Fixed layout: There is no concept of labeling area. The chart label is specified in a fixed location so that it has a floating effect on the plot area. In other words, the plot area side does not automatically adjust itself to the adjacent label position. This gives the user full control of exactly how to display the chart.

The spacing area controls the offset of the Highcharts display on each side. As long as the chart margins are not defined, increasing or decreasing the spacing area has a global effect on the plot area measurements in both automatic and fixed layouts.

Chart margins and spacing settings

In this section, we will see how chart margins and spacing settings have an effect on the overall layout. Chart margins can be configured with the properties margin, marginTop, marginLeft, marginRight, and marginBottom, and they are not enabled by default. Setting chart margins has a global effect on the plot area, so that none of the label positions or chart spacing configurations can affect the plot area size. Hence, all the chart elements are in a fixed layout mode with respect to the plot area. The margin option is an array of four margin values covered for each direction, the same as in CSS, starting from north and going clockwise. Also, the margin option has a lower precedence than any of the directional margin options, regardless of their order in the chart section.

Spacing configurations are enabled by default with a fixed value on each side. These can be configured in the chart section with the property names spacing, spacingTop, spacingLeft, spacingBottom, and spacingRight.

In this example, we are going to increase or decrease the margin or spacing property on each side of the chart and observe the effect. The following are the chart settings:

            chart: {
                renderTo: 'container',
                type: ...
                marginTop: 10,
                marginRight: 0,
                spacingLeft: 30,
                spacingBottom: 0
            },

The following screenshot shows what the chart looks like:

Chart margins and spacing settings

The marginTop property fixes the plot area's top border 10 pixels away from the container border. It also changes the top border into fixed layout for any label elements, so the chart title and subtitle float on top of the plot area. The spacingLeft property increases the spacing area on the left-hand side, so it pushes the y axis title further in. As it is in automatic layout (without declaring marginLeft), it also pushes the plot area's west border in. Setting marginRight to 0 will override all the default spacing on the chart's right-hand side and change it to fixed layout mode. Finally, setting spacingBottom to 0 makes the legend touch the lower bar of the container, so it also stretches the plot area downwards. This is because the bottom edge is still in automatic layout even though spacingBottom is set to 0.

Chart label properties

Chart labels such as xAxis.title, yAxis.title, legend, title, subtitle, and credits share common property names, as follows:

  • align: This is for the horizontal alignment of the label. Possible keywords are 'left', 'center', and 'right'. As for the axis title, it is 'low', 'middle', and 'high'.
  • floating: This is to give the label position a floating effect on the plot area. Setting this to true will cause the label position to have no effect on the adjacent plot area's boundary.
  • margin: This is the margin setting between the label and the side of the plot area adjacent to it. Only certain label types have this setting.
  • verticalAlign: This is for the vertical alignment of the label. The keywords are 'top', 'middle', and 'bottom'.
  • x: This is for horizontal positioning in relation to alignment.
  • y: This is for vertical positioning in relation to alignment.

As for the labels' x and y positioning, they are not used for absolute positioning within the chart. They are designed for fine adjustment with the label alignment. The following diagram shows the coordinate directions, where the center represents the label location:

Chart label properties

We can experiment with these properties with a simple example of the align and y position settings, by placing both title and subtitle next to each other. The title is shifted to the left with align set to 'left', whereas the subtitle alignment is set to 'right'. In order to make both titles appear on the same line, we change the subtitle's y position to 15, which is the same as the title's default y value:

 title: {
     text: 'Web browsers ...',
     align: 'left'
 },
 subtitle: {
     text: 'From 2008 to present',
     align: 'right',
     y: 15
 },

The following is a screenshot showing both titles aligned on the same line:

Chart label properties

In the following subsections, we will experiment with how changes in alignment for each label element affect the layout behavior of the plot area.

Title and subtitle alignments

Title and subtitle have the same layout properties, and the only differences are that the default values and title have the margin setting. Specifying verticalAlign for any value changes from the default automatic layout to fixed layout (it internally switches floating to true). However, manually setting the subtitle's floating property to false does not switch back to automatic layout. The following is an example of title in automatic layout and subtitle in fixed layout:

    title: {
       text: 'Web browsers statistics'
    },
    subtitle: {
       text: 'From 2008 to present',
       verticalAlign: 'top',
       y: 60    
    },

The verticalAlign property for the subtitle is set to 'top', which switches the layout into fixed layout, and the y offset is increased to 60. The y offset pushes the subtitle's position further down. Due to the fact that the plot area is not in an automatic layout relationship to the subtitle anymore, the top border of the plot area goes above the subtitle. However, the plot area is still in automatic layout towards the title, so the title is still above the plot area:

Title and subtitle alignments

Legend alignment

Legends show different behavior for the verticalAlign and align properties. Apart from setting the alignment to 'center', all other settings in verticalAlign and align remain in automatic positioning. The following is an example of a legend located on the right-hand side of the chart. The verticalAlign property is switched to the middle of the chart, where the horizontal align is set to 'right':

          legend: {
                align: 'right',
                verticalAlign: 'middle',
                layout: 'vertical'
          },

The layout property is assigned to 'vertical' so that it causes the items inside the legend box to be displayed in a vertical manner. As we can see, the plot area is automatically resized for the legend box:

Legend alignment

Note that the border decoration around the legend box is disabled in the newer version. To display a round border around the legend box, we can add the borderWidth and borderRadius options using the following:

          legend: {
                align: 'right',
                verticalAlign: 'middle',
                layout: 'vertical',
                borderWidth: 1,
                borderRadius: 3
          },

Here is the legend box with a round corner border:

Legend alignment

Axis title alignment

Axis titles do not use verticalAlign. Instead, they use the align setting, which is either 'low', 'middle', or 'high'. The title's margin value is the distance between the axis title and the axis line. The following is an example of showing the y-axis title rotated horizontally instead of vertically (which it is by default) and displayed on the top of the axis line instead of next to it. We also use the y property to fine-tune the title location:

            yAxis: {
                title: {
                    text: 'Percentage %',
                    rotation: 0,
                    y: -15,
                    margin: -70,
                    align: 'high'
                },
                min: 0
            },

The following is a screenshot of the upper-left corner of the chart showing that the title is aligned horizontally at the top of the y axis. Alternatively, we can use the offset option instead of margin to achieve the same result.

Axis title alignment

Credits alignment

Credits is a bit different from other label elements. It only supports the align, verticalAlign, x, and y properties in the credits.position property (shorthand for credits: { position: … }), and is also not affected by any spacing setting. Suppose we have a graph without a legend and we have to move the credits to the lower-left area of the chart, the following code snippet shows how to do it:

            legend: {
                enabled: false
            },
            credits: {
                position: { 
                   align: 'left'
                },
                text: 'Joe Kuan',
                href: 'http://joekuan.wordpress.com'
            },

However, the credits text is off the edge of the chart, as shown in the following screenshot:

Credits alignment

Even if we move the credits label to the right with x positioning, the label is still a bit too close to the x axis interval label. We can introduce extra spacingBottom to put a gap between both labels, as follows:

            chart: {
                   spacingBottom: 30,
                    ....
            },
            credits: {
                position: { 
                   align: 'left',
                   x: 20,
                   y: -7
                },
            },
            ....

The following is a screenshot of the credits with the final adjustments:

Credits alignment

Experimenting with an automatic layout

In this section, we will examine the automatic layout feature in more detail. For the sake of simplifying the example, we will start with only the chart title and without any chart spacing settings:

     chart: {
         renderTo: 'container',
         // border and plotBorder settings
         borderWidth: 2,
         .....
     },
     title: {
            text: 'Web browsers statistics,
     },

From the preceding example, the chart title should appear as expected between the container and the plot area's borders:

Experimenting with an automatic layout

The space between the title and the top border of the container has the default setting spacingTop for the spacing area (a default value of 10-pixels high). The gap between the title and the top border of the plot area is the default setting for title.margin, which is 15-pixels high.

By setting spacingTop in the chart section to 0, the chart title moves up next to the container top border. Hence the size of the plot area is automatically expanded upwards, as follows:

Experimenting with an automatic layout

Then, we set title.margin to 0; the plot area border moves further up, hence the height of the plot area increases further, as follows:

Experimenting with an automatic layout

As you may notice, there is still a gap of a few pixels between the top border and the chart title. This is actually due to the default value of the title's y position setting, which is 15 pixels, large enough for the default title font size.

The following is the chart configuration for setting all the spaces between the container and the plot area to 0:

chart: {
     renderTo: 'container',
     // border and plotBorder settings
     .....
     spacingTop: 0
},
title: {
     text: null,
     margin: 0,
     y: 0
}

If we set title.y to 0, all the gap between the top edge of the plot area and the top container edge closes up. The following is the final screenshot of the upper-left corner of the chart, to show the effect. The chart title is not visible anymore as it has been shifted above the container:

Experimenting with an automatic layout

Interestingly, if we work backwards to the first example, the default distance between the top of the plot area and the top of the container is calculated as:

spacingTop + title.margin + title.y = 10 + 15 + 15 = 40

Therefore, changing any of these three variables will automatically adjust the plot area from the top container bar. Each of these offset variables actually has its own purpose in the automatic layout. Spacing is for the gap between the container and the chart content; thus, if we want to display a chart nicely spaced with other elements on a web page, spacing elements should be used. Equally, if we want to use a specific font size for the label elements, we should consider adjusting the y offset. Hence, the labels are still maintained at a distance and do not interfere with other components in the chart.

Experimenting with a fixed layout

In the preceding section, we have learned how the plot area dynamically adjusted itself. In this section, we will see how we can manually position the chart labels. First, we will start with the example code from the beginning of the Experimenting with automatic layout section and set the chart title's verticalAlign to 'bottom', as follows:

chart: {
    renderTo: 'container',
    // border and plotBorder settings    .....
},
title: {
    text: 'Web browsers statistics',
    verticalAlign: 'bottom'
},

The chart title is moved to the bottom of the chart, next to the lower border of the container. Notice that this setting has changed the title into floating mode; more importantly, the legend still remains in the default automatic layout of the plot area:

Experimenting with a fixed layout

Be aware that we haven't specified spacingBottom, which has a default value of 15 pixels in height when applied to the chart. This means that there should be a gap between the title and the container bottom border, but none is shown. This is because the title.y position has a default value of 15 pixels in relation to spacing. According to the diagram in the Chart label properties section, this positive y value pushes the title towards the bottom border; this compensates for the space created by spacingBottom.

Let's make a bigger change to the y offset position this time to show that verticalAlign is floating on top of the plot area:

 title: {
     text: 'Web browsers statistics',
     verticalAlign: 'bottom',
     y: -90
 },

The negative y value moves the title up, as shown here:

Experimenting with a fixed layout

Now the title is overlapping the plot area. To demonstrate that the legend is still in automatic layout with regard to the plot area, here we change the legend's y position and the margin settings, which is the distance from the axis label:

               legend: {
                   margin: 70,
                   y: -10
               },

This has pushed up the bottom side of the plot area. However, the chart title still remains in fixed layout and its position within the chart hasn't been changed at all after applying the new legend setting, as shown in the following screenshot:

Experimenting with a fixed layout

By now, we should have a better understanding of how to position label elements, and their layout policy relating to the plot area.