Nano Hash - криптовалюты, майнинг, программирование

Apple Workout Rings SpriteKit Animation

Я пытаюсь воссоздать кольца Apple Workout Rings в своем приложении WatchOS. Я использую SpriteKit и GameScene для анимации. Однако я не могу понять, как реализовать перекрывающиеся кольца и включить градиент.

Кольца для тренировок

Я попытался использовать SKShader, чтобы включить эффект градиента. Однако SKShapeNode игнорирует окончание строки, когда присутствует SKShader, поэтому я не могу получить закругленные края.

Я также рассмотрел другие подходы, такие как: Circle Progress View как приложение активности

Однако я не знаю, как использовать этот подход для watchOS, поскольку SpriteKit работает с концепцией узлов, а этот подход имеет дело с CGContext.

    class GameScene: SKScene {

    func circle(radius:CGFloat, percent:CGFloat) -> CGPath {

        let start:CGFloat = 0
        let end = ((CGFloat.pi * 2)) * percent
        let center = CGPoint.zero
        let corePath = CGMutablePath()
        corePath.addArc(center: center, radius: radius, startAngle: start, endAngle: end, clockwise: true)
        return corePath
    }
    // Animated Timer for Progress Circle
    func countdownCircle(circle:SKShapeNode, steps:Int, duration:TimeInterval, completion:@escaping ()->Void)  {
        guard let path = circle.path else {
            return
        }
        let radius = path.boundingBox.width/2
        let timeInterval = duration/TimeInterval(steps)
        let increment = 1 / CGFloat(steps)

        var percent = CGFloat(1.0)
        let animate = SKAction.run {
            percent -= increment
            circle.path = self.circle(radius: radius, percent:percent)
        }
        let wait = SKAction.wait(forDuration:timeInterval)
        let action = SKAction.sequence([wait, animate])
        run(SKAction.repeatForever(action)) {
            self.run(SKAction.wait(forDuration:timeInterval/2)) {
                circle.path = nil
                completion()

            }

            //(action,count:steps-1)
        }
    }
    // Animated Timer for Shadow Circle
    func countdownShadow(circle:SKShapeNode, steps:Int, duration:TimeInterval, completion:@escaping ()->Void)  {
        guard let path = circle.path else {
            return
        }
        let radius = path.boundingBox.width/2
        let timeInterval = duration/TimeInterval(steps)
        let increment = 1 / CGFloat(steps)
        var percent = CGFloat(1.0)
        let animate = SKAction.run {
            percent -= increment
            circle.path = self.circle(radius: radius, percent:percent)
        }
        let wait = SKAction.wait(forDuration:timeInterval)
        let action = SKAction.sequence([wait, animate])
        run(SKAction.repeatForever(action)) {
            self.run(SKAction.wait(forDuration:timeInterval)) {
                circle.path = nil
                completion()
            }
        }
    }
//(action,count:steps-1)

override func sceneDidLoad() {

    let pathForCircle = CGMutablePath()
    pathForCircle.addArc(center: CGPoint.zero, radius: 100, startAngle: 0, endAngle: CGFloat(Double.pi * 2), clockwise: true)

    // This is the circle that indicates the progress.
        let progressCircle = SKShapeNode()
        progressCircle.lineCap = .round
        progressCircle.position = CGPoint(x: 0, y: 15)
        progressCircle.strokeColor = SKColor.green
        progressCircle.lineWidth = 20
        progressCircle.path = pathForCircle
        progressCircle.zPosition = 4
        self.addChild(progressCircle)
        countdownCircle(circle: progressCircle, steps: 400, duration: 5){
            print("Done")
        }

    // This is the circle that gives the ring the shadow effect.
        let shadowCircle = SKShapeNode()
        shadowCircle.lineCap = .round
        shadowCircle.position = CGPoint(x: 0, y: 15)
        shadowCircle.strokeColor = SKColor.black
        shadowCircle.glowWidth = 30
        shadowCircle.zPosition = 3
        shadowCircle.path = pathForCircle
        self.addChild(shadowCircle)
        countdownShadow(circle: shadowCircle, steps: 400, duration: 5){
            print("Done")
        }

    // This is the bottommost circle.

        let bottommostCircle = SKShapeNode()
        bottommostCircle.position = CGPoint(x: 0, y: 15)
        bottommostCircle.lineCap = .butt
        bottommostCircle.strokeColor = SKColor.green
        bottommostCircle.alpha = 0.2
        bottommostCircle.lineWidth = 20
        bottommostCircle.path = pathForCircle
        bottommostCircle.zPosition = 0
        self.addChild(bottommostCircle)

}

override func update(_ currentTime: TimeInterval) {
    // Called before each frame is rendered
}
 }

Ответы:


1

на GitHub есть множество реализаций Spritekit точно такого же типа.

Вот один из них выглядит особенно хорошо.

https://github.com/HarshilShah/ActivityRings

11.04.2018
Новые материалы

Кластеризация: более глубокий взгляд
Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

Как написать эффективное резюме
Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

Частный метод Python: улучшение инкапсуляции и безопасности
Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

Как я автоматизирую тестирование с помощью Jest
Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..