开发者

Allow horizontal scrolling only in the core-plot barchart?

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

Allow horizontal scrolling only in the core-plot barchart?

My problem is that i want the enabling of grapgh mo开发者_如何学运维vement 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....


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


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.


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜