Padding problem


#1

This is using Xamarin. I’m displaying a stock market graph.

I have a chart that is made up of 4 series connected together. This lets me color each one differently even
though the whole thing is displayed as one contiguous line chart. I’m trying to insert some blank padding space in between the plotted series and the X and Y axes.

I’ve looked at various methods of doing so and I don’t think any of them will work for my situation. So first of all, “AutoCalculateRange” is set to false on my axes. When the user presses one of the 4 change scale buttons (weekly, monthly, yearly, 5-years) I then call SetRange for both axes. Thus if you were viewing the 5 year scale and hit the yearly scale, the chart changes the ranges to fit a yearly view. Because the actual data never changes, just the range, I can’t pad the range manually using the various techniques I’ve seen.

Is there a way to just change the area in which my line chart is rendered? Here’s an example showing a 5-year view:

Circled in red is the area I’m talking about that I’d like to insert distance between the axes for.

Here’s a yearly view:

You can see that this is really just the 5-year view but with the range shrunk to encapsulate just the most recent year of data (as evidenced by the colors of the 4 series).


#2

Hi Architekt,

You can move the axes away from the chart’s plot area using the secondaryAxisOffset property: that property is intended for use if you have multiple axes on the same side of a chart, to separate them, but it might help in this instance. Please note that if you move the axes away from the plot area then they will no longer meet at the origin.

If that solution won’t work for you, an alternative would be to alter your datasource so that it only provides the relevant data for the current scale. That way you could set autoCalculateRange to true and use the rangePaddingLow/rangePaddingHigh properties to add padding to your chart.

I hope one of these solutions will work for you.

Kind regards,

Alison


#3

Hi, I tried the secondaryAxisOffset thing and it almost worked. But I ran into something I couldn’t figure out how to fix. Check this screenshot: I managed to move the X axis down some but the tick marks didn’t move and the labels no longer appear. Is there something else I should be doing to get around this? Thanks.


#4

Hi Architekt,

It appears that the secondaryAxisOffset isn’t taken into account when calculating the tick mark position in this case. As I mentioned before, it’s not really intended to be used this way: it’s really for use when a chart has multiple axes in the same position.

However, you can get around this by adjusting it yourself by implementing the delegate method sChart:alterTickMark:beforeAddingToAxis: as follows:

func sChart(_ chart: ShinobiChart, alter tickMark: SChartTickMark, beforeAddingTo axis: SChartAxis) {
    if (axis.isXAxis()) {
        tickMark.tickMarkView?.center.y += axis.secondaryAxisOffset
    }
}

You would also need to manually set the axis’s width property to give it enough space to lay everything out correctly.

Having looked into this further however, I do think it may be better for you to alter your data source so you can use the range padding properties and make better use of the automatic calculations of the axes.

Kind regards,

Alison


#5

Thanks that worked. Regarding altering the data source I can’t. I need to color different parts of the line chart in different colors (which was a topic I brought up a while ago). Unless there’s now a way to color different regions of a single data source in different colors, I’m stuck connecting 4 data sources together to achieve this.


#6

Hi Architekt,

I’m glad that worked. In terms of your data source, have you tried doing something along the following lines?

func sChart(_ chart: ShinobiChart, numberOfDataPointsForSeriesAt seriesIndex: Int) -> Int {
    if (seriesIndex == 0) {
        switch currentDataRange {
        case .year:
            return data.count
        case .month:
            return 30
        case .week:
            return 7
        }
    } else {
        switch currentDataRange {
        case .year, .month:
            return 10
        case .week:
            return 7
        }
    }
}
    
    
func sChart(_ chart: ShinobiChart, dataPointAt dataIndex: Int, forSeriesAt seriesIndex: Int) -> SChartData {
    let index = data.count - self.sChart(chart, numberOfDataPointsForSeriesAt: seriesIndex) + dataIndex
    return data[index]
}

If you’ve already got your data stored in an array, you can just return the last X points of it for any series, where X depends on the seriesIndex and the current data range. This example will just put the last 10 points in a separate series to change their colour, but as you need more colours you could just add more cases to the numberOfDataPointsForSeries function. In each case you’re drawing the new series on top of the old, which makes the calculations simpler as well as resolving your previous crosshair issue.

Kind regards,

Alison