ios – Learn how to apply non-uniform scaling to a rotated UIView (rectangle) over Mapbox with out distortion?

0
1
ios – Learn how to apply non-uniform scaling to a rotated UIView (rectangle) over Mapbox with out distortion?


I’m making an attempt to permit non-uniform scaling (horizontal or vertical) of a UIView rectangle that’s positioned over a Mapbox mapView and has already been rotated. Uniform scaling works properly, however once I try to use non-uniform scaling (scaling solely X or Y) utilizing transforms after rotation, the rectangle turns into distorted like a parallelogram.

To keep away from distortion, I as an alternative redraw the rectangle utilizing coordinate math on the finish of the gesture, however this makes the scaling really feel abrupt and never clean. I need to obtain clean, stay non-uniform scaling after rotation with out visible distortion. I’ve tried utilizing rework.scaledBy(x:y:), however it doesn’t preserve the rectangle’s orthogonality post-rotation.

How can I obtain clean, interactive, non-uniform scaling on a rotated view with out it deforming?

Code Snippets

Right here’s the pinchProcess gesture handler:

@objc func handlePinchGesture(_ recognizer: UIPinchGestureRecognizer) {
    guard isScalingEnabled, let targetView = self.scalingView else { return }

    if recognizer.state == .started {
        previousScale = 1.0
        initialPinchLocation = recognizer.location(in: targetView)
    }

    if recognizer.state == .ended || recognizer.state == .cancelled {
        if hasRotationApplied {
            gestureDelegate?.applyScalingAndRedraw(for: targetView, axis: lastScaleAxis, scaleFactor: finalScaleValue)
        } else {
            gestureDelegate?.finalizeSnap(for: targetView, usingPoints: originalPoints)
        }
        return
    }

    if recognizer.numberOfTouches < 2 {
        initialPinchLocation = recognizer.location(in: targetView)
        return
    }

    let touchPointA = recognizer.location(ofTouch: 0, in: targetView)
    let touchPointB = recognizer.location(ofTouch: 1, in: targetView)
    lastScaleAxis = detectScaleAxis(from: touchPointA, to: touchPointB, basedOn: originalPoints)

    let scaleFactor = recognizer.scale / previousScale
    let xDiff = originalPoints[1].x - originalPoints[0].x
    let yDiff = originalPoints[1].y - originalPoints[0].y

    if xDiff == 0 || yDiff == 0 {
        hasRotationApplied = false

        change detectGestureDirection(touchPointA, point2: touchPointB) {
        case "V":
            targetView.rework = targetView.rework.scaledBy(x: 1, y: scaleFactor)
        case "H":
            targetView.rework = targetView.rework.scaledBy(x: scaleFactor, y: 1)
        default:
            targetView.rework = targetView.rework.scaledBy(x: scaleFactor, y: scaleFactor)
        }

        previousScale = recognizer.scale
    } else {
        finalScaleValue = recognizer.scale
        hasRotationApplied = true
        targetView.rework = targetView.rework.scaledBy(x: scaleFactor, y: scaleFactor)
    }

    previousScale = recognizer.scale
}
func applyScalingAndRedraw(for view: UIView, axis: String, scaleFactor: CGFloat) {
    // Computes new factors primarily based on the scaling axis and applies redraw logic
    // Geometry strategies replace coordinates and redraw the rectangle accurately
}

LEAVE A REPLY

Please enter your comment!
Please enter your name here