因此,我正在努力學習如何在 UIKit 中畫圓,而且我已經基本掌握了畫圓的方法,但我還想實作一件事。在下面的視頻中,當圓的尾巴到達終點時,我希望尾巴不要完全到達頭部,這意味著我希望圓的大小不要完全縮小。
我在下面的視頻中實作了這一點,但是仍然存在著尾巴消失而影片在頭部重新開始的情況。所以我希望尾巴的消失不會消失。
視頻演示: https://github.com/DJSimonSays93/CircleAnimation/blob/main/README.md
這里是代碼:
class SpinningView。UIView {
let circleLayer = CAShapeLayer()
let rotationAnimation: CAAnimation = {
let animation = CABasicAnimation(keyPath: "transform.rotation.z")
animation.fromValue = 0
animation.toValue = Double.pi * 2
animation.duration = 3 //增加這個持續時間可以減緩圓圈影片的效果。
animation.repeatCount = MAXFLOAT。
return animation
}()
override func awakeFromNib() {
super.awakeFromNib()
setup()
}
func setup() {
circleLayer.lineWidth = 10.0
circleLayer.fillColor = nil
//circleLayer.strokeColor = UIColor(red: 0.8078, green: 0.2549, blue: 0.2392, alpha: 1.0).cgColor
circleLayer.strokeColor = UIColor.systemBlue.cgColor
circleLayer.lineCap = .round
layer.addSublayer(circleLayer)
updateAnimation()
}
override func layoutSubviews() {
super.layoutSubviews()
let center = CGPoint(x: bounds.midX, y: bounds.midY)
let radius = min(bounds.width, bounds. height) / 2 - circleLayer.lineWidth / 2
let startAngle: CGFloat = -90.0
let endAngle: CGFloat = startAngle 360.0
circleLayer.position = center
circleLayer.path = createCircle(startAngle: startAngle, endAngle: endAngle, radius: radius).cgPath
}
private func updateAnimation() {
//strokeStartAnimation beginTime duration值需要與strokeAnimationGroup.duration值相加。
let strokeStartAnimation: CABasicAnimation = CABasicAnimation(keyPath: "strokeStart" /span>)
strokeStartAnimation.beginTime = 0.5
strokeStartAnimation.fromValue = 0
strokeStartAnimation.toValue = 0.93 //change this to 0.93 for cool effect
strokeStartAnimation.duration = 3.0
strokeStartAnimation.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
let strokeEndAnimation: CABasicAnimation = CABasicAnimation(keyPath: "strokeEnd" /span>)
strokeEndAnimation.fromValue = 0
strokeEndAnimation.toValue = 1.0
strokeEndAnimation.duration = 2.0
strokeEndAnimation.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
let colorAnimation = CABasicAnimation(keyPath: "strokeColor"/span>)
colorAnimation.fromValue = UIColor.systemBlue.cgColor
colorAnimation.toValue = UIColor.systemRed.cgColor
let strokeAnimationGroup: CAAnimationGroup = CAAnimationGroup()
strokeAnimationGroup.duration = 3.5 ()
strokeAnimationGroup.repeatCount = Float.infinity
strokeAnimationGroup.fillMode = .forwards
strokeAnimationGroup.isRemovedOnCompletion = false
strokeAnimationGroup.animations = [ strokeStartAnimation, strokeEndAnimation, colorAnimation]
circleLayer.add(strokeAnimationGroup, forKey: nil)
circleLayer.add(rotationAnimation, forKey: "rotation"/span>)
}
private func createCircle(startAngle: CGFloat, endAngle: CGFloat, radius: CGFloat) -> UIBezierPath {
return UIBezierPath(arcCenter: CGPoint.zero,
radius: 半徑。
startAngle: startAngle.toRadians(),
endAngle: endAngle.toRadians()。
順時針。true)
}
uj5u.com熱心網友回復:
像這樣嗎?
這里沒有什么特別之處。它幾乎與你的初始代碼完全相同,只是對旋轉角度做了一點調整。
方法
你的初始影片在開始時看起來很好!就像你說的,"啪 "的一聲,就像你說的。就像你說的,影片從strokeEnd的0%處重新開始的 "snap "是它的特點。
正如 @MadProgrammer 所指出的,理論上你可以通過不在 0% 處開始或結束筆畫來擺脫 "啪"。這可以確保總是有一部分的筆觸是可見的。
這是一個很好的開始,但不幸的是strokeStart和strokeEnd不允許超出[0.0, 1.0]范圍的值。因此,你無法準確地創建一個影片(沒有許多關鍵幀),以便在每個影片回圈中筆觸位置重疊(因為你需要使用超出范圍的值來覆寫整個圓)。
因此,我所做的是無論如何都要使用上述方法,最后得到了如下所示的影片。影片開始和結束時的筆畫弧長是相等的--非常重要。
然后,使用你現有的旋轉影片,我非常輕微地在筆畫影片中旋轉整個圖畫,使開始和結束的弧線看起來落在彼此的上面。旋轉角度的計算方法如下。
0.07是通過用strokeStartAnimation.toValue的初始值減去1.0而選出的。
- 那么標度弧線的長度將是,0.07 (S). 。
- 圓的半徑為
bounds.width / 2(r). - 為了獲得弧長(L),我們需要用標量長度乘以周長(P)。
- 弧長(L)和旋轉角度(theta)之間的關系是,
2 * Theta * r = L
但L也等于S * P,所以代入一些,我們得到。
theta = 2S (單位:弧度)
解決方案
因此,隨著這一點的解決。解決方案是對你的代碼做如下修改。startOffset。
startOffset來設定strokeStart影片的toValue。
startOffset來設定strokeEnd影片的fromValuerotationAnimation的to值為2 * theta。
最終的旋轉影片看起來像這樣:
var rotationAnimation: CAAnimation{
get{
let radius = Double(bounds.width) / 2.0<
let 周長 = 2 * Double.pi * radius
letTheta =周長 *。 運算子">* startOffset / (2 * radius)
let animation = CABasicAnimation(keyPath: "transform.rotation.z")
animation.fromValue = 0
animation.toValue = Theta * 2 Double. pi * 2。
animation.duration = 3.5.
animation.repeatCount = MaxFLOAT
return animation。
}
}
而筆畫:
let strokeStartAnimation: CABasicAnimation = CABasicAnimation(keyPath: "strokeStart" /span>)
strokeStartAnimation.beginTime = 0.5
strokeStartAnimation.fromValue = 0
strokeStartAnimation.toValue = 1.0 - startOffset
strokeStartAnimation.duration = 3.0
strokeStartAnimation.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
let strokeEndAnimation: CABasicAnimation = CABasicAnimation(keyPath: "strokeEnd" /span>)
strokeEndAnimation.fromValue = startOffset
strokeEndAnimation.toValue =1.0
strokeEndAnimation.duration = 2.0
strokeEndAnimation.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
我對你現有的代碼做了一個pull request。試試吧,讓我知道情況如何。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/330565.html
標籤:
上一篇:谷歌應用程式腳本-使用列名(不是在row1)而不是列號
下一篇:tkinter的鍵盤快捷鍵問題
