guoyingtao / Mantis

An iOS Image cropping library, which mimics the Photo App written in Swift.
MIT License
921 stars 183 forks source link

Rotate Public Function in CropViewController #303

Closed bobby-kim-km closed 1 year ago

bobby-kim-km commented 1 year ago

Can you make a public function that can adjust the rotations on the CropView controller?

I want to apply the rotation using the rotary-view I made

guoyingtao commented 1 year ago

@bobby-kim-km Do you mean you want to replace the rotary-view (pointed by the red arrow in the picture below) with your own view?

image
bobby-kim-km commented 1 year ago

Yes.

bobby-kim-km commented 1 year ago

@guoyingtao

I want using my own rotate controller view that outside Mantis crop view

image

bobby-kim-km commented 1 year ago

I checked the #308 and I think you understood it differently, so I'm sorry to say it again

guoyingtao commented 1 year ago

Hi @bobby-kim-km Please check #308, I added a new protocol RotationControlViewProtocol and a new parameter rotationControlView in Mantis.cropViewController()

For your case, your own rotation controller view need to conform to RotationControlViewProtocol and set isAttachedToCropView to false

bobby-kim-km commented 1 year ago

Hi @guoyingtao

I think that's right.

When will this be distributed as an official version and available by swift package manager?

guoyingtao commented 1 year ago

@bobby-kim-km Can you have a test with this #308 to verify it works for you? After that I can release a new version.

bobby-kim-km commented 1 year ago

I need to recreate the view to conform with protocol cuz my rotate controller is swiftUI.. I'll give it a try. But if you can make a public function with angle argument in CropViewController, I think it'll be okay. I can using this function

guoyingtao commented 1 year ago

@bobby-kim-km There is some UI status changes during the rotating and after rotating, so only providing an angle argument is not enough.

bobby-kim-km commented 1 year ago
cropViewController(image: UIImage,
                               config: Mantis.Config = Mantis.Config(),
                               cropToolbar: CropToolbarProtocol = CropToolbar(frame: .zero),
                               rotationControlView: RotationControlViewProtocol? = nil) -> Mantis.CropViewController

I created a view using RotationControlViewProtocol And I made a CropViewController with the above function, but it doesn't work

guoyingtao commented 1 year ago

@bobby-kim-km Can you also post your Mantis.Config settings? Also can you provide more details about it? Like when you rotate your own rotation control view, the image does not rotate (Something like that)

Thank you!

guoyingtao commented 1 year ago

I also updated #308 to fix some issues.

bobby-kim-km commented 1 year ago

This is rotate controller view code

import UIKit
import Mantis

class WheelPicker: UIView, RotationControlViewProtocol {

    var isAttachedToCropView: Bool = false
    var didUpdateRotationValue: (Mantis.Angle) -> Void = { _ in }
    var didFinishRotation: () -> Void = {}
    func setupUI(withAllowableFrame allowableFrame: CGRect) {}

    private var startOffsetX: CGFloat = 0.0
    private var selectedAngle: CGFloat = 0.0
    let numberOfLines = 91

    override init(frame: CGRect) {
        super.init(frame: frame)
        let panGesture = UIPanGestureRecognizer(target: self, action: #selector(handlePanGesture(_:)))
        addGestureRecognizer(panGesture)
    }

    required init?(coder: NSCoder) {
        super.init(coder: coder)
        let panGesture = UIPanGestureRecognizer(target: self, action: #selector(handlePanGesture(_:)))
        addGestureRecognizer(panGesture)
    }

    override func draw(_ rect: CGRect) {
        super.draw(rect)

        guard let context = UIGraphicsGetCurrentContext() else { return }

        context.setFillColor(UIColor.editingTabBg.cgColor)
        context.fill(rect)

        context.setStrokeColor(UIColor.gray.cgColor)
        context.setLineWidth(1.5)
        context.setLineCap(.square)
        let lineHeight: CGFloat = rect.height * (5/8)
        let lineSpacing = rect.width / CGFloat(numberOfLines - 1)
        for i in 0..<numberOfLines {
            let x = lineSpacing * CGFloat(i) - startOffsetX
            let startPoint = CGPoint(x: x, y: rect.height - lineHeight)
            let endPoint = CGPoint(x: x, y: rect.height)

            context.move(to: startPoint)
            context.addLine(to: endPoint)
        }
        context.strokePath()

        context.setStrokeColor(UIColor.white.cgColor)
        context.setLineWidth(2.0)
        context.setLineCap(.square)
        let x = rect.width / 2
        let startPoint = CGPoint(x: x, y: 0)
        let endPoint = CGPoint(x: x, y: rect.height)
        context.move(to: startPoint)
        context.addLine(to: endPoint)
        context.strokePath()
    }

    @objc private func handlePanGesture(_ gesture: UIPanGestureRecognizer) {
        switch gesture.state {
        case .began:
            startOffsetX = 0.0
        case .changed:
            let translation = gesture.translation(in: self)
            startOffsetX -= translation.x
            gesture.setTranslation(CGPoint.zero, in: self)
            updateSelectedAngle()
        default:
            break
        }
    }

    private func updateSelectedAngle() {
        let lineSpacing = bounds.width / CGFloat(numberOfLines - 1)
        let adjustedOffsetX = startOffsetX.truncatingRemainder(dividingBy: lineSpacing)
        let adjustedX = bounds.width / 2 + adjustedOffsetX
        let angle = ((adjustedX / bounds.width) * 90 - 45) * (-1)
        selectedAngle += angle
        if selectedAngle > 45.0 {
            selectedAngle = 45.0
        } else if selectedAngle < -45.0 {
            selectedAngle = -45.0
        }
        updateRotationValue(by: Mantis.Angle(degrees: selectedAngle))
    }

    @discardableResult func updateRotationValue(by angle: Mantis.Angle) -> Bool {
        let isWithinLimit = selectedAngle != 45.0 || selectedAngle != -45.0
        if isWithinLimit {
            didUpdateRotationValue(angle)
        }
        return isWithinLimit
    }

    func reset() {}

}

This is config setting code

func makeImageCropper(context: Context) -> UIViewController {
        var config = Mantis.Config()
        config.showAttachedCropToolbar = false
        config.cropViewConfig.cropShapeType = .rect
        config.presetFixedRatioType = .canUseMultiplePresetFixedRatio()
        config.cropViewConfig.showAttachedRotationControlView = true
        config.cropViewConfig.rotationControlViewHeight = 0
        let cropViewController = Mantis.cropViewController(
            image: image!,
            config: config,
            rotationControlView: viewModel.rotateWheelPicker!
        )
        cropViewController.delegate = context.coordinator
        return cropViewController
    }
bobby-kim-km commented 1 year ago

When I touched crop-view the rotate controller view is gone

I think it's because of the code below

       case .touchCropboxHandle(let tappedEdge):
            cropAuxiliaryIndicatorView.handleIndicatorHandleTouched(with: tappedEdge)
            rotationDial?.isHidden = true
            rotationControlView?.isHidden = true
bobby-kim-km commented 1 year ago

@guoyingtao

I used 55c7f10c14498ce53430ca0d7f77244558da6184 this commit code And Run!!

Thanks u!! 😀

guoyingtao commented 1 year ago

@bobby-kim-km I released Mantis 2.10.0, please have a try and let me know if it works for you.

bobby-kim-km commented 1 year ago

Okay. I will try

guoyingtao commented 1 year ago

Hi @bobby-kim-km Can you confirm if Mantis 2.10.0 works for your case? If so, can you close the issue? Thanks!