Animejs-鼠标跟随赞助小爱心

498 阅读1分钟

近期在逛 animejs官网 的时候发现一个有意思的效果,一开始确实没有什么头绪,后来发现官方有提供部分 示例 ,就学着去找掉灵感咯✨~

anime-love2.gif

实现效果

知识点

.cloneNode() 节点复制

  1. 复制节点结构和属性,这里复制的就是svg小爱心节点

image.png

  1. 给复制的节点添加class样式
  2. 添加元素
const $el = /** @type {HTMLElement} */ ($icon.cloneNode(true));
$el.classList.add("icon-love");
$square.appendChild($el);

爱心跟随鼠标移动

anime-love3.gif

  1. 创建监听鼠标位置移动方法onMouseMove
  2. 创建createAnimatable动画,同步光标位置变化到小爱心.icon-love-box元素上(这里尽量避免直接控制svg标签,因为x,y的位置变化不会生效,尽量用div标签套一下) image.png
const $demo = document.body;
let bounds = $demo.getBoundingClientRect();

/**
 * 创建鼠标跟随的可动画方法createAnimatable
 * 高效地为目标属性制作动画,使其成为在值频繁更改的情况下(例如光标事件或动画循环)
 */
const animatableSquare = createAnimatable(".icon-love-box", {
  x: 500, // Define the x duration to be 500ms
  y: 500, // Define the y duration to be 500ms
  ease: "out(3)"
});

// 监听鼠标位置,square跟随鼠标位置移动
const onMouseMove = (e) => {
  const { width, height, left, top } = bounds;
  const hw = width / 2;
  const hh = height / 2;
  const x = utils.clamp(e.clientX - left - hw, -hw, hw);
  const y = utils.clamp(e.clientY - top - hh, -hh, hh);
  // 添加同步位置动画
  animatableSquare.x(x); // Animate the x value in 500ms
  animatableSquare.y(y); // Animate the y value in 500ms
};
window.addEventListener("mousemove", onMouseMove);

爱心根据鼠标位置生成

anime-love4.gif

  1. 创建createTimer定时器动画,等同于setInterval每隔多久循环loop调用一次创建动画
  2. mouseXmouseY在监听鼠标位置信息时记录的全局变量,这里用于作为创建小爱心动画的起始位置坐标
  3. .appendChild创建节点,动画执行结束后.removeChild移除节点
// 创建小爱心动画
const animateIcon = () => {
  const $el = /** @type {HTMLElement} */ ($icon.cloneNode(true));
  $el.classList.add("icon-love");
  $square.appendChild($el);
  animate($el, {
    translateY: {
      from: mouseY,
      to: mouseY + utils.random(-155, -200),
      ease: "out"
    },
    translateX: [
      {
        from: mouseX + utils.random(-10, 10),
        to: mouseX + utils.random(-40, 40),
        ease: "out"
      },
      { to: mouseX + utils.random(-40, 40), ease: "inOut(2)" }
    ],
    scale: [1, 1.2, 1, 0.1],
    opacity: [
      {
        from: 0,
        to: 1,
        ease: "out"
      },
      { to: 0, ease: "inOut(2)" }
    ],
    ease: "inOut(2)",
    duration: utils.random(500, 1000),
    delay: utils.snap(utils.random(0, 500), 30)
  }).then(() => {
    $square.removeChild($el);
  });
};
const play = () => {
  // 执行一个重复动画
  createTimer({
    loop: true,
    duration: 30,
    onLoop: animateIcon
  });
};
play();

移入移出按钮控制动画

  • 为了控制鼠标移入到按钮中时创建,移出时消失,我这里添加了hovering来判断是否在按钮中
  • loveIconMax 控制最大展示爱心的数量,避免太多导致页面卡顿
  • duration动画时间可以控制爱心生成速度
...
// 创建小爱心动画
const animateIcon = () => {
  if (!hovering) return;
  // 获取当前爱心元素图标个数,控制最多展示数量,超出不再添加
  if (utils.$(".icon-love").length > loveIconMax) return;
  ...
  animate($el, {
    ...
    ease: "inOut(2)",
    duration: utils.random(500, 1000),
    delay: utils.snap(utils.random(0, 500), 30)
  }).then(() => {
    $square.removeChild($el);
  });
};