Swift 4 放大镜功能实现

先上效果图吧,框框被限制在了image内了。

1234072-20180323151632896-1044388747.gif

这个feature我把它用在了我的app里了,博客写得不容易,来star下啦? https://github.com/Imputes/Nike-Collection/


就好像Ray Wenderlich的iOS Apprentice一书说的一样,要实现任何feature都要列个任务清单。所以我们先列个任务清单:

1. 实现把一个可拖动的View限制在一个特定的View里。

2. 实现把框到的image放大。




首先讲第一点:

既然要实现拖动的feature,Google之后就知道Cocoa Touch框架里的UIKit module里有一个UIPanGestureRecognizer类,有了这个类之后就可以实现拖拽feature了。

那么Google之后又知道了有两种方式:

一种是纯代码(在要放大的View所在的controller里或者view里, 在willAppear时刻或者didLoad时刻或者layoutSubView时刻写上, xxxView是拖拽的View):

let panGesture = UIPanGestureRecognizer.init(target: self, action: #selector(handlePan(sender: )))
xxxView.addGestureRecognizer(panGesture)

之后再在放大的View所在的类中写selector, 就是观察者panGestureRecognizer观察到被观察者(在这里是要拖拽的View)的变化之后执行的function。

@objc func handlePan(sender: UIPanGestureRecognizer) {
...
}


另一种是直接在storyboard里面拖panGesture到要拖拽的view上即可,再用IBAction连接到代码里,这个Action里写的东西和前面的handlePan一样。




那么如何限制在所在view里呢?

Easy playing! 只要在action里添加(assistView是铺在上面的UIView,):

let transition = sender.translation(in: self.assistView)
        let changeX = (sender.view?.center.x)! + transition.x
        let changeY = (sender.view?.center.y)! + transition.y
        var limitCenter = CGPoint.init(x: changeX, y: changeY)
        limitCenter.y = max((sender.view?.frame.size.height)! / 2, limitCenter.y)
        limitCenter.y = min(self.assistView.frame.size.height - (sender.view?.frame.size.height)! / 2, limitCenter.y)
        limitCenter.x = max((sender.view?.frame.size.width)! / 2, limitCenter.x)
        limitCenter.x = min(self.assistView.frame.size.width - (sender.view?.frame.size.width)! / 2, limitCenter.x)
        sender.view?.center = limitCenter
        sender.setTranslation(CGPoint.zero, in: self.assistView)

到了这一步之后就可以把这个view限制在imageView里了。

至此第一步实现。




那么第二步就简单了(因为可以直接Google到),

在所在类里写上这两个functions:

private func snapshotTargetView(view: UIView!, inRect rect: CGRect!) -> UIImage! {
        let scale = UIScreen.main.scale
        
        //Snapshot of view
        UIGraphicsBeginImageContextWithOptions(rect.size, false, scale)
        UIGraphicsGetCurrentContext()?.translateBy(x: -rect.origin.x, y: -rect.origin.y)
        view.layer.render(in: UIGraphicsGetCurrentContext()!)
        
        //Need this to stop screen flashing, but it's slower
        let snapshotImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return snapshotImage
    }
    
    private func resizeImage(image: UIImage, toNewSize newSize:CGSize) -> UIImage {
        let scale = UIScreen.main.scale
        
        UIGraphicsBeginImageContextWithOptions(newSize, false, scale)
        image.draw(in: CGRect(x:0, y:0, width:newSize.width, height:newSize.height))
        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return newImage!
}

再在Action里加上这两句(resultImageView是放大后要put的地方):

 let transition = sender.translation(in: self.assistView)
        let changeX = (sender.view?.center.x)! + transition.x
        let changeY = (sender.view?.center.y)! + transition.y
        var limitCenter = CGPoint.init(x: changeX, y: changeY)
        limitCenter.y = max((sender.view?.frame.size.height)! / 2, limitCenter.y)
        limitCenter.y = min(self.assistView.frame.size.height - (sender.view?.frame.size.height)! / 2, limitCenter.y)
        limitCenter.x = max((sender.view?.frame.size.width)! / 2, limitCenter.x)
        limitCenter.x = min(self.assistView.frame.size.width - (sender.view?.frame.size.width)! / 2, limitCenter.x)
        sender.view?.center = limitCenter
        sender.setTranslation(CGPoint.zero, in: self.assistView)

        // add this two lines
        let imges = snapshotTargetView(view: self.productImageView, inRect: sender.view?.frame)
        resultImageView.image = resizeImage(image: images!, toNewSize: resultImageView.frame.size)

OK了?。

效果:

1234072-20180323151632896-1044388747.gif

转载于:https://www.cnblogs.com/zhuzi1995/p/8592531.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值