捏缩放关注夹点位置(如在Safari中)

时间:2013-12-05 01:48:13

标签: ios math nsarray core-plot pinchzoom

所以我有效地拥有了一个我想要水平缩放的图像,但也能够尊重捏的位置。所以如果你捏在左边,它会放大到左边。理想情况下,你捏的点会留在你的手指。

我的情况稍微具体一点,我正在绘制图表上的数据,所以我将操纵一个数据数组并取一个子集。但是,我确信数学是相似的。 (但是,我不能只使用Affinetransform作为我发现的大多数例子)

有什么想法吗?

3 个答案:

答案 0 :(得分:0)

您使用的是UIScrollView吗?据我所知,你会免费获得这种行为。

答案 1 :(得分:0)

我为标准UIView构建了以下解决方案,其中UIScrollViewCGAffineTransform缩放不合适,因为我不希望视图的子视图偏斜。我也将它与CorePlot线图一起使用。

缩放位于用户开始捏合的位置。

这是一个简单的实现:

@interface BMViewController ()

@property (nonatomic, assign) CGFloat pinchXCoord; // The point at which the pinch occurs
@property (nonatomic, assign) CGFloat minZoomProportion; // The minimum zoom proportion allowed. Used to control minimum view width
@property (nonatomic, assign) CGFloat viewCurrentXPosition; // The view-to-zoom’s frame’s current origin.x value.
@property (nonatomic, assign) CGFloat originalViewWidth, viewCurrentWidth; // original and current frame width of the view.

@end

@implementation BMViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    // Setup the pinch gesture recognizer
    UIPinchGestureRecognizer *pinchZoomRecognizer = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(pinchZoomGestureDetected:)];
    [self.view addGestureRecognizer:pinchZoomRecognizer];
}

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    self.originalViewWidth = self.view.frame.size.width;
    self.viewCurrentWidth = self.originalViewWidth;
}

- (void)pinchZoomGestureDetected:(UIPinchGestureRecognizer *)recognizer
{
    CGPoint pinchLocation = [recognizer locationInView:self.view];
    if (recognizer.state == UIGestureRecognizerStateBegan) {
        self.viewCurrentWidth = self.view.frame.size.width;
        self.viewCurrentXPosition = self.view.frame.origin.x;

        // Set the pinch X coordinate to a point relative to the bounds of the view
        self.pinchXCoord = pinchLocation.x - self.viewCurrentXPosition;
        self.minZoomProportion = self.originalViewWidth / self.viewCurrentWidth;
    }

    CGFloat proportion = recognizer.scale;
    CGFloat width = self.viewCurrentWidth * MAX(proportion, self.minZoomProportion); // Set a minimum zoom width (the original size)
    width = MIN(self.originalViewWidth * 4, width); // Set a maximum zoom width (original * 4)
    CGFloat rawX = self.viewCurrentXPosition + ((self.viewCurrentWidth - width) * (self.pinchXCoord / self.viewCurrentWidth)); // Calculate the new X value
    CGRect frame = self.view.frame;
    CGFloat newXValue = MIN(rawX, 0); // Don't let the view move too far right
    newXValue = MAX(newXValue, self.originalViewWidth - width); // Don't let the view move too far left
    self.view.frame = CGRectMake(newXValue, frame.origin.y, width, frame.size.height);
    NSLog(@"newXValue: %f, width: %f", newXValue, width);
}

@end

这就是为了调整UIView的水平轴所需要做的全部工作。

对于Core-Plot,假设CPTGraphHostingView是正在调整大小的UIViewController视图的子视图。当CPTGraphHostingView的框架/边界发生变化时会重新绘制layoutSubviews,因此,在包含视图的CPTGraphHostingView方法中,更改self.graphHostingView.frame = self.bounds; self.graphHostingView.hostedGraph.plotAreaFrame.frame = self.bounds; 并绘制区域相对于其父级边界的框架(即您应该调整大小的视图)。像这样:

layoutSubviews

我没有尝试在缩放时更改图表上的数据,但我无法想象它会太难。在包含视图的reloadData中,拨打CPTGraph上的{{1}}。

答案 2 :(得分:0)

默认的捏合手势处理程序围绕手势点缩放图形。使用绘图空间委托将缩放限制为仅一个轴。