canvas鼠标交互粒子动画效果代码
代码语言:html
所属分类:粒子
代码描述:canvas鼠标交互粒子动画效果代码
下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开
<!DOCTYPE html> <html lang="en" > <head> <meta charset="UTF-8"> <style> /* global */ @import url(//fonts.googleapis.com/css?family=Open+Sans); *, *::before, *::after { margin: 0; padding: 0; border: 0; box-sizing: border-box; } *:focus { outline: none; } body { display: flex; align-items: center; justify-content: center; height: 100vh; background: radial-gradient(#202020, #000000); overflow: hidden; } canvas { touch-action: none; } </style> </head> <body translate="no"> <script > //--- 'use strict'; //--- console.clear(); //--- let w = 0; let h = 0; let initialWidth = w; let initialHeight = h; let animationFrame = null; let isTouchDevice = false; const canvas = document.createElement('canvas'); const context = canvas.getContext('2d', { willReadFrequently: true }); let imageData = null; let data = null; const center = { x: w / 2, y: h / 2 }; const border = { left: 1, top: 1, right: w, bottom: h }; let pointerPos = { x: center.x, y: center.y }; let pointerDown = false; let pointerMoveTimeout; const pointerMoveTimeoutTime = 2500; //--- const text = [ { text: '250', x: 0, y: 0, ox: 0, oy: 0, offsetX: 0, offsetY: -60, fontSizeFactor: 2.25, fontWeight: 'bold', fontSize: 0 }, { text: 'FOLLOWERS', x: 0, y: 0, ox: 0, oy: 0, offsetX: 0, offsetY: 180, fontSizeFactor: 8.5, fontWeight: 'bold', fontSize: 0 }]; const dotsCountMax = 20164; const dotsRadius = 3; const dotsDistance = 0; const dotsDiameter = dotsRadius * 2; const dotsSpeed = 10; const dotsWobbleFactor = 0.95; const dotsWobbleSpeed = 0.05; const dotsMaxEscapeRouteLengthBasis = 100; let dotsMaxEscapeRouteLength = 100; const dotsMouseDistanceSensitivitySpeed = 5; const dotsMouseDistanceSensitivityMax = 250; const dotsMouseDistanceSensitivityMinBasis = 100; let dotsMouseDistanceSensitivityMin = 100; let dotsMouseDistanceSensitivity = dotsMouseDistanceSensitivityMin; let dotsHolder = []; let dotsCount = dotsCountMax; let introPath = []; let introInterval = null; let introIndex = 0; let introPathCoordinatesCount = 256; let introSpeedBasis = 10; let introSpeed = introSpeedBasis; //--- function init() { isTouchDevice = 'ontouchstart' in window || navigator.maxTouchPoints > 0 || navigator.msMaxTouchPoints > 0; //--- if (isTouchDevice === true) { canvas.addEventListener('touchmove', cursorMoveHandler, false); canvas.addEventListener('touchend', cursorLeaveHandler, false); canvas.addEventListener('touchcancel ', cursorLeaveHandler, false); } else { canvas.addEventListener('pointermove', cursorMoveHandler, false); canvas.addEventListener('pointerdown', cursorDownHandler, false); canvas.addEventListener('pointerup', cursorUpHandler, false); canvas.addEventListener('pointerleave', cursorLeaveHandler, false); } //--- initialWidth = calculateDimensions(dotsCount, dotsDiameter, dotsDistance, dotsMouseDistanceSensitivityMax); initialHeight = initialWidth; //--- document.body.appendChild(canvas); window.addEventListener('resize', onResize, false); restart(); } function onResize(event) { restart(); } function calculateDimensions(dotsCount, dotsDiameter, dotsDistance, dotsMouseDistanceSensitivityMax) { return Math.ceil(Math.sqrt(dotsCount)) * (dotsDiameter + dotsDistance) + dotsMouseDistanceSensitivityMax * 1; } function restart() { const innerWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth; const innerHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight; //--- const changeDimensions = c => { let dotsCountSQRT = Math.ceil(Math.sqrt(dotsCount)); dotsCountSQRT += c; dotsCount = dotsCountSQRT * dotsCountSQRT; w = calculateDimensions(dotsCount, dotsDiameter, dotsDistance, dotsMouseDistanceSensitivityMax); h = w; }; //--- w = calculateDimensions(dotsCount, dotsDiameter, dotsDistance, dotsMouseDistanceSensitivityMax); h = w; if (w < innerWidth || h < innerHeight) { while ((w < innerWidth || h < innerHeight) && dotsCount < dotsCountMax) changeDimensions(2); } if (w > innerWidth || h > innerHeight) { while (w > innerWidth || h > innerHeight) changeDimensions(-2); } //--- canvas.width = w; canvas.height = h; imageData = context.getImageData(0, 0, w, h); data = imageData.data; //--- center.x = w / 2; center.y = h / 2; pointerPos.x = -10000; pointerPos.y = -10000; border.right = w; border.bottom = h; //--- initTextCanvas(); const scaleFactor = Math.min(w / initialWidth, h / initialHeight); const calculateFontSize = (w, baseFontSize, scaleFactor) => Math.round(w / baseFontSize * scaleFactor); const adjustOffset = (offset, scaleFactor) => offset * scaleFactor; text.forEach(t => { t.ox = adjustOffset(t.offsetX, scaleFactor); t.oy = adjustOffset(t.offsetY, scaleFactor); t.x = center.x + t.ox; t.y = center.y + t.oy; t.fontSize = calculateFontSize(w, t.fontSizeFactor, scaleFactor); drawTextToCanvas(t); }); //--- dotsMouseDistanceSensitivityMin = Math.round(dotsMouseDistanceSensitivityMinBasis * scaleFactor); dotsMaxEscapeRouteLength = Math.round(dotsMaxEscapeRouteLengthBasis * scaleFactor); //--- removeDots(); addDots(); //--- if (animationFrame != null) { cancelAnimFrame(animationFrame); } render(); //--- introSpeed = Math.round(introSpeedBasis / scaleFactor); initIntroPath(introPathCoordinatesCount); stopIntro(); playIntro(); } //--- function initTextCanvas() { context.fillStyle = 'white'; context.fillRect(0, 0, w, h); context.fillStyle = 'black'; } function drawTextToCanvas({ text, x, y, fontWeight, fontSize, color = 'black', align = 'center', baseline = 'middle' }) { context.font = `${fontWeight} ${fontSize}px 'Open Sans', sans-serif`; context.textAlign = align; context.textBaseline = baseline; context.fillText(text, x, y); } function isPixelBlack(x, y) { const imageData = context.getImageData(x, y, 1, 1).data; return imageData[0] === 0 && imageData[1] === 0 && imageData[2] === 0; } //--- function addDots() { const dotsPerRow = Math.ceil(Math.sqrt(dotsCount)); const xs = Math.round(center.x - dotsPerRow * (dotsDiameter + dotsDistance) / 2) + dotsDiameter; const ys = Math.round(center.y - dotsPerRow * (dotsDiameter + dotsDistance) / 2) + dotsDiameter; for (let i = 0; i < dotsCount; i++) { const x = xs + i % dotsPerRow * (dotsDistance + dotsDiameter); const y = ys + Math.floor(i / dotsPerRow) * (dotsDistance + dotsDiameter); let dot = null; if (isPixelBlack(x, y) === true) { dot = addDot(x, y, dotsRadius, dotsDiameter, 255, Math.floor(Math.random() * 255), 155, 255); } else { dot = addDot(x, y, dotsRadius, dotsDiameter, Math.floor(Math.random() * 255), 0, 155, 255); } dotsHolder.push(dot); } } function addDot(x, y, radius, diameter, r, g, b, a) { const dot = {}; dot.cx = x; dot.cy = y; dot.x = x; dot.y = y; dot.sx = 0; dot.sy = 0; dot.radius = radius; dot.minRadius = radius * 0.75; dot.maxRadius = radi.........完整代码请登录后点击上方下载按钮下载查看
网友评论0