我有1个视图,包含2个子视图。其中一个比另一个大10倍。我有一个大手势识别器(位于顶部)。
我希望能够通过手指之间的锚点捏合手势来缩放大一个。我希望小家伙能够从相同的全球位置锚点进行相同的变换,但不会改变自己的锚点。
希望我自己解释一下。这是代码:
- (void)twoFingerPinch:(UIPinchGestureRecognizer *)gestureRecognizer
{
//this changes the anchor point of "big" without moving it
[self adjustAnchorPointForGestureRecognizer:gestureRecognizer];
if ([gestureRecognizer state] == UIGestureRecognizerStateBegan || [gestureRecognizer state] == UIGestureRecognizerStateChanged) {
CGAffineTransform transform = CGAffineTransformScale([[gestureRecognizer view] transform], [gestureRecognizer scale], [gestureRecognizer scale]);
float scale = sqrt(transform.a*transform.a+transform.c*transform.c);
//this transforms "big"
[gestureRecognizer view].transform = transform;
//anchor point location in little view
CGPoint pivote = [gestureRecognizer locationInView:little];
CGAffineTransform transform_t = CGAffineTransformConcat(CGAffineTransformMakeTranslation(-pivote.x, -pivote.y), transform);
transform_t = CGAffineTransformConcat(transform_t, CGAffineTransformMakeTranslation(pivote.x, pivote.y));
little.transform = transform_t;
}
[gestureRecognizer setScale:1];
}
但这不起作用,小视图不断跳跃并疯狂。
编辑:更多信息。
好的,这是图表:
红色方块是大视图,黑色方块是小视图。虚线方块是主视图。
该行:[self adjustAnchorPointForGestureRecognizer:gestureRecognizer];将大视图锚点更改为捏手势的中心。这很有效。
当我缩放大视图时,小视图应缩放相同的数量并移动,使其在大视图中居中,就像现在一样。也就是说,它应该使用与大视图相同的锚点进行缩放。
如果可能的话,我想将这些转换保留在CGAffineTransform中的小视图中。
答案 0 :(得分:2)
好的,我终于找到了它。我不知道这是否是更好的解决方案,但它确实有效。
- (void)twoFingerPinch:(UIPinchGestureRecognizer *)gestureRecognizer
{
[self adjustAnchorPointForGestureRecognizer:gestureRecognizer];
if ([gestureRecognizer state] == UIGestureRecognizerStateBegan || [gestureRecognizer state] == UIGestureRecognizerStateChanged) {
CGAffineTransform transform = CGAffineTransformScale([[gestureRecognizer view] transform], [gestureRecognizer scale], [gestureRecognizer scale]);
float scale = sqrt(transform.a*transform.a+transform.c*transform.c);
if((scale>0.1)&&(scale<20)) {
[gestureRecognizer view].transform = transform;
CGPoint anchor = [gestureRecognizer locationInView:little];
anchor = CGPointMake(anchor.x - little.bounds.size.width/2, anchor.y-little.bounds.size.height/2);
CGAffineTransform affineMatrix = little.transform;
affineMatrix = CGAffineTransformTranslate(affineMatrix, anchor.x, anchor.y);
affineMatrix = CGAffineTransformScale(affineMatrix, [gestureRecognizer scale], [gestureRecognizer scale]);
affineMatrix = CGAffineTransformTranslate(affineMatrix, -anchor.x, -anchor.y);
little.transform = affineMatrix;
[eagleView setTransform:little.transform];
[gestureRecognizer setScale:1];
}
}
}
那个eaglView系列,是我需要CGAffineTransform并且无法更改锚点的真正原因。我将它发送到OpenGL来改变模型视图变换矩阵。
现在,通过用户反馈,它可以同时完成3种变换(旋转,缩放,平移)。
修改强>
只是一点注意:似乎当我移动视图太快时,eaglView和UIView会失去同步。所以我不直接将变换应用于UIViews,我将它们与eaglView中的信息一起应用。像这样:
- (void)twoFingerPinch:(UIPinchGestureRecognizer *)gestureRecognizer
{
[self adjustAnchorPointForGestureRecognizer:gestureRecognizer];
if ([gestureRecognizer state] == UIGestureRecognizerStateBegan || [gestureRecognizer state] == UIGestureRecognizerStateChanged) {
CGAffineTransform transform = CGAffineTransformScale([[gestureRecognizer view] transform], [gestureRecognizer scale], [gestureRecognizer scale]);
float scale = sqrt(transform.a*transform.a+transform.c*transform.c);
if((scale>0.1)&&(scale<20)) {
//[gestureRecognizer view].transform = transform;
CGPoint anchor = [gestureRecognizer locationInView:little];
anchor = CGPointMake(anchor.x - little.bounds.size.width/2, anchor.y-little.bounds.size.height/2);
CGAffineTransform affineMatrix = little.transform;
affineMatrix = CGAffineTransformTranslate(affineMatrix, anchor.x, anchor.y);
affineMatrix = CGAffineTransformScale(affineMatrix, [gestureRecognizer scale], [gestureRecognizer scale]);
affineMatrix = CGAffineTransformTranslate(affineMatrix, -anchor.x, -anchor.y);
//little.transform = affineMatrix;
[eagleView setTransform:affineMatrix];
[gestureRecognizer setScale:1];
CGAffineTransform transform = CGAffineTransformMakeRotation(eaglView.myRotation*M_PI/180);
transform = CGAffineTransformConcat(CGAffineTransformMakeScale(eaglView.myScale, eaglView.myScale), transform);
transform = CGAffineTransformConcat(transform, CGAffineTransformMakeTranslation(eaglView.myTranslate.x, -eaglView.myTranslate.y));
little.transform = transform;
big.transform = transform;
}
}
}
答案 1 :(得分:0)
要使用捏合的中心作为锚点来缩放较小的视图,那么您需要手动计算新的位置:
CGRect frame = little.frame; // Returns the frame based on the current transform
frame.origin.x = (frame.origin.x - pivot.x) * gestureRecognizer.scale;
frame.origin.y = (frame.origin.y - pivot.y) * gestureRecognizer.scale;
frame.width = frame.width * gestureRecognizer.scale;
frame.height = frame.height * gestureRecognizer.scale;
然后,更新转换。就个人而言,我会根据视图的实际位置而不是转换当前的变换来做到这一点 - 我觉得它更容易思考。例如:
little.transform = CGAffineTransformIndentity; // Remove the current transform
CGRect orgFrame = little.frame
CGFloat scale = frame.width / orgFrame.size.width;
CGAffineTransform t = CGAffineTransformMakeScale(scale, scale);
t = CGAffineTransformConcat(t, CGAffineTransformMakeTranslation(newFrame.origin.x - frame.origin.x, newFrame.origin.y - frame.origin.y));
little.transform = t;
请注意,我只是输入了我的头脑中的代码来给你和想法。它需要测试和调试!
此外,如果您使用基于原始捏的缩放值而不是每次都重置它然后转换变换,则可以删除其中一些代码。
添