J'ai un UIScrollView
qui contient un long texte. Je souhaite informer les utilisateurs qu'il a plus de contenu à lire. Par conséquent, j'ai ajouté une flèche avec UIBezierPath
en bas.
class ArrowView: UIView { var arrowPath: UIBezierPath! // Only override draw() if you perform custom drawing. // An empty implementation adversely affects performance during animation. override func draw(_ rect: CGRect) { // Drawing code self.drawArrow(from: CGPoint(x: rect.midX, y: rect.minY), to: CGPoint(x: rect.midX, y: rect.maxY), tailWidth: 10, headWidth: 25, headLength: 20) //arrowPath.fill() } override init(frame: CGRect) { super.init(frame: frame) self.backgroundColor = UIColor.darkGray } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) } private func drawArrow(from start: CGPoint, to end: CGPoint, tailWidth: CGFloat, headWidth: CGFloat, headLength: CGFloat){ let length = hypot(end.x - start.x, end.y - start.y) let tailLength = length - headLength func p(_ x: CGFloat, _ y: CGFloat) -> CGPoint { return CGPoint(x: x, y: y) } let points: [CGPoint] = [ p(0, tailWidth / 2), p(tailLength, tailWidth / 2), p(tailLength, headWidth / 2), p(length, 0), p(tailLength, -headWidth / 2), p(tailLength, -tailWidth / 2), p(0, -tailWidth / 2) ] let cosine = (end.x - start.x) / length let sine = (end.y - start.y) / length let transform = CGAffineTransform(a: cosine, b: sine, c: -sine, d: cosine, tx: start.x, ty: start.y) let path = CGMutablePath() path.addLines(between: points, transform: transform) path.closeSubpath() arrowPath = UIBezierPath.init(cgPath: path) } }
Ma question: Comment puis-je réaliser une animation clignotante sur la flèche. Supposons qu'il a un calque dégradé du blanc au bleu. Il devrait commencer par du blanc au bleu, puis le bleu devrait être vu au point de départ, puis le blanc devrait commencer à être vu au point d'arrivée de Arrow et ce cercle devrait continuer.
Enfin, cette animation doit informer les utilisateurs qu'ils peuvent faire défiler la vue.
Comment puis-je y parvenir?
3 Réponses :
Vous pouvez placer votre flèche dans un objet UIView. Vous pourriez alors avoir l'UIView sur une minuterie où il a changé l'alpha correctement. En fonction du clignotement ou de la décoloration, vous pouvez néanmoins utiliser les animations UIView pour compléter l'animation souhaitée.
Je dis un uiview, au lieu d'utiliser le scrollview car vous ne voulez pas masquer le scrollview. Vous le placerez donc dans une vue dans laquelle il n’y a qu’un conteneur pour le chemin bezier.
Vous pouvez essayer d'utiliser CAGradientLayer avec CAAnimation. Ajoutez un dégradé à votre vue:
override func animationDidStop(anim: CAAnimation!, finished flag: Bool) { self.toColors = self.fromColors; self.fromColors = self.gradient?.colors animateLayer() }
et pour continuer l'animation du dégradé dans l'ordre cyclique comme:
override func viewDidAppear(animated: Bool) { self.gradient = CAGradientLayer() self.gradient?.frame = self.view.bounds self.gradient?.colors = [ UIColor.white.cgColor, UIColor.white.cgColor] self.view.layer.insertSublayer(self.gradient, atIndex: 0) animateLayer() } func animateLayer(){ var fromColors = self.gradient.colors var toColors: [AnyObject] = [UIColor.blue.cgColor,UIColor.blue.cgColor] self.gradient.colors = toColors var animation : CABasicAnimation = CABasicAnimation(keyPath: "colors") animation.fromValue = fromColors animation.toValue = toColors animation.duration = 3.00 animation.isRemovedOnCompletion = true animation.fillMode = CAMediaTimingFillMode.forwards animation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.linear) animation.delegate = self self.gradient?.addAnimation(animation, forKey:"animateGradient") }
Cela ajoutera un dégradé à l'ensemble de l'UIView personnalisé, pas seulement à la flèche?
vous devez remplacer self.view par votre arrowView
Je l'ai résolu en utilisant CABasicAnimation ()
. Cela ajoute d'abord un calque de dégradé à UIView
personnalisé, puis applique un masque dessus, puis ajoute une animation.
override func draw(_ rect: CGRect) { // Drawing code self.drawArrow(from: CGPoint(x: rect.midX, y: rect.minY), to: CGPoint(x: rect.midX, y: rect.maxY), tailWidth: 10, headWidth: 20, headLength: 15) //arrowPath.fill() let startColor = UIColor(red:0.87, green:0.87, blue:0.87, alpha:1.0).cgColor let finishColor = UIColor(red:0.54, green:0.54, blue:0.57, alpha:1.0).withAlphaComponent(0.5).cgColor let gradient = CAGradientLayer() gradient.frame = self.bounds gradient.colors = [startColor,finishColor] let shapeMask = CAShapeLayer() shapeMask.path = arrowPath.cgPath gradient.mask = shapeMask let animation = CABasicAnimation(keyPath: "colors") animation.fromValue = [startColor, finishColor] animation.toValue = [finishColor, startColor] animation.duration = 2.0 animation.autoreverses = true animation.repeatCount = Float.infinity //add the animation to the gradient gradient.add(animation, forKey: nil) self.layer.addSublayer(gradient) }