灏天阁

那些你不知道的炫酷按钮交互效果

· Yin灏

今天分享的主要内容来源于 Aaron Iker ,有兴趣的可以去看看原设计。为方便国内访问,本文有稍加整理修改,涉及到的代码较多,文中只展示核心部分代码,完整代码可在文末码上掘金看源码。特别说明,因涉及细节的动画比较多,所以导致 CSS 的代码量会比较高,部分效果依赖于 gsap,animejs,three 等动画库,如需线上环境使用,请留意整体性能影响,主要是按钮交互效果的参考与借鉴。

收藏按钮

此交互效果适用于用户收藏或是喜欢某个内容的时候。观察下图,我们可以将动画拆分为以下几个步骤,这里的交互效果主要是星星的动画。

  • 星星在交互过程中有旋转
  • 有两段上下移动的过程
  • 星星中途有变化为圆形
  • 从第二段跳出星星改变了颜色
  • 此时星星的表情也变更为嘴角上扬
  • 星星跳出过程中底部增加了一个椭圆的从无到有再到无的过程 收藏 基于以上主要的动画过程开始编码,这里使用 gsap 实现,当然使用常规 CSS 也是可行的。核心代码如下,CSS 部分代码较多可看文末源码:
// 上下跳出动画
gsap.to(button, {
  keyframes: [
    {
      "--star-y": "-36px",
      duration: 0.3,
      ease: "power2.out",
    },
    {
      "--star-y": "48px",
      "--star-scale": 0.4,
      duration: 0.325,
      onStart() {
        // 中途变圆形
        button.classList.add("star-round");
      },
    },
    {
      "--star-y": "-64px",
      "--star-scale": 1,
      duration: 0.45,
      ease: "power2.out",
      onStart() {
        // 高亮黄色
        button.classList.toggle("active");
        setTimeout(() => button.classList.remove("star-round"), 100);
      },
    },
    {
      "--star-y": "0px",
      duration: 0.45,
      ease: "power2.in",
    },
    {
      "--button-y": "3px",
      duration: 0.11,
    },
    {
      "--button-y": "0px",
      "--star-face-scale": 0.65,
      duration: 0.125,
    },
    {
      "--star-face-scale": 1,
      duration: 0.15,
    },
  ],
  clearProps: true,
  onComplete() {
    button.classList.remove("animated");
  },
});
// 底部圆形变化
gsap.to(button, {
  keyframes: [
    {
      "--star-hole-scale": 0.8,
      duration: 0.5,
      ease: "elastic.out(1, .75)",
    },
    {
      "--star-hole-scale": 0,
      duration: 0.2,
      delay: 0.2,
    },
  ],
});
// 星星旋转
gsap.to(button, {
  "--star-rotate": "360deg",
  duration: 1.55,
  clearProps: true,
});

发布按钮

此交互效果适用于发布新版本,提交云部署等类型功能时,观察以下动图分析动画步骤如下:

  • 点击按钮时箭头开始伸缩效果
  • 箭头背景出现向下运动的小云朵
  • 上传完成出现 ☑️ 小图标
  • 文案变更:处理前-过程中-处理完成 首先是按钮中箭头的伸缩效果,hover 按钮的时候也会有此效果,--icon-arrow-y改变箭头的 y 轴数值,--icon-line-offset改变箭头自身的高度。
fromTo(
  button,
  {
    "--icon-arrow-y": "0px",
    "--icon-line-offset": "21px",
    duration: 0.15,
  },
  {
    repeat: -1,
    keyframes: [
      {
        "--icon-arrow-y": "-6px",
        "--icon-line-offset": "24px",
        duration: 0.6,
      },
      {
        "--icon-arrow-y": "0px",
        "--icon-line-offset": "21px",
        duration: 0.85,
        ease: "power2.out",
      },
    ],
  }
);

然后创建云朵的动画,因为云朵飞出后则移除了元素,所以开启一个定时器不断创建云朵。

function createCloud(node, parent) {
  let elem = node.cloneNode(true);
  parent.appendChild(elem);
  set(elem, {
    x: gsap.utils.random(-8, 8),
    y: -36,
  });
  to(elem, {
    y: 36,
    duration: gsap.utils.random(0.4, 1.5),
    onComplete() {
      elem.remove();
    },
  });
}
// 定时创建
cloudInterval = setInterval(() => {
  createCloud(clone, button.querySelector(".icon"));
}, 400);

最后是结束状态,结束时移除云朵和箭头,显示带 ☑️ 小图标,并变更文案。

clearInterval(cloudInterval);
// 将箭头移动到可视区外
to(button, {
  duration: 0.25,
  keyframes: [
    {
      "--icon-line-offset": "13px",
    },
    {
      "--icon-arrow-offset": "4px",
    },
  ],
});
// 显示带☑️小图标
to(button, {
  "--icon-tick-offset": "0px",
  duration: 0.25,
  delay: 0.3,
});
to(button, {
  "--icon-circle-scale": 1,
  duration: 0.7,
  delay: 0.2,
  ease: "elastic.out(1, .75)",
});

整个通过控制元素的透明度和 y 轴偏移量显示不同的状态文案,以下时完成状态文案控制代码。

span {
  opacity: var(--o, var(--text-normal-o));
  transform: translateY(var(--y, var(--text-normal-y))) translateZ(0);
  &.done {
    --o: var(--text-done-o);
    --y: var(--text-done-y);
  }
}
/* 完成状态显示 */
to(button, {
    '--text-done-o': 1,
    '--text-done-y': '0px',
    duration: .3,
    delay: .1
})

按钮点星效果

此交互效果适用于 github 给开源项目点星的时候用,也可以用于类似加星加赞等场景。此效果除了 gsap 之外还用到了 threejs,通过观察下面等动图,可分析出动画主要有以下几个步骤:

  • 鼠标悬停时会出现 3D 星星并带有翻转动画
  • 点击按钮时星星会产生抛物线的运动轨迹到按钮后面的数字
  • 星星经过按钮数字的时候,数字+1,并有+1 的文字和星星一同飞出
  • 点击时文案变化并向左移动 整体效果很炫,星星数量增加的效果很真实,星星的运动轨迹让交互效果锦上添花。此处贴一下星星运动轨迹的代码,其他的代码涉及 threejs 绘制星星的较多,有兴趣的可查看源码。
gsap.to(object.position, {
  duration: 0.7,
  motionPath: {
    path: [
      {
        x: 0,
        y: -0.5,
      },
      {
        x: 5.45,
        y: -5,
      },
      {
        x: 10.9,
        y: -0.5,
      },
      {
        x: 7,
        y: 7,
      },
    ],
    curviness: 1.2,
  },
  ease: "sine.in",
});

删除按钮

此交互效果适用于删除逻辑,将删除的含义表述的很真实,点击删除按钮时,动画效果步骤如下:

  • 点击按钮左侧图标平移居中显示并改变图标形式,按钮文案淡出隐藏
  • 从上往下出现蓝色纸张经过碎纸机图标时变化为蓝色条形,形象化碎纸机的功能
  • 蓝色条形移出图标时下方出现打勾蓝色图标,代表执行完成

此处代码纯 CSS 实现,没有使用其他动画库,点击按钮添加一个 class 类,在 CSS 通过不同的 class 实现动画效果。以下代码简单列举其中几个属性的变化:

.delete-button {
  span {
    opacity: var(--span-opacity, 1);
    transform: translateX(var(--span-x, 0)) translateZ(0);
    transition: transform 0.4s ease var(--span-delay, 0.2s), opacity 0.3s ease
        var(--span-delay, 0.2s);
  }
  .trash {
    transform: translate(var(--trash-x, 0), var(--trash-y, 1px)) translateZ(0)
      scale(var(--trash-scale, 0.64));
  }
  /* 点击后 */
  &.delete {
    /* 文案隐藏 */
    --span-opacity: 0;
    --span-x: 16px;
    --span-delay: 0s;
    /* 图标居中显示 */
    --trash-x: 46px;
    --trash-y: 2px;
    --trash-scale: 1;
    --trash-lines-opacity: 0;
    --trash-line-scale: 0;
  }
}

点赞按钮

此交互效果适用于用户点赞的场景,主要亮点是其中的大拇指的动作,完美的诠释了真实场景中点赞的动作,整个动画步骤可拆解如下:

  • 鼠标悬停时手掌往下,大拇指按下
  • 点击按钮时,大拇指弹出,整个图标有细微向上的动画
  • 点击完成时,按钮变色,文案变更 此处实现使用点击添加 class 结合 gsap 实现,首先来看细微的大拇指动画。整个大拇指是由一个元素和一个伪元素实现,hover 样式到点击后样式改变其旋转的角度即可。
/* 未点击hover时 */
&:not(.liked) {
  &:hover {
    --hand-rotate: 8;
    --hand-thumb-1: -12deg;
    --hand-thumb-2: 36deg;
  }
}
/* 默认 */
.thumb {
  transform: scale(0.85) translateY(-0.5px) rotate(var(--hand-thumb-1, -45deg)) translateZ(
      0
    );
  &:before {
    transform: rotate(var(--hand-thumb-2, -45deg)) translateZ(0);
  }
}

这里的--hand-rotate是整个手掌的动画控制,使用 gsap 的调用方式。

gsap.fromTo(
  button,
  {
    "--hand-rotate": 8,
  },
  {
    ease: "none",
    keyframes: [
      {
        "--hand-rotate": -45,
        duration: 0.16,
        ease: "none",
      },
      {
        "--hand-rotate": 15,
        duration: 0.12,
        ease: "none",
      },
      {
        "--hand-rotate": 0,
        duration: 0.2,
        ease: "none",
        clearProps: true,
      },
    ],
  }
);

提交按钮

此交互逻辑适用商城提交订单后的效果,提交按钮后会出现包裹装车运走的动画效果,给用户的感觉就是发货速度很快,主要动画拆解为如下几个步骤:

  • 点击按钮后折叠成一个进度条
  • 进度条上方出现卡车并出现包裹装车
  • 卡车从左到右运动,进度条进度填满
  • 按钮恢复原样文案变更并增加绿色打勾

这个效果里面出现的元素较多,就一个卡车就费了不少功夫,还带有进度条的提示,因涉及到的动画步骤及细节较多,此处还是使用 gsap 实现,基于此还效果可以稍加修改为下载按钮的交互,如下图所示,只不过这里是出现卡车后掉下一个包裹,比较适用于下载的场景。

进度按钮

此交互效果适用于按钮执行时间比较长的场景,比如上传或是下载的时候,这类功能平常遇到的还是比较多的,大都是增加一个 loading 处理,但以下几个效果相信可以给你新的启发,这部分的效果较多就不详细说明了。

下面整个过程从白色背景到成功后的蓝色背景,再加上文案和图标的向上淡出淡入的动画,整个过程不回给用户很枯燥的感觉,边框,百分比及 loading 都在变化,相对是比较充实。 这个效果可能有人会说按钮元素太多了,那么看下面这个相对简洁吧,如果是上传可以改变箭头的方向,由下往上过渡完成。

最后来一个用圆环展示进度的形式,效果也是非常简洁舒服。

源码在线预览

结束

今天整体的按钮交互分享就结束了,相信看到这些效果会给在开发中带来一定的启发吧,下次再有老板或业务方说你这个效果还不够炫的时候,拿出这份效果,惊呆掉他们的下巴。但是日常前端开发都是还原设计稿,设计稿不一定如此,但是在适合的场景可以给他们参考,好的交互效果给用户的感觉是很棒的,我们实现更好的交互效果给到用户也是很棒的感觉,耶~

参考

gsap 官网

aaroniker

tin-fung-hk

- Book Lists -