根据时间对 UIBezierPath 上的 UIImageView 进行动画处理 iOS Swift
Animate UIImageView on UIBezierPath according to time iOS Swift
我用 UIBezierPath
创建了无穷大 ♾ 符号,并在同一路径上设置了太阳视图的动画。但我想根据路径上的时间设置太阳视图。太阳视图总是从 UIBezierPath
的初始点开始动画。
以下是我无法完成的任务:
- 每当用户进入应用程序时,我需要根据时间在 UIBezierPath
上设置太阳视图并从该特定点开始动画。
class LineDraw: UIView
{
var path: UIBezierPath!
let circleLayer = CAShapeLayer()
var circlePathSize:CGSize?
let circleView = UIView()
let sunImage = UIImageView()
override init(frame: CGRect)
{
super.init(frame: frame)
// self.backgroundColor = UIColor.white
}
required init?(coder aDecoder: NSCoder)
{
super.init(coder: aDecoder)
}
override func draw(_ rect: CGRect) {
let height = self.frame.height
let width = self.frame.width
let heightFactor = height/4
let widthFactor = width/4
path = UIBezierPath()
path.lineWidth = 3.0
path.move(to: CGPoint(x:widthFactor, y: heightFactor))
path.addCurve(to: CGPoint(x:widthFactor * 3, y: heightFactor * 3), controlPoint1: CGPoint(x:widthFactor * 2, y: heightFactor), controlPoint2: CGPoint(x:widthFactor * 2, y: heightFactor * 3))
path.move(to: CGPoint(x:widthFactor * 3, y: heightFactor * 3))
path.addCurve(to: CGPoint(x:widthFactor * 3, y: heightFactor), controlPoint1: CGPoint(x:widthFactor * 4, y: heightFactor * 3), controlPoint2: CGPoint(x:widthFactor * 4, y: heightFactor))
path.move(to: CGPoint(x:widthFactor * 3, y: heightFactor))
path.addCurve(to: CGPoint(x:widthFactor, y: heightFactor * 3), controlPoint1: CGPoint(x:widthFactor * 2, y: heightFactor), controlPoint2: CGPoint(x:widthFactor * 2, y: heightFactor * 3))
path.move(to: CGPoint(x:widthFactor, y: heightFactor * 3))
path.addCurve(to: CGPoint(x:widthFactor, y: heightFactor), controlPoint1: CGPoint(x:0, y: heightFactor * 3), controlPoint2: CGPoint(x:0, y: heightFactor))
UIColor.purple.setStroke()
path.stroke()
animateCircleOnPath()
}
func animateCircleOnPath() {
let animation = CAKeyframeAnimation(keyPath: "position");
animation.duration = 20.0
animation.repeatCount = MAXFLOAT
sunImage.frame.size = CGSize(width: 40, height: 40)
animation.path = path.cgPath
sunImage.image = #imageLiteral(resourceName: "Logo")
self.addSubview(sunImage)
sunImage.layer.add(animation, forKey: nil)
}
}
当前输出
有点不清楚,但似乎您需要做的就是修改您的 CAKeyframeAnimation
。尝试如下操作:
let animation = CAKeyframeAnimation(keyPath: "position");
animation.duration = 24*60*60 // 24 hours
animation.timeOffset = {
let date = Date() // Now
let startDateComponents = Calendar.autoupdatingCurrent.dateComponents([.year, .month, .day], from: Date()) // Describing components that will return start of this day
let startDate = Calendar.autoupdatingCurrent.date(from: startDateComponents)!
let endDate = date
return endDate.timeIntervalSince(startDate)
}()
正如您所说:
Sun view will complete single loop in 24 hours.
我们将持续时间设置为 24 小时 animation.duration = 24*60*60
。您应该注意,由于夏令时,一天可能有 23 小时或 25 小时。这是一个边缘案例,但可能值得考虑。因此,使用 animation.duration = todayEndDate.timeIntervalSince(todayStartDate)
可以改善持续时间。但是现在应该是 24 小时。
然后是
Whenever user enter in app I need to set sun view on UIBezierPath
according to time and start animating from that particular point.
所有需要做的就是设置一个正确的 timeOffset
如果我假设正确的话应该是当天的持续时间;所以在 13:23 应该是 13 小时 23 分钟,具体取决于您的当地时间和日历。
这里的棘手部分是 "depending on your local time and calendar"。因此,同时生活在世界不同地区的 2 个人会看到不同位置的太阳位置。我希望这是有道理的。所以我们需要检索这一天开始的 Date
。所以我们使用以下内容:
let startDateComponents = Calendar.autoupdatingCurrent.dateComponents([.year, .month, .day], from: Date())
let startDate = Calendar.autoupdatingCurrent.date(from: startDateComponents)!
我们需要使用电流 Date
并从中提取年月日(没有小时和分钟)。为此,我们需要根据谁的观点进行选择。为此,使用 Calendar
和 TimeZone
。 autoupdatingCurrent
是设备正在使用的任何内容。
然后我们使用相同的日历来组成 Date
背面,现在默认情况下应该将小时、分钟、秒...设置为 0,这实际上是 returns 作为这一天的开始.
当我们使用时间间隔 timeIntervalSince
减去两个日期(当前日期和今天开始的日期)时,我们得到 timeOffset
.
所需的持续时间
我希望这一切都解决了。
我用 UIBezierPath
创建了无穷大 ♾ 符号,并在同一路径上设置了太阳视图的动画。但我想根据路径上的时间设置太阳视图。太阳视图总是从 UIBezierPath
的初始点开始动画。
以下是我无法完成的任务:
- 每当用户进入应用程序时,我需要根据时间在 UIBezierPath
上设置太阳视图并从该特定点开始动画。
class LineDraw: UIView
{
var path: UIBezierPath!
let circleLayer = CAShapeLayer()
var circlePathSize:CGSize?
let circleView = UIView()
let sunImage = UIImageView()
override init(frame: CGRect)
{
super.init(frame: frame)
// self.backgroundColor = UIColor.white
}
required init?(coder aDecoder: NSCoder)
{
super.init(coder: aDecoder)
}
override func draw(_ rect: CGRect) {
let height = self.frame.height
let width = self.frame.width
let heightFactor = height/4
let widthFactor = width/4
path = UIBezierPath()
path.lineWidth = 3.0
path.move(to: CGPoint(x:widthFactor, y: heightFactor))
path.addCurve(to: CGPoint(x:widthFactor * 3, y: heightFactor * 3), controlPoint1: CGPoint(x:widthFactor * 2, y: heightFactor), controlPoint2: CGPoint(x:widthFactor * 2, y: heightFactor * 3))
path.move(to: CGPoint(x:widthFactor * 3, y: heightFactor * 3))
path.addCurve(to: CGPoint(x:widthFactor * 3, y: heightFactor), controlPoint1: CGPoint(x:widthFactor * 4, y: heightFactor * 3), controlPoint2: CGPoint(x:widthFactor * 4, y: heightFactor))
path.move(to: CGPoint(x:widthFactor * 3, y: heightFactor))
path.addCurve(to: CGPoint(x:widthFactor, y: heightFactor * 3), controlPoint1: CGPoint(x:widthFactor * 2, y: heightFactor), controlPoint2: CGPoint(x:widthFactor * 2, y: heightFactor * 3))
path.move(to: CGPoint(x:widthFactor, y: heightFactor * 3))
path.addCurve(to: CGPoint(x:widthFactor, y: heightFactor), controlPoint1: CGPoint(x:0, y: heightFactor * 3), controlPoint2: CGPoint(x:0, y: heightFactor))
UIColor.purple.setStroke()
path.stroke()
animateCircleOnPath()
}
func animateCircleOnPath() {
let animation = CAKeyframeAnimation(keyPath: "position");
animation.duration = 20.0
animation.repeatCount = MAXFLOAT
sunImage.frame.size = CGSize(width: 40, height: 40)
animation.path = path.cgPath
sunImage.image = #imageLiteral(resourceName: "Logo")
self.addSubview(sunImage)
sunImage.layer.add(animation, forKey: nil)
}
}
当前输出
有点不清楚,但似乎您需要做的就是修改您的 CAKeyframeAnimation
。尝试如下操作:
let animation = CAKeyframeAnimation(keyPath: "position");
animation.duration = 24*60*60 // 24 hours
animation.timeOffset = {
let date = Date() // Now
let startDateComponents = Calendar.autoupdatingCurrent.dateComponents([.year, .month, .day], from: Date()) // Describing components that will return start of this day
let startDate = Calendar.autoupdatingCurrent.date(from: startDateComponents)!
let endDate = date
return endDate.timeIntervalSince(startDate)
}()
正如您所说:
Sun view will complete single loop in 24 hours.
我们将持续时间设置为 24 小时 animation.duration = 24*60*60
。您应该注意,由于夏令时,一天可能有 23 小时或 25 小时。这是一个边缘案例,但可能值得考虑。因此,使用 animation.duration = todayEndDate.timeIntervalSince(todayStartDate)
可以改善持续时间。但是现在应该是 24 小时。
然后是
Whenever user enter in app I need to set sun view on UIBezierPath according to time and start animating from that particular point.
所有需要做的就是设置一个正确的 timeOffset
如果我假设正确的话应该是当天的持续时间;所以在 13:23 应该是 13 小时 23 分钟,具体取决于您的当地时间和日历。
这里的棘手部分是 "depending on your local time and calendar"。因此,同时生活在世界不同地区的 2 个人会看到不同位置的太阳位置。我希望这是有道理的。所以我们需要检索这一天开始的 Date
。所以我们使用以下内容:
let startDateComponents = Calendar.autoupdatingCurrent.dateComponents([.year, .month, .day], from: Date())
let startDate = Calendar.autoupdatingCurrent.date(from: startDateComponents)!
我们需要使用电流 Date
并从中提取年月日(没有小时和分钟)。为此,我们需要根据谁的观点进行选择。为此,使用 Calendar
和 TimeZone
。 autoupdatingCurrent
是设备正在使用的任何内容。
然后我们使用相同的日历来组成 Date
背面,现在默认情况下应该将小时、分钟、秒...设置为 0,这实际上是 returns 作为这一天的开始.
当我们使用时间间隔 timeIntervalSince
减去两个日期(当前日期和今天开始的日期)时,我们得到 timeOffset
.
我希望这一切都解决了。