How to use Rotation and Translation for an Image s

2019-08-23 10:17发布

问题:

I using CGAffineTransformMakeRotation for the Rotation of an Image and CGAffineTransformMakeTranslation for the Translation of an Image. This is my code:

-(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];
}

My Problem is the Image is only Translating it is not Rotating. If I use the Rotate and Translate separately means it works Pretty well. How can I modify my code to work both well?

回答1:

The problem is that you are making an individual rotation and then translation and setting it. So the rotation is overridden by the translation. You must do something like this,

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

imageView.transform= transform;

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

But this will not animate the rotation. It will just jump from the current transform to the end transform.

And you don't seem to have an end point defined.



回答2:

Here is my code, I didn't have time to filter out the code, but it includes all the feature like rotate, translate and scale the image in scrollview.

import UIKit

import AudioToolbox import PureLayout

let MIN_ZOOM_SCALE:CGFloat = 1 let MAX_ZOOM_SCALE:CGFloat = 5 let DEFAULT_ZOOM_SCALE:CGFloat = 2

let markerSize:CGFloat = GET_PROPORTIONAL_HEIGHT(height: 50)

class 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)

// let 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)") // let 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("already opened") return } tempSuperView?.isHidden = false self.configurator.doShowTopBottomButtons() tempSuperView?.transform = CGAffineTransform.init(translationX: 0, y: tempSuperView!.height) UIView.animate(withDuration: 0.2, animations: { 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("already closed") return }

    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()

// let 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("did drag : (openingPercent)") openingPercent > 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(touchedPoint: sender.location(in: sender.view)) self.addButtonWithAtPoint(touchedPoint: 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("SINGLE TAP")

    if(self.isPullViewOpened){

// print("SINGLE TAP : don't close.. opened") }else{ self.hidePullViewFromBottom(animated: true) }

}

func doubleTapHandler(_ sender:UITapGestureRecognizer){

// print("DOUBLE TAP (scrollView.minimumZoomScale) (scrollView.maximumZoomScale) (scrollView.zoomScale)")

    // 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("\n\n(#function) (scrollView.zoomScale) __ (scrollView.contentSize) __ (scrollView.contentOffset) \n")

    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){

// print("scroll : don't close.. opened") }else{ self.hidePullViewFromBottom(animated: true) } }

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

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

    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("\n(#function)\n") // } // func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer) { // print("\n(#function)\n") // } // func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) { // print("\n(#function)\n") // } // func scrollViewWillBeginDecelerating(_ scrollView: UIScrollView) { // print("\n(#function)\n") // } // func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { // print("\n(#function)\n") // }

}