一个简单的收藏动画

 起因是我们App原生和h5都有类似的内容卡片列表,h5版本较老。产品经理提出了需求,h5要做一番更新,与App样式保持一致。本来要求只是基本样式调整,但热情如我,把收藏动画这种细节也复刻了出来(我是一个多么实在又优秀的程序员啊呜呜呜~)

喏,效果就是这么个效果,喜欢的需要的可以直接拿走代码啦~

拆分动作

最难的事情是我只有星星图片,没有动画的设计稿,想要实现只能靠肉眼观察,app上的收藏按钮点了不下百次吧,一边点一边在脑海里拆分动作~ 那么我们观察这个动画,从点击到结束,有几个要素

  • 星星填充颜色并放大

  • 周围有四个小圆点随星星放大一起扩散

  • 从中间扩散的圆环,比放大动画出现的晚一些

  • 星星放大后缩小到原位,四周的圆点扩散到最大后消失。

确定结构

首先是需要两张图片,星星线框图和填充图, 当然也可以换成svg、合成雪碧图什么的。

分析动画元素,我准备用一个div元素来放置星星,使用伪元素::before::after分别实现四个圆点和带透明度的圆环,结构如下。

<div id="star">
   ::before
   ::after
</div>

div主体给上宽高,用星星图片做背景填充。点击时切换背景图片。 半透明的圆比较好做,就是 绝对定位+圆角+rgba背景色。四个圆点相对复杂些,先写一个小圆点,用到box-shadow多重阴影复制四个圆, 这四个经过尝试调整到合适的大小和位置。

#star{
  position: relative;
  display: inline-block;
  width: 30px;
  height: 30px;
  background-image: url(star.png);
  background-repeat: no-repeat;
  background-size: 100%;
}
#star::before{
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
  border-radius: 50%;
  background: rgba(254, 208, 1, 0.1);
}
#star::after{
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 10%;
  height: 10%;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: transparent;
  box-shadow: 15px -15px 0 #fed001, 15px 15px 0 #fed001,
    -15px -15px 0 #fed001, -15px 15px 0 #fed001;
}

添加动画

设计动画的过程就是根据拆分的动作,大概规划一下关键帧,然后反复调试参数,得到一个满意的效果收手。这里直接放代码吧

/* 放大 */
@keyframes banuce {
  0% {
    transform: scale(0.8);
  }
  100% {
    transform: scale(1.35);
  }
}
/* 缩放加透明度变化 */
@keyframes circle {
  0% {
    transform: scale(0.2);
    opacity: 0.8;
  }
  100% {
    transform: scale(1.5);
    opacity: 1;
  }
}
/* 出现。用opacity来控制元素隐藏显示 */
@keyframes show {
  0% {
    opacity: 1;
  }
}
    
/* 星星整体放大,并反向播放一次,实现弹出缩回效果 */
#star{
  animation: banuce 0.2s ease 0s 2 alternate;
}
/* 给半透明圆环加额外的扩散效果,加一点延迟。 */
#star::before{
  opacity: 0;
  animation: circle 0.3s ease 0.02s 1 alternate;
}
/* 两个伪元素都给一个初始透明度0,让它们在自身动画完成后消失 */
#star::after{
  opacity: 0;
  animation: show 0.2s steps(1,end) 0s 1;
}

加入点击事件

将动画样式拆出一个class .fill, 在点击时给元素添加类,从而实现状态变化。现在放上完整代码

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    @keyframes banuce {
      0% {
        transform: scale(0.8);
      }
      100% {
        transform: scale(1.35);
      }
    }
    @keyframes circle {
      0% {
        transform: scale(0.2);
        opacity: 0.8;
      }
      100% {
        transform: scale(1.5);
        opacity: 1;
      }
    }
    @keyframes show {
      0% {
        opacity: 1;
      }
    }
    .wrap {
      width: 100vw;
      height: 100vh;
      display: flex;
      justify-content: center;
      align-items: center;
    }
    #star {
      display: inline-block;
      width: 30px;
      height: 30px;
      background-image: url(star.png);
      background-repeat: no-repeat;
      background-size: 100%;
      background-position: center;
    }
    .fill {
      position: relative;
      animation: banuce 0.2s ease 0s 2 alternate;
      background-image: url(star_fill.png) !important;
    }
    .fill::before {
      opacity: 0;
      content: '';
      position: absolute;
      left: 50%;
      top: 50%;
      width: 10%;
      height: 10%;
      transform: translate(-50%, -50%);
      border-radius: 50%;
      background: transparent;
      box-shadow: 15px -15px 0 #fed001, 15px 15px 0 #fed001,
        -15px -15px 0 #fed001, -15px 15px 0 #fed001;
      animation: show 0.2s steps(1, end) 0s 1;
    }
    .fill::after {
      opacity: 0;
      content: '';
      position: absolute;
      left: 0;
      right: 0;
      top: 0;
      bottom: 0;
      animation: circle 0.3s ease 0.02s 1 alternate;
      border-radius: 50%;
      background: rgba(254, 208, 1, 0.1);
    }
  </style>
</head>
<body>
  <div class="wrap">
    <div id="star"></div>
  </div>
  <script>
    window.onload = ()=> {
      const starEl = document.getElementById('star');
      starEl.addEventListener('click', (e)=>{
        starEl.className = 'fill';
        setTimeout(()=>{
          starEl.className = '';
        }, 1000)
      })
    }
  </script>
</body>
</html>

再来一个慢动作,把时间都*2看一下效果

—— end

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android 收藏动画效果可以有很多种实现方式,这里提供一种比较简单的做法,通过使用属性动画和自定义插值器实现。 首先在布局文件中添加一个 ImageView 控件作为收藏按钮,如下: ```xml <ImageView android:id="@+id/img_collect" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_collect"/> ``` 然后在代码中为 ImageView 添加点击事件,在点击事件中添加动画效果,如下: ```java // 获取布局文件中的控件 ImageView imgCollect = findViewById(R.id.img_collect); // 为 ImageView 添加点击事件 imgCollect.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // 创建一个属性动画实现旋转和缩放效果 ObjectAnimator anim1 = ObjectAnimator.ofFloat(imgCollect, "rotation", 0, 45); anim1.setDuration(300); anim1.setInterpolator(new MyInterpolator()); ObjectAnimator anim2 = ObjectAnimator.ofFloat(imgCollect, "scaleX", 1, 1.2f, 1); anim2.setDuration(300); anim2.setInterpolator(new MyInterpolator()); ObjectAnimator anim3 = ObjectAnimator.ofFloat(imgCollect, "scaleY", 1, 1.2f, 1); anim3.setDuration(300); anim3.setInterpolator(new MyInterpolator()); // 创建一个 AnimatorSet,按顺序播放动画 AnimatorSet animSet = new AnimatorSet(); animSet.playSequentially(anim1, anim2, anim3); animSet.start(); } }); ``` 其中,MyInterpolator 是自定义的一个插值器类,用于控制动画的变化速度,可以根据个人喜好进行调整。这里是一个简单实现: ```java public class MyInterpolator implements Interpolator { @Override public float getInterpolation(float input) { return (float) Math.pow(input, 2); } } ``` 这样就可以实现一个简单收藏按钮动画效果了。需要注意的是,代码中的图片资源需要自行添加,并根据实际情况进行调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值