前端炫酷动画--图片(一)

news2025/1/21 6:17:15

目录

一、四角线框的跟随移动

二、元素倒影(-webkit-box-reflect)

三、模特换装(mask+blend)

四、元素平滑上升

五、无限视差滚动

六、判断鼠标进入方向(轮播方向)

七、环形旋转效果

八、黑白小球交替旋转

九、hover时圆形放大

十、画一棵随机树(canvas)

十一、代码雨效果(canvas)

一、四角线框的跟随移动

    <style>
      body {
        background: black;
      }
      .container {
        width: 400px;
        height: 40vh;
        position: relative;
        display: grid; /* 使用 Grid 布局 */
        grid-template-columns: repeat(2, 1fr); /* 设置两列 */
        grid-gap: 20px; /* 设置网格项之间的间距 */
        justify-items: center;
        align-items: center;
        margin: 20px;
      }
      .pointer {
        position: absolute;
        --l: 30px; /* 长度 */
        --g: 15px; /* 间隔 */
        --t: 3px; /* 粗细 */
        --s: 394px; /* 框住的大小 */
        --x: 0px;
        --y: 0px;
        width: calc(var(--s) + var(--g) * 2);
        height: calc(var(--s) + var(--g) * 2);
        border: var(--t) solid #fff;
        left: calc(var(--x) - var(--g));
        top: calc(var(--y) - var(--g));
        transition: 0.5s;
        /* 圆锥渐变(conic-gradient)作为遮罩效果 */
        -webkit-mask: conic-gradient(
            at var(--l) var(--l),
            transparent 75%,
            red 75%
          )
          0 0 / calc(100% - var(--l)) calc(100% - var(--l));
      }
    </style>
  <body>
    <div class="container">
      <div class="pointer"></div>
      <div class="item">
        <img src="https://picsum.photos/id/371/400/400" alt="" />
      </div>
      <div class="item">
        <img src="https://picsum.photos/id/372/400/400" alt="" />
      </div>
      <div class="item">
        <img src="https://picsum.photos/id/374/400/400" alt="" />
      </div>
      <div class="item">
        <img src="https://picsum.photos/id/376/400/400" alt="" />
      </div>
    </div>
    <script>
      const imgs = document.querySelectorAll(".container img");
      const pointer = document.querySelector(".pointer");
      for (const img of imgs) {
        img.onmouseenter = () => {
          pointer.style.setProperty("--x", img.offsetLeft + "px");
          pointer.style.setProperty("--y", img.offsetTop + "px");
          pointer.style.setProperty("--s", img.offsetWidth + "px");
        };
      }
    </script>
  </body>

二、元素倒影(-webkit-box-reflect)

      .card {
        box-shadow: 0 0 8px #fff;
        width: 200px;
        -webkit-box-reflect: below 15px
          linear-gradient(transparent, transparent, #0005);
      }

三、模特换装(mask+blend)

前提:准备一张白色完整图片和要换装的衣服块图片,后期再混合

    <style>
      .card {
        width: 300px;
        height: 500px;
        position: relative;
      }
      .source {
        display: block;
        width: 100%;
        height: 100%;
        object-fit: cover;
      }
      .skirt {
        position: absolute;
        inset: 0; /*等同于 left:0;top:0;bottom: 0;right: 0; */
        background:red;
        --mask:url(./partImg.png) 50% 50% / cover;
        /* 将用蒙版将衣服块“染成”背景色 */
        mask:var(--mask);
        -webkit-mask:var(--mask);
        /* 混合衣服块和背景色 */
        mix-blend-mode: multiply;
      }
    </style>
  <body>
    <div class="card">
      <img src="./whiteImg.png" alt="" class="source" />
      <div class="skirt"></div>
    </div>
  </body>

四、元素平滑上升

// useSlideIn.js
const DISTANCE = 150;
const DURATION = 500;
const map = new WeakMap();
const ob = new IntersectionObserver((entries) => {
  for (const entry of entries) {
    if (entry.isIntersecting) {
      // 该元素和视口相交 播放该元素的动画
      const animation = map.get(entry.target);
      if (animation) {
        animation.play();
        ob.unobserve(entry.target); // 播放一次,取消观察
      }
    }
  }
});
function isBelowViewport(el) {
  const rect = el.getBoundingClientRect();
  return rect.top - DISTANCE > window.innerHeight;
}
export default {
  mounted(el) {
    if (!isBelowViewport(el)) {
      return;
    }
    const animation = el.animate(
      [
        {
          transform: `translateY(${DISTANCE}px)`,
          opacity: 0.5
        },
        {
          transform: 'translateY(0)',
          opacity: 1
        }
      ],
      {
        duration: DURATION,
        easing: 'ease-in-out',
        fill: 'forwards'
      }
    );
    animation.pause();
    ob.observe(el);
    map.set(el, animation);
  },
  unmounted(el) {
    ob.unobserve(el);
  }
};
<template>
  <div>
    <div v-slide-in class="item" v-for="n in 10" :key="n">{
  
  { n }}BOX</div>
  </div>
</template>
<script>
import slideIn from './useSlideIn';
export default {
  directives: {
    'slide-in': slideIn
  },
};
</script>

五、无限视差滚动

  <style>
    .scroll-container {
      display: flex;
      overflow: hidden;
      position: relative;
      height: 400px; /* 设置容器高度 */
    }
    .item {
      position: absolute;
      width: 100%;
      height: 100%;
      transition: transform 0.5s ease;
    }
    .item img {
      width: 100%;
      height: 100%;
      object-fit: cover;
    }
    .scroll-down .cur {
      transform: translateY(100%);
    }
    .scroll-up .cur {
      transform: translateY(-100%);
    }
  </style>
<body>
  <div class="scroll-container"></div>
  <script>
    const imgs = [
      "https://picsum.photos/id/376/800/800",
      "https://picsum.photos/id/372/800/800",
      "https://picsum.photos/id/373/800/800",
      "https://picsum.photos/id/374/800/800",
      "https://picsum.photos/id/375/800/800"
    ];
    const container = document.querySelector(".scroll-container");
    let curIndex = 0;
    function getPrevIndex() {
      return curIndex === 0 ? imgs.length - 1 : curIndex - 1;
    }
    function getNextIndex() {
      return curIndex === imgs.length - 1 ? 0 : curIndex + 1;
    }
    function createElement(i) {
      const div = document.createElement("div");
      div.className = "item";
      const img = document.createElement("img");
      img.src = imgs[i];
      div.appendChild(img);
      container.appendChild(div);
      return div;
    }
    function resetElements() {
      container.innerHTML = "";
      const prevIndex = getPrevIndex();
      const nextIndex = getNextIndex();
      createElement(prevIndex).classList.add("prev");
      const curItem = createElement(curIndex);
      curItem.classList.add("cur");
      createElement(nextIndex).classList.add("next");
    }
    resetElements();
    let isAnimation = false;
    window.addEventListener("wheel", (e) => {
      if (!e.deltaY || isAnimation) {
        return;
      }
      isAnimation = true;
      if (e.deltaY > 0) {
        curIndex = getNextIndex();
        container.classList.add("scroll-down");
      } else {
        curIndex = getPrevIndex();
        container.classList.add("scroll-up");
      }
    });
    container.addEventListener("transitionend", () => {
      container.classList.remove("scroll-down");
      container.classList.remove("scroll-up");
      isAnimation = false;
      resetElements();
    });
  </script>
</body>

六、判断鼠标进入方向(轮播方向)

    <script>
      const container = document.querySelector(".container");
      const rect = container.getBoundingClientRect();
      const theta = Math.atan2(rect.height, rect.width);
      container.addEventListener("mouseenter", (e) => {
        const x = e.offsetX - rect.width / 2;
        const y = rect.height / 2 - e.offsetY;
        const d = Math.atan2(y, x);
        if (d < theta && d >= -theta) {
          container.classList.add("right");
        } else if (d >= theta && d < Math.PI - theta) {
          container.classList.add("top");
        } else if (d >= Math.PI - theta || d < -(Math.PI - theta)) {
          container.classList.add("left");
        } else {
          container.classList.add("bottom");
        }
      });
      container.addEventListener("mouseleave", () => {
        container.className = "container";
      });
    </script>

七、环形旋转效果

$size: 300px;
$imgSize: 80px;
.container {
  width: $size;
  height: $size;
  outline: 1px solid #000;
  margin: 0 auto;
  position: relative;
  margin-top: 60px;
  display: flex;
  justify-content: center;
  align-items: start;
  border-radius: 50%;
  animation: rotation 20s linear infinite;
  @keyframes rotation {
    to {
      transform: rotate(calc(360deg - var(--initDeg, 0deg)));
    }
  }
  .item {
    width: $imgSize;
    height: $imgSize;
    position: absolute;
    margin-top: -40px;
    img {
      width: 100%;
      height: 100%;
      object-fit: cover;
      border-radius: 50%;
    }
  }
}
$n: 5;
$pDeg: 360deg / $n;
.item {
  transform-origin: center $size / 2 + $imgSize / 2;
  @for $i from 1 through $n {
    $deg: $pDeg * ($i - 1);
    &:nth-child(#{$i}) {
      transform: rotate($deg);
      img {
        --initDeg:#{$deg};
        transform: rotate(-$deg); //将歪斜的图片矫正
        animation: rotation 20s linear infinite reverse;
      }
    }
  }
}

八、黑白小球交替旋转

  <div class="loading">
    <!-- 快捷键:div.dot*36 -->
  </div>
body {
  background: #66c7f4;
}
$ballSize: 10px; //小球尺寸
$containerSize: 150px; //容器尺寸
$n: 36;
$pDeg: 360deg / $n;
$d:2s;
.loading {
  width: $containerSize;
  height: $containerSize;
  margin: 50px auto;
  position: relative;
  border-radius: 50%;
  // outline: 1px solid #fff;
}
.dot {
  position: absolute;
  left: 50%;
  top: 0;
  width: $ballSize;
  height: $ballSize;
  margin-left: -$ballSize / 2;
  margin-top: -$ballSize / 2;
  perspective: 70px;
  // background: #f40;
  transform-origin: center $containerSize / 2 + $ballSize / 2;
  perspective: 70px;
  transform-style: preserve-3d;
  @for $i from 1 through $n {
    &:nth-child(#{$i}) {
      transform: rotate($pDeg * ($i - 1));
      &::before,
      &::after {
        animation-delay: -$d / $n * ($i - 1) * 6;
      }
    }
    &::before,
    &::after {
      content: "";
      position: absolute;
      width: 100%;
      height: 100%;
      border-radius: 50%;
    }
    &::before {
      background: #000;
      top: -100%;
      animation: rotation-black $d infinite;
      @keyframes rotation-black {
        0% {
          animation-timing-function: ease-in;
        }
        25% {
          transform: translate3d(0, 100%, $ballSize);
          animation-timing-function: ease-out;
        }
        50% {
          transform: translate3d(0, 200%, 0);
          animation-timing-function: ease-in;
        }
        75% {
          transform: translate3d(0, 100%, -$ballSize);
          animation-timing-function: ease-out;
        }
      }
    }
    &::after {
      background: #fff;
      top: 100%;
      animation: rotation-white $d infinite;
      @keyframes rotation-white {
        0% {
          animation-timing-function: ease-in;
        }
        25% {
          transform: translate3d(0, -100%, -$ballSize);
          animation-timing-function: ease-out;
        }
        50% {
          transform: translate3d(0, -200%, 0);
          animation-timing-function: ease-in;
        }
        75% {
          transform: translate3d(0, -100%, $ballSize);
          animation-timing-function: ease-out;
        }
      }
    }
  }
}

九、hover时圆形放大

    <style>
      .avatar {
        width: 200px;
        height: 200px;
        border-radius: 50%;
        background: url("./qiang.jpg");
        cursor: pointer;
        position: relative;
      }
      .avatar::before,
      .avatar::after {
        content: "";
        position: absolute;
        inset: 0;
        border-radius: 50%;
      }
      .avatar::before {
        background: rgba(0, 0, 0, 0.5);
      }
      .avatar::after {
        background: inherit; /* 继承自父元素 */
        clip-path: circle(0% at 50% 50%);
        transition: .3s;
      }
      .avatar:hover::after {
        clip-path: circle(50% at 50% 50%);
      }
    </style>
  <body>
    <div class="avatar"></div>
  </body>

十、画一棵随机树(canvas)

  <body>
    <canvas id="bg"></canvas>
    <script>
      const cvs = document.getElementById("bg");
      const ctx = cvs.getContext("2d");
      cvs.width = window.innerWidth;
      cvs.height = window.innerHeight;
      // 更改坐标原点
      ctx.translate(cvs.width / 2, cvs.height);
      ctx.scale(1, -1);
      // 画树干
      drawBranch([0, 0], 200, 30, 90);
      function drawBranch(v0, length, thick, dir) {
        if (thick < 10 && Math.random() < 0.3) {
          return;
        }
        if (thick < 2) {
          ctx.beginPath();
          ctx.arc(...v0, 10, 0, 2 * Math.PI);
          ctx.fillStyle = "red";
          ctx.fill();
          return;
        }
        ctx.beginPath();
        ctx.moveTo(...v0);
        const v1 = [
          v0[0] + length * Math.cos((dir * Math.PI) / 180),
          v0[1] + length * Math.sin((dir * Math.PI) / 180),
        ];
        ctx.lineTo(...v1);
        ctx.lineWidth = thick;
        ctx.fillStyle = "#333";
        ctx.lineCap = "round";
        ctx.stroke();
        // 递归调用画左右两边的树枝
        drawBranch(v1, length * 0.8, thick * 0.8, dir + Math.random() * 30);
        drawBranch(v1, length * 0.8, thick * 0.8, dir - Math.random() * 30);
      }
    </script>
  </body>

十一、代码雨效果(canvas)

  <body>
    <canvas id="bg"></canvas>
    <script>
      const cvs = document.getElementById("bg");
      const width = window.innerWidth * devicePixelRatio,
        height = window.innerHeight * devicePixelRatio;
      // 设置canvas尺寸为窗口尺寸
      cvs.width = width;
      cvs.height = height;
      const ctx = cvs.getContext("2d");
      const fontSize = 20 * devicePixelRatio;
      const columnWidth = fontSize; //列宽
      const columnCount = Math.floor(width / columnWidth); //列的数量
      const nextChar = new Array(columnCount).fill(0); //每列下一个文字是第几个文字
      // 获取随机颜色 (HEX 格式)
      function getRandomColor() {
        const r = Math.floor(Math.random() * 256);
        const g = Math.floor(Math.random() * 256);
        const b = Math.floor(Math.random() * 256);
        // 将每个颜色分量转换为两位的十六进制格式,并拼接成 HEX 颜色值
        return `#${((1 << 24) | (r << 16) | (g << 8) | b)
          .toString(16)
          .slice(1)
          .toUpperCase()}`;
      }
      // 获取随机字符
      function getRandomChar() {
        const chars =
          "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
        const randomIndex = Math.floor(Math.random() * chars.length);
        return chars[randomIndex];
      }
      function draw() {
        ctx.fillStyle = "rgba(0,0,0,0.1)";
        ctx.fillRect(0, 0, width, height);
        for (let i = 0; i < columnCount; i++) {
          const char = getRandomChar();
          ctx.fillStyle ='green';//赋值为getRandomColor()就是随机彩色
          ctx.font = `${fontSize}px "Roboto Mono"`;
          const x = columnWidth * i;
          const index = nextChar[i];
          const y = (index + 1) * fontSize;
          ctx.fillText(char, x, y);
          if (y > height && Math.random() > 0.99) {
            nextChar[i] = 0;
          } else {
            nextChar[i]++;
          }
        }
      }
      draw();
      setInterval(draw, 40);
    </script>
  </body>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2279677.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

AI刷题-病毒在封闭空间中的传播时间

目录 问题描述 输入格式 输出格式 解题思路&#xff1a; 问题理解 数据结构选择 算法步骤 代码实现&#xff1a; 1.初始化&#xff1a; 2.设置边界条件&#xff1a; 3.判断 4.更新&#xff1a; 5.返回 最终的实现代码如下&#xff1a; 运行结果&#xff1a; …

SQL表间关联查询详解

简介 本文主要讲解SQL语句中常用的表间关联查询方式&#xff0c;包括&#xff1a;左连接&#xff08;left join&#xff09;、右连接&#xff08;right join&#xff09;、全连接&#xff08;full join&#xff09;、内连接&#xff08;inner join&#xff09;、交叉连接&…

路由器旁挂三层网络实现SDWAN互联(爱快SD-WAN)

近期因公司新办公区建设&#xff0c;原有的爱快路由器的SDWAN功能实现分支之间互联的服务还需要继续使用。在原有的小型网络中&#xff0c;使用的爱快路由器当作网关设备&#xff0c;所以使用较为简单,如下图所示。 现变更网络拓扑为三层网络架构&#xff0c;但原有的SDWAN分支…

麦田物语学习笔记:制作[SceneName]Attribute特性

基本流程 因为在现有的项目中,像开始场景的切换或者Telepot组件都需要手动输入场景名,有时还可能键入出错,而该特性能用选择的方式去解决这一问题 1.代码实现 SceneNameDrawer.cs //参数绘制 using UnityEditor; using UnityEngine; #if UNITY_EDITOR [CustomPropertyDrawer(…

HTML之拜年/跨年APP(改进版)

目录&#xff1a; 一&#xff1a;目录 二&#xff1a;效果 三&#xff1a;页面分析/开发逻辑 1.页面详细分析&#xff1a; 2.开发逻辑&#xff1a; 四&#xff1a;完整代码&#xff08;不多废话&#xff09; index.html部分 app.json部分 二&#xff1a;效果 三&#xff1a;页面…

【2024 年度总结】从小白慢慢成长

【2024 年度总结】从小白慢慢成长 1. 加入 CSDN 的契机2. 学习过程2.1 万事开头难2.2 下定决心开始学习2.3 融入技术圈2.4 完成万粉的目标 3. 经验分享3.1 工具的选择3.2 如何提升文章质量3.3 学会善用 AI 工具 4. 保持初心&#xff0c;继续前行 1. 加入 CSDN 的契机 首次接触…

一文大白话讲清楚webpack基本使用——2——css相关loader的配置和使用

一文大白话讲清楚webpack基本使用——2——css相关loader的配置和使用 1. 建议按文章顺序从头看是看 第一篇&#xff1a;一文大白话讲清楚啥是个webpack第二篇&#xff1a;一文大白话讲清楚webpack基本使用——1——完成webpack的初步构建然后看本篇&#xff0c;Loader的配置…

如何将 session 共享存储到 redis 中

文章目录 一. 分布式 session 登录1.1 什么是分布式&#xff1f;1.2 Session 共享1.3 为什么服务器 A 登录后&#xff0c;请求发到服务器 B&#xff0c;不认识该用户&#xff1f;1.4 共享存储 二. Session 共享实现Redis三. 测试session共享四. cookie设置4.1 前端4.2 后端 一.…

Debezium日常分享系列之:对于从Oracle数据库进行快照的性能优化

Debezium日常分享系列之&#xff1a;对于从Oracle数据库进行快照的性能优化 源数据库Kafka Connect监控测试结果 源数据库 Oracle 19c&#xff0c;本地&#xff0c;CDB数据库主机的I/O带宽为6 GB/s&#xff0c;由此主机上运行的所有数据库共享临时表空间由42个文件组成&#x…

STM32 FreeROTS Tickless低功耗模式

低功耗模式简介 FreeRTOS 的 Tickless 模式是一种特殊的运行模式&#xff0c;用于最小化系统的时钟中断频率&#xff0c;以降低功耗。在 Tickless 模式下&#xff0c;系统只在有需要时才会启动时钟中断&#xff0c;而在无任务要运行时则完全进入休眠状态&#xff0c;从而降低功…

Redis - General - 未授权访问漏洞(用户配置问题)

0x01&#xff1a;产品简介 Redis&#xff08;Remote Dictionary Service&#xff0c;远程数据服务&#xff09;&#xff0c;是一款开源的基于内存的键值对存储系统&#xff0c;其主要被用作高性能缓存服务器使用&#xff08;比如作为消息中间件和用于 Session 共享&#xff09…

学习threejs,使用OrbitControls相机控制器

&#x1f468;‍⚕️ 主页&#xff1a; gis分享者 &#x1f468;‍⚕️ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕️ 收录于专栏&#xff1a;threejs gis工程师 文章目录 一、&#x1f340;前言1.1 ☘️THREE.OrbitControls 相机控…

SQL和MySQL以及DAX的日期表生成?数字型日期?将生成的日期表插入到临时表或者实体表中

几种生成日期表的方法 如何用SQL语句生成日期表呢&#xff1f; 如何用MySQL语句生成日期表呢&#xff1f; 如何用DAX语句生成日期表呢&#xff1f; 1. MySQL生成日期表 1.1 日期格式&#xff1a;yyyy-MM-dd 字符型 2024-01-02 -- 生成日期表 WITH RECURSIVE temp_dateTable …

C# 动态创建Label和ComboBox控件并修改Text

背景&#xff1a;在做项目的时候可能需要根据一定数量创建某些控件并修改其属性&#xff0c;本文以控件label、ConboBox控件进行动态创建。 程序运行前后的的Form动态图 代码如下&#xff1a; using System; using System.Collections.Generic; using System.ComponentModel; …

2025年编程语言热度分析:Python领跑,Go与Rust崛起

TIOBE Index&#xff08;TIOBE 编程语言指数&#xff09;是一个衡量编程语言流行度的排名系统。它通过分析多种搜索引擎、在线编程社区、技术论坛、问答网站&#xff08;如 Google、Bing、Yahoo、Wikipedia、Stack Overflow&#xff09;等的搜索和讨论数据&#xff0c;评估不同…

【从零开始入门unity游戏开发之——C#篇46】C#补充知识点——命名参数和可选参数

考虑到每个人基础可能不一样&#xff0c;且并不是所有人都有同时做2D、3D开发的需求&#xff0c;所以我把 【零基础入门unity游戏开发】 分为成了C#篇、unity通用篇、unity3D篇、unity2D篇。 【C#篇】&#xff1a;主要讲解C#的基础语法&#xff0c;包括变量、数据类型、运算符、…

python学opencv|读取图像(三十九 )阈值处理Otsu方法

【1】引言 前序学习了5种阈值处理方法&#xff0c;包括(反)阈值处理、(反)零值处理和截断处理&#xff0c;还学习了一种自适应处理方法&#xff0c;相关文章链接为&#xff1a; python学opencv|读取图像&#xff08;三十三&#xff09;阈值处理-灰度图像-CSDN博客 python学o…

【Idea】编译Spring源码 read timeout 问题

Idea现在是大家工作中用的比较多的开发工具&#xff0c;尤其是做java开发的&#xff0c;那么做java开发&#xff0c;了解spring框架源码是提高自己技能水平的一个方式&#xff0c;所以会从spring 官网下载源码&#xff0c;导入到 Idea 工具并编译&#xff0c;但是发现build的时…

macOS安装Gradle环境

文章目录 说明安装JDK安装Gradle 说明 gradle8.5最高支持jdk21&#xff0c;如果使用jdk22建议使用gradle8.8以上版本 安装JDK mac系统安装最新&#xff08;截止2024.9.13&#xff09;Oracle JDK操作记录 安装Gradle 下载Gradle&#xff0c;解压将其存放到资源java/env目录…

VMware Workstation Pro 17免费开放,再也不用到处找license了

VMware Workstation Pro 17免费开放啦 VMware Workstation Pro 17.6.2 版本介绍一、免费开放二、性能与稳定性提升三、重要问题修复1. Linux 快照崩溃问题解决2. Windows 11 主机优化3. Linux 内核兼容性增强 四、功能亮点1. 全新的性能优化2. 稳定性和可靠性增强3. 更友好的用…