这又是一款基于html5 canvas的3d动画杰作,它是一个可以随风飘动的3d衣服摇摆动画特效,非常逼真。当我们将鼠标滑过衣服时,衣服将会出现摇摆的动画,点击鼠标时,衣服将会更加剧烈地摆动。
在线演示 源码下载
html代码
xml/html code复制内容到剪贴板
div style=width:500px;margin:10px auto> canvas id=cv width=480 height=300>canvas> p>3d on 2d canvas demop> p>move cursor to pan / click to swingp> div>
p3d库js代码,主要用来处理3d效果的
javascript code复制内容到剪贴板
window.p3d = { texture: null, g: null }; p3d.clear = function(f, w, h) { var g = this.g; g.beginpath(); g.fillstyle = f; g.fillrect(0, 0, w, h); } p3d.num_cmp = function(a,b){return a-b;} p3d.drawtriangle = function(poss, uvs, shade_clr) { var w = this.texture.width; var h = this.texture.height; var g = this.g; var vad = [ poss[1].x - poss[0].x , poss[1].y - poss[0].y ]; var vbd = [ poss[2].x - poss[0].x , poss[2].y - poss[0].y ]; var va = [ uvs[1].u - uvs[0].u , uvs[1].v - uvs[0].v ]; var vb = [ uvs[2].u - uvs[0].u , uvs[2].v - uvs[0].v ]; va[0] *= w; va[1] *= h; vb[0] *= w; vb[1] *= h; var m = new m22(); m._11 = va[0]; m._12 = va[1]; m._21 = vb[0]; m._22 = vb[1]; var im = m.getinvert(); if (!im) return false; var a = im._11 * vad[0] + im._12 * vbd[0]; var b = im._21 * vad[0] + im._22 * vbd[0]; var c = im._11 * vad[1] + im._12 * vbd[1]; var d = im._21 * vad[1] + im._22 * vbd[1]; var wu = uvs[0].u * w; var hv = uvs[0].v * h; var du = wu * a + hv * b; var dv = wu * c + hv * d; g.save(); g.beginpath(); g.moveto(poss[0].x, poss[0].y); g.lineto(poss[1].x, poss[1].y); g.lineto(poss[2].x, poss[2].y); g.clip(); g.transform(a, c, b, d, poss[0].x - du, poss[0].y - dv); // bounds var bx = [wu, wu+va[0], wu+vb[0]]; var by = [hv, hv+va[1], hv+vb[1]]; bx.sort(p3d.num_cmp); by.sort(p3d.num_cmp); var bw = bx[2] - bx[0]; var bh = by[2] - by[0]; if ((bx[0]+bw) if ((by[0]+bh) if (bx[0] >= 1) {bx[0]--; bw++;} if (by[0] >= 1) {by[0]--; bh++;} g.drawimage(this.texture, bx[0], by[0], bw, bh, bx[0], by[0], bw, bh); if (shade_clr) { g.fillstyle = shade_clr; g.fillrect(bx[0], by[0], bw, bh); } g.restore(); return true; } p3d.drawtestbyindexbuffer = function(pos_buf, ix_buf, culling) { var g = this.g; if ((ix_buf.length%3) != 0) throw invalid index buffer length!; var len = ix_buf.length/3; var i, ibase, vbase; var poss = [{},{},{}]; g.strokewidth = 1; for (i = 0, ibase = 0;i { vbase = ix_buf[ibase++] poss[0].x = pos_buf[vbase++]; poss[0].y = pos_buf[vbase ]; vbase = ix_buf[ibase++] poss[1].x = pos_buf[vbase++]; poss[1].y = pos_buf[vbase ]; vbase = ix_buf[ibase++] poss[2].x = pos_buf[vbase++]; poss[2].y = pos_buf[vbase ]; // z component of cross product var ax = poss[1].x - poss[0].x; var ay = poss[1].y - poss[0].y; var cx = poss[2].x - poss[1].x; var cy = poss[2].y - poss[1].y; var cull = ( (((ax * cy) - (ay * cx))*culling) g.beginpath(); g.strokestyle = cull ? #592 : #0f0; g.moveto(poss[0].x, poss[0].y); g.lineto(poss[1].x, poss[1].y); g.lineto(poss[2].x, poss[2].y); g.lineto(poss[0].x, poss[0].y); g.stroke(); } } p3d.drawbyindexbuffer = function(pos_buf, ix_buf, tx_buf, culling, z_clip) { var w, h; var color_polygon = !this.texture; if (this.texture) { w = this.texture.width; h = this.texture.height; } var g = this.g; var m = new m22(); if (!culling) culling = 0; if ((ix_buf.length%3) != 0) throw invalid index buffer length!; var i, ibase, vbase, tbase, poss = [{},{},{}]; var len = ix_buf.length/3; var uv_0u, uv_0v, uv_1u, uv_1v, uv_2u, uv_2v; for (i = 0, ibase = 0;i { tbase = ix_buf[ibase++] vbase = tbase poss[0].x = pos_buf[vbase++]; uv_0u = tx_buf[tbase++]; poss[0].y = pos_buf[vbase++]; uv_0v = tx_buf[tbase]; if (z_clip && (pos_buf[vbase] 1)) {ibase += 2; continue;} tbase = ix_buf[ibase++] vbase = tbase poss[1].x = pos_buf[vbase++]; uv_1u = tx_buf[tbase++]; poss[1].y = pos_buf[vbase++]; uv_1v = tx_buf[tbase]; if (z_clip && (pos_buf[vbase] 1)) {++ibase; continue;} tbase = ix_buf[ibase++] vbase = tbase poss[2].x = pos_buf[vbase++]; uv_2u = tx_buf[tbase++]; poss[2].y = pos_buf[vbase++]; uv_2v = tx_buf[tbase]; if (z_clip && (pos_buf[vbase] 1)) {continue;} var vad = [ poss[1].x - poss[0].x , poss[1].y - poss[0].y ]; var vbd = [ poss[2].x - poss[0].x , poss[2].y - poss[0].y ]; var vcd = [ poss[2].x - poss[1].x , poss[2].y - poss[1].y ]; // z component of cross product if( (((vad[0] * vcd[1]) - (vad[1] * vcd[0]))*culling) continue; if (color_polygon) { g.fillstyle = uv_0u; g.beginpath(); g.moveto(poss[0].x, poss[0].y); g.lineto(poss[1].x, poss[1].y); g.lineto(poss[2].x, poss[2].y); g.fill(); continue; } var va = [ uv_1u - uv_0u , uv_1v - uv_0v ]; var vb = [ uv_2u - uv_0u , uv_2v - uv_0v ]; va[0] *= w; va[1] *= h; vb[0] *= w; vb[1] *= h; m._11 = va[0]; m._12 = va[1]; m._21 = vb[0]; m._22 = vb[1]; var im = m.getinvert(); if (!im) { continue;} var a = im._11 * vad[0] + im._12 * vbd[0]; var b = im._21 * vad[0] + im._22 * vbd[0]; var c = im._11 * vad[1] + im._12 * vbd[1]; var d = im._21 * vad[1] + im._22 * vbd[1]; var wu = uv_0u * w; var hv = uv_0v * h; var du = wu * a + hv * b; var dv = wu * c + hv * d; g.save(); g.beginpath(); g.moveto(poss[0].x, poss[0].y); g.lineto(poss[1].x, poss[1].y); g.lineto(poss[2].x, poss[2].y); g.clip(); g.transform(a, c, b, d, poss[0].x - du, poss[0].y - dv); // bounds var bx = [wu, wu+va[0], wu+vb[0]]; var by = [hv, hv+va[1], hv+vb[1]]; bx.sort(p3d.num_cmp); by.sort(p3d.num_cmp); var bw = bx[2] - bx[0]; var bh = by[2] - by[0]; if ((bx[0]+bw) if ((by[0]+bh) if (bx[0] >= 1) {bx[0]--; bw++;} if (by[0] >= 1) {by[0]--; bh++;} g.drawimage(this.texture, bx[0], by[0], bw, bh, bx[0], by[0], bw, bh); /* if (shade_clr) { g.fillstyle = shade_clr; g.fillrect(bx[0], by[0], bw, bh); } */ g.restore(); } } function vec3(_x, _y, _z) { this.x = _x || 0; this.y = _y || 0; this.z = _z || 0; } vec3.prototype = { zero: function() { this.x = this.y = this.z = 0; }, sub: function(v) { this.x -= v.x; this.y -= v.y; this.z -= v.z; return this; }, add: function(v) { this.x += v.x; this.y += v.y; this.z += v.z; return this; }, copyfrom: function(v) { this.x = v.x; this.y = v.y; this.z = v.z; return this; }, norm:function() { return math.sqrt(this.x*this.x + this.y*this.y + this.z*this.z); }, normalize: function() { var nrm = math.sqrt(this.x*this.x + this.y*this.y + this.z*this.z); if (nrm != 0) { this.x /= nrm; this.y /= nrm; this.z /= nrm; } return this; }, smul: function(k) { this.x *= k; this.y *= k; this.z *= k; return this; }, dpwith: function(v) { return this.x*v.x + this.y*v.y + this.z*v.z; }, cp: function(v, w) { this.x = (w.y * v.z) - (w.z * v.y); this.y = (w.z * v.x) - (w.x * v.z); this.z = (w.x * v.y) - (w.y * v.x); return this; }, tostring: function() { return this.x + , + this.y + , + this.z; } } function m44(cpy) { if (cpy) this.copyfrom(cpy); else { this.ident(); } } m44.prototype = { ident: function() { this._12 = this._13 = this._14 = 0; this._21 = this._23 = this._24 = 0; this._31 = this._32 = this._34 = 0; this._41 = this._42 = this._43 = 0; this._11 = this._22 = this._33 = this._44 = 1; return this; }, copyfrom: function(m) { this._11 = m._11; this._12 = m._12; this._13 = m._13; this._14 = m._14; this._21 = m._21; this._22 = m._22; this._23 = m._23; this._24 = m._24; this._31 = m._31; this._32 = m._32; this._33 = m._33; this._34 = m._34; this._41 = m._41; this._42 = m._42; this._43 = m._43; this._44 = m._44; return this; }, transvec3: function(out, x, y, z) { out[0] = x * this._11 + y * this._21 + z * this._31 + this._41; out[1] = x * this._12 + y * this._22 + z * this._32 + this._42; out[2] = x * this._13 + y * this._23 + z * this._33 + this._43; out[3] = x * this._14 + y * this._24 + z * this._34 + this._44; }, transvec3rot: function(out, x, y, z) { out[0] = x * this._11 + y * this._21 + z * this._31; out[1] = x * this._12 + y * this._22 + z * this._32; out[2] = x * this._13 + y * this._23 + z * this._33; }, perspectivelh: function(vw, vh, z_near, z_far) { this._11 = 2.0*z_near/vw; this._12 = 0; this._13 = 0; this._14 = 0; this._21 = 0; this._22 = 2*z_near/vh; this._23 = 0; this._24 = 0; this._31 = 0; this._32 = 0; this._33 = z_far/(z_far-z_near); this._34 = 1; this._41 = 0; this._42 = 0; this._43 = z_near*z_far/(z_near-z_far); this._44 = 0; return this; }, lookatlh: function(aup, afrom, aat) { var ax = new vec3(); var ay = new vec3(); var az = new vec3(aat.x, aat.y, aat.z); az.sub(afrom).normalize(); ax.cp(aup, az).normalize(); ay.cp(az, ax); this._11 = ax.x; this._12 = ay.x; this._13 = az.x; this._14 = 0; this._21 = ax.y; this._22 = ay.y; this._23 = az.y; this._24 = 0; this._31 = ax.z; this._32 = ay.z; this._33 = az.z; this._34 = 0; this._41 = -afrom.dpwith(ax); this._42 = -afrom.dpwith(ay); this._43 = -afrom.dpwith(az); this._44 = 1; return this; }, mul: function(a, b) { this._11 = a._11*b._11 + a._12*b._21 + a._13*b._31 + a._14*b._41; this._12 = a._11*b._12 + a._12*b._22 + a._13*b._32 + a._14*b._42; this._13 = a._11*b._13 + a._12*b._23 + a._13*b._33 + a._14*b._43; this._14 = a._11*b._14 + a._12*b._24 + a._13*b._34 + a._14*b._44; this._21 = a._21*b._11 + a._22*b._21 + a._23*b._31 + a._24*b._41; this._22 = a._21*b._12 + a._22*b._22 + a._23*b._32 + a._24*b._42; this._23 = a._21*b._13 + a._22*b._23 + a._23*b._33 + a._24*b._43; this._24 = a._21*b._14 + a._22*b._24 + a._23*b._34 + a._24*b._44; this._31 = a._31*b._11 + a._32*b._21 + a._33*b._31 + a._34*b._41; this._32 = a._31*b._12 + a._32*b._22 + a._33*b._32 + a._34*b._42; this._33 = a._31*b._13 + a._32*b._23 + a._33*b._33 + a._34*b._43; this._34 = a._31*b._14 + a._32*b._24 + a._33*b._34 + a._34*b._44; this._41 = a._41*b._11 + a._42*b._21 + a._43*b._31 + a._44*b._41; this._42 = a._41*b._12 + a._42*b._22 + a._43*b._32 + a._44*b._42; this._43 = a._41*b._13 + a._42*b._23 + a._43*b._33 + a._44*b._43; this._44 = a._41*b._14 + a._42*b._24 + a._43*b._34 + a._44*b._44; return this; }, translate: function(x, y, z) { this._11 = 1; this._12 = 0; this._13 = 0; this._14 = 0; this._21 = 0; this._22 = 1; this._23 = 0; this._24 = 0; this._31 = 0; this._32 = 0; this._33 = 1; this._34 = 0; this._41 = x; this._42 = y; this._43 = z; this._44 = 1; return this; }, transpose33: function() { var t; t = this._12; this._12 = this._21; this._21 = t; t = this._13; this._13 = this._31; this._31 = t; t = this._23; this._23 = this._32; this._32 = t; return this; }, // opengl style rotation glrotate: function(angle, x, y, z) { var s = math.sin( angle ); var c = math.cos( angle ); var xx = x * x; var yy = y * y; var zz = z * z; var xy = x * y; var yz = y * z; var zx = z * x; var xs = x * s; var ys = y * s; var zs = z * s; var one_c = 1.0 - c; /* this._11 = (one_c * xx) + c; this._21 = (one_c * xy) - zs; this._31 = (one_c * zx) + ys; this._41 = 0; this._12 = (one_c * xy) + zs; this._22 = (one_c * yy) + c; this._32 = (one_c * yz) - xs; this._42 = 0; this._13 = (one_c * zx) - ys; this._23 = (one_c * yz) + xs; this._33 = (one_c * zz) + c; this._43 = 0;