好看的css星星效果边框

给客户做的动效图,结果应证了还是第一版的好,不忍舍弃,放这里,喜欢的人自取;

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Particle Star Border Demo</title>
  <style>
    body, html {
      background-color: #cccccc;
    }

    .item-container {
      position: relative;
      width: 300px;
      height: 150px;
      margin: 50px auto;
      border-radius: 16px;
      padding: 10px;
    }

    .item-border-canvas {
      position: absolute;
      inset: 0;
      width: 100%;
      height: 100%;
      z-index: 9;
      pointer-events: none;
      border-radius: 10px;
    }

    .item-content-canvas {
      position: relative;
      z-index: 1;
      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
      background: linear-gradient(to bottom, #fff8e1, #fff0c2);
      border-radius: 10px;
      width: 100%;
      height: 100%;
      display: flex;
      justify-content: center;
      align-items: center;
      font-size: 24px;
      font-weight: bold;
      color: #ff9900;
    }
  </style>
</head>
<body>

<div class="item-container">
  <canvas id="borderCanvas" class="item-border-canvas"></canvas>
  <div class="item-content-canvas">
    ✨布灵布灵的星星✨
  </div>
</div>

<script>
(function () {
  const show = true; // 控制是否显示星星边框
  if (!show) return;

  const canvas = document.getElementById("borderCanvas");
  const ctx = canvas.getContext("2d");
  const offset = 15;
  let w, h, perimeter;
  let stars = [];
  let animationId;

  function initCanvas() {
    canvas.width = canvas.clientWidth;
    canvas.height = canvas.clientHeight;
    w = canvas.width;
    h = canvas.height;
    perimeter = 2 * (w + h);
    initStars();
  }

  function initStars() {
    stars = [];
    for (let i = 0; i < 40; i++) {
      stars.push({
        distance: Math.random() * perimeter,
        speed: 0.07 + Math.random() * 0.06,
        flickerPhase: Math.random() * Math.PI * 2,
        flickerSpeed: 0.006 + Math.random() * 0.009,
        maxSize: 10 + Math.random() * 5,
        rotate: Math.random() * Math.PI * 2,
      });
    }
  }

  function getPointOnPerimeter(distance) {
    let d = distance % perimeter;
    if (d < w) return { x: d, y: offset };
    d -= w;
    if (d < h) return { x: w - offset, y: d };
    d -= h;
    if (d < w) return { x: w - d, y: h - offset };
    return { x: offset, y: h - (d - w) };
  }

  function pulse(t) {
    return Math.pow(Math.sin(t), 4);
  }

  function drawStar(ctx, cx, cy, spikes, outerRadius, innerRadius, alpha, rotation) {
    let rot = rotation - Math.PI / 2;
    const step = Math.PI / spikes;
    ctx.beginPath();
    ctx.moveTo(cx + Math.cos(rot) * outerRadius, cy + Math.sin(rot) * outerRadius);

    for (let i = 0; i < spikes; i++) {
      rot += step;
      ctx.lineTo(cx + Math.cos(rot) * innerRadius, cy + Math.sin(rot) * innerRadius);
      rot += step;
      ctx.lineTo(cx + Math.cos(rot) * outerRadius, cy + Math.sin(rot) * outerRadius);
    }

    ctx.closePath();
    const r = Math.floor(220 + 35 * alpha);
    const g = Math.floor(190 + 50 * alpha);
    const b = Math.floor(60 + 30 * alpha);
    ctx.fillStyle = `rgba(${r},${g},${b},0.95)`;
    ctx.shadowBlur = 12;
    ctx.shadowColor = `rgba(${r},${g},${b},0.6)`;
    ctx.fill();

    if (alpha > 0.9) {
      ctx.beginPath();
      ctx.arc(cx, cy, outerRadius / 2, 0, 2 * Math.PI);
      ctx.fillStyle = `rgba(255, 245, 200, ${alpha * 0.7})`;
      ctx.fill();
    }
  }

  function animate() {
    ctx.clearRect(0, 0, w, h);
    stars.forEach(star => {
      star.distance += star.speed;
      const pos = getPointOnPerimeter(star.distance);
      const flicker = pulse(star.flickerPhase % (Math.PI * 2));
      const size = flicker * star.maxSize;
      drawStar(ctx, pos.x, pos.y, 5, size, size / 2, flicker, star.rotate);
      star.flickerPhase += star.flickerSpeed;
    });
    animationId = requestAnimationFrame(animate);
  }

  window.addEventListener("resize", () => {
    initCanvas();
  });

  initCanvas();
  animate();
})();
</script>
</body>
</html>
相关推荐
泯泷13 小时前
手搓JSVMM第 8 篇:函数调用:参数、返回值与调用帧
前端·javascript·前端框架
Sherotree13 小时前
Google Antigravity——Agent 被提到主界面
前端·ide·后端·edge浏览器
Mr数据杨13 小时前
【Codex】用学生入学评估模块建立新生能力画像
android·java·javascript·django·codex·项目开发
里欧跑得慢14 小时前
Flutter 像素级还原:设计稿到代码的视觉无损转换技巧
前端·css·flutter·web
里欧跑得慢14 小时前
Flutter 三方库 function_tree — 鸿蒙应用开发中的动态数学公式解析与计算神器,实现鸿蒙深度适配下的复杂函数逻辑运行时求值实战(适配鸿蒙 HarmonyOS Next ohos)
android·前端·安全·flutter·华为·harmonyos
苏灿烤鱼14 小时前
没有机密文件,也没有付费数据,在浏览器里造一颗"间谍卫星"
前端·javascript·github
泯泷15 小时前
手搓JSVM第 5 篇:写第一个编译器:从 AST 生成 IR
前端·javascript·算法
泯泷15 小时前
手搓JSVM第 7 篇:控制流:if、while 与 jump
前端·javascript·算法
泯泷15 小时前
手搓JSVM第 6 篇:把 IR 编成字节码:emit 与 label fixup
前端·javascript·算法
泯泷15 小时前
手搓JSVM第 3 篇:从栈式 VM 到寄存器式 VM:为什么我们选择寄存器
前端·javascript·算法