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) * ls3; Z = 0; R(prl1 = Math.PI * 2 / rw * (j - 1) * twists + t_, 0, 0); tx1 = X; ty1 = Y; tz1 = Z; R(0, 0, Math.PI * 2 / rw * (j - 1)); ax1 = X; ay1 = Y; az1 = Z; X = S(p = Math.PI * 2 / parts * m) * ls3; Y = C(p) * ls3; Z = 0; R(prl2 = Math.PI * 2 / rw * j * twists + t_, 0, 0); tx2 = X; ty2 = Y; tz2 = Z; R(0, 0, Math.PI * 2 / rw * j); ax2 = X; ay2 = Y; az2 = Z; p1a = Math.atan2(ax2 - ax1, az2 - az1); p2a = Math.PI / 2 + Math.acos((ay2 - ay1) / (Math.hypot(ax2 - ax1, ay2 - ay1, az2 - az1) + .001)); X = S(p = Math.PI * 2 / parts * m) * ls3; Y = C(p) * ls3; Z = 0; R(Math.PI * 2 / rw * j * twists + t_, 0, 0); tx1b = X; ty1b = Y; tz1b = Z; R(0, 0, Math.PI * 2 / rw * j); ax1b = X; ay1b = Y; az1b = Z; X = S(p = Math.PI * 2 / parts * m) * ls3; Y = C(p) * ls3; Z = 0; R(Math.PI * 2 / rw * (j + 1) * twists + t_, 0, 0); tx2b = X; ty2b = Y; tz2b = Z; R(0, 0, Math.PI * 2 / rw * (j + 1)); ax2b = X; ay2b = Y; az2b = Z; p1b = Math.atan2(ax2b - ax1b, az2b - az1b); p2b = Math.PI / 2 + Math.acos((ay2b - ay1b) / (Math.hypot(ax2b - ax1b, ay2b - ay1b, az2b - az1b) + .001)); } a = []; X = S(p = Math.PI * 2 / cl * i) * ls1; Y = C(p) * ls1; Z = 0; //R(0,0,-p1a) R(prl1, p2a, 0); X += ls2 + tx1, Y += ty1, Z += tz1; R(0, 0, Math.PI * 2 / rw * j); a = [...a, [X, Y, Z]]; X = S(p = Math.PI * 2 / cl * (i + 1)) * ls1; Y = C(p) * ls1; Z = 0; //R(0,0,-p1a) R(prl1, p2a, 0); X += ls2 + tx1, Y += ty1, Z += tz1; R(0, 0, Math.PI * 2 / rw * j); a = [...a, [X, Y, Z]]; X = S(p = Math.PI * 2 / cl * (i + 1)) * ls1; Y = C(p) * ls1; Z = 0; //R(0,0,-p1b) R(prl2, p2b, 0); X += ls2 + tx2, Y += ty2, Z += tz2; R(0, 0, Math.PI * 2 / rw * (j + 1)); a = [...a, [X, Y, Z]]; X = S(p = Math.PI * 2 / cl * i) * ls1; Y = C(p) * ls1; Z = 0; //R(0,0,-p1b) R(prl2, p2b, 0); X += ls2 + tx2, Y += ty2, Z += tz2; R(0, 0, Math.PI * 2 / rw * (j + 1)); a = [...a, [X, Y, Z]]; ret = [...ret, a]; } } return ret; }; Cylinder = (rw, cl, ls1, ls2, caps = false) => { let a = []; for (let i = rw; i--;) { let b = []; for (let j = cl; j--;) { X = S(p = Math.PI * 2 / cl * j) * ls1; Y = (1 / rw * i - .5) * ls2; Z = C(p) * ls1; b = [...b, [X, Y, Z]]; } if (caps) a = [...a, b]; for (let j = cl; j--;) { b = []; X = S(p = Math.PI * 2 / cl * j) * ls1; Y = (1 / rw * i - .5) * ls2; Z = C(p) * ls1; b = [...b, [X, Y, Z]]; X = S(p = Math.PI * 2 / cl * (j + 1)) * ls1; Y = (1 / rw * i - .5) * ls2; Z = C(p) * ls1; b = [...b, [X, Y, Z]]; X = S(p = Math.PI * 2 / cl * (j + 1)) * ls1; Y = (1 / rw * (i + 1) - .5) * ls2; Z = C(p) * ls1; b = [...b, [X, Y, Z]]; X = S(p = Math.PI * 2 / cl * j) * ls1; Y = (1 / rw * (i + 1) - .5) * ls2; Z = C(p) * ls1; b = [...b, [X, Y, Z]]; a = [...a, b]; } } b = []; for (let j = cl; j--;) { X = S(p = Math.PI * 2 / cl * j) * ls1; Y = ls2 / 2; Z = C(p) * ls1; b = [...b, [X, Y, Z]]; } if (caps) a = [...a, b]; return a; }; Tetrahedron = size => { ret = []; a = []; let h = size / 1.4142 / 1.25; for (i = 3; i--;) { X = S(p = Math.PI * 2 / 3 * i) * size / 1.25; Y = C(p) * size / 1.25; Z = h; a = [...a, [X, Y, Z]]; } ret = [...ret, a]; for (j = 3; j--;) { a = []; X = 0; Y = 0; Z = -h; a = [...a, [X, Y, Z]]; X = S(p = Math.PI * 2 / 3 * j) * size / 1.25; Y = C(p) * size / 1.25; Z = h; a = [...a, [X, Y, Z]]; X = S(p = Math.PI * 2 / 3 * (j + 1)) * size / 1.25; Y = C(p) * size / 1.25; Z = h; a = [...a, [X, Y, Z]]; ret = [...ret, a]; } ax = ay = az = ct = 0; ret.map(v => { v.map(q => { ax += q[0]; ay += q[1]; az += q[2]; ct++; }); }); ax /= ct; ay /= ct; az /= ct; ret.map(v => { v.map(q => { q[0] -= ax; q[1] -= ay; q[2] -= az; }); }); return ret; }; StellatedDodecahedron = size => { let a = []; let core = subDividedIcosahedron(size).map((v, i) => { ax = ay = az = 0; v.map(q => { ax += q[0]; ay += q[1]; az += q[2]; }); ax /= v.length; ay /= v.length; az /= v.length; d = Math.hypot(ax, ay, az); ls = d * 4.5 / size; v.map((q, j) => { b = []; l1 = j; l2 = (j + 1) % v.length; X = v[l1][0]; Y = v[l1][1]; Z = v[l1][2]; b = [...b, [X, Y, Z]]; X = v[l2][0]; Y = v[l2][1]; Z = v[l2][2]; b = [...b, [X, Y, Z]]; X = ax * ls; Y = ay * ls; Z = az * ls; b = [...b, [X, Y, Z]]; a = [...a, b]; }); return v; }); maxd = -1e6; a.map(v => { v.map(q => { X = q[0]; Y = q[1]; Z = q[2]; if ((d = Math.hypot(X, Y, Z)) > maxd) maxd = d; }); }); return a.map(v => { v.map(q => { X = q[0]; Y = q[1]; Z = q[2]; d = Math.hypot(X, Y, Z); q[0] /= maxd; q[1] /= maxd; q[2] /= maxd; q[0] *= size; q[1] *= size; q[2] *= size; }); return v; }); }; .........完整代码请登录后点击上方下载按钮下载查看
网友评论0