缩放 UIViews 组但保持其位置
Scale group of UIViews but keeping its position
我正在尝试使用捏合手势(在基本视图上)一次缩放多个 UIView。虽然它看起来很简单,但我很难让它正常工作。
假设我有 3 个像这样堆叠的视图
----------------------------------------------
| |
| ------- -------- |
| | | | | |
| | V1 | --------------- | | |
| | | X | v2 | Y | v3 | |
| ------- --------------- | | |
| -------- |
---------------------------------------------
捏合时,我通过使用比例 属性
计算变换来缩放 3 个视图中的每一个
CGAffineTransform v1Transform = CGAffineTransformScale( v1.transform,recognizer.scale, recognizer.scale);
v1.transform = v1Transform
CGAffineTransform v2Transform = CGAffineTransformScale( v2.transform,recognizer.scale, recognizer.scale);
v2.transform = v2Transform
CGAffineTransform v3Transform = CGAffineTransformScale( v3.transform,recognizer.scale, recognizer.scale);
v3.transform = v3Transform
并使用当前比例更改每个视图的中心,像这样
CGPoint v1Center = CGPointMake(v1.center.x * recognizer.scale, node.imgView.center.y * recognizer.scale);
CGPoint v2Center = CGPointMake(v2.center.x * recognizer.scale, node.imgView.center.y * recognizer.scale);
CGPoint v3Center = CGPointMake(v3.center.x * recognizer.scale, node.imgView.center.y * recognizer.scale);
v1.cente = v1Center;
v2.center = v2Center;
v3.center = v3Center;
虽然这对三个视图的每一个都进行了统一缩放,但我觉得中心点太偏了,缩放看起来很奇怪。请检查以下问题的屏幕截图
如您所见,虽然缩放按预期工作并且所有 3 个视图一起缩放。中心仍然是一个问题。我希望从所有 3 个视图的实际位置完成比例,我不希望它们在 gif 中像这样移动。
有办法吗?非常感谢任何帮助
发生的事情是,您还缩放了视图相对于屏幕角 0,0 的 x 和 y 位置。您需要相对于屏幕中心或捏合手势的中心来执行此操作。我想不起来了,但我认为有一种方法可以指定比例尺的锚点,否则您将不得不手动计算位置调整。
如果我没理解错的话,您想要缩放一组元素时的通常行为,即它们从所有选定元素的中心开始缩放。
我以前做过这个,它在 Swift 中,它使用了我制作的库的一些扩展,称为 CGMath*,但它应该足够好作为伪代码:
let scale = recognizer.scale
// Reset the scale of the recognizer. We'll scale the views by the change in the last tick.
recognizer.scale = 1
// Get the center of all selected views as a CGPoint
let center = views.map { [=10=].center }.reduce(CGPoint.zero, +) / CGFloat(views.count)
views.forEach {
// Scale the view
[=10=].scale *= scale
// Get the distance from this view to the center of all views, this is a CGPoint
let distance = [=10=].center - center
// Multiply the distance by the scale and add it to the center of all views. Set that as the view's center.
[=10=].center = center + (distance * scale)
}
*CGMath 中的扩展使得加减点成为可能。
@EmilioPelaez 答案按预期工作。这是他的伪代码的 obj-c 版本,以防有人感兴趣
CGPoint newCenter =CGPointZero;
for(UIView *node in self.selectedNodes){
newCenter = CGPointMake(newCenter.x + node.center.x, newCenter.y + node.center.y);
}
newCenter = CGPointMake(newCenter.x/self.selectedNodes.count, newCenter.y/self.selectedNodes.count);
for(UIview *node in self.selectedNodes){
CGAffineTransform newTransform = CGAffineTransformScale( node.transform,recognizer.scale, recognizer.scale);
node.transform = newTransform;
CGPoint distance = CGPointMake(node.center.x - newCenter.x, node.center.y - newCenter.y);
CGPoint delta= CGPointMake(distance.x * recognizer.scale, distance.y * recognizer.scale);
node.center =CGPointMake(newCenter.x + delta.x, newCenter.y + delta.y);
}
我正在尝试使用捏合手势(在基本视图上)一次缩放多个 UIView。虽然它看起来很简单,但我很难让它正常工作。
假设我有 3 个像这样堆叠的视图
----------------------------------------------
| |
| ------- -------- |
| | | | | |
| | V1 | --------------- | | |
| | | X | v2 | Y | v3 | |
| ------- --------------- | | |
| -------- |
---------------------------------------------
捏合时,我通过使用比例 属性
计算变换来缩放 3 个视图中的每一个CGAffineTransform v1Transform = CGAffineTransformScale( v1.transform,recognizer.scale, recognizer.scale);
v1.transform = v1Transform
CGAffineTransform v2Transform = CGAffineTransformScale( v2.transform,recognizer.scale, recognizer.scale);
v2.transform = v2Transform
CGAffineTransform v3Transform = CGAffineTransformScale( v3.transform,recognizer.scale, recognizer.scale);
v3.transform = v3Transform
并使用当前比例更改每个视图的中心,像这样
CGPoint v1Center = CGPointMake(v1.center.x * recognizer.scale, node.imgView.center.y * recognizer.scale);
CGPoint v2Center = CGPointMake(v2.center.x * recognizer.scale, node.imgView.center.y * recognizer.scale);
CGPoint v3Center = CGPointMake(v3.center.x * recognizer.scale, node.imgView.center.y * recognizer.scale);
v1.cente = v1Center;
v2.center = v2Center;
v3.center = v3Center;
虽然这对三个视图的每一个都进行了统一缩放,但我觉得中心点太偏了,缩放看起来很奇怪。请检查以下问题的屏幕截图
如您所见,虽然缩放按预期工作并且所有 3 个视图一起缩放。中心仍然是一个问题。我希望从所有 3 个视图的实际位置完成比例,我不希望它们在 gif 中像这样移动。
有办法吗?非常感谢任何帮助
发生的事情是,您还缩放了视图相对于屏幕角 0,0 的 x 和 y 位置。您需要相对于屏幕中心或捏合手势的中心来执行此操作。我想不起来了,但我认为有一种方法可以指定比例尺的锚点,否则您将不得不手动计算位置调整。
如果我没理解错的话,您想要缩放一组元素时的通常行为,即它们从所有选定元素的中心开始缩放。
我以前做过这个,它在 Swift 中,它使用了我制作的库的一些扩展,称为 CGMath*,但它应该足够好作为伪代码:
let scale = recognizer.scale
// Reset the scale of the recognizer. We'll scale the views by the change in the last tick.
recognizer.scale = 1
// Get the center of all selected views as a CGPoint
let center = views.map { [=10=].center }.reduce(CGPoint.zero, +) / CGFloat(views.count)
views.forEach {
// Scale the view
[=10=].scale *= scale
// Get the distance from this view to the center of all views, this is a CGPoint
let distance = [=10=].center - center
// Multiply the distance by the scale and add it to the center of all views. Set that as the view's center.
[=10=].center = center + (distance * scale)
}
*CGMath 中的扩展使得加减点成为可能。
@EmilioPelaez 答案按预期工作。这是他的伪代码的 obj-c 版本,以防有人感兴趣
CGPoint newCenter =CGPointZero;
for(UIView *node in self.selectedNodes){
newCenter = CGPointMake(newCenter.x + node.center.x, newCenter.y + node.center.y);
}
newCenter = CGPointMake(newCenter.x/self.selectedNodes.count, newCenter.y/self.selectedNodes.count);
for(UIview *node in self.selectedNodes){
CGAffineTransform newTransform = CGAffineTransformScale( node.transform,recognizer.scale, recognizer.scale);
node.transform = newTransform;
CGPoint distance = CGPointMake(node.center.x - newCenter.x, node.center.y - newCenter.y);
CGPoint delta= CGPointMake(distance.x * recognizer.scale, distance.y * recognizer.scale);
node.center =CGPointMake(newCenter.x + delta.x, newCenter.y + delta.y);
}