我试图以这样的方式屏蔽UIImageView,它允许用户在不移动其蒙版的情况下拖动图像。效果类似于人们如何在Instagram应用程序中定位图像,基本上允许用户定义图像的裁剪区域。
这是一个动画GIF,用于演示我之后的所作所为。
这是我目前如何屏蔽图像并将其重新定位在拖动/平移事件上。
import UIKit
class ViewController: UIViewController {
var dragDelta = CGPoint()
@IBOutlet weak var imageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
attachMask()
// listen for pan/drag events //
let pan = UIPanGestureRecognizer(target:self, action:#selector(onPanGesture))
pan.maximumNumberOfTouches = 1
pan.minimumNumberOfTouches = 1
self.view.addGestureRecognizer(pan)
}
func onPanGesture(gesture:UIPanGestureRecognizer)
{
let point:CGPoint = gesture.locationInView(self.view)
if (gesture.state == .Began){
print("begin", point)
// capture our drag start position
dragDelta = CGPoint(x:point.x-imageView.frame.origin.x, y:point.y-imageView.frame.origin.y)
} else if (gesture.state == .Changed){
// update image position based on how far we've dragged from drag start
imageView.frame.origin.y = point.y - dragDelta.y
} else if (gesture.state == .Ended){
print("ended", point)
}
}
func attachMask()
{
let mask = CAShapeLayer()
mask.path = UIBezierPath(roundedRect: CGRect(x: 0, y: 100, width: imageView.frame.size.width, height: 400), cornerRadius: 5).CGPath
mask.anchorPoint = CGPoint(x: 0, y: 0)
mask.fillColor = UIColor.redColor().CGColor
view.layer.addSublayer(mask)
imageView.layer.mask = mask;
}
}
这会导致图像和蒙版一起移动,如下所示。 关于如何锁定"的任何建议这个面具可以在它下面独立移动,非常感谢。
答案 0 :(得分:2)
将面具和框架彼此分开移动以达到此效果并不是实现此目的的最佳方式。大多数执行此类效果的应用都会执行以下操作:
用户现在可以根据需要平移并放大UIImageView。
接下来,如果您正在裁剪图像:
获取可见矩形(取自Getting the visible rect of an UIScrollView's content)
CGRect visibleRect = [scrollView convertRect:scrollView.bounds toView:zoomedSubview];
在UIImage上使用您喜欢的任何裁剪方法来获取必要的内容。
这是处理这种交互的最流畅的方式,代码保持非常简单!
答案 1 :(得分:1)
刚想通了。将CAShapeLayer的position属性设置为拖动时UIImageView位置的倒数将将CAShapeLayer锁定在其原始位置,但默认情况下,CoreAnimation会在重新分配位置时尝试对其进行动画处理。
可以通过将两个位置设置包装在CATransaction中来禁用此功能,如下所示。
func onPanGesture(gesture:UIPanGestureRecognizer)
{
let point:CGPoint = gesture.locationInView(self.view)
if (gesture.state == .Began){
print("begin", point)
// capture our drag start position
dragDelta = CGPoint(x:point.x-imageView.frame.origin.x, y:point.y-imageView.frame.origin.y)
} else if (gesture.state == .Changed){
// update image & mask positions based on the distance dragged
// and wrap both assignments in a CATransaction transaction to disable animations
CATransaction.begin()
CATransaction.setDisableActions(true)
mask.position.y = dragDelta.y - point.y
imageView.frame.origin.y = point.y - dragDelta.y
CATransaction.commit()
} else if (gesture.state == .Ended){
print("ended", point)
}
}
<强>更新强>
这是我相信AlexKoren建议的实现。此方法在UIScrollView中嵌套UIImageView,并使用UIScrollView来屏蔽图像。
class ViewController: UIViewController, UIScrollViewDelegate {
@IBOutlet weak var scrollView: UIScrollView!
var imageView:UIImageView = UIImageView()
override func viewDidLoad() {
super.viewDidLoad()
let image = UIImage(named: "point-bonitas")
imageView.image = image
imageView.frame = CGRectMake(0, 0, image!.size.width, image!.size.height);
scrollView.delegate = self
scrollView.contentMode = UIViewContentMode.Center
scrollView.addSubview(imageView)
scrollView.contentSize = imageView.frame.size
let scale = scrollView.frame.size.width / scrollView.contentSize.width
scrollView.minimumZoomScale = scale
scrollView.maximumZoomScale = scale // set to 1 to allow zoom out to 100% of image size //
scrollView.zoomScale = scale
// center image vertically in scrollview //
let offsetY:CGFloat = (scrollView.contentSize.height - scrollView.frame.size.height) / 2;
scrollView.contentOffset = CGPointMake(0, offsetY);
}
func scrollViewDidZoom(scrollView: UIScrollView) {
print("zoomed")
}
func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? {
return imageView
}
}
答案 2 :(得分:0)
另一种可能更简单的方法是将图像视图放在滚动视图中,让滚动视图为您管理它。它处理一切。