JavaScript对XML的一些DOM操作(续篇 three.js上路)

JavaScript对XML的一些DOM操作(续篇 three.js上路)

原文 JavaScript对XML的一些DOM操作

上次完成了对XML的解析程序后,由kylin审阅后,被严肃的批评了,太没有面向对象的概念了,设计思路停留在面向过程中无法自拔,JavaScript还弄个啥多维数组,不开窍。

因此,改写了一下原有程序,开始补习设计模式。顺带 弄了个Three.js升级下效果。

题外话 啥是Three.js

Three.js中文站

Three.js是基于原生WebGL封装运行的三维引擎,在所有WebGL引擎中,Three.js是国内文资料最多、使用最广泛的三维引擎。

知乎

提到 Three.js,就必须说一下 OpenGL 和 WebGL。
OpenGL 大概许多人都有所听闻,它是最常用的跨平台图形处理开源库。
WebGL 就是基于 OpenGL 设计的面向 web 的 3D 图形标准,它提供了一系列 JavaScript API,通过这些 API 进行图形渲染,系统硬件会加速 3D 渲染,从而获得较高性能。
而 Three.js 是 JavaScript 编写的 WebGL 第三方库,通过对 WebGL 接口的封装与简化而形成的一个易用的图形库。
WebGL 与 Three.js 对比
通过上面的简介,我们知道 WebGL 和 Three.js 都可以进行 Web 端的 3D 图形开发。那问题来了,既然我们有了 WebGL,为什么还需要 Three.js?
这是因为前端工程师想要短时间上手 WebGL 还是挺有难度的。
WebGL 门槛相对较高,计算机图形学需要相对较多的数学知识。一个前端程序员或许还熟悉解析几何,但是还熟悉线性代数的应该寥寥无几了(比如求个逆转置矩阵试试?),更何况使用中强调矩阵运算中的物理意义,这在教学中也是比较缺失。
于是,Three.js 对 WebGL 提供的接口进行了非常好的封装,简化了很多细节,大大降低了学习成本。并且,几乎没有损失 WebGL 的灵活性。
因此,从 Three.js 入手是值得推荐的,这可以让你在较短的学习后就能面对大部分需求场景。

总的来说 就是目前在web上如果你想做3D的开发,Three.js是最佳的选择。易上手,灵活性高。

学习资料 推荐 郭隆邦 老师的中文站。 当然英语水平到位,看官网更合适。我这种英语渣还是老老实实看中文站的说~T_T

Three.js官网
Three.js中文站

项目

回到项目,还是上次那个程序

先上效果,上次的是将XML文件解析,平面图形化,这次就多做一步,做成了3D的实体,并且做了一个恶趣味小功能,点击板件,那个板件就会飘出来。
在这里插入图片描述

Tips
  1. Three.js核心
    a.场景
    b.相机
    c.渲染器
    三者缺一不可,场景需要添加场景对象 比如光源(点光源,平行光源,环境光源) 网格模型,模型又由立方体和材质组成。 这些多看手册,不是很难。
    相机就是正交相机和透视相机。
    渲染器主要就是刷新渲染的问题。

  2. 编码过程中遇到的小问题:
    a 设置camera.lookat() 一直显示不正常,不是按照角度来的,后来调试代码才发现。camara.lookat() 一定要在设置camera.position之后,如果相机的位置都没确定 何来lookat的偏置。
    b 选择一个物体,参考了这篇blog,讲的很清楚,但是有一个问题要注意,最后的一句其实是有一点问题的,对于原例是没问题,因为原例中每个实体都是建立的一种新的材质。所以选中时更改object的material对象的颜色属性是ok的,但是对于我这个项目,材质是共用的。如果更改就是更改了所有的material,大家一起变红。

intersects[ i ].object.material.color.set( 0xff0000 )
源码
<!doctype html>
<html>

<head>
    <meta charset="utf-8">
</head>

<body>
    <div>
        <input type="file" id="files" style="display: none" onchange="fileImport();">
        <input type="button" id="fileImport" value="导入">
    </div>
    <div id="table">
    </div>
    <canvas id="3Dtable">
    </canvas>
    <script src="jquery-3.4.1.js"></script>
    <script src="Three.js"></script>
    <script src=".\three.js-master\examples\js\controls\OrbitControls.js"></script>
    <script>
        $("#fileImport").click(function () {
            $("#files").click();
        })
        function fileImport() {

            var loadMNO = function (cb) {
                var selectedFile = document.getElementById('files').files[0];
                var name = selectedFile.name;
                var size = selectedFile.size;
                var reader = new FileReader();//这是核心,读取操作就是由它完成.
                reader.readAsText(selectedFile);//读取文件的内容,也可以读取文件的URL
                reader.onload = function () {
                    //当读取完成后回调这个函数,然后此时文件的内容存储到了result中,直接操作即可
                    var myxml = this.result
                    cb(this.result)
                }
            }
            loadMNO(function (cb1) {
                var parser = new DOMParser();
                var xmlDoc2 = parser.parseFromString(cb1, 'text/xml')

                var parts = new Object

                var listNum = 0

                var FOGLIO = xmlDoc2.getElementsByTagName("FOGLIO")
                for (var a = 0; a < FOGLIO.length; a++) {
                    var nome = FOGLIO[a].getElementsByTagName("NOME")
                    for (var b = 0; b < nome.length; b++) {
                        var PROFILO = nome[b].getElementsByTagName("PROFILO")

                        //绘制幕布
                        var size = PROFILO[0].getElementsByTagName("VARIABILE")
                        for (var i = 0; i < size.length; i++) {
                            if (size[i].getAttribute('NAME') == "LPX" || size[i].getAttribute('name') == "LPX")
                                var xsize = parseInt(size[i].childNodes[0].nodeValue)
                            if (size[i].getAttribute('NAME') == "LPY" || size[i].getAttribute('name') == "LPY")
                                var ysize = parseInt(size[i].childNodes[0].nodeValue)
                            if (size[i].getAttribute('NAME') == "LPZ" || size[i].getAttribute('name') == "LPZ")
                                var zsize = parseInt(size[i].childNodes[0].nodeValue)

                        }

                        var drawTag = PROFILO[0].getElementsByTagName("DRW")
                        var min_max = drawTag[0].getElementsByTagName("Original")


                        var pos = PROFILO[0].getElementsByTagName("POS")
                        for (var k = 0; k < pos.length; k++) {
                            var xpos = pos[k].getElementsByTagName("X")
                            var ypos = pos[k].getElementsByTagName("Y")
                            var deg = pos[k].getElementsByTagName("DEG")
                            parts = { board: a, xsize: xsize, ysize: ysize, zsize: zsize, x: parseInt(xpos[0].childNodes[0].nodeValue), y: parseInt(ypos[0].childNodes[0].nodeValue), deg: parseInt(deg[0].childNodes[0].nodeValue), minX: parseInt(min_max[0].getAttribute("minX")), minY: parseInt(min_max[0].getAttribute("minY")), maxX: parseInt(min_max[0].getAttribute("maxX")), maxY: parseInt(min_max[0].getAttribute("maxY")) }
                            partList[listNum] = parts
                            listNum++
                        }

                    }
                }
                draw()
                draw3d()
            });

            var standard = function (input) {

                var width = 0.8 * window.innerWidth;
                var height = window.innerHeight;
                return parseFloat(input / bordX * width)
            }


            var bordX = 2440
            var bordY = 1220
            var partList = []
            var partListFor3D = []

            var reverseY = function (input) {
                return bordY - input
            }


            function draw() {
                var clear = document.getElementById("table")
                while (clear.hasChildNodes()) {
                    clear.removeChild(clear.firstChild)
                }

                n = 0
                for (i = 0; i < partList[partList.length - 1].board + 1; i++) {

                    var oDiv = document.createElement('div');
                    canvas = document.createElement('canvas');

                    oDiv.appendChild(canvas)
                    document.getElementById("table").appendChild(oDiv)
                    var width = canvas.width = 0.8 * window.innerWidth;
                    var height = canvas.height = window.innerHeight;
                    var ctx = canvas.getContext('2d')
                    ctx.fillStyle = 'rgb(197, 197, 197)';
                    ctx.fillRect(0, 0, width, 0.5 * width)

                    for (j = n; (j < partList.length) && (partList[j].board < i + 1); j++, n = j) {
                        ctx.fillStyle = 'rgb(231, 143, 43)';
                        if (partList[j].deg == 0)
                            ctx.fillRect(standard(partList[j].x + partList[j].minX), standard(reverseY(partList[j].y + partList[j].minY)), standard(partList[j].maxX - partList[j].minX), standard(-partList[j].maxY + partList[j].minY))
                        if (partList[j].deg == -90 || partList[j].deg == 270)
                            ctx.fillRect(standard(partList[j].x + partList[j].minY), standard(reverseY(partList[j].y - partList[j].minX)), standard(partList[j].maxY - partList[j].minY), standard(partList[j].maxX - partList[j].minX))
                        if (partList[j].deg == 90)
                            ctx.fillRect(standard(partList[j].x - partList[j].minY), standard(reverseY(partList[j].y + partList[j].minX)), standard(-partList[j].maxY + partList[j].minY), standard(-partList[j].maxX + partList[j].minX))
                    }
                }

            }


            function draw3d() {
                    m=0
                    var _3dModelList = []
                    var scene = new THREE.Scene()
                    // var geometry = new THREE.BoxGeometry(100, 100, 100)
                    var material = new THREE.MeshLambertMaterial({ color: 0XC55724 })

                    for (r = 0; r < partList[partList.length - 1].board + 1; r++) {
                    var MDF = new THREE.MeshLambertMaterial({ color: 0XC5C5C5 })
                    var MdfBoard = new THREE.BoxGeometry(bordX, bordY, 20)
                    var meshMDF = new THREE.Mesh(MdfBoard, MDF)
                    scene.add(meshMDF)
                    meshMDF.position.set(bordX/ 2+3000*r, bordY / 2, -20)
                    console.log(meshMDF.position)
                    for (j = m; (j < partList.length) && (partList[j].board < r+ 1); j++, m = j) {
                        partListFor3D[j] = partList[j]
                        // console.log(partListFor3D[j].deg)
                        console.log(r+"  "+j)
                        console.log(partList[j].board)
                        if (partListFor3D[j].deg == 0) {

                            partListFor3D[j].x = parseFloat(partListFor3D[j].x) +parseFloat(partListFor3D[j].minX) + parseFloat(partListFor3D[j].maxX-partListFor3D[j].minX) / 2+r*3000
                            partListFor3D[j].y = parseFloat(partListFor3D[j].y) + parseFloat(partListFor3D[j].minY) +parseFloat(partListFor3D[j].maxY-partListFor3D[j].minY) / 2
                            partListFor3D[j].xsize=parseFloat(partListFor3D[j].maxX-partListFor3D[j].minX)
                            partListFor3D[j].ysize=parseFloat(partListFor3D[j].maxY-partListFor3D[j].minY)
                        }
                        if (partList[j].deg == -90 || partList[j].deg == 270) {
                            var temp
                            temp = partListFor3D[j].ysize
                            partListFor3D[j].ysize = parseFloat(partListFor3D[j].maxX-partListFor3D[j].minX)
                            partListFor3D[j].xsize = parseFloat(partListFor3D[j].maxY-partListFor3D[j].minY)
                            partListFor3D[j].x =  parseFloat(partListFor3D[j].x) + parseFloat(partListFor3D[j].xsize)/2+partListFor3D[j].minY+r*3000
                            partListFor3D[j].y = parseFloat(partListFor3D[j].y) - parseFloat(partListFor3D[j].ysize)/2-partListFor3D[j].minX
                        }
                        if (partList[j].deg == 90) {
                            partListFor3D[j].ysize = parseFloat(partListFor3D[j].maxX-partListFor3D[j].minX)
                            partListFor3D[j].xsize = parseFloat(partListFor3D[j].maxY-partListFor3D[j].minY)
                            partListFor3D[j].x = parseFloat(partListFor3D[j].x) + parseFloat(partListFor3D[j].xsize)/2-partListFor3D[j].maxY+r*3000
                            partListFor3D[j].y = parseFloat(partListFor3D[j].y) + parseFloat(partListFor3D[j].ysize)/2+partListFor3D[j].minX
                        }

                    }
                    }

                    for (i = 0; i < partListFor3D.length; i++) {
                        var _3dModel = new THREE.BoxGeometry(partListFor3D[i].xsize, partListFor3D[i].ysize, partListFor3D[i].zsize)
                        var mesh = new THREE.Mesh(_3dModel, material)
                        _3dModelList[i] = mesh
                        scene.add(mesh)
                        mesh.position.set(partListFor3D[i].x, partListFor3D[i].y, 0)
                    }
                    var raycaster = new THREE.Raycaster();
                    var mouse = new THREE.Vector2();
                    var goUp = function (e) {
                        // console.log(e)
                        function up() {

                            e.position.z += 0.05

                        }
                        setInterval(up, 1.0 / 60)
                    }

                    function onMouseClick(event) {

                        //通过鼠标点击的位置计算出raycaster所需要的点的位置,以屏幕中心为原点,值的范围为-1到1.

                        mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
                        mouse.y = - (event.clientY / window.innerHeight) * 2 + 1;

                        // 通过鼠标点的位置和当前相机的矩阵计算出raycaster
                        raycaster.setFromCamera(mouse, camera);

                        // 获取raycaster直线和所有模型相交的数组集合
                        var intersects = raycaster.intersectObjects(scene.children);

                        console.log(intersects);
                        //  mesh.material.color.set(0xff0000)
                        //将所有的相交的模型的颜色设置为红色,如果只需要将第一个触发事件,那就数组的第一个模型改变颜色即可
                        for (var i = 0; i < intersects.length; i++) {

                            goUp(intersects[0].object)


                        }

                    }

                    window.addEventListener('click', onMouseClick, false);

                    var point1 = new THREE.PointLight(0xffffff)
                    var point2 = new THREE.PointLight(0xffffff)
                    point1.position.set(1000, 500, 1000)
                    point2.position.set(5000, 200, 1000)
                    scene.add(point1)
                    scene.add(point2)
                    var ambient = new THREE.AmbientLight(0x444444)
                    scene.add(ambient)
                    var width1 = window.innerWidth
                    var height1 = window.innerHeight
                    var k = width1 / height1
                    var s = 3000
                    var axisHelper = new THREE.AxesHelper(2500)
                    //scene.add(axisHelper)
                    var camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s, 1, 100000)
                    camera.position.set(300, 600, 5000)
                    camera.lookAt(meshMDF.position)
                    console.log(meshMDF.position)
                    var renderer = new THREE.WebGLRenderer({ canvas: document.getElementById("3Dtable") });
                    renderer.setSize(width1, height1)
                    renderer.setClearColor(0xb9d3ff, 1)
                    document.body.appendChild(renderer.domElement)
                    function render() {
                        renderer.render(scene, camera)
                        requestAnimationFrame(render)
                    }
                    render();
                    var controls = new THREE.OrbitControls(camera, renderer.domElement);
                    //controls.addEventListener('change',render)
                
            }
            }

    </script>

</body>

</html>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值