Saya telah bermain dengan Kanvas selama dua atau tiga minggu, dan bermain dengan objek rata adalah sama, jadi saya mula bermain-main dengan 3D.
Kerana kanvas Kanvas masih rata, jadi jika anda ingin mempunyai 3D, anda mesti mengabstrakkan paksi Z. Kemudian tukar koordinat 3D kepada koordinat 2D, lukiskannya pada kanvas, dan kemudian gunakan putaran dan kesan transformasi lain untuk mencipta perasaan 3D. Melakukan 3D secara amnya melibatkan pergi dari titik ke garis, dan kemudian dari garis ke permukaan.
【Titik】
Jika anda klik padanya, saya telah menulis catatan blog tentang 3D sebelum ini Menghuraikan awan tag 3D sebenarnya sangat mudah Walaupun catatan blog ini bercakap tentang awan tag 3D yang dilaksanakan menggunakan div, tetapi punca utama ialah Prinsip 3D adalah sama, ia adalah 3D termudah yang terdiri daripada mata. Setiap label adalah titik. Anda juga boleh menonton DEMO ini secara terus:
3DBall
Terdapat sejumlah lima ratus objek titik di dalamnya. Setiap objek titik menukar saiz dan ketelusannya mengikut paksi Z mereka, dan kemudian mengagihkannya secara sama rata pada sfera sfera titik.
【Barisan】
Setelah anda tahu cara membuat titik, garisan akan menjadi mudah, hanya sambungkan titik. Saya tidak melakukan DEMO mengenai perkara ini, tetapi ia sebenarnya tidak sukar. Hanya gelung moveTo, kemudian lineTo, dan baris akan keluar.
【Mi】
Catatan blog ini terutamanya bercakap tentang wajah.
Tanpa berlengah lagi, mari buat DEMO dahulu:
Kiub 3D
Untuk membuat kubus, saya menggunakan tiga objek: objek titik, objek luas dan kubus itu sendiri:
Berikut ialah objek titik x, y, z ialah koordinat tiga dimensi bagi titik tersebut. fallLength ialah panjang fokus.
Kod XML/HTMLSalin kandungan ke papan keratan
- var Vektor = fungsi(x,y,z){
-
ini.x = x;
-
ini.y = y
-
ini.z = z;
ini._get2d-
= fungsi(){
var
skala-
= fallLength/(fallLength this.z);
var x
= -
centerX ini.x*skala
var y
= -
centerY ini.y*skala
kembali {x:x, y:y};
-
-
Kemudian khalayak sasaran:
Halaman sifat objek muka mudah difahami Muka adalah segi empat sama, v1v2v3v4 ialah empat bucu muka Atribut zIndex adalah sangat penting luar atau dalam. Ini mestilah Ya, supaya apabila melukis dengan kanvas, permukaan ini boleh dilukis di bahagian hadapan dan tidak akan ditutupi oleh permukaan lain. Nilai zIndex juga mudah difahami Ia ialah koordinat paksi-z purata bagi puncak, yang sebenarnya ialah koordinat paksi-z bagi titik tengah. Warna adalah warna permukaan ini.
Kod XML/HTMLSalin kandungan ke papan keratan
- var Muka = fungsi(vector1,vector2,vector3,vector4,color){
-
ini.v1 = vektor1;
-
ini.v2 = vektor2;
-
ini.v3 = vektor3;
-
ini.v4 = vektor4;
-
warna ini = warna;
-
ini.zIndex = (ini.v1.z ini.v2.z ini.v3.z ini.v4.z)/4;
-
ini.draw = fungsi(){
- ctx.save();
- ctx.beginPath();
- ctx.moveTo(this.v1._get2d().x , this.v1._get2d().y);
- ctx.lineTo(this.v2._get2d().x , this.v2._get2d().y);
- ctx.lineTo(this.v3._get2d().x , this.v3._get2d().y);
- ctx.lineTo(this.v4._get2d().x , this.v4._get2d().y);
- ctx.closePath();
-
// ctx.fillStyle = "rgba(" parseInt()*th2.5. "," parseInt(Math.random()*255) "," parseInt(Math.random()*255) ",0.2)";
-
ctx.fillStyle = ini.warna;
- ctx.fill();
- }
- }
最后是立方体本身对象:
因为立方体最后要旋转,所以,立方体对象里面不仅有面对象,还物莬家才会引起面的旋转。length是立方体的边长,_initVector是初始化立方体的各个顶点,_draw方法就是把所有点形成面,将面放入数组,然后对面进行排序(就是根据面就是根据钎就是根据钎就面面后,调用每个面里的draw方法。立方体就出来了。
Kod XML/HTML复制内容到剪贴板
- var Kiub = fungsi(panjang){
-
ini.panjang = panjang;
-
ini.muka = [];
-
ini.vektor = [];
- }
-
Kiub.prototaip = {
- _initVector:function(){
- this.vectors[0] = new Vector(-this.length/2 , -this.length/2 , this.length/2);
- vektor ini[1] = Vektor baharu(-ini.panjang/2 , ini.panjang/2 , ini.panjang/2);
- ni.vektor[2] = vektor baharu(ini.panjang/2 , -ini.panjang/2 , ini.panjang/2);
- vektor ini[3] = Vektor baharu(ini.panjang/2 , ini.panjang/2 , ini.panjang/2);
- ni.vektor[4] = vektor baharu(ini.panjang/2 , -ini.panjang/2 , -ini.panjang/2);
- ni.vektor[5] = vektor baharu(ini.panjang/2 , ini.panjang/2 , -ini.panjang/2);
- vektor ini[6] = Vektor baharu(-ini.panjang/2 , -ini.panjang/2 , -ini.panjang/2);
- vektor ini[7] = Vektor baharu(-ini.panjang/2 , ini.panjang/2 , -ini.panjang/2);
- },
- _draw:function(){
- this.faces[0] = new Face(this.vectors[0] , this.vectors[1] , this.vectors[3] , this.vectors[2] "); "#6c6
- this.faces[1] = new Face(this.vectors[2] , this.vectors[3] , this.vectors[5] , this.vectors[4] , "#6cc");
- this.faces[2] = new Face(this.vectors[4] , this.vectors[5] , this.vectors[7] , this.vectors[6] , "#cc6"
- this.faces[3] = new Face(this.vectors[6] , this.vectors[7] , this.vectors[1] , this.vectors[0] "); "#c6c
- this.faces[4] = new Face(this.vectors[1] , this.vectors[3] , this.vectors[5] , this.vectors[7] "); "#666
- this.faces[5] = new Face(this.vectors[0] , this.vectors[2] , this.vectors[4] , this.vectors[6] , "#ccc");
-
- this.faces.sort(function(a , b){
- kembali b.zIndex - a.zIndex;
- });
- this.faces.foreach(function(){
- this.draw();
- })
- }
- }
立方体做好了,接下来就可以让它动起来了。根据鼠标位置改来就可以让它动起来了。根据鼠标位置改来就可以让它动起来了。根据鼠标位置改召位置改让它动起来了。 X和rotateY方法就是让所有点绕X轴旋转以及绕Y轴旋转。这个的原理我在之前那个博文上好像有说过。。。。如果想了解更多,可以自己去瀾中度过了变换。绕X轴和绕Y轴是最简单的旋转矩阵了。当然,如果有兴趣的还可以去搜一下绕任意轴旋转矩阵。。。这个有点复杂, 我本来想用它来做个魔方, 不过遇到一些问题, 暂时还没解决。好吧, 扯远了。通过 Rotatex和rotateY两个方法可以让每个点获得下一帧的位置,在动画循环中重绘。这样得下一帧的位置,在动画循环中重绘。这样,佬小的罬小了。
Kod XML/HTML复制内容到剪贴板
- if("addEventListener" dalam tetingkap){
- window.addEventListener("mousemove" , function(event){
-
var x = acara.clientX - kanvas.offset Kiri; -
-
var y = acara.clientY - canvas.offsetTopY; -
-
sudutY = x*0.0001;
-
angleX = y*0.0001;
- });
- }
- lain {
- window.attachEvent("onmousemove" , function(event){
-
var x = acara.clientX - kanvas.offset Kiri; -
-
var y = acara.clientY - canvas.offsetTopY; -
-
sudutY = x*0.0001;
-
angleX = y*0.0001;
- });
- }
-
-
- fungsi rotateX(vektor){
-
var kos = Matematik.cos(angleX);
-
var dosa = Math.sin(angleX);
- vectors.foreach(function(){
-
var y1 = ini.y * cos - ini;.z * dosa
-
var z1 = ini.z * cos ini;.y * dosa
-
ini.y = y1;
-
ini.z = z1;
- });
- }
-
- fungsi putarY(vektor){
-
var cos = Math.cos(angleY);
-
var dosa = Matematik.sin(angleY);
- vectors.foreach(function(){
-
var x1 = ini.x * cos - ini;.z * dosa
-
var z1 = ini.z * cos ini;.x * dosa
-
ini.x = x1;
-
ini.z = z1;
- })
- }
-
-
-
-
kiub = baharu Kiub(80);
- kubus._initVector();
- fungsi initAnimate(){
- kubus._draw();
-
- bernyawa();
- }
-
- fungsi menghidupkan(){
- ctx.clearRect(0,0,canvas.width,canvas.height)
-
- putarY(kubus.vektor);
- rotateX(cube.vectors);
- kubus._draw();
- jika("requestAnimationFrame" dalam tetingkap){
- permintaanAnimationFrame(animate);
- }
- lain jika("webkitRequestAnimationFrame" dalam tetingkap){
- webkitRequestAnimationFrame(animate);
- }
- lain jika("msRequestAnimationFrame" dalam tetingkap){
- msRequestAnimationFrame(animate);
- }
- lain jika("mozRequestAnimationFrame" dalam tetingkap){
- mozRequestAnimationFrame(animate);
- }
- lain {
- setTimeout(animate , 16);
- }
- }
Saya tidak akan menyiarkan semua kod, anda boleh melihatnya melalui konsol dalam DEMO. Saya tidak merujuk mana-mana rangka kerja lain atau apa-apa seperti itu, hanya salin dan anda boleh menggunakannya.
Selepas anda boleh menulis kiub berputar, anda juga boleh membuat berbilang kiub berputar.
Poke DEMO: Muka: 3D Cube 2 3D Cube Line (Saya rasa ini lebih sejuk tanpa muka)