簡體   English   中英

如何僅在特定角度范圍內為UIView的旋轉設置動畫?

[英]How can I animate a UIView's rotation only within a certain degree range?

在我的應用程序中,我模擬了一個模擬讀數撥盤,就像您在汽車儀表板上或控制面板上可能會看到的那樣。 運行以下代碼片段,以了解我的意思:

 svg { height: 100vh; } #dial { fill: white; stroke: #CCCCCC; stroke-dasharray: 405; transform: rotate(135deg); transform-origin: center; } #pointer { fill: #FF0000; animation: 2s infinite alternate dialrotate; transform-origin: bottom center; animation-timing-function: ease-in-out; } @keyframes dialrotate { from { transform: rotate(-135deg); } to { transform: rotate(135deg); } } 
 <?xml version="1.0" encoding="utf-8"?> <svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200"> <circle id="dial" cx="99.5" cy="100.5" r="86"/> <polygon id="pointer" points="100.1,25.5 98.2,100 102,100"/> </svg> 

(我沒有在我的應用程序中使用SVG,我只是使用SVG將示例放在一起,因為我主要是Web開發人員)

這是我現在如何對表盤運動進行動畫處理的方式:

UIView.animate(
    withDuration: 0.1,
    delay: 0.0,
    options: .curveEaseOut,
    animations: {
        self.dialPointer.transform = CGAffineTransform.init(rotationAngle: radians);
    },
    completion: nil
)

我想為兩個極端(270度)之間的指針方向設置動畫。 但是我不希望指針在表盤邊界之外的較短的90度路徑上旋轉; 即這是錯誤的:

 svg { height: 100vh; } #dial { fill: white; stroke: #CCCCCC; stroke-dasharray: 405; transform: rotate(135deg); transform-origin: center; } #pointer { fill: #FF0000; animation: 2s infinite alternate dialrotate; transform-origin: bottom center; animation-timing-function: ease-in-out; } @keyframes dialrotate { from { transform: rotate(225deg); } to { transform: rotate(135deg); } } 
 <?xml version="1.0" encoding="utf-8"?> <svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200"> <circle id="dial" cx="99.5" cy="100.5" r="86"/> <polygon id="pointer" points="100.1,25.5 98.2,100 102,100"/> </svg> 

如何強制UIView的旋轉沿長距離旋轉,而不是沿最短方向旋轉?

您已經發現,默認情況下,在插入角度值時,UIView動畫會采用最短路徑。 您有兩種選擇:

  1. 您可以將動畫分解為幾個較短的步驟,或對其進行關鍵幀設置。
  2. 您可以改用CABasicAnimation並使用累積動畫來動畫化圖層的變換

操場上的例子:

import PlaygroundSupport
import UIKit

let rect = CGRect(x: 0, y: 0, width: 300, height: 300)
let view = UIView(frame: rect)
let bar = UIView(frame: rect.insetBy(dx: 40, dy: 140))
bar.backgroundColor = .red
view.addSubview(bar)

let animation = CABasicAnimation(keyPath: "transform.rotation.z")
animation.toValue = 1.25 * CGFloat.pi
animation.isCumulative = true
animation.duration = 5
bar.layer.add(animation, forKey: "spin")
bar.layer.transform = CATransform3DMakeRotation(1.25 * CGFloat.pi, 0, 0, 1)
PlaygroundPage.current.liveView = view

你可以這樣

UIView.animate(
    withDuration: 0.1,
    delay: 0.0,
    options: .curveEaseOut,
    animations: {
        if radians > CGFloat.pi {
            self.dialPointer.transform = CGAffineTransform.init(rotationAngle: CGFloat.pi);
        }
        self.dialPointer.transform = CGAffineTransform.init(rotationAngle: radians);
    },
    completion: nil
)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM