canvas实现火箭助推器火花火焰动画效果代码
代码语言:html
所属分类:动画
代码描述:canvas实现火箭助推器火花火焰动画效果代码
下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开
<!DOCTYPE html> <html lang="en" > <head> <meta charset="UTF-8"> <style> body,html{ background: #000; margin: 0; height: 100vh; overflow: hidden; } #c{ background:#000; position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); } </style> </head> <body> <canvas id=c> <script id="rendered-js" > c = document.querySelector('#c'); c.width = 1920; c.height = 1080; x = c.getContext('2d'); C = Math.cos; S = Math.sin; t = 0; T = Math.tan; rsz = window.onresize = () => { setTimeout(() => { if (document.body.clientWidth > document.body.clientHeight * 1.77777778) { c.style.height = '100vh'; setTimeout(() => c.style.width = c.clientHeight * 1.77777778 + 'px', 0); } else { c.style.width = '100vw'; setTimeout(() => c.style.height = c.clientWidth / 1.77777778 + 'px', 0); } }, 0); }; rsz(); async function Draw() { if (!t) { oX = oY = oZ = Rl = Pt = Yw = 0; reflect = (a, n) => { let d1 = Math.hypot(...a) + .0001; let d2 = Math.hypot(...n) + .0001; a[0] /= d1; a[1] /= d1; a[2] /= d1; n[0] /= d2; n[1] /= d2; n[2] /= d2; let dot = -a[0] * n[0] + -a[1] * n[1] + -a[2] * n[2]; let rx = -a[0] - 2 * n[0] * dot; let ry = -a[1] - 2 * n[1] * dot; let rz = -a[2] - 2 * n[2] * dot; return [-rx * d1, -ry * d1, -rz * d1]; }; spawnTunnel = ( tx, ty, tz, rw, cl, sp = 1, rad = .5, theta1 = 0, theta2 = 0, theta1ModFreq = 0, theta1ModMag = 0, theta2ModFreq = 0, theta2ModMag = 0, theta1Offset = 0, theta2Offset = 0, radModFreq = 0, radModMag = 0, radModOffset = 0, showLine = false) => { let X_ = X = tx; let Y_ = Y = ty; let Z_ = Z = tz; let ret = []; let p2a, p2, p2a1, ls; if (showLine) x.beginPath(); for (let i = cl + 1; i--;) { let p1 = theta1 + C(Math.PI * 2 / cl * i * theta1ModFreq + theta1Offset) * theta1ModMag; let p2 = theta2 + C(Math.PI * 2 / cl * i * theta2ModFreq + theta2Offset) * theta2ModMag; let p2a1 = theta2 + C(Math.PI * 2 / cl * (i + 1) * theta2ModFreq + theta2Offset) * theta2ModMag; let lsa = rad + C(Math.PI * 2 / cl * i * radModFreq + radModOffset) * rad / 2 * radModMag; let lsb = rad + C(Math.PI * 2 / cl * (i + 1) * radModFreq + radModOffset) * rad / 2 * radModMag; if (i == cl) { p2a = p2; ls = lsa; } else if (i == 0) { p2a = p2a1; ls = lsb; } else { p2a = (p2 + p2a1) / 2; ls = (lsa + lsb) / 2; } let a = []; for (let j = rw + 1; j--;) { p = Math.PI * 2 / rw * j + Math.PI / rw; X = S(p) * ls; Y = 0; Z = C(p) * ls; R(-p2a + Math.PI / 2, 0, 0); R(0, 0, -p1); a = [...a, [X + X_, Y + Y_, Z + Z_]]; } ret = [...ret, a]; if (showLine) { X = X_; Y = Y_; Z = Z_; R(Rl, Pt, Yw, 1); if (Z > 0) x.lineTo(...Q()); } vx = C(p1) * C(p2) * sp; vy = S(p2) * sp; vz = S(p1) * C(p2) * sp; X_ += vx; Y_ += vy; Z_ += vz; } if (showLine) stroke('#f00', '', 2, false); a = []; ret.map((v, i) => { if (i) { let s1 = ret[i]; let s2 = ret[i - 1]; for (let j = rw; j--;) { b = []; let l1_ = (j + 0) % rw; let l2_ = (j + 1) % rw; X = s1[l1_][0]; Y = s1[l1_][1]; Z = s1[l1_][2]; b = [...b, [X, Y, Z]]; X = s1[l2_][0]; Y = s1[l2_][1]; Z = s1[l2_][2]; b = [...b, [X, Y, Z]]; X = s2[l2_][0]; Y = s2[l2_][1]; Z = s2[l2_][2]; b = [...b, [X, Y, Z]]; X = s2[l1_][0]; Y = s2[l1_][1]; Z = s2[l1_][2]; b = [...b, [X, Y, Z]]; a = [...a, b]; } } }); return a; }; HSVFromRGB = (R, G, B) => { let R_ = R / 256; let G_ = G / 256; let B_ = B / 256; let Cmin = Math.min(R_, G_, B_); let Cmax = Math.max(R_, G_, B_); let val = Cmax; //(Cmax+Cmin) / 2 let delta = Cmax - Cmin; let sat = Cmax ? delta / Cmax : 0; let min = Math.min(R, G, B); let max = Math.max(R, G, B); let hue = 0; if (delta) { if (R >= G && R >= B) hue = (G - B) / (max - min); if (G >= R && G >= B) hue = 2 + (B - R) / (max - min); if (B >= G && B >= R) hue = 4 + (R - G) / (max - min); } hue *= 60; while (hue < 0) hue += 360; while (hue >= 360) hue -= 360; return [hue, sat, val]; }; RGBFromHSV = (H, S, V) => { while (H < 0) H += 360; while (H >= 360) H -= 360; let C = V * S; let X = C * (1 - Math.abs(H / 60 % 2 - 1)); let m = V - C; let R_, G_, B_; if (H >= 0 && H < 60) R_ = C, G_ = X, B_ = 0; if (H >= 60 && H < 120) R_ = X, G_ = C, B_ = 0; if (H >= 120 && H < 180) R_ = 0, G_ = C, B_ = X; if (H >= 180 && H < 240) R_ = 0, G_ = X, B_ = C; if (H >= 240 && H < 300) R_ = X, G_ = 0, B_ = C; if (H >= 300 && H < 360) R_ = C, G_ = 0, B_ = X; let R = (R_ + m) * 256; let G = (G_ + m) * 256; let B = (B_ + m) * 256; return [R, G, B]; }; R = R2 = (Rl, Pt, Yw, m) => { M = Math; A = M.atan2; H = M.hypot; //if(m){ // X-=oX // Y-=oY // Z-=oZ //} X = S(p = A(X, Z) + Yw) * (d = H(X, Z)); Z = C(p) * d; Y = S(p = A(Y, Z) + Pt) * (d = H(Y, Z)); Z = C(p) * d; X = S(p = A(X, Y) + Rl) * (d = H(X, Y)); Y = C(p) * d; if (m) { X += oX; Y += oY; Z += oZ; } }; Q = () => [c.width / 2 + X / Z * 700, c.height / 2 + Y / Z * 700]; I = (A, B, M, D, E, F, G, H) => (K = ((G - E) * (B - F) - (H - F) * (A - E)) / (J = (H - F) * (M - A) - (G - E) * (D - B))) >= 0 && K <= 1 && (L = ((M - A) * (B - F) - (D - B) * (A - E)) / J) >= 0 && L <= 1 ? [A + K * (M - A), B + K * (D - B)] : 0; Rn = Math.random; async function loadOBJ(url, scale, tx, ty, tz, rl, pt, yw, recenter = true) { let res; await fetch(url, res => res).then(data => data.text()).then(data => { a = []; data.split("\nv ").map(v => { a = [...a, v.split("\n")[0]]; }); a = a.filter((v, i) => i).map(v => [...v.split(' ').map(n => +n.replace("\n", ''))]); ax = ay = az = 0; a.map(v => { v[1] *= -1; if (recenter) { ax += v[0]; ay += v[1]; az += v[2]; } }); ax /= a.length; ay /= a.length; az /= a.length; a.map(v => { X = (v[0] - ax) * scale; Y = (v[1] - ay) * scale; Z = (v[2] - az) * scale; R2(rl, pt, yw, 0); v[0] = X; v[1] = Y * (url.indexOf('bug') != -1 ? 2 : 1); v[2] = Z; }); maxY = -6e6; a.map(v => { if (v[1] > maxY) maxY = v[1]; }); a.map(v => { v[1] -= maxY - oY; v[0] += tx; v[1] += ty; v[2] += tz; }); b = []; data.split("\nf ").map(v => { b = [...b, v.split("\n")[0]]; }); b.shift(); b = b.map(v => v.split(' ')); b = b.map(v => { v = v.map(q => { return +q.split('/')[0]; }); v = v.filter(q => q); return v; }); res = []; b.map(v => { e = []; v.map(q => { e = [...e, a[q - 1]]; }); e = e.filter(q => q); res = [...res, e]; }); }); return res; } function loadAnimation(name, size, X, Y, Z, rl, pt, yw, speed = 1) { let rootURL = 'https://srmcgann.github.io/animations'; if (typeof animations == 'undefined') animations = []; if (typeof animationFrameData == 'undefined') animationFrameData = []; if (typeof animationsCT == 'undefined') animationsCT = 0; let animation = { name, speed, frameCt: 0, fileList: '', curFrame: 0, loopRangeStart: 0, loopRangeEnd: 0, hasLoop: false, looping: false, //frameData: [], loaded: false, active: true, idx: animationsCT++ }; fetch(`${rootURL}/${name}/fileList.json`).then(v => v.json()).then(data => { animation.fileList = data.fileList; if (animation.fileList.hasLoop) { animation.hasLoop = true; animation.looping = true; animation.loopRangeStart = animation.fileList.loopRangeStart; animation.loopRangeEnd = animation.fileList.loopRangeEnd; } let fd = Array(+animation.fileList.fileCount); for (let i = 0; i < +animation.fileList.fileCount; i++) { let file = `${rootURL}/${name}/${animation.fileList.fileName}${i + (name.indexOf('tree') != -1 ? 1 : 0)}.${animation.fileList.suffix}`; loadOBJ(file, size, X, Y, Z, rl, pt, yw, false).then(el => { fd[i] = el; animation.frameCt++; if (animation.frameCt == +animation.fileList.fileCount) { console.log(`loaded animation: ${name}`); console.log('animation: ', animation); animation.loaded = true; animations = [...animations, animation]; animationFrameData = [...animationFrameData, fd]; if (animations.length == 4) { landScapeLoaded = true; loadLandscape(); } } }); } }); return name; } drawAnimation = (ox, oy, oz, animation, scol = '#8888', fcol = '', lineWidth = 2, glowing = true, overrideGlobalAlpha = 1, speed = 1, scale = 1, normal = false, theta = 0) => { animation.curFrame += animation.speed * speed; if (0 && animation.hasLoop && animation.looping) { animation.curFrame %= Math.min(animation.loopRangeEnd, animation.frameCt); if (animation.curFrame < 1) animation.curFrame = Math.max(0, animation.loopRangeStart); } else { animation.curFrame %= animation.frameCt; }; (l = animationFrameData[animation.idx])[Math.min(animation.curFrame | 0, l.length - 2)].map((v, i) => { x.beginPath(); v.map(q => { X = q[0] * scale; Y = q[1] * scale; Z = q[2] * scale; if (normal) { let nx1 = normal[0]; let ny1 = normal[1]; let nz1 = normal[2]; let nx2 = normal[3]; let ny2 = normal[4]; let nz2 = normal[5]; let yw = Math.atan2(nx2 - nx1, nz2 - nz1); let pt = -Math.acos((ny2 - ny1) / (Math.hypot(nx2 - nx1, ny2 - ny1, nz2 - nz1) + .001)) + Math.PI; R(0, 0, -yw + theta); R(0, pt, 0); R(0, 0, yw); } X += ox; Y += oy; Z += oz; R(Rl, Pt, Yw, 1); if (Z > 0) x.lineTo(...Q()); }); stroke(scol, fcol, lineWidth, glowing, overrideGlobalAlpha); }); }; geoSphere = (mx, my, mz, iBc, size) => { let collapse = 0; let B = Array(iBc).fill().map(v => { X = Rn() - .5; Y = Rn() - .5; Z = Rn() - .5; return [X, Y, Z]; }); for (let m = 200; m--;) { B.map((v, i) => { X = v[0]; Y = v[1]; Z = v[2]; B.map((q, j) => { if (j != i) { X2 = q[0]; Y2 = q[1]; Z2 = q[2]; d = 1 + (Math.hypot(X - X2, Y - Y2, Z - Z2) * (3 + iBc / 40) * 3) ** 4; X += (X - X2) * 99 / d; Y += (Y - Y2) * 99 / d; Z += (Z - Z2) * 99 / d; } }); d = Math.hypot(X, Y, Z); v[0] = X / d; v[1] = Y / d; v[2] = Z / d; if (collapse) { d = 25 + Math.hypot(X, Y, Z); v[0] = (X - X / d) / 1.1; v[1] = (Y - Y / d) / 1.1; v[2] = (Z - Z / d) / 1.1; } }); } mind = 6e6; B.map((v, i) => { X1 = v[0]; Y1 = v[1]; Z1 = v[2]; B.map((q, j) => { X2 = q[0]; Y2 = q[1]; Z2 = q[2]; if (i != j) { d = Math.hypot(a = X1 - X2, b = Y1 - Y2, e = Z1 - Z2); if (d < mind) mind = d; } }); }); a = []; B.map((v, i) => { X1 = v[0]; Y1 = v[1]; Z1 = v[2]; B.map((q, j) => { X2 = q[0]; Y2 = q[1]; Z2 = q[2]; if (i != j) { d = Math.hypot(X1 - X2, Y1 - Y2, Z1 - Z2); if (d < mind * 2) { if (!a.filter(q => q[0] == X2 && q[1] == Y2 && q[2] == Z2 && q[3] == X1 && q[4] == Y1 && q[5] == Z1).length) a = [...a, [X1 * size, Y1 * size, Z1 * size, X2 * size, Y2 * size, Z2 * size]]; } } }); }); B.map(v => { v[0] *= size; v[1] *= size; v[2] *= size; v[0] += mx; v[1] += my; v[2] += mz; }); return [mx, my, mz, size, B, a]; }; Normal = (facet, autoFlipNormals = false, X1 = 0, Y1 = 0, Z1 = 0) => { let ax = 0,ay = 0,az = 0; facet.map(q_ => {ax += q_[0], ay += q_[1], az += q_[2];}); ax /= facet.length, ay /= facet.length, az /= facet.length; let b1 = facet[2][0] - facet[1][0],b2 = facet[2][1] - facet[1][1],b3 = facet[2][2] - facet[1][2]; let c1 = facet[1][0] - facet[0][0],c2 = facet[1][1] - facet[0][1],c3 = facet[1][2] - facet[0][2]; let crs = [b2 * c3 - b3 * c2, b3 * c1 - b1 * c3, b1 * c2 - b2 * c1]; d = Math.hypot(...crs) + .001; let nls = 1; //normal line length crs = crs.map(.........完整代码请登录后点击上方下载按钮下载查看
网友评论0