搜索
首页web前端H5教程利用HTML5绘制点线面组成的3D图形的示例_html5教程技巧

玩Canvas玩了有两三个礼拜了,平面的东西玩来玩去也就那样,所以就开始折腾3D了。

  因为Canvas画布终究还是平面的,所以要有3D就得抽象出一个Z轴。然后再把3D坐标转换成2D坐标,画到画布上,再通过旋转等变换效果来产生3D感。做3D一般就是由点到线,然后由线到面。

  【点】

  点的话,之前我有写过关于3D的博文 解析3D标签云,其实很简单 ,这篇博文虽然讲的是用div实现的3D标签云,但是追根到底产生的3D原理是一样的,就是最简单的由点构成的3D了。每一个标签就是一个点。也可以直接看这个DEMO:
2015512164236104.png (344×329)

3DBall
里面的总共有五百个点对象,每个点对象相应的根据他们的Z轴来改变他们的大小和透明度,再平均分布在球面上,就构成了点球体了。

  【线】

  如果知道怎么做点之后,线也就容易了,只要把点连起来就行了。这个没做DEMO,不过也确实不难。就循环moveTo,然后lineTo,线就出来了。

  【面】

  这篇博文主要讲面滴。
二话不说,先上个DEMO吧 :
2015512164305697.png (170×168)

3D立方体

做一个立方体,我用了三个对象:点对象,面对象,以及立方体本身一个对象:

  下面这个是点对象,x,y,z是点的三维坐标,_get2d方法是把三维坐标转换到二维层面来。fallLength是焦距。

XML/HTML Code复制内容到剪贴板
  1. var Vector = function(x,y,z){   
  2.             this.x = x;   
  3.             this.y = y;   
  4.             this.z = z;   
  5.             this._get2d = function(){   
  6.                 var scale = fallLength/(fallLength+this.z);   
  7.                 var x = centerX + this.x*scale;   
  8.                 var y = centerY + this.y*scale;   
  9.                 return {x:x , y:y};   
  10.             }   
  11.         }  


  然后是面对象:

  面对象的属性页很容易理解,一个面就是一个正方形 , v1v2v3v4是面的四个顶点,zIndex这个属性很重要,是代表这个面的层级,是在最外面还是在里面,这个必须要有,这样当用canvas画的时候才能让这个面画在最前面,才不会被其他的面遮盖。zIndex的值也很容易理解,就是顶点z轴坐标的平均值,其实也就是中心点的z轴坐标。颜色就是这个面的颜色啦。

XML/HTML Code复制内容到剪贴板
  1. var Face = function(vector1,vector2,vector3,vector4,color){   
  2.             this.v1 = vector1;   
  3.             this.v2 = vector2;   
  4.             this.v3 = vector3;   
  5.             this.v4 = vector4;   
  6.             this.color = color;   
  7.             this.zIndex = (this.v1.z + this.v2.z + this.v3.z + this.v4.z)/4;   
  8.             this.draw = function(){   
  9.                 ctx.save();   
  10.                 ctx.beginPath();   
  11.                 ctx.moveTo(this.v1._get2d().x , this.v1._get2d().y);   
  12.                 ctx.lineTo(this.v2._get2d().x , this.v2._get2d().y);   
  13.                 ctx.lineTo(this.v3._get2d().x , this.v3._get2d().y);   
  14.                 ctx.lineTo(this.v4._get2d().x , this.v4._get2d().y);   
  15.                 ctx.closePath();   
  16.                 // ctx.fillStyle = "rgba("+parseInt(Math.random()*255)+","+parseInt(Math.random()*255)+","+parseInt(Math.random()*255)+",0.2)";   
  17.                 ctx.fillStyle = this.color;   
  18.                 ctx.fill();   
  19.             }   
  20.         }  


  最后是立方体本身对象:

  因为立方体最后要旋转,所以,立方体对象里面不仅有面对象,还要有点对象,点旋转后才会引起面的旋转。length是立方体的边长,_initVector是初始化立方体的各个顶点,_draw方法就是把所有点形成面,将面放入数组,然后对面进行排序(就是根据面里的zIndex排序),排序好后,调用每个面里的draw方法。立方体就出来了。

XML/HTML Code复制内容到剪贴板
  1. var Cube = function(length){   
  2.             this.length = length;   
  3.             this.faces = [];   
  4.             this.vectors = [];   
  5.         }   
  6.         Cube.prototype = {   
  7.             _initVector:function(){   
  8.                 this.vectors[0] = new Vector(-this.length/2 , -this.length/2 , this.length/2);   
  9.                 this.vectors[1] = new Vector(-this.length/2 , this.length/2 , this.length/2);    
  10.                 this.vectors[2] = new Vector(this.length/2 , -this.length/2 , this.length/2);    
  11.                 this.vectors[3] = new Vector(this.length/2 , this.length/2 , this.length/2);    
  12.                 this.vectors[4] = new Vector(this.length/2 , -this.length/2 , -this.length/2);   
  13.                 this.vectors[5] = new Vector(this.length/2 , this.length/2 , -this.length/2);   
  14.                 this.vectors[6] = new Vector(-this.length/2 , -this.length/2 , -this.length/2);   
  15.                 this.vectors[7] = new Vector(-this.length/2 , this.length/2 , -this.length/2);   
  16.             },   
  17.             _draw:function(){   
  18.                 this.faces[0] = new Face(this.vectors[0] , this.vectors[1] , this.vectors[3] , this.vectors[2] , "#6c6");   
  19.                 this.faces[1] = new Face(this.vectors[2] , this.vectors[3] , this.vectors[5] , this.vectors[4] , "#6cc");   
  20.                 this.faces[2] = new Face(this.vectors[4] , this.vectors[5] , this.vectors[7] , this.vectors[6] , "#cc6");   
  21.                 this.faces[3] = new Face(this.vectors[6] , this.vectors[7] , this.vectors[1] , this.vectors[0] , "#c6c");   
  22.                 this.faces[4] = new Face(this.vectors[1] , this.vectors[3] , this.vectors[5] , this.vectors[7] , "#666");   
  23.                 this.faces[5] = new Face(this.vectors[0] , this.vectors[2] , this.vectors[4] , this.vectors[6] , "#ccc");   
  24.   
  25.                 this.faces.sort(function(a , b){   
  26.                     return b.zIndex - a.zIndex;   
  27.                 });   
  28.                 this.faces.foreach(function(){   
  29.                     this.draw();   
  30.                 })   
  31.             }   
  32.         }  


  立方体做好了,接下来就可以让它动起来了。根据鼠标位置改变立方体转动的角度。rotateX和rotateY方法就是让所有点绕X轴旋转以及绕Y轴旋转。这个的原理我在之前那个博文上好像有说过。。。。如果想了解更多,可以自己去百度一下计算机图形学3D变换。绕X轴和绕Y轴是最简单的旋转矩阵了。当然,如果有兴趣的还可以去搜一下绕任意轴旋转矩阵。。。这个有点复杂,我本来想用它来做个魔方,不过遇到一些问题,暂时还没解决。好吧,扯远了。通过rotateX和rotateY两个方法可以让每个点获得下一帧的位置,在动画循环中重绘。这样,转动的立方体就做出来了。

XML/HTML Code复制内容到剪贴板
  1. if("addEventListener" in window){   
  2.             window.addEventListener("mousemove" , function(event){   
  3.                 var x = event.clientX - canvas.offsetLeft - centerX;   
  4.                 var y = event.clientY - canvas.offsetTop - centerY;   
  5.                 angleY = x*0.0001;   
  6.                 angleX = y*0.0001;   
  7.             });   
  8.         }   
  9.         else {   
  10.             window.attachEvent("onmousemove" , function(event){   
  11.                 var x = event.clientX - canvas.offsetLeft - centerX;   
  12.                 var y = event.clientY - canvas.offsetTop - centerY;   
  13.                 angleY = x*0.0001;   
  14.                 angleX = y*0.0001;   
  15.             });   
  16.         }   
  17.            
  18.   
  19.         function rotateX(vectors){   
  20.             var cos = Math.cos(angleX);   
  21.             var sin = Math.sin(angleX);   
  22.             vectors.foreach(function(){   
  23.                 var y1 = this.y * cos - this.z * sin;   
  24.                 var z1 = this.z * cos + this.y * sin;   
  25.                 this.y = y1;   
  26.                 this.z = z1;   
  27.             });   
  28.         }   
  29.   
  30.         function rotateY(vectors){   
  31.             var cos = Math.cos(angleY);   
  32.             var sin = Math.sin(angleY);   
  33.             vectors.foreach(function(){   
  34.                 var x1 = this.x * cos - this.z * sin;   
  35.                 var z1 = this.z * cos + this.x * sin;   
  36.                 this.x = x1;   
  37.                 this.z = z1;   
  38.             })   
  39.         }   
  40.   
  41.            
  42.   
  43.         cube = new Cube(80);   
  44.         cube._initVector();   
  45.         function initAnimate(){   
  46.             cube._draw();   
  47.   
  48.             animate();   
  49.         }   
  50.   
  51.         function animate(){   
  52.             ctx.clearRect(0,0,canvas.width,canvas.height)   
  53.                
  54.             rotateY(cube.vectors);   
  55.             rotateX(cube.vectors);   
  56.             cube._draw();   
  57.             if("requestAnimationFrame" in window){   
  58.                 requestAnimationFrame(animate);   
  59.             }   
  60.             else if("webkitRequestAnimationFrame" in window){   
  61.                 webkitRequestAnimationFrame(animate);   
  62.             }   
  63.             else if("msRequestAnimationFrame" in window){   
  64.                 msRequestAnimationFrame(animate);   
  65.             }   
  66.             else if("mozRequestAnimationFrame" in window){   
  67.                 mozRequestAnimationFrame(animate);   
  68.             }   
  69.             else {   
  70.                 setTimeout(animate , 16);   
  71.             }   
  72.         }   


全部代码我就不贴了,DEMO里通过控制台都可以看到。我也没引用其他什么框架之类的,直接copy下来就能用了。

  能写好转动的一个立方体后,多个立方体转动也可以做出来了。
2015512164340019.png (484×463)

戳DEMO:面:3D立方体2    3D立方体线(这个纯碎觉得没有面更酷而已)

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
html5的div一行可以放两个吗html5的div一行可以放两个吗Apr 25, 2022 pm 05:32 PM

html5的div元素默认一行不可以放两个。div是一个块级元素,一个元素会独占一行,两个div默认无法在同一行显示;但可以通过给div元素添加“display:inline;”样式,将其转为行内元素,就可以实现多个div在同一行显示了。

html5中列表和表格的区别是什么html5中列表和表格的区别是什么Apr 28, 2022 pm 01:58 PM

html5中列表和表格的区别:1、表格主要是用于显示数据的,而列表主要是用于给数据进行布局;2、表格是使用table标签配合tr、td、th等标签进行定义的,列表是利用li标签配合ol、ul等标签进行定义的。

html5怎么让头和尾固定不动html5怎么让头和尾固定不动Apr 25, 2022 pm 02:30 PM

固定方法:1、使用header标签定义文档头部内容,并添加“position:fixed;top:0;”样式让其固定不动;2、使用footer标签定义尾部内容,并添加“position: fixed;bottom: 0;”样式让其固定不动。

html5中不支持的标签有哪些html5中不支持的标签有哪些Mar 17, 2022 pm 05:43 PM

html5中不支持的标签有:1、acronym,用于定义首字母缩写,可用abbr替代;2、basefont,可利用css样式替代;3、applet,可用object替代;4、dir,定义目录列表,可用ul替代;5、big,定义大号文本等等。

HTML5中画布标签是什么HTML5中画布标签是什么May 18, 2022 pm 04:55 PM

HTML5中画布标签是“<canvas>”。canvas标签用于图形的绘制,它只是一个矩形的图形容器,绘制图形必须通过脚本(通常是JavaScript)来完成;开发者可利用多种js方法来在canvas中绘制路径、盒、圆、字符以及添加图像等。

html5废弃了哪个列表标签html5废弃了哪个列表标签Jun 01, 2022 pm 06:32 PM

html5废弃了dir列表标签。dir标签被用来定义目录列表,一般和li标签配合使用,在dir标签对中通过li标签来设置列表项,语法“<dir><li>列表项值</li>...</dir>”。HTML5已经不支持dir,可使用ul标签取代。

Html5怎么取消td边框Html5怎么取消td边框May 18, 2022 pm 06:57 PM

3种取消方法:1、给td元素添加“border:none”无边框样式即可,语法“td{border:none}”。2、给td元素添加“border:0”样式,语法“td{border:0;}”,将td边框的宽度设置为0即可。3、给td元素添加“border:transparent”样式,语法“td{border:transparent;}”,将td边框的颜色设置为透明即可。

html5为什么只需要写doctypehtml5为什么只需要写doctypeJun 07, 2022 pm 05:15 PM

因为html5不基于SGML(标准通用置标语言),不需要对DTD进行引用,但是需要doctype来规范浏览器的行为,也即按照正常的方式来运行,因此html5只需要写doctype即可。“!DOCTYPE”是一种标准通用标记语言的文档类型声明,用于告诉浏览器编写页面所用的标记的版本。

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
2 周前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
2 周前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
2 周前By尊渡假赌尊渡假赌尊渡假赌

热工具

Dreamweaver Mac版

Dreamweaver Mac版

视觉化网页开发工具

螳螂BT

螳螂BT

Mantis是一个易于部署的基于Web的缺陷跟踪工具,用于帮助产品缺陷跟踪。它需要PHP、MySQL和一个Web服务器。请查看我们的演示和托管服务。

PhpStorm Mac 版本

PhpStorm Mac 版本

最新(2018.2.1 )专业的PHP集成开发工具

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

mPDF

mPDF

mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),