化石原创文章,转载请注明来源并保留原文链接


WebGL中,使用html本身的元素做UI能借助浏览器本身的渲染能力和布局能力,在大多数场合都非常有效。刚入手WebGL的时候,很多人跟本人一样,可能缺乏对HTML的深度认知,因此不知道怎么能让html元素和WebGL的目标canvas做一定的整合。这里做一定的步骤说明。

1、使用一个div,包起canvas和canvas重合的元素。

2、canvas的style,带上:position:absolute;

3、和canvas重合的元素,假设用一个div都包起来的话,这个div同样带上:position:absolute;

原理说明:

1、position: absolute 这个会让div或者canvas都以父元素的位置绝对定位。

2、因为canvas和跟它重合的元素都是以同一个div做父元素,因此,两者就能够在位置上重合。

3、在这个做法上,canvas需要写在UI元素的前面。也就是让浏览器先渲染canvas,再渲染UI。

一段演示的html代码如下:

<html>

<head>
    <title>Test</title>
</head>

<body>
    <div id="mainLayout" style="width: 1280; margin: auto; ">
        <p>这里是html的元素,不在canvas重合区域的部分</p>
    </div>
    <div id="canvasLayout" style="width: 1280; margin: auto; ">
        <canvas id="canvas" style="position: absolute; width: 500px; height: 500px;"></canvas>
        <div id="canvashud" style="position: absolute;">
            <p>这里是canvas重合的部分的字</p>
            <button>这里是canvas重合的部分的按钮</button>
        </div>
    </div>
    <script>
         var canvas = document.getElementById('canvas');
         var gl = canvas.getContext('experimental-webgl');
         gl.clearColor(0.5, 0.5, 0.5, 0.9);
         gl.clear(gl.COLOR_BUFFER_BIT);
    </script>
</body>

</html>

化石原创文章,转载请注明来源并保留原文链接



化石原创文章,转载请注明来源并保留原文链接


1、使用了一个config.js,把bootstrap、vuejs、jquery加载。jquery本身会导出jquery的全局变量。config.js内容如下:

'use strict';

requirejs.config({

    baseUrl: '.',

    paths: {
        'jquery': 'plugin/jquery-3.4.1.min',
        'bootstrap': 'plugin/bootstrap.min',
        'popper': 'plugin/popper.min',
        'vue': 'plugin/vue.min',
    },

    shim: {
        'bootstrap': {
            deps: ['jquery', 'popper'],
            exports: 'bootstrap'
        },
        'vue': {
            deps: ['jquery'],
            exports: 'vue'
        },
    }
});

2、使用到jquery、vue的地方,只要在config.js被加载后,就可以如下用:

define(['jquery', 'vue'], function ($, Vue) {
    function mainPageModule() { };

    mainPageModule.prototype.run = function () {
        $('#mainLayout').load('sub.html', function() {
            var vm = new Vue({
                el: '#vue_det',
                data: {
                    firstname: "Ria",
                    lastname: "Singh",
                    htmlcontent: "<div><h1>Vue Js Template</h1></div>"
                }
            });
        });
    };

    return mainPageModule;
});

为保证config.js加载优先,因此在html中,该文件使用data-main加载

 <script src='plugin/require.js' data-main='config'></script> 

3、bootstrap涉及的javascript文件,已经在第1步做好了。bootstrap主要是需要jquery和popper两个js。因此上面有popper的字眼。测试的html内容:

<div id="vue_det">
    <h1>Firstname : {{firstname}}</h1>
    <h1>Lastname : {{lastname}}</h1>
    <div>{{htmlcontent}}</div>
    <button type="button" class="btn btn-primary">Primary</button>
</div>
<div class="card" style="width: 18rem;">
    <img src="./image/color48.png" style="width:32; height:32;" class="card-img-top" alt="...">
    <div class="card-body">
        <h5 class="card-title">Card title</h5>
        <p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's
            content.</p>
        <a href="#" class="btn btn-primary">Go somewhere</a>
    </div>
</div>

演示结果如图:

图1,vue bootstrap jquery requirejs演示

工程源码(使用visual studio code 1.40版本):

https://github.com/jycgame/workingframework/tree/master


化石原创文章,转载请注明来源并保留原文链接



化石原创文章,转载请注明来源并保留原文链接


把相关的东西放在不同的html中会让大html变的小很多,这样在开发的时候容易组织结构、查找东西。

一、使用JQuery

1、定义一个sub.html,内容如下

 <div> This is an included file </div> 

2、定义一个sample.html,内容如下

<html> 
	  <head> 
	    <script src="/jquery.js"></script> 
	    <script> 
	    $(function(){
	      $("#Content").load("sub.html"); 
	    });
    </script> 
  </head> 

<body> 
     <div id="Content"></div>
  </body> 
</html>

这样,在加载sample的时候,sub会被加载并加入到sample的结构中。

二、使用AngularJS

1、定义一个index.html,内容如下

<html>
   <head>
      <title>Angular JS Includes</title>
      <script src = "./angular.min.js">
      </script>
      
      <style>
         table, th , td {
            border: 1px solid grey;
            border-collapse: collapse;
            padding: 5px;
         }
         table tr:nth-child(odd) {
            background-color: #f2f2f2;
         }
         table tr:nth-child(even) {
            background-color: #ffffff;
         }
      </style>
   </head>
   
   <body>
      <h2>AngularJS Sample Application</h2>
      
      <div ng-app = "mainApp" ng-controller = "studentController">
         <div ng-include = "'./main.html'"></div>
         <div ng-include = "'./subjects.html'"></div>
      </div>
      
      <script>
         var mainApp = angular.module("mainApp", []);
         
         mainApp.controller('studentController', function($scope) {
            $scope.student = {
               firstName: "Mahesh",
               lastName: "Parashar",
               fees:500,
               
               subjects:[
                  {name:'Physics',marks:70},
                  {name:'Chemistry',marks:80},
                  {name:'Math',marks:65},
                  {name:'English',marks:75},
                  {name:'Hindi',marks:67}
               ],
               fullName: function() {
                  var studentObject;
                  studentObject = $scope.student;
                  return studentObject.firstName + " " + studentObject.lastName;
               }
            };
         });
      </script>
      
   </body>
</html>

2、定义一个main.html

<table border="0">
    <tr>
        <td>Enter first name:</td>
        <td><input type="text" ng-model="student.firstName"></td>
    </tr>

    <tr>
        <td>Enter last name: </td>
        <td><input type="text" ng-model="student.lastName"></td>
    </tr>

    <tr>
        <td>Name: </td>
        <td>{{student.fullName()}}</td>
    </tr>
</table>

3、再定义一个subjects.html

<p>Subjects:</p>
<table>
    <tr>
        <th>Name</th>
        <th>Marks</th>
    </tr>

    <tr ng-repeat="subject in student.subjects">
        <td>{{ subject.name }}</td>
        <td>{{ subject.marks }}</td>
    </tr>
</table>

这样,在index.html加载的时候,main.html和subjects.html会被加载并合并到index.html中的studentController下面对应的两个div中。


化石原创文章,转载请注明来源并保留原文链接



化石原创文章,转载请注明来源并保留原文链接


gCoord 地理坐标系转换工具,支持WGS84/GCJ02/BD09等常用坐标系互转 。做国内项目的时候比较方便。

https://github.com/hujiulong/gcoord

最简单的方式是直接引用:

<script src="https://unpkg.com/gcoord/dist/gcoord.js"></script>

想作为服务器本地的:

npm install gcoord --save

然后在npm安装gcoord的目录的node_modules\gcoord\dist下,拷贝gcoord.js到项目中,然后通过本地路径引用即可。譬如:

<script type="text/javascript" src="./3rdParty/gcoord.js"></script>

化石原创文章,转载请注明来源并保留原文链接



化石原创文章,转载请注明来源并保留原文链接


项目中,倾斜摄影模型从osgb而来,使用3dtile工具转化成了3d tiles格式供Cesium使用。然后服务器会给出一定的坐标。倾斜摄影模型的坐标和服务器给出的坐标都是基于wgs84的。

如果使用google地图,只使用卫星地图( http://mt1.google.cn/vt/lyrs=s&hl=zh-CN&x={x}&y={y}&z={z}&s=Gali )的话,那么倾斜摄影和服务器给的坐标,都能和卫星地图完美配合。无需做任何事情。

然而地图上使用的时候必须看到道路标识,所以给到Cesium的tiles路径就变成了: http://mt1.google.cn/vt/lyrs=y&hl=zh-CN&x={x}&y={y}&z={z}&gl=cn。

可以看出来,请求的api中,参数lyrs从s变成了y,这个决定了从google服务器上请求下来的瓦片图,带有道路合成。参数也多了一个gl=cn,没有这个参数的话,会发现请求到的瓦片图,道路和卫星图是不匹配的,也就是道路有偏差。

所以瓦片请求路径就成了带gl=cn的那个。

不过使用这个瓦片图,其实google是为了符合中国规范,对图做了偏移。所以,所有wgs84的坐标信息(原来的),在这份地图上看起来都有了错位。因而我们需要解决两个问题:

1、tileset在该地图上的位置改动

2、服务器给到wgs84坐标后,我们得换算成现在地图上的坐标

下面是相关的方式:

1、tileset

所涉项目tileset数量很少,所以采用手工方式改动经纬度,看位置信息。最后记录下合适的经纬度。最后配合下面的代码,使tileset在加载准备好以后,自动放置到最后的位置。

var params = {
    tx: 120.7521311337607,    //longitude
    ty: 31.19968924358735,    //latitude
    tz: 0.1,                  //height
    rx: 0,                    //degree
    ry: 0,                    //degree
    rz: 0                     //degree
};
	
function update3dtilesMaxtrix(tileset, params) {
    // rotation maxtrix construct, first we get matrix3, then matrix4 from matrix3
    var mx = Cesium.Matrix3.fromRotationX(Cesium.Math.toRadians(params.rx));
    var my = Cesium.Matrix3.fromRotationY(Cesium.Math.toRadians(params.ry));
    var mz = Cesium.Matrix3.fromRotationZ(Cesium.Math.toRadians(params.rz));
    var rotationX = Cesium.Matrix4.fromRotationTranslation(mx);
    var rotationY = Cesium.Matrix4.fromRotationTranslation(my);
    var rotationZ = Cesium.Matrix4.fromRotationTranslation(mz);

    // translation matrix4
    var position = Cesium.Cartesian3.fromDegrees(params.tx, params.ty, params.tz);
    var m = Cesium.Transforms.eastNorthUpToFixedFrame(position);

    // concate translation and all rotations
    Cesium.Matrix4.multiply(m, rotationX, m);
    Cesium.Matrix4.multiply(m, rotationY, m);
    Cesium.Matrix4.multiply(m, rotationZ, m);

    // update tileset's matrix4
    tileset._root.transform = m;
}

viewer.scene.primitives.add(tileset).readyPromise.then(function(t) {
	update3dtilesMaxtrix(t, params);
});

viewer.zoomTo(tileset);

2、服务器给的wgs84坐标信息

使用gcoord库,把每个wgs84坐标转化成gcj02坐标即可。示例代码:

var result = gcoord.transform(
  [116.403988, 39.914266],    // 经纬度坐标
  gcoord.WGS84,               // 当前坐标系
  gcoord.GCJ02                // 目标坐标系
);

化石原创文章,转载请注明来源并保留原文链接