【问题标题】:Circle scale animation works a bit weird圆形比例动画有点奇怪
【发布时间】:2017-05-23 13:49:17
【问题描述】:

我正在为我的 GMSMarker 设置动画,使其在几秒钟内脉冲一次。

func addWave()
    {
//        circleView.layer.cornerRadius = size / 2

        //Scale
        let scaleAnimation = CABasicAnimation(keyPath: "transform.scale")
        scaleAnimation.fromValue = 1
        scaleAnimation.toValue = zoom

        //Opacity
        let alphaAnimation = CABasicAnimation(keyPath: "opacity")
        alphaAnimation.toValue = 0.0

        //Corner radius
//        let cornerRadiusAnimation = CABasicAnimation(keyPath: "cornerRadius")
//        cornerRadiusAnimation.fromValue = size / 2
//        cornerRadiusAnimation.toValue = (size * zoom)/2

        //Animation Group
        let animations: [CAAnimation] = [scaleAnimation, alphaAnimation]

        let animationGroup = CAAnimationGroup()
        animationGroup.duration = duration
        animationGroup.animations = animations
        animationGroup.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)
        animationGroup.repeatCount = 1
        animationGroup.fillMode = kCAFillModeForwards
        animationGroup.isRemovedOnCompletion = false
        circleView.layer.add(animationGroup, forKey: "group")
    }

结果如下:

如果我取消注释 Corner radius 部分,它看起来像这样:

所以我需要一个建议。

【问题讨论】:

    标签: swift cabasicanimation


    【解决方案1】:

    根据我的观察,我认为这一定是您的 CAShapeLayer 路径错误的问题,因此会掩盖圆圈。

    我刚刚写了一个雷达动画,希望对你有帮助。

        let scaleAnimation = CABasicAnimation(keyPath: "transform.scale")
        scaleAnimation.fromValue = 0
        scaleAnimation.toValue = 1
    
        let alphaAnimation = CABasicAnimation(keyPath: "opacity")
        alphaAnimation.fromValue = 1
        alphaAnimation.toValue = 0
    
        let animations = CAAnimationGroup()
        animations.duration = 0.8
        animations.repeatCount = Float.infinity
        animations.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)
        animations.animations = [scaleAnimation, alphaAnimation]
    
        circleView.layer.add(animations, forKey: "animations")
    

    我所做的是,我使用了两个 CAShapeLayer(一个是橙色标记,另一个是标记背面的 rader 层)。动画应用于雷达层。

        radarLayer = CAShapeLayer()
        radarLayer.frame = CGRect(x: 0, y: 0, width: self.frame.size.width, height: self.frame.size.height);
        radarLayer.path = UIBezierPath(rect: radarLayer.frame).cgPath
        radarLayer.fillColor = UIColor.orange.cgColor
        radarLayer.position = CGPoint(x: self.frame.size.width/2, y: self.frame.size.height/2)
        radarLayer.cornerRadius = radarLayer.frame.size.width/2
        radarLayer.masksToBounds = true
        radarLayer.opacity = 0
        self.layer.addSublayer(radarLayer)
    
        circleLayer = CAShapeLayer()
        circleLayer.frame = CGRect(x: 0, y: 0, width: 16, height: 16);
        circleLayer.path = UIBezierPath(rect: circleLayer.frame).cgPath
        circleLayer.fillColor = UIColor.orange.cgColor
        circleLayer.position = CGPoint(x: self.frame.size.width/2, y: self.frame.size.height/2)
        circleLayer.cornerRadius = circleLayer.frame.size.width/2
        circleLayer.masksToBounds = true
        self.layer.addSublayer(circleLayer)
    

    附言。我是 Swift 的新手,如果我在某个地方错了,请赐教:)

    例如:http://i.imgur.com/v2jFWgw.jpg

    【讨论】:

    • 谢谢!看起来我搞砸了层次和基础知识,你的回答帮助我做对了:)
    【解决方案2】:

    以下内容摘自 Google 关于标记的文档:

    视图的行为就像 clipsToBounds 设置为 YES,而不管其实际值如何。您可以应用在边界之外起作用的变换,但您绘制的对象必须在对象的范围内。所有的变换/移位都被监控和应用。简而言之:子视图必须包含在视图中。

    其结果,至少对我而言,正是问题中提到的行为:方形圆圈动画。我想在动画结束时添加到标记内的图像比容器大,所以一旦添加到标记中,它就会被剪裁到它的边界。

    以下是我所做的:

    public var pulseImageView: UIImageView = {
        let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 300, height: 300))
        imageView.image = PaletteElements.pulseLocation.value
        imageView.contentMode = .center
    
        let pulseAnimation = CABasicAnimation(keyPath: "transform.scale.xy")
        pulseAnimation.repeatCount = Float.infinity
        pulseAnimation.fromValue = 0
        pulseAnimation.toValue = 2.0
        pulseAnimation.isRemovedOnCompletion = false
    
        let fadeOutAnimation = CABasicAnimation(keyPath: "opacity")
        fadeOutAnimation.duration = 2.5
        fadeOutAnimation.fromValue = 1.0
        fadeOutAnimation.toValue = 0
        fadeOutAnimation.repeatCount = Float.infinity
    
        let animationGroup = CAAnimationGroup()
        animationGroup.duration = 2.5
        animationGroup.animations = [pulseAnimation, fadeOutAnimation]
        animationGroup.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeOut)
        animationGroup.repeatCount = .greatestFiniteMagnitude
        animationGroup.fillMode = CAMediaTimingFillMode.forwards
        animationGroup.isRemovedOnCompletion = false
        imageView.layer.add(animationGroup, forKey: "pulse")
    
        return imageView
    }()
    

    我在帮助程序类中定义了一个 var,因此我可以在需要时检索图像。我的原始图像,脉冲图像,是 116x116,所以我将 imageView 创建为 300x300,contentMode = .center,所以小图像在中心并且没有被拉伸。我选择 300x300 是因为我的动画将脉冲图像放大到其初始值 (116x2) 的 2 倍,因此我为执行整个动画腾出了空间。

    最后我将它作为标记添加到地图中:

    let pulseMarker = GMSMarker(position: userLocation.coordinate)
    pulseMarker.iconView = pulseImageView
    pulseMarker.groundAnchor = CGPoint(x: 0.5, y: 0.5)
    pulseMarker.map = googleMapView
    

    希望对你有帮助。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-10-31
    • 1970-01-01
    • 2016-07-28
    • 1970-01-01
    • 1970-01-01
    • 2023-03-14
    • 1970-01-01
    相关资源
    最近更新 更多