我正在使用CoreGraphics从两个NSArray
对象的数据中绘制图表(一个包含水平数据的数组,一个包含垂直数据)。虽然这可行,但我想实现缩放功能,以便当用户捏住图表时,可视数据会根据其缩放进行缩放。
这样就像这样:
成为这样的:
我已经有一个名为dataRange
的变量,当渲染图形时,它被限制在这个值范围内。 dataRange
是NSRange
,意味着它由起始位置和长度指定。但是,我不确定如何计算这些值,因为用户正在捏出来产生缩放效果。
在考虑如何实现这一目标后,我想出了以下内容:
确定每个手指在屏幕上的位置,并找出我需要放大的数组中的元素
随着位置越来越接近图表的两侧,相应地设置可见数据的范围
但是,该方法存在一些问题。首先,它忽略了图形是否先前已放大,这意味着用户无法放大多次。它也与您期望的相反,因为捏合增加了可见数据的范围(缩小),而捏合意味着减小可见数据的范围(放大)。我想要与此相反。
执行此操作的代码在-touchesMoved:withEvent
:
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
NSSet *allTouches = [event allTouches];
if ([allTouches count] == 2) {
CGFloat xPositionStart = 0.0f, xPositionEnd = 0.0f;
CGFloat touchPositions[2] = {0.0f, 0.0f};
for (UITouch *object in allTouches) {
CGPoint touchLocation = [object locationInView:self];
if (touchPositions[0] == 0.0f) {
touchPositions[0] = touchLocation.x;
} else {
touchPositions[1] = touchLocation.x;
}
}
if (touchPositions[0] > touchPositions[1]) {
xPositionEnd = touchPositions[0];
xPositionStart = touchPositions[1];
} else {
xPositionStart = touchPositions[0];
xPositionEnd = touchPositions[1];
}
CGFloat xPositionStartActual = (xPositionStart / self.frame.size.width) * [self.horizontalValues count];
CGFloat xPositionEndActual = (xPositionEnd / self.frame.size.width) * [self.horizontalValues count];
self.dataRange = NSMakeRange(xPositionStartActual, xPositionEndActual - xPositionStartActual);
[self setNeedsDisplay];
}
}
我有点陷入困境,因为我无法找到用现有方法解决这些问题的方法。如果有人能指出我做错了什么,我会很感激。
答案 0 :(得分:1)
您可以使用UIPinchGestureRecognizer进行自定义缩放。这就是我完成同样任务的方式:
- (void)pinchToZoom:(UIPinchGestureRecognizer *)recognizer {
NSUInteger numTouches = [recognizer numberOfTouches], i;
for ( i = 0; i < numTouches; ++i ) {
CGPoint location = [recognizer locationOfTouch:i inView:self.view];
// now you can do something with points of your pinch if you wish
}
// next calculate the current zoomScale TAKING INTO ACCOUNT previous value
if (fabs(previousPinchScale - recognizer.scale) > 0.01) {
previousPinchScale = recognizer.scale;
zoomScale = beginScale * recognizer.scale;
if (zoomScale < minimumCameraScale) zoomScale = minimumCameraScale;
if (zoomScale > maximumCameraScale) zoomScale = maximumCameraScale;
// now make the zoom using CGAffineTransform
CGAffineTransform affineTransform = CGAffineTransformMakeScale(zoomScale, zoomScale);
[CATransaction begin];
[CATransaction setAnimationDuration:duration];
[self.layer setAffineTransform:affineTransform];
[CATransaction commit];
}
}
现在我解释一下我使用的每个浮动属性是什么意思:
previousPinchScale - 一个变量,用于确定您是否捏合某个重要比例(大于0.01)。这是因为没有多次调用setAffineTransform,因为它的动作非常慢。在init方法中设置previousPinchScale = -1。
beginScale - 用于自定义缩放平滑查看的变量。您可以在委托方法中设置它:
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
if ( [gestureRecognizer isKindOfClass:[UIPinchGestureRecognizer class]] ) {
beginScale = zoomScale;
}
}
zoomScale - 一个确定图形当前缩放的变量(如UIScrollView属性)。
minimumZoomScale,maximumZoomScale - 应该是明显的:)
这是一般方法,它可以缩放整个图形。 如果您只想缩放它的某些部分,可以将affineTransform应用于此部分,而不是整个视图。如果要实现缩放的“反向”效果,可以将所有浮点值乘以-1。您还可以根据用户捏的点来添加图形的一些偏移量。
我希望所有这些对你有所帮助。
祝你好运!
答案 1 :(得分:0)
您不希望缩放比例,因为它会缩放所有内容。尝试缩放内容视图的宽度和高度约束。将图表视图放在滚动视图中作为内容视图。