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>
相关推荐
ttod_qzstudio3 分钟前
事件冒泡踩坑记:一个TDesign Checkbox引发的思考
前端·javascript·vue.js·tdesign
IT_陈寒6 分钟前
Vue3性能优化实战:这7个技巧让我的应用加载速度提升40%
前端·人工智能·后端
Reuuse6 分钟前
登录突然失效:Axios 拦截器判空、localStorage 脏数据与环境变量踩坑
开发语言·前端
早川不爱吃香菜6 分钟前
MCP 教程:将 Figma 设计稿转化为前端代码
前端·figma
修炼前端秘籍的小帅8 分钟前
PinMe——极简、免费和无需服务器的开源前端部署工具
前端
XXYBMOOO10 分钟前
基于 HTML5 Canvas 的终端日志流可视化实现(支持多 Pane / 运维模式)
运维·前端·html5
悟能不能悟12 分钟前
vue导出excel文件
前端·vue.js·excel
闭上眼让寒冷退却15 分钟前
知识库发布按钮引发的查询版本发布状态(轮询?——>调用后端接口)以及api接口设计学习
java·前端·javascript
sleeppingfrog19 分钟前
konva实现canvas画图基础版本
前端·javascript·css
jingling55523 分钟前
Mark3D | 用 Mars3D 实现一个炫酷的三维地图
前端·javascript·3d·前端框架·html