HTML视口动画

animista.js

复制代码
const getParamet = {
  getAnimistaClass(element) {
    return element.getAttribute("animista-class");
  },
  getIntervalTime(element) {
    return element.getAttribute("interval-time")
      ? Number(element.getAttribute("interval-time"))
      : null;
  },
  getBeforeTime(element) {
    return element.getAttribute("before-time")
      ? Number(element.getAttribute("before-time"))
      : null;
  },
  getTime(element) {
    return element.getAttribute("time")
      ? Number(element.getAttribute("time"))
      : null;
  },
};
class AnimistaParamet {
  animistaClass = null;
  intervalTime = null;
  beforeTime = null;
  time = null;
  constructor(parentElement, resetAnimistaParamet) {
    if (!resetAnimistaParamet) resetAnimistaParamet = {};
    if (!(parentElement instanceof Element))
      throw new Error("parentElement not is Element");
    this.animistaClass =
      getParamet.getAnimistaClass(parentElement) ||
      resetAnimistaParamet.animistaClass ||
      "";
    this.intervalTime =
      getParamet.getIntervalTime(parentElement) ||
      resetAnimistaParamet.intervalTime;
    this.beforeTime =
      getParamet.getBeforeTime(parentElement) ||
      resetAnimistaParamet.beforeTime;
    this.time = getParamet.getTime(parentElement);
  }
}

const getParentAnimistaParamet = (parentElement) => {
  const parentParamet = new AnimistaParamet(parentElement);
  return parentParamet;
};

const getParentAnimista = (parentElement, parentParamet) => {
  let time = parentParamet.beforeTime || 0;
  const childElements = parentElement.children;
  const childrenElementParamet = [];
  for (let i = 0; i < childElements.length; i++) {
    const itemElement = childElements[i];
    const itemParamet = new AnimistaParamet(itemElement, parentParamet);
    itemParamet.time =
      itemParamet.time === null
        ? time + i * itemParamet.intervalTime + (itemParamet.beforeTime || 0)
        : itemParamet.time;
    childrenElementParamet.push({
      itemElement,
      itemParamet,
    });
  }
  return childrenElementParamet;
};

const setParentAnimista = (childrenElementParamet) => {
  childrenElementParamet.forEach((item) => {
    setTimeout(() => {
      item.itemParamet.animistaClass &&
        item.itemElement.classList.add(item.itemParamet.animistaClass);
      item.itemElement.classList.remove("hide");
    }, item.itemParamet.time);
  });
};
const targets = document.querySelectorAll(".animista_box");
const parentAnimistaParametMap = new Map();
targets.forEach((item) => {
  parentAnimistaParametMap.set(item.id, getParentAnimistaParamet(item));
  item.classList.add("hide");
});
if ("IntersectionObserver" in window) {
  const observer = new IntersectionObserver(
    (entries) => {
      entries.forEach((entry) => {
        if (entry.isIntersecting) {
          const parentAnimistaParamet = parentAnimistaParametMap.get(
            entry.target.id
          );
          if (!parentAnimistaParamet) return;

          const parentAnimista = getParentAnimista(
            entry.target,
            parentAnimistaParamet
          );
          setParentAnimista(parentAnimista);
        } else {
        }
      });
    },
    {
      root: null,
      rootMargin: "0px",
      threshold: 0.1,
    }
  );
  targets.forEach((target) => {
    observer.observe(target);
  });
} else {
  console.log("浏览器不支持 Intersection Observer");
}

animista.css

复制代码
/* ----------------------------------------------
 * Generated by Animista on 2025-2-19 18:25:51
 * Licensed under FreeBSD License.
 * See http://animista.net/license for more info. 
 * w: http://animista.net, t: @cssanimista
 * ---------------------------------------------- */

/**
 * ----------------------------------------
 * animation slide-in-blurred-left
 * ----------------------------------------
 */
@-webkit-keyframes slide-in-blurred-left {
  0% {
    -webkit-transform: translateX(-1000px) scaleX(2.5) scaleY(0.2);
    transform: translateX(-1000px) scaleX(2.5) scaleY(0.2);
    -webkit-transform-origin: 100% 50%;
    transform-origin: 100% 50%;
    -webkit-filter: blur(40px);
    filter: blur(40px);
    opacity: 0;
  }
  100% {
    -webkit-transform: translateX(0) scaleY(1) scaleX(1);
    transform: translateX(0) scaleY(1) scaleX(1);
    -webkit-transform-origin: 50% 50%;
    transform-origin: 50% 50%;
    -webkit-filter: blur(0);
    filter: blur(0);
    opacity: 1;
  }
}
@keyframes slide-in-blurred-left {
  0% {
    -webkit-transform: translateX(-1000px) scaleX(2.5) scaleY(0.2);
    transform: translateX(-1000px) scaleX(2.5) scaleY(0.2);
    -webkit-transform-origin: 100% 50%;
    transform-origin: 100% 50%;
    -webkit-filter: blur(40px);
    filter: blur(40px);
    opacity: 0;
  }
  100% {
    -webkit-transform: translateX(0) scaleY(1) scaleX(1);
    transform: translateX(0) scaleY(1) scaleX(1);
    -webkit-transform-origin: 50% 50%;
    transform-origin: 50% 50%;
    -webkit-filter: blur(0);
    filter: blur(0);
    opacity: 1;
  }
}
.slide-in-blurred-left {
  -webkit-animation: slide-in-blurred-left 0.6s
    cubic-bezier(0.165, 0.84, 0.44, 1) both;
  animation: slide-in-blurred-left 0.6s cubic-bezier(0.165, 0.84, 0.44, 1) both;
}
/* ----------------------------------------------
 * Generated by Animista on 2025-2-19 18:28:1
 * Licensed under FreeBSD License.
 * See http://animista.net/license for more info. 
 * w: http://animista.net, t: @cssanimista
 * ---------------------------------------------- */

/**
 * ----------------------------------------
 * animation slide-in-blurred-bottom
 * ----------------------------------------
 */
@-webkit-keyframes slide-in-blurred-bottom {
  0% {
    -webkit-transform: translateY(1000px) scaleY(2.5) scaleX(0.2);
    transform: translateY(1000px) scaleY(2.5) scaleX(0.2);
    -webkit-transform-origin: 50% 100%;
    transform-origin: 50% 100%;
    -webkit-filter: blur(40px);
    filter: blur(40px);
    opacity: 0;
  }
  100% {
    -webkit-transform: translateY(0) scaleY(1) scaleX(1);
    transform: translateY(0) scaleY(1) scaleX(1);
    -webkit-transform-origin: 50% 50%;
    transform-origin: 50% 50%;
    -webkit-filter: blur(0);
    filter: blur(0);
    opacity: 1;
  }
}
@keyframes slide-in-blurred-bottom {
  0% {
    -webkit-transform: translateY(1000px) scaleY(2.5) scaleX(0.2);
    transform: translateY(1000px) scaleY(2.5) scaleX(0.2);
    -webkit-transform-origin: 50% 100%;
    transform-origin: 50% 100%;
    -webkit-filter: blur(40px);
    filter: blur(40px);
    opacity: 0;
  }
  100% {
    -webkit-transform: translateY(0) scaleY(1) scaleX(1);
    transform: translateY(0) scaleY(1) scaleX(1);
    -webkit-transform-origin: 50% 50%;
    transform-origin: 50% 50%;
    -webkit-filter: blur(0);
    filter: blur(0);
    opacity: 1;
  }
}
.slide-in-blurred-bottom {
  -webkit-animation: slide-in-blurred-bottom 0.6s cubic-bezier(0.23, 1, 0.32, 1)
    both;
  animation: slide-in-blurred-bottom 0.6s cubic-bezier(0.23, 1, 0.32, 1) both;
}

html

bash 复制代码
 <div animista-class="slide-in-blurred-left" interval-time="100" class="animista_box">
 </div>
相关推荐
梦帮科技7 分钟前
GRAVIS v4.0:基于Web的极速套利架构设计与实时数据流实现
前端·人工智能·rust·自动化·区块链·智能合约·数字货币
爱勇宝38 分钟前
办公资料反复修改、补传、交接混乱,我做了个桌面工具来解决这件事
前端·后端·程序员
微信开发api-视频号协议1 小时前
企业微信外部群开发自动化实践过程
java·前端·微信·自动化·企业微信·ipad
甲维斯1 小时前
Fable5:20美金的顶级设计师!
前端·人工智能
kyriewen2 小时前
我同时用了 Claude Code、Cursor 和 Codex,说说三个工具的真实差距——2026 年选错工具比不用 AI 更浪费时间
前端·ai编程·claude
Jackson__2 小时前
为了拯救我的腰椎和颈椎,我做了款浏览器插件!
前端·javascript·开源
闲猫2 小时前
Python FastAPI + SQLAlchemy 入门教程:从零搭建你的第一个 Web 应用
前端·python·fastapi
林小帅3 小时前
NestJS v11 + Prisma v7 ESM 迁移配置解析
前端·javascript·后端
IT_陈寒3 小时前
React的setState竟然不是立刻生效的,害我调试半天
前端·人工智能·后端
简简单单就是我_hehe3 小时前
前端埋点日志解决方案:完整 User-Agent 解析工具实现,爬虫识别、设备品牌、操作系统、浏览器版本全解析(附完整源码)
前端·爬虫