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