canvas实现彩色线条绘制屏保动画效果代码
代码语言:html
所属分类:动画
代码描述:canvas实现彩色线条绘制屏保动画效果代码
下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开
<!DOCTYPE html> <html lang="en" > <head> <meta charset="UTF-8"> <style> :root { background: black; color: white; } </style> </head> <body translate="no"> <script > const particles = 4; const minD = 0.05; // min/max distance const maxD = 1; const maxV = 20; // max velocity const maxF = 10; // max force const F = 0.0186125; // attraction force const G = 0.003; // gravity const canvas = document.createElement("canvas"); canvas.style.position = "absolute"; canvas.style.top = canvas.style.left = 0; document.body.appendChild(canvas); const buffer = document.createElement("canvas"); const bufferCtx = buffer.getContext("2d"); const ctx = canvas.getContext("2d"); let w, h, hw, hh; const PI2 = Math.PI * 2; const random = (min = -1, max = 1) => Math.random() * (max - min) + min; const resize = () => { w = Math.max(innerWidth, 1) - innerWidth % 2; h = Math.max(innerHeight, 1) - innerHeight % 2; hw = w / 2; hh = h / 2; canvas.width = buffer.width = w; canvas.height = buffer.height = h; initContext(); }; const initContext = () => { ctx.translate(hw, hh); ctx.fillStyle = "white"; ctx.strokeStyle = "white"; ctx.lineWidth = 1.3; ctx.fillRect(-hw, -hh, w, h); bufferCtx.fillStyle = "black"; bufferCtx.fillRect(0, 0, w, h); }; resize(false); const debounce = (fn, delay) => { let timeout; return () => { if (timeout) clearTimeout(timeout); timeout = setTimeout(() => fn(), delay); }; }; const debouncedResize = debounce(resize, 100); addEventListener("resize", () => debouncedResize()); const createPoints = (count, source, phase = Math.random() * PI2) => Array.from({ length: count }, (_, i) => { const x = source?.x ?? Math.sin(phase + i / count * PI2) * .9; const y = source?.y ?? Math.cos(phase + i / count * PI2) * .9; const dx = source?.dx ?? -x / 4; const dy = source?.dy ?? -y / 4; return { x, y, dx, dy, closest: null }; }); const project2d = ({ x, y }) => { return { x: Math.round(x * hw), y: Math.round(y * hh) }; }; const distance = (p1, p2) => Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2)); const map = (value, min = 0, max = 1, targetMin = 0, targetMax = 1) => targetMin + (value - min) * (targetMax - targetMin) / (max - min); let firstHit = false; const updatePoint = dt => (p, i, points) => { p.dy += G * dt; p.closest = getClosestPoints(points, p); const [cdx, cdy] = p.closest.reduce((sum, cp) => { const dx = cp.x - p.x; const dy = cp.y - p.y; const d = distance(cp, p); if (d > maxD) return sum; if (d < minD) { const rStr = .5 * (1 - d / minD); sum[0] -= dx / d * rStr; sum[1] -= dy / d * rStr; return sum; } const mag = Math.min(maxF, (1 - d / maxD) / (d * d)); const force = mag; // p.closest.length; sum[0] += dx / d * force; sum[1] += dy / d * force; return sum; }, [0, 0]); const dtF = Math.min(maxF * dt, F * dt); p.dx += Math.max(-dtF, Math.min(dtF, cdx * F * dt)); p.dy += Math.max(-dtF, Math.min(dtF, cdy * F * dt)); const dtV = maxV * dt; p.dx = Math.max(-dtV, Math.min(dtV, p.dx)); p.dy = Math.max(-dtV, Math.min(dtV, p.dy)); if (msP) { const mdx = i % 2 ? msX - p.x : p.x - msX; const mdy = i % 2 ? msY - p.y : p.y - msY; const mdd = distance(p, { x: msX, y: msY }); if (mdd < .7) { p.dx = (p.dx * 19 + mdx * (.7 - mdd)) / 20; p.dy = (p.dy * 19 + mdy * (.7 - mdd)) / 20; } } let collide = false; if (p.x <= -1 || p.x >= 1) { p.x = Math.min(1 - 1 / w, Math.max(-1 + 1 / w, p.x)); p.dx *= -1; collide = true; } if (p.y < -1 || p.y > 1) { p.y = Math.min(1 - 1 / h, Math.max(-1 + 1 / h, p.y)); p.dy *= -1; collide = true; } p.x += p.dx * dt; p.y += p.dy * dt; const shatter = collide && (random(0, 100) > 81.6 || !firstHit); if (shatter) { firstHit = true; const newPoints = createPoints(Math.round(random(1, 2)), p); const normX = p.x <= -1 ? 1 : p.x >= 1 ? -1 : 0; const normY = p.y <= -1 ? 1 : p.y >= 1 ? -1 : 0; const speed = Math.sqrt(p.dx * p.dx + p.dy * p.dy); const dot = p.dx * normX + p.dy * normY; const refX = p.dx - 2 * dot * normX; const refY = p.dy - 2 * dot * normY; const spreadA = Math.PI / 4; const loss = .5; newPoints.forEach((np, i, a) => { np.x += random(-.01, .01); np.y += random(-.01, .01); np.x = Math.max(-1, Math.min(1, np.........完整代码请登录后点击上方下载按钮下载查看
网友评论0