如何在iPhone中同时使用旋转和翻译图像?

时间:2011-07-14 13:00:13

标签: iphone objective-c cgaffinetransform

我使用CGAffineTransformMakeRotation进行图像旋转,使用CGAffineTransformMakeTranslation进行图像翻译。这是我的代码:

-(void)rotateTranslate
{
    r++;
    CGAffineTransform transform = CGAffineTransformMakeRotation(r);
    imageView.transform = transform;
    x++;
    y++;
    CGAffineTransform transform1=CGAffineTransformMakeTranslation(x,y);
    imageView.transform= transform1;
    [self performSelector:@selector(rotateTranslate) withObject:self afterDelay:0.2];
}

我的问题是图像只是翻译它不是旋转的。如果我单独使用Rotate和Translate意味着它的效果非常好。如何修改我的代码才能很好地工作?

2 个答案:

答案 0 :(得分:3)

问题在于您正在进行单独旋转,然后进行翻译和设置。因此,翻译会覆盖旋转。你必须做这样的事情,

CGAffineTransform transform = CGAffineTransformRotate(imageView.transform, 1);
transform = CGAffineTransformTranslate(transform, 1, 1);

imageView.transform= transform;

[self performSelector:@selector(rotateTranslate) withObject:self afterDelay:0.2];

但这不会为旋转设置动画。它只会从当前变换跳转到结束变换。

并且您似乎没有定义终点。

答案 1 :(得分:-1)

这是我的代码,我没有时间过滤掉代码,但它包含所有功能,如旋转,翻译和缩放滚动视图中的图像。

import UIKit

导入AudioToolbox 导入PureLayout

让MIN_ZOOM_SCALE:CGFloat = 1 设MAX_ZOOM_SCALE:CGFloat = 5 让DEFAULT_ZOOM_SCALE:CGFloat = 2

让markerSize:CGFloat = GET_PROPORTIONAL_HEIGHT(身高:50)

类ViewController:UIViewController,UIScrollViewDelegate,AGConfiguratorDelegate,UITableViewDataSource,UITableViewDelegate {

@IBOutlet weak var scrollView: UIScrollView!
@IBOutlet weak var imageView: UIImageView!

@IBOutlet weak var btnTest: UIButton!
@IBOutlet weak var btnTest1: UIButton!
@IBOutlet weak var btnTest2: UIButton!


var markerCount:Int = 0
var arrPlacedMarkers = [UIButton]()
var isPullViewOpened:Bool = false
var table:UITableView!
var viewHeader:UIView!

var viewBtnContainer:UIView!

var timerRotateButtons:Timer!

var btnRotateLeft:UIButton!
var btnRotateRight:UIButton!
var selectedBtnMarker:UIButton?

var maxYTouchPointToScrollUp:CGFloat = -1

let configurator = AGPullViewConfigurator()

//MARK:- VIEW
override func viewDidLoad() {
    super.viewDidLoad()

    self.doSetupUI()

    DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 2) {

// var xx = SCREEN_WIDTH * 257.076682316119 / self.imageView.image!.size.width // var yy = SCREEN_HEIGHT * 599.097704011388 / self.imageView.image!.size.height

// var xx = SCREEN_WIDTH * 395.150738305702 / self.imageView.image!.size.width // var yy = SCREEN_HEIGHT * 295.700957624736 / self.imageView.image!.size.height

        var xx = SCREEN_WIDTH * 253.0 / self.imageView.image!.size.width
        var yy = SCREEN_HEIGHT * 591.549295774648 / self.imageView.image!.size.height


        print("xx : \(xx) yy : \(yy) ")
        xx = xx + (markerSize/2)
        yy = yy + (markerSize/2)
        print("xx : \(xx) yy : \(yy) ")

        self.addButtonWithAtPoint(touchedPoint: CGPoint(x: xx, y: yy))

        print("\nMAP : \(self.imageView.image!.size)")
        print("SCR : \(self.scrollView.frame)")
        print("VIE : \(self.view.frame)")
    }
}

override func viewWillLayoutSubviews() {
    super.viewWillLayoutSubviews()
}

//For correct working of layout in early versions of iOS 10
override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    self.configurator.layoutPullView()

    let pullViewHeight = self.configurator.contentView.superview?.frame.size.height

    self.maxYTouchPointToScrollUp = (SCREEN_HEIGHT - (pullViewHeight)! - scrollView.frame.origin.y)
}

//MARK:- SAVE MARKER IN DEFAULTS

func saveMarkerInDefault(){

    var counter:Int = 0

    for eachButton in arrPlacedMarkers{

        print(" \(counter) x : \(eachButton.frame.origin.x) y : \(eachButton.frame.origin.y)")
        if(counter == 0){

            let xPos = eachButton.frame.origin.x
            let yPos = eachButton.frame.origin.y

            let newXPos = (imageView.image!.size.width * xPos) / SCREEN_WIDTH
            let newYPos = (imageView.image!.size.height * yPos) / SCREEN_HEIGHT

            print("default stored   x : \(newXPos) y : \(newYPos)")

            UserDefaults.standard.set(newXPos, forKey: "xPos")
            UserDefaults.standard.set(newYPos, forKey: "yPos")
        }

        counter += 1
    }
}

func getMarkerFromDefaults() -> [AIMarker]{

    var arrSavedMarker = [AIMarker]()

    if let xPos = UserDefaults.standard.object(forKey: "xPos") as? CGFloat{
        if let yPos = UserDefaults.standard.object(forKey: "yPos") as? CGFloat{
            let marker = AIMarker(x: xPos, y: yPos)
            arrSavedMarker.append(marker)
        }
    }

    return arrSavedMarker
}


//MARK:- UI SETUP
func doSetupUI() {


    btnTest.isHidden = true
    btnTest1.isHidden = true
    btnTest2.isHidden = true


    // IMAGEVIEW
    imageView.clipsToBounds = true
    imageView.contentMode = UIViewContentMode.scaleToFill
    imageView.isUserInteractionEnabled = true
    imageView.image = UIImage(named: "RoomPlan2")

    self.scrollView.applyBorderDefault()


    // SCROLLVIEW
    scrollView.minimumZoomScale = MIN_ZOOM_SCALE
    scrollView.maximumZoomScale = MAX_ZOOM_SCALE
    scrollView.zoomScale = DEFAULT_ZOOM_SCALE

    scrollView.delegate = self
    scrollView.bounces = false
    scrollView.bouncesZoom = false


    // SINGLE TAP
    let singleTap = UITapGestureRecognizer(target: self, action: #selector(self.singleTapHandler(_ :)))
    singleTap.numberOfTapsRequired = 1
    singleTap.numberOfTouchesRequired = 1
    imageView.addGestureRecognizer(singleTap)


    // DOUBLE TAP
    let doubleTap = UITapGestureRecognizer(target: self, action: #selector(self.doubleTapHandler(_ :)))
    doubleTap.numberOfTapsRequired = 2
    doubleTap.numberOfTouchesRequired = 1
    imageView.addGestureRecognizer(doubleTap)
    singleTap.require(toFail: doubleTap)


    // LONG PRESS
    let longPressGesture = UILongPressGestureRecognizer(target: self, action: #selector(self.longPressHandlerForMapImageView(_:)))
    imageView.addGestureRecognizer(longPressGesture)


    self.doSetupRotateButtons()

    self.doSetupPullView()



}

func doSetupRotateButtons(){


    let btnSize:CGFloat = GET_PROPORTIONAL_HEIGHT(height: 30)
    let viewBtnContainerTrailingSpace:CGFloat = GET_PROPORTIONAL_HEIGHT(height: 10)
    let spaceBetweenBtns:CGFloat = GET_PROPORTIONAL_HEIGHT(height: 10)


    // VIEW BTN CONTAINER
    viewBtnContainer = UIView(forAutoLayout: ())
    self.view.addSubview(viewBtnContainer)
    viewBtnContainer.autoPinEdge(toSuperviewEdge: ALEdge.trailing, withInset: GET_PROPORTIONAL_HEIGHT(height: viewBtnContainerTrailingSpace))

    // BTN ROTATE LEFT
    btnRotateLeft = UIButton(type: .system)
    viewBtnContainer.addSubview(btnRotateLeft)
    btnRotateLeft.addTarget(self, action: #selector(self.btnRotateLeftHandler(sender:)), for: .touchUpInside)
    btnRotateLeft.isExclusiveTouch = true
    btnRotateLeft.setImage(UIImage(named: "rotate_left"), for: .normal)
    btnRotateLeft.imageView?.contentMode = UIViewContentMode.scaleAspectFit

    btnRotateLeft.autoSetDimensions(to: CGSize(width: btnSize, height: btnSize))
    btnRotateLeft.autoPinEdgesToSuperviewEdges(with: UIEdgeInsetsMake(5, 5, 5, 5), excludingEdge: ALEdge.trailing)



    // BTN ROTATE RIGHT
    btnRotateRight = UIButton(type: .system)
    viewBtnContainer.addSubview(btnRotateRight)
    btnRotateRight.addTarget(self, action: #selector(self.btnRotateRightHandler(sender:)), for: .touchUpInside)
    btnRotateRight.isExclusiveTouch = true
    btnRotateRight.setImage(UIImage(named: "rotate_right"), for: .normal)
    btnRotateRight.imageView?.contentMode = UIViewContentMode.scaleAspectFit

    btnRotateRight.autoSetDimensions(to: CGSize(width: btnSize, height: btnSize))
    btnRotateRight.autoPinEdgesToSuperviewEdges(with: UIEdgeInsetsMake(5, 5, 5, 5), excludingEdge: ALEdge.leading)
    btnRotateRight.autoPinEdge(ALEdge.leading, to: ALEdge.trailing, of: btnRotateLeft, withOffset: spaceBetweenBtns)



    btnRotateLeft.tag = 111
    btnRotateRight.tag = 222

    // ADDING LONG PRESS GESTURE
    let longPressGestureRotateLeft = UILongPressGestureRecognizer(target: self, action: #selector(self.longPressHandlerForRotateLeftButton(_:)))
    btnRotateLeft.addGestureRecognizer(longPressGestureRotateLeft)

    let longPressGestureRotateRight = UILongPressGestureRecognizer(target: self, action: #selector(self.longPressHandlerForRotateRightButton(_:)))
    btnRotateRight.addGestureRecognizer(longPressGestureRotateRight)

// viewBtnContainer.applyBorder(color:UIColor.red,width:2) // btnRotateRight.applyBorderDefault() // btnRotateLeft.applyBorderDefault()

}

//MARK:- *********
func doSetupPullView(){

    self.configurator.setupPullView(forSuperview: self.view, colorScheme: ColorSchemeTypeWhite)

//让pullViewHeight = self.configurator.contentView.superview?.frame.size.height // print(" PULL VIEW HEIGHT:((self.configurator.contentView.superview?.frame)!)") // print(" IMG:(imageView.frame)SC:(scrollView.frame)") // print(" SCREEN HEIGHT:(SCREEN_HEIGHT)XX:(SCREEN_HEIGHT - pullViewHeight! - scrollView.frame.origin.y)") //让maxBottomTapValue =(SCREEN_HEIGHT - pullViewHeight! - scrollView.frame.origin.y)

    viewBtnContainer.autoPinEdge(toSuperviewEdge: ALEdge.bottom, withInset: (height: self.configurator.contentView.superview!.frame.size.height))

    self.configurator.percentOfFilling = 90//85
    self.configurator.delegate = self
    self.configurator.needBounceEffect = true
    self.configurator.animationDuration = 0.45
    self.configurator.enableShowingWithTouch = true;
    self.configurator.enableHidingWithTouch = true;
    self.configurator.enableBlurEffect(withBlurStyle: .dark)


    self.hidePullViewFromBottom(animated: false)

    //Test UITableView
    table = UITableView(frame: CGRect(), style: .plain)
    table.dataSource = self
    table.delegate = self
    table.separatorStyle = .none;
    table.backgroundColor = UIColor.clear
    table.isUserInteractionEnabled = false



    let viewFooter = UIView(frame: CGRect(x: 0, y: 0, width: SCREEN_WIDTH, height: GET_PROPORTIONAL_HEIGHT(height: 40)))
    viewFooter.backgroundColor = UIColor.lightGray
    let btnRemoveMarker = UIButton(forAutoLayout: ())
    btnRemoveMarker.setTitle("Remove Marker", for: .normal)
    btnRemoveMarker.addTarget(self, action: #selector(self.btnRemoveMarkerTapHandler(_:)), for: .touchUpInside)
    viewFooter.addSubview(btnRemoveMarker)
    btnRemoveMarker.autoCenterInSuperview()

    table.tableFooterView = viewFooter


    //Filling whole AGPullView with test UITableView
    self.configurator.fullfillContentView(with: table)

    self.configurator.blockBtnCloseHandler = {
        if(self.isPullViewOpened){
            self.configurator.hide(animated: true)
        }else{
            self.hidePullViewFromBottom(animated: true)
        }
    }
}

//MARK:- *********

//MARK:- SHOW / HIDE PULL VIEW

func showPullViewAtBottom(animated isAnimated:Bool){

    let tempSuperView = self.configurator.contentView.superview
    if(tempSuperView!.transform.isIdentity && tempSuperView?.isHidden == false){

// print("已经打开")             返回         }         tempSuperView?.isHidden = false         self.configurator.doShowTopBottomButtons()         tempSuperView?.transform = CGAffineTransform.init(translationX:0,y:tempSuperView!.height)         UIView.animate(withDuration:0.2,动画:{             tempSuperView?.transform = CGAffineTransform.init(translationX:0,y:0)         }){(bbb)in         }

    showRotateButtons(withAnimation: isAnimated)
}

func hidePullViewFromBottom(animated isAnimated:Bool){

    let tempSuperView = self.configurator.contentView.superview

    if(tempSuperView!.transform.isIdentity && tempSuperView?.isHidden == true){

// print("已经关闭")             返回         }

    let duration:TimeInterval = isAnimated ? 0.2 : 0.0

    UIView.animate(withDuration: duration, animations: {
        tempSuperView?.transform = CGAffineTransform.init(translationX: 0, y: tempSuperView!.height)
    }) { (bbb) in
        tempSuperView?.transform = CGAffineTransform.init(translationX: 0, y: 0)
        tempSuperView?.isHidden = true
        self.configurator.doHideTopBottomButtons()
    }

    hideRotateButtons(withAnimation: isAnimated)

}

//MARK:- SHOW / HIDE ROTATE BUTTONS
func showRotateButtons(withAnimation animated:Bool){

    if self.viewBtnContainer != nil{
        UIView.animate(withDuration: animated ? 0.2 : 0.0, animations: {
            self.viewBtnContainer.alpha = 1
        }) { (bb) in
        }
    }

}

func hideRotateButtons(withAnimation animated:Bool){

    if self.viewBtnContainer != nil{
        UIView.animate(withDuration: animated ? 0.1 : 0.0, animations: {
            self.viewBtnContainer.alpha = 0
        }) { (bb) in
        }
    }

}


//MARK:- ADD BUTTON

func addButtonWithAtPoint(touchedPoint:CGPoint) {

    print("\n\n\nTOUCH POINT : \(touchedPoint)")


    // CREATING BUTTON FOR MARKER
    let xPos = touchedPoint.x - (markerSize/2)
    let yPos = touchedPoint.y - (markerSize/2)





    let btnMarker = UIButton(type: .custom)
    btnMarker.frame = CGRect(x: xPos, y: yPos, width: markerSize, height: markerSize)

    print("xpos : \(xPos) ypos : \(yPos)----\(btnMarker.frame)")
    print("ce----\(btnMarker.center)")

    btnMarker.setTitleColor(UIColor.white, for: .normal)
    btnMarker.setTitle("M\(markerCount + 1)", for: .normal)
    btnMarker.tag = markerCount
    btnMarker.titleLabel?.numberOfLines = 1
    btnMarker.titleLabel?.adjustsFontSizeToFitWidth = true
    btnMarker.titleLabel?.lineBreakMode = .byClipping
    btnMarker.addTarget(self, action: #selector(self.btnMarkerTapHandler(_:)), for: .touchUpInside)
    self.imageView.addSubview(btnMarker)

    let imageArrow = UIImage(named: "arrow")
    btnMarker.setImage(imageArrow, for: .normal)


    // ADDING PAN GESTURE
    let panGesture = UIPanGestureRecognizer(target: self, action: #selector(self.panGestureHandler(_:)))
    btnMarker.addGestureRecognizer(panGesture)


    // ADDING ROTATION GESTURE

// let rotateGesture = UIRotationGestureRecognizer(target:self,action:#selector(self.rotationGestureHandler(_ :))) // btnMarker.addGestureRecognizer(rotateGesture)

    // ADDING MARKER IN MAIN ARRAY
    self.arrPlacedMarkers.append(btnMarker)
    markerCount += 1


    // SCALING MARKER AS PER MAP'S CURRENT ZOOM SCALE
    let invertedTransform = CGAffineTransform.inverted(imageView.transform)
    for eachSubview in imageView.subviews{
        let angle = atan2f(Float(eachSubview.transform.b), Float(eachSubview.transform.a));
        eachSubview.transform = invertedTransform().rotated(by: CGFloat(angle))
    }


    playVibrate()

    presentPullViewForMarker(btnMarker: btnMarker)

// btnMarker.applyBorderDefault()     }

func playVibrate(){

// AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);     }

func presentPullViewForMarker(btnMarker:UIButton){

    self.selectedBtnMarker = btnMarker

    self.showPullViewAtBottom(animated: true)
    (viewHeader.subviews.first as! UIButton).setTitle("Add Photos for : \((btnMarker.titleLabel?.text)!)", for: .normal)
}


//MARK:- BUTTON EVENTS

func btnMarkerTapHandler(_ sender:UIButton){
    self.presentPullViewForMarker(btnMarker: sender)
}

func btnAddPhotosTapHandler(_ sender:UIButton){

    saveMarkerInDefault()

//让secondVC = self.storyboard?.instantiateViewController(withIdentifier:" SecondViewController")as! SecondViewController // self.navigationController?.pushViewController(secondVC,animated:true) // self.present(secondVC,animated:true){ //
//}     }

func btnRemoveMarkerTapHandler(_ sender:UIButton){



    if let selectedBtnMarker = self.selectedBtnMarker {

        showAlertWithTitle(title: "Remove Marker \((selectedBtnMarker.titleLabel?.text)!)", message: "Are you sure you want to remove this marker ?", buttons: ["Cancel","Yes"], showsCancelOption: false, completion: { (selectedIndex) in
            if(selectedIndex == 1){
                if let validIndex = self.arrPlacedMarkers.index(of: selectedBtnMarker){
                    self.arrPlacedMarkers.remove(at: validIndex)
                    self.selectedBtnMarker?.removeFromSuperview()


                    DispatchQueue.main.async {
                        self.configurator.hide(animated: true)

                        DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.4) {
                            self.hidePullViewFromBottom(animated: true)
                        }
                    }


                }
            }
        })
    }
}

//MARK:-
func btnRotateLeftHandler(sender:UIButton){
    if let selectedBtnMarker = self.selectedBtnMarker {
        selectedBtnMarker.rotate(angle: -5)
    }
}
func btnRotateRightHandler(sender:UIButton){
    if let selectedBtnMarker = self.selectedBtnMarker {
        selectedBtnMarker.rotate(angle: 5)
    }
}




//MARK:-

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return 10
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = UITableViewCell()
    cell.backgroundColor = UIColor.clear
    cell.textLabel?.textColor = UIColor.gray
    cell.textLabel?.text = "Photo \(indexPath.row + 1)"
    return cell;
}

func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {

    viewHeader = UIView(frame: CGRect(x: 0, y: 0, width: SCREEN_WIDTH, height: 100))
    viewHeader.backgroundColor = UIColor.lightGray
    let btnAddPhotos = UIButton(forAutoLayout: ())
    btnAddPhotos.setTitle("Add Photos", for: .normal)
    btnAddPhotos.addTarget(self, action: #selector(self.btnAddPhotosTapHandler(_:)), for: .touchUpInside)
    viewHeader.addSubview(btnAddPhotos)
    btnAddPhotos.autoCenterInSuperview()

    return viewHeader
}

func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    return GET_PROPORTIONAL_HEIGHT(height: 40)
}


//MARK:-
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    self.configurator.handleTouchesBegan(touches)
}

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
    self.configurator.handleTouchesMoved(touches)
}

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    self.configurator.handleTouchesEnded(touches)
}


//MARK:- AGPullView DELEGATES
func didDrag(_ pullView: AGPullView!, withOpeningPercent openingPercent: Float) {

// print(&#34;拖拽:(openingPercent)&#34;)         openingPercent&gt; 0.0? hideRotateButtons(withAnimation:true):showRotateButtons(withAnimation:true)     }

func didShow(_ pullView: AGPullView!) {
    print("shown");
    isPullViewOpened = true
    table.isUserInteractionEnabled = true

    hideRotateButtons(withAnimation: true)
}

func didHide(_ pullView: AGPullView!) {
    print("hidden")
    isPullViewOpened = false
    table.isUserInteractionEnabled = false

    showRotateButtons(withAnimation: true)
}

func didTouch(toShow pullView: AGPullView!) {
    print("touched to show")
}

func didTouch(toHide pullView: AGPullView!) {
    print("touched to hide")
}

//MARK:- PAN GESTURE HANDLER

func panGestureHandler(_ recognizer:UIPanGestureRecognizer){

    if(recognizer.state == .changed || recognizer.state == .ended) {
        let draggedButton = recognizer.view

        var newFrame = draggedButton?.frame
        if(newFrame!.origin.x < 0.0){
            newFrame!.origin.x = 0.0
        }
        if(newFrame!.origin.y < 0.0){
            newFrame!.origin.y = 0.0
        }

        let oldXPlusWidth = newFrame!.origin.x + newFrame!.size.width
        let trailingMarginToKeep = self.imageView.bounds.size.width - newFrame!.size.width
        if(oldXPlusWidth > self.imageView.bounds.size.width){
            newFrame!.origin.x = trailingMarginToKeep
        }

        let oldYPlusHeight = newFrame!.origin.y + newFrame!.size.height
        let bottomMarginToKeep = self.imageView.bounds.size.height - newFrame!.size.height
        if(oldYPlusHeight > self.imageView.bounds.size.height){
            newFrame!.origin.y = bottomMarginToKeep
        }

        let translationPoint = recognizer.translation(in: self.imageView)

        newFrame?.origin.x += translationPoint.x
        newFrame?.origin.y += translationPoint.y

        let centerX:CGFloat = newFrame!.origin.x + (newFrame!.size.width/2)
        let centerY:CGFloat = newFrame!.origin.y + (newFrame!.size.height/2)

        draggedButton?.center = CGPoint(x: centerX, y: centerY)

        recognizer.setTranslation(CGPoint.zero, in: self.imageView)
    }
}


//MARK:- ROTATION GESTURE HANDLER
func rotationGestureHandler(_ recognizer:UIRotationGestureRecognizer){
    recognizer.view!.transform = recognizer.view!.transform.rotated(by: recognizer.rotation)
    recognizer.rotation = 0
}

//MARK:- LONG PRESS HANDLER
func longPressHandlerForMapImageView(_ sender:UILongPressGestureRecognizer){

    if sender.state == .began{

// self.addButtonWithAtPoint(touchingPoint:sender.location(in:sender.view))             self.addButtonWithAtPoint(touchingPoint:sender.location(in:imageView))         }     }

func longPressHandlerForRotateLeftButton(_ sender:UILongPressGestureRecognizer){

    switch sender.state {
    case .began:
        self.timerRotateButtons = Timer.scheduledTimer(timeInterval: 0.01, target: self, selector: #selector(self.timerHandlerForRotateButton(sender:)), userInfo: sender.view, repeats: true)
    case .ended:
        self.timerRotateButtons.invalidate()
        self.timerRotateButtons = nil
    default:
        break
    }
}

func longPressHandlerForRotateRightButton(_ sender:UILongPressGestureRecognizer){

    switch sender.state {
    case .began:
        self.timerRotateButtons = Timer.scheduledTimer(timeInterval: 0.01, target: self, selector: #selector(self.timerHandlerForRotateButton(sender:)), userInfo: sender.view, repeats: true)
    case .ended:
        self.timerRotateButtons.invalidate()
        self.timerRotateButtons = nil
    default:
        break
    }
}

//MARK:- TIMER 
func timerHandlerForRotateButton(sender:Timer){

    if let btn:UIButton = sender.userInfo as? UIButton{
        var rotateAngle:CGFloat = 0
        if(btn == btnRotateLeft){
            rotateAngle = -1
        }else if(btn == btnRotateRight){
            rotateAngle = 1
        }
        if let selectedBtnMarker = self.selectedBtnMarker {
            selectedBtnMarker.rotate(angle: rotateAngle)
        }
    }
}



//MARK:- TAP GESTURE HANDLER
func singleTapHandler(_ sender:UITapGestureRecognizer){

// print(&#34; SINGLE TAP&#34;)

    if(self.isPullViewOpened){

// print(&#34; SINGLE TAP:不要关闭..打开&#34;)         }其他{             self.hidePullViewFromBottom(动画:true)         }

}

func doubleTapHandler(_ sender:UITapGestureRecognizer){

// print(&#34; DOUBLE TAP(scrollView.minimumZoomScale)(scrollView.maximumZoomScale)(scrollView.zoomScale)&#34;)

    // ZOOM RESET
    if(scrollView.zoomScale > scrollView.minimumZoomScale){
        scrollView.setZoomScale(scrollView.minimumZoomScale, animated: true)
    }else{
        // ZOOM IN
        let zoomRect = self.zoomRectForScale(scale: DEFAULT_ZOOM_SCALE, withCenter: sender.location(in: sender.view))
        scrollView.zoom(to: zoomRect, animated: true)
    }
}


func zoomRectForScale(scale:CGFloat, withCenter center:CGPoint) -> CGRect {

    var zooomRect:CGRect = CGRect()
    zooomRect.size.height = imageView.frame.size.height / scale
    zooomRect.size.width = imageView.frame.size.width / scale

    let tempCenter = imageView.convert(center, from: self.imageView)
    zooomRect.origin.x = tempCenter.x - (zooomRect.size.width / 2.0)
    zooomRect.origin.y = tempCenter.y - (zooomRect.size.height / 2.0)
    return zooomRect
}


//MARK:- BUTTION EVENTS
@IBAction func btnTestPressed(_ sender: Any) {
    //      print("BTN 10 % TAP")


    showAlertWithTitle(title: "title", message: "message", buttons: ["b1","b2"], showsCancelOption: false) { (selecgtedIndex) in
        print("selected \(selecgtedIndex)")
    }
}

@IBAction func btnTest1Pressed(_ sender: Any) {
    //      print("\n\nBTN 90 % TAP")
}

@IBAction func btnTest2Pressed(_ sender: Any) {
    //      print("BTN RESET TAP")
    scrollView.setZoomScale(1, animated: true)
}



//MARK:- SCROLLVIEW DELEGATE

func viewForZooming(in scrollView: UIScrollView) -> UIView? {
    return imageView
}


func scrollViewDidScroll(_ scrollView: UIScrollView) {

// print(&#34; \ n \ n(#function)(scrollView.zoomScale)__(scrollView.contentSize)__(scrollView.contentOffset)\ n&#34;)

    let invertedTransform = CGAffineTransform.inverted(imageView.transform)
    for eachSubview in imageView.subviews{
        let angle = atan2f(Float(eachSubview.transform.b), Float(eachSubview.transform.a));
        eachSubview.transform = invertedTransform().rotated(by: CGFloat(angle))
    }

    if(self.isPullViewOpened){

//打印(&#34;滚动:不要关闭..打开&#34;)         }其他{             self.hidePullViewFromBottom(动画:true)         }     }

//MARK:-
func scrollViewShouldScrollToTop(_ scrollView: UIScrollView) -> Bool {
    print("\n\(#function)\n")
    return false
}

// func scrollViewDidScrollToTop(_ scrollView:UIScrollView){ // print(&#34; \ n(#function)\ n&#34;) //} // //
// // MARK: - // func scrollViewDidEndScrollingAnimation(_ scrollView:UIScrollView){ // print(&#34; \ n(#function)\ n&#34;) //}     //标记:- // func scrollViewWillBeginZooming(_ scrollView:UIScrollView,with view:UIView?){ // print(&#34; \ n(#function)\ n&#34;) //} // func scrollViewDidZoom(_ scrollView:UIScrollView){ // print(&#34; \ n(#function)(scrollView.zoomScale)__(scrollView.contentSize)__(scrollView.contentOffset)&#34;) //}     func scrollViewDidEndZooming(_ scrollView:UIScrollView,with view:UIView?,atScale scale:CGFloat){ // print(&#34; \ n(#function)\ n&#34;)

    let invertedTransform = CGAffineTransform.inverted(imageView.transform)
    for eachSubview in imageView.subviews{
        let angle = atan2f(Float(eachSubview.transform.b), Float(eachSubview.transform.a));
        eachSubview.transform = invertedTransform().rotated(by: CGFloat(angle))
    }

// for i in 0 ..

// for i in 0 ..

}


//MARK:-

// func scrollViewWillBeginDragging(_ scrollView:UIScrollView){ // print(&#34; \ n(#function)\ n&#34;) //} // func scrollViewWillEndDragging(_ scrollView:UIScrollView,withVelocity velocity:CGPoint,targetContentOffset:UnsafeMutablePointer){ // print(&#34; \ n(#function)\ n&#34;) //} // func scrollViewDidEndDragging(_ scrollView:UIScrollView,willDecelerate decelerate:Bool){ // print(&#34; \ n(#function)\ n&#34;) //} // func scrollViewWillBeginDecelerating(_ scrollView:UIScrollView){ // print(&#34; \ n(#function)\ n&#34;) //} // func scrollViewDidEndDecelerating(_ scrollView:UIScrollView){ // print(&#34; \ n(#function)\ n&#34;) //}

}