canvas三维物体变形动画效果代码
代码语言:html
所属分类:三维
代码描述:canvas三维物体变形动画效果代码,物体变换成不同切片的不同形状。
下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开
<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<style>
body, html{
margin: 0;
height: 100vh;
background: linear-gradient(-45deg, #333, #000);
overflow: hidden;
}
#c{
border: 3px solid #fff3;
position: absolute;
background: #04f1;
left: 50%;
top: 50%;
border-radius: 10px;
transform: translate(-50%, -50%);
}
</style>
</head>
<body translate="no">
<canvas id=c>
<script >
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 = () => {
let b = document.body;
let margin = 10;
let n;
let d = .5625;
if (b.clientHeight / b.clientWidth > d) {
c.style.width = `${(n = b.clientWidth) - margin * 2}px`;
c.style.height = `${n * d - margin * 2}px`;
} else {
c.style.height = `${(n = b.clientHeight) - margin * 2}px`;
c.style.width = `${n / d - margin * 2}px`;
}
};
rsz();
async function Draw() {
if (!t) {
oX = oY = oZ = 0;
Rn = Math.random;
R = (Rl, Pt, Yw, m) => {
let p;
M = Math;
A = M.atan2;
H = M.hypot;
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;
}
};
R2 = (Rl, Pt, Yw, m = false) => {
M = Math;
A = M.atan2;
H = M.hypot;
if (m) {
X -= oX;
Y -= oY;
Z -= oZ;
}
X = S(p = A(X, Y) + Rl) * (d = H(X, Y));
Y = C(p) * d;
Y = S(p = A(Y, Z) + Pt) * (d = H(Y, Z));
Z = C(p) * d;
X = S(p = A(X, Z) + Yw) * (d = H(X, Z));
Z = C(p) * d;
};
Q = () => [c.width / 2 + X / Z * 1e3, c.height / 2 + Y / Z * 1e3];
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;
Normal = (facet, autoFlipNormals = false, X1 = 0, Y1 = 0, Z1 = 0, flip_ = false) => {
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];
crs = [b2 * c3 - b3 * c2, b3 * c1 - b1 * c3, b1 * c2 - b2 * c1];
d = Math.hypot(...crs) + .0001;
let nls = 1; //normal line length
crs = crs.map(q => q / d * nls);
let X1_ = ax,Y1_ = ay,Z1_ = az;
let flip = 1;
if (autoFlipNormals) {
let d1_ = Math.hypot(X1_ - X1, Y1_ - Y1, Z1_ - Z1);
let d2_ = Math.hypot(X1 - (ax + crs[0] / 99), Y1 - (ay + crs[1] / 99), Z1 - (az + crs[2] / 99));
flip = d2_ > d1_ ? -1 : 1;
}
if (flip_) flip *= -1;
let X2_ = ax + (crs[0] *= flip),Y2_ = ay + (crs[1] *= flip),Z2_ = az + (crs[2] *= flip);
return [X1_, Y1_, Z1_, X2_, Y2_, Z2_];
};
drawRotatedImage = (img, tx, ty, w, h, theta) => {
x.save();
x.translate(tx, ty);
x.rotate(theta);
x.drawImage(img, -w / 2, -h / 2, w, h);
x.restore();
};
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];
};
burst = new Image();
burst.src = "https://srmcgann.github.io/temp/burst.png";
burst1 = new Image();
burst1.src = "https://srmcgann.github.io/temp/burst1.png";
burst2 = new Image();
burst2.src = "https://srmcgann.github.io/temp/burst2.png";
burst3 = new Image();
burst3.src = "https://srmcgann.github.io/temp/burst3.png";
burst4 = new Image();
burst4.src = "https://srmcgann.github.io/temp/burst4.png";
burstz = [burst1, burst2, burst3, burst4];
//burstz = [ burst, burst, burst, burst]
sphere_monochrome = new Image();
sphere_monochrome.src = 'https://srmcgann.github.io/temp13/sphere_monochrome.png';
starsLoaded = false, starImgs = [{ loaded: false }];
starImgs = Array(9).fill().map((v, i) => {
let a = { img: new Image(), loaded: false };
a.img.onload = () => {
a.loaded = true;
setTimeout(() => {
if (starImgs.filter(v => v.loaded).length == 9) starsLoaded = true;
}, 0);
};
a.img.src = `https://srmcgann.github.io/stars/star${i + 1}.png`;
return a;
});
Pip = (tx, ty, tz, facet) => {
let ax = 0;
let ay = 0;
facet.map((v, i) => {
ax += v[0];
ay += v[1];
});
ax /= facet.length;
ay /= facet.length;
let X1 = ax;
let Y1 = ay;
let X2 = tx;
let Y2 = ty;
let ct = 0;
let l;
facet.map((v, i) => {
let l1 = i;
let l2 = (i + 1) % facet.length;
let X3 = facet[l1][0];
let Y3 = facet[l1][1];
let X4 = facet[l2][0];
let Y4 = facet[l2][1];
if (l = I(X1, Y1, X2, Y2, X3, Y3, X4, Y4)) ct++;
});
return [ct == 0, [tx - ax, ty - ay]];
};
lineFaceI = (X1, Y1, Z1, X2, Y2, Z2, facet, autoFlipNormals = false, showNormals = false) => {
let X_, Y_, Z_, d, m, l_, K, J, L, p;
let 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;
let Q_ = () => [c.width / 2 + X_ / Z_ * 1e3, c.height / 2 + Y_ / Z_ * 1e3];
let R_ = (Rl, Pt, Yw, m) => {
let M = Math,A = M.atan2,H = M.hypot;
X_ = S(p = A(X_, Z_) + Yw) * (d = H(X_, Z_));
Z_ = C(p) * d;
X_ = S(p = A(X_, Y_) + Rl) * (d = H(X_, Y_));
Y_ = C(p) * d;
Y_ = S(p = A(Y_, Z_) + Pt) * (d = H(Y_, Z_));
Z_ = C(p) * d;
if (m) {X_ += oX, Y_ += oY, Z_ += oZ;}
};
let rotSwitch = m => {
switch (m) {
case 0:R_(0, 0, Math.PI / 2);break;
case 1:R_(0, Math.PI / 2, 0);break;
case 2:R_(Math.PI / 2, 0, Math.PI / 2);break;}
};
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 = .25; //normal line length
crs = crs.map(q => q / d * nls);
let X1_ = ax,Y1_ = ay,Z1_ = az;
let flip = 1;
if (autoFlipNormals) {
let d1_ = Math.hypot(X1_ - X1, Y1_ - Y1, Z1_ - Z1);
let d2_ = Math.hypot(X1 - (ax + crs[0] / 99), Y1 - (ay + crs[1] / 99), Z1 - (az + crs[2] / 99));
flip = d2_ > d1_ ? -1 : 1;
}
let X2_ = ax + (crs[0] *= flip),Y2_ = ay + (crs[1] *= flip),Z2_ = az + (crs[2] *= flip);
if (showNormals) {
x.beginPath();
X_ = X1_, Y_ = Y1_, Z_ = Z1_;
R_(Rl, Pt, Yw, 1);
if (Z_ > 0) x.lineTo(...Q_());
X_ = X2_, Y_ = Y2_, Z_ = Z2_;
R_(Rl, Pt, Yw, 1);
if (Z_ > 0) x.lineTo(...Q_());
x.lineWidth = 5;
x.strokeStyle = '#f004';
x.stroke();
}
let p1_ = Math.atan2(X2_ - X1_, Z2_ - Z1_);
let p2_ = -(Math.acos((Y2_ - Y1_) / (Math.hypot(X2_ - X1_, Y2_ - Y1_, Z2_ - Z1_) + .001)) + Math.PI / 2);
let isc = false,iscs = [false, false, false];
X_ = X1, Y_ = Y1, Z_ = Z1;
R_(0, -p2_, -p1_);
let rx_ = X_,ry_ = Y_,rz_ = Z_;
for (let m = 3; m--;) {
if (isc === false) {
X_ = rx_, Y_ = ry_, Z_ = rz_;
rotSwitch(m);
X1_ = X_, Y1_ = Y_, Z1_ = Z_ = 5, X_ = X2, Y_ = Y2, Z_ = Z2;
R_(0, -p2_, -p1_);
rotSwitch(m);
X2_ = X_, Y2_ = Y_, Z2_ = Z_;
facet.map((q_, j_) => {
if (isc === false) {
let l = j_;
X_ = facet[l][0], Y_ = facet[l][1], Z_ = facet[l][2];
R_(0, -p2_, -p1_);
rotSwitch(m);
let X3_ = X_,Y3_ = Y_,Z3_ = Z_;
l = (j_ + 1) % facet.length;
X_ = facet[l][0], Y_ = facet[l][1], Z_ = facet[l][2];
R_(0, -p2_, -p1_);
rotSwitch(m);
let X4_ = X_,Y4_ = Y_,Z4_ = Z_;
if (l_ = I_(X1_, Y1_, X2_, Y2_, X3_, Y3_, X4_, Y4_)) iscs[m] = l_;
}
});
}
}
if (iscs.filter(v => v !== false).length == 3) {
let iscx = iscs[1][0],iscy = iscs[0][1],iscz = iscs[0][0];
let pointInPoly = true;
ax = 0, ay = 0, az = 0;
facet.map((q_, j_) => {ax += q_[0], ay += q_[1], az += q_[2];});
ax /= facet.length, ay /= facet.length, az /= facet.length;
X_ = ax, Y_ = ay, Z_ = az;
R_(0, -p2_, -p1_);
X1_ = X_, Y1_ = Y_, Z1_ = Z_;
X2_ = iscx, Y2_ = iscy, Z2_ = iscz;
facet.map((q_, j_) => {
if (pointInPoly) {
let l = j_;
X_ = facet[l][0], Y_ = facet[l][1], Z_ = facet[l][2];
R_(0, -p2_, -p1_);
let X3_ = X_,Y3_ = Y_,Z3_ = Z_;
l = (j_ + 1) % facet.length;
X_ = facet[l][0], Y_ = facet[l][1], Z_ = facet[l][2];
R_(0, -p2_, -p1_);
let X4_ = X_,Y4_ = Y_,Z4_ = Z_;
if (I_(X1_, Y1_, X2_, Y2_, X3_, Y3_, X4_, Y4_)) pointInPoly = false;
}
});
if (pointInPoly) {
X_ = iscx, Y_ = iscy, Z_ = iscz;
R_(0, p2_, 0);
R_(0, 0, p1_);
isc = [[X_, Y_, Z_], [crs[0], crs[1], crs[2]]];
}
}
return isc;
};
TruncatedOctahedron = ls => {
let shp = [],a = [];
mind = 6e6;
for (let i = 6; i--;) {
X = S(p = Math.PI * 2 / 6 * i + Math.PI / 6);
Y = C(p);
Z = 0;
if (Y < mind) mind = Y;
a = [...a, [X, Y, Z]];
}
let theta = .6154797086703867;
a.map(v => {
X = v[0];
Y = v[1] - mind;
Z = v[2];
R(0, theta, 0);
v[0] = X;
v[1] = Y;
v[2] = Z + 1.5;
});
b = JSON.parse(JSON.stringify(a)).map(v => {
v[1] *= -1;
return v;
});
shp = [...shp, a, b];
e = JSON.parse(JSON.stringify(shp)).map(v => {
v.map(q => {
X = q[0];
Y = q[1];
Z = q[2];
R(0, 0, Math.PI);
q[0] = X;
q[1] = Y;
q[2] = Z;
});
return v;
});
shp = [...shp, ...e];
e = JSON.parse(JSON.stringify(shp)).map(v => {
v.map(q => {
X = q[0];
Y = q[1];
Z = q[2];
R(0, 0, Math.PI / 2);
q[0] = X;
q[1] = Y;
q[2] = Z;
});
return v;
});
shp = [...shp, ...e];
coords = [
[[3, 1], [4, 3], [4, 4], [3, 2]],
[[3, 4], [3, 3], [2, 4], [6, 2]],
[[1, 4], [0, 3], [0, 4], [4, 2]],
[[1, 1], [1, 2], [6, 4], [7, 3]],
[[3, 5], [7, 5], [1, 5], [3, 0]],
[[2, 5], [6, 5], [0, 5], [4, 5]]];
a = [];
coords.map(v => {
b = [];
v.map(q => {
X = shp[q[0]][q[1]][0];
Y = shp[q[0]][q[1]][1];
Z = shp[q[0]][q[1]][2];
b = [...b, [X, Y, Z]];
});
a = [...a, b];
});
shp = [...shp, ...a];
return shp.map(v => {
v.map(q => {
q[0] /= 3;
q[1] /= 3;
q[2] /= 3;
q[0] *= ls;
q[1] *= ls;
q[2] *= ls;
});
return v;
});
};
Torus = (rw, cl, ls1, ls2, parts = 1, twists = 0, part_spacing = 1.5) => {
t_ = C(t) * 8;
let ret = [],tx = 0,ty = 0,tz = 0,prl1 = 0,p2a = 0,prl2 = 0,p2b = 0;
tx1 = ty1 = tz1 = tx2 = ty2 = tz2 = 0;
for (let m = parts; m--;) {
avgs = Array(rw).fill().map(v => [0, 0, 0]);
for (j = rw; j--;) for (let i = cl; i--;) {
if (parts > 1) {
ls3 = ls1 * part_spacing;
X = S(p = Math.PI * 2 / parts * m) * ls3;
Y = C(p) * .........完整代码请登录后点击上方下载按钮下载查看
网友评论0