Question

I am using core-plot lib to draw bar charts in my app like this ......

My problem is that i want the enabling of grapgh movement only in horizontal direction so that I can see the records for a long period of time, But the problem is that i just wnt to keep the y axis fixed to its place,

How can i do this?

Waiting for help....

Was it helpful?

Solution

Only recently has rudimentary user interaction been enabled in Core Plot graphs. To enable scrolling in any direction, you can set the allowsUserInteraction property of the plot space to YES.

We currently have no means of locking that movement to one direction. The scrolling action takes place in the -pointingDeviceDraggedAtPoint: method on CPXYPlotSpace, so you could subclass CPXYPlotSpace, copy over its implementation of that method, and alter it to only allow movement in the X direction. Even better, we'd appreciate any contributions to extend the functionality of the CPXYPlotSpace to add support for unidirectional movement.

OTHER TIPS

If you are using Core-Plot 0.2.2 or greater (possibly earlier) then you can add a method on your plot space's delegate to handle the following:

-(CGPoint)plotSpace:(CPTPlotSpace *)space willDisplaceBy:(CGPoint)displacement {
    return CGPointMake(displacement.x, 0);
}

This will restrict the plot movement to horizontal only. This assumes you have allowed interacting with the plot space by setting allowsUserInteraction = YES.

Limit scrolling by setting a delegate (i.e., CPPlotSpaceDelegate) on the plot space and implement the willChangePlotRangeTo method. You can do other cool things at the same time. Here's how I limit the display to quadrant one:

- (CPPlotRange *)plotSpace:(CPPlotSpace *)space
    willChangePlotRangeTo:(CPPlotRange *)newRange
            forCoordinate:(CPCoordinate)coordinate {

    // Display only Quadrant I: never let the location go negative.
    //
    if (newRange.locationDouble < 0.0F) {
        newRange.location = CPDecimalFromFloat(0.0);
    }

    // Adjust axis to keep them in view at the left and bottom;
    // adjust scale-labels to match the scroll.
    //
    CPXYAxisSet *axisSet = (CPXYAxisSet *)self.graph.axisSet;
        if (coordinate == CPCoordinateX) {
            axisSet.yAxis.orthogonalCoordinateDecimal = newRange.location;
            axisSet.xAxis.titleLocation = CPDecimalFromFloat(newRange. newRange.locationDouble +
                                                             (newRange.lengthDouble / 2.0F));
        } else {
            axisSet.xAxis.orthogonalCoordinateDecimal = newRange.location;
            axisSet.yAxis.titleLocation = CPDecimalFromFloat(newRange.locationDouble +
                                                             (newRange.lengthDouble / 2.0F));
        }

    return newRange;
}

See: CPPlotSpace.h

I used a simple way to "disable" the vertical scroll

    CPPlotRange *globalYRange = [CPPlotRange plotRangeWithLocation:CPDecimalFromDouble(minY) length:CPDecimalFromDouble(maxY)];
    plotSpace.globalYRange = globalYRange;

For, minY and maxY I put the values I displayed, like that the vertical limits are what you see, so you can't vertical scroll

It worked for me, after I saw your topic, so I wanted to complete your answers with mine

Using CorePlot 1.0 -- To restrict scrolling to just horizontal and scaling as well, I implemented the two CPTPlotSpaceDelegate methods: method by Steve Tranby with a modified method suggested by supperAly/edo42.

-(CGPoint)plotSpace:(CPTPlotSpace *)space willDisplaceBy:(CGPoint)displacement
{
    return CGPointMake(displacement.x, 0);
}

-(CPTPlotRange *)plotSpace:(CPTPlotSpace *)space willChangePlotRangeTo:(CPTPlotRange *)newRange forCoordinate:(CPTCoordinate)coordinate
{
    if (coordinate == CPTCoordinateY) {
    newRange = ((CPTXYPlotSpace*)space).yRange;
    }
    return newRange;
}

i am using CorePlot 0.2.2

-(CPPlotRange *)plotSpace:(CPPlotSpace *)space willChangePlotRangeTo:(CPPlotRange *)newRange forCoordinate:(CPCoordinate)coordinate;
{
    CPXYPlotSpace * plot_space = (CPXYPlotSpace*)space;
    plot_space.globalYRange = plot_space.yRange;
    return newRange;
}

u will need to add CPPlotSpaceDelegate,CPLineStyleDelegate protocols to your controller

and add (for CPLineStyleDelegate)

-(void)lineStyleDidChange:(CPLineStyle *)lineStyle
{
//empty
}

the system will keep the original range of y axis

All you have to do to fix the y axis after Answer 4 with the comment incl. ( newRange.doublePrecisionLocation is now newRange.locationDouble ) is to set plotSpace.globalYRange = plotSpace.yRange;

thanks to supperAly when my interface implements "CPPlotSpaceDelegate" protocol and the project can not be complied normally , and shows that: your interface xxx doesn't implement 'CPLineStyleDelegate' protocol, which make me confuse. so i add the method : -(void)lineStyleDidChange:(CPLineStyle *)lineStyle { //empty } for CPLineStyleDelegate and add <CPLineStyleDelegate> to my interface and the problems have gone.

The following code is based on Tom Donaldson's answer and has been tested with CorePlot 1.5.1:

- (CPTPlotRange *)plotSpace:(CPTPlotSpace *)space
      willChangePlotRangeTo:(CPTPlotRange *)newRange
              forCoordinate:(CPTCoordinate)coordinate
{
    CPTMutablePlotRange *range = [CPTMutablePlotRange plotRangeWithLocation:newRange.location length:newRange.length];

    // Display only Quadrant I: never let the location go negative.
    //
    if (range.locationDouble < 0.0F)
    {
        range.location = CPTDecimalFromFloat(0.0);
    }

    // Adjust axis to keep them in view at the left and bottom;
    // adjust scale-labels to match the scroll.
    //
    CPTXYAxisSet *axisSet = (CPTXYAxisSet *) space.graph.axisSet;
    if (coordinate == CPTCoordinateX)
    {
        axisSet.yAxis.orthogonalCoordinateDecimal = range.location;
        axisSet.xAxis.titleLocation               = CPTDecimalFromDouble(range.locationDouble + (range.lengthDouble / 2.0F));
    }
    else
    {
        axisSet.xAxis.orthogonalCoordinateDecimal = range.location;
        axisSet.yAxis.titleLocation               = CPTDecimalFromDouble(range.locationDouble + (range.lengthDouble / 2.0F));
    }

    return range;
}

You can override the

-(void)scaleBy:(CGFloat)interactionScale aboutPoint:(CGPoint)plotAreaPoint`

function in CPTXYPlotSpace and take out all the code related to the movement for y axis.

@Andrew S: "I'm getting 'assignment to read-only property' on newRange.location = CPTDecimalFromFloat(0.0);"

I had that, too, and, following the "CurvedScatterPlot" example in the Core-Plot gallery app, used a mutable copy of newRange in plotSpace:willChangePlotRangeTo:forCoordinate: ...

CPTMutablePlotRange *changedRange = [newRange mutableCopy];

changedRange.location = CPTDecimalFromCGFloat(0.0F); then passes muster and I used changedRange in the if...else block.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top