Leaflet开发:webgl方式加载point

简介: Leaflet开发:webgl方式加载point

解决方案来源于github,基于Leaflet的地图的,使用webgl方式加载了8万多个点,除去互联网上访问数据,渲染的时候没有出现卡顿的情况,缩放也没有卡顿,此方式可以作为一个地图上加载特征图层的方式。

这种方式不同于使用Leaflet的API加载point,这个是在地图的上层覆盖一个canvas对象,使用的是开源的L.CanvasOverlay.js,github上可以搜索到这个,将point绘制在canvas上,在地图范围或级别的动态变化时,计算vertex shader中的变换矩阵,保持和地图上的位置一致。

json坐标数据量:
image.png
关键的shader:

<!-- vertex shader -->

    <script id="vshader" type="x-shader/x-vertex">

        uniform mat4 u_matrix;

        attribute vec4 a_vertex;

        attribute float a_pointSize;

        attribute vec4 a_color;

        varying vec4 v_color;



        void main() {

        // Set the size of the point

        gl_PointSize =  a_pointSize; 

        // multiply each vertex by a matrix.

        gl_Position = u_matrix * a_vertex;  

        // pass the color to the fragment shader

        v_color = a_color;

        }

    </script>

    <!-- fragment shader --> 

    <script id="fshader" type="x-shader/x-fragment">

        precision mediump float;

        varying vec4 v_color;

        void main() {



        float border = 0.05;

        float radius = 0.5;

        vec4 color0 = vec4(0.0, 0.0, 0.0, 0.0);

        vec4 color1 = vec4(v_color[0], v_color[1], v_color[2], 0.2);



        vec2 m = gl_PointCoord.xy - vec2(0.5, 0.5);

        float dist = radius - sqrt(m.x * m.x + m.y * m.y);



        float t = 0.0;

        if (dist > border)

        t = 1.0;

        else if (dist > 0.0)

        t = dist / border;



        // float centerDist = length(gl_PointCoord - 0.5);

        // works for overlapping circles if blending is enabled

        gl_FragColor = mix(color0, color1, t);

        

        /*

        // -- another way for circle

        float centerDist = length(gl_PointCoord - 0.5);

        float radius = 0.5;

        // works for overlapping circles if blending is enabled

        gl_FragColor = vec4(v_color[0], v_color[1], v_color[2], 0.2 * step(centerDist, radius));

        */



        /*

        // simple circles

        float d = distance (gl_PointCoord, vec2(0.5,0.5));

        if (d < 0.5 ){

        gl_FragColor =vec4(v_color[0], v_color[1], v_color[2], 0.2);

        }

        else{

        discard;

        }

        */



        // -- squares

        //gl_FragColor = v_color;

        //gl_FragColor =vec4(v_color[0], v_color[1], v_color[2], 0.2); // v_color;



        }



    </script>



// -- converts latlon to pixels at zoom level 0 (for 256x256 tile size) , inverts y coord )

        // -- source : http://build-failed.blogspot.cz/2013/02/displaying-webgl-data-on-google-maps.html

//将经纬度转换像素的代码,在第一级别进行转换

        function LatLongToPixelXY(latitude, longitude) {

            var pi_180 = Math.PI / 180.0;

            var pi_4 = Math.PI * 4;

            var sinLatitude = Math.sin(latitude * pi_180);

            var pixelY = (0.5 - Math.log((1 + sinLatitude) / (1 - sinLatitude)) / (pi_4)) * 256;

            var pixelX = ((longitude + 180) / 360) * 256;



            var pixel = { x: pixelX, y: pixelY };



            return pixel;

        }



//计算转换的矩阵

function drawingOnCanvas(canvasOverlay, params) {

            if (gl == null) return;



            gl.clear(gl.COLOR_BUFFER_BIT);

            

            pixelsToWebGLMatrix.set([2 / canvas.width, 0, 0, 0, 0, -2 / canvas.height, 0, 0, 0, 0, 0, 0, -1, 1, 0, 1]);

            gl.viewport(0, 0, canvas.width, canvas.height);



            var pointSize = Math.max(leafletMap.getZoom() - 4.0, 1.0);

            gl.vertexAttrib1f(gl.aPointSize, pointSize);



            // -- set base matrix to translate canvas pixel coordinates -> webgl coordinates

            mapMatrix.set(pixelsToWebGLMatrix);



            var bounds = leafletMap.getBounds();

            var topLeft = new L.LatLng(bounds.getNorth(), bounds.getWest());

            var offset = LatLongToPixelXY(topLeft.lat, topLeft.lng);



            // -- Scale to current zoom

            var scale = Math.pow(2, leafletMap.getZoom());

            scaleMatrix(mapMatrix, scale, scale);



            translateMatrix(mapMatrix, -offset.x, -offset.y);



            // -- attach matrix value to 'mapMatrix' uniform in shader

            gl.uniformMatrix4fv(u_matLoc, false, mapMatrix);

            gl.drawArrays(gl.POINTS, 0, numPoints);



        }

image.png

相关文章
|
3月前
|
JavaScript 数据可视化
基于fabric.js的图片编辑器, 画布背景实现原理
基于vue3 + fabric.js + vite + element-plus + typescript等技术,画布背景原理分析
基于fabric.js的图片编辑器, 画布背景实现原理
|
JavaScript 前端开发 定位技术
Leaflet系列:动态勾画polygon
Leaflet如何实现动态勾画polygon
208 0
|
定位技术 API
基于Leaflet.draw的自定义绘制实战
本文介绍了如何基于leaflet.draw进行自定义绘制,同时获取对象的bbox和geojson信息。
521 0
基于Leaflet.draw的自定义绘制实战
|
JavaScript 前端开发 Web App开发
带你读《Three. js开发指南: 基于WebGL和HTML5在网页上渲染 3D图形和动画(原书第3版)》之一:使用Three.js创建你的第一个三维场景
本书将介绍如何直在浏览器中创建漂亮的3D场景和动画,并且充分发挥WebGL和现代浏览器的潜能。首先介绍基本概念和基础组件,然后通过逐渐扩展示例代码逐步深讲解更多高级技术。在本书中读者将学到如何从外部加载3D模型和具有真实效果的材质纹理、学习使用Three.js提供的摄像机组件来实现在3D场景中飞行和走动、如何将HTML5视频和画布作为材质贴在3D模型表面。此外还将学习变形动画和骨骼动画,甚至还会涉及在场景中使用物理模拟的方法,例如重力、碰撞检测等等。
|
9月前
|
定位技术
echarts引入百度地图通过脚本bmap.min.js解决关闭底图可点功能的底层解决方案
echarts引入百度地图通过脚本bmap.min.js解决关闭底图可点功能的底层解决方案
68 0
|
9月前
|
定位技术 API
Cesium开发:关于加载CGCS2000切片
Cesium开发:关于加载CGCS2000切片
413 0
|
存储 Web App开发 机器学习/深度学习
【网页特性】geolocation | video | Web Workers | 拖拽 | FileReader | canvas操作 | 弧度与角度转换
【网页特性】geolocation | video | Web Workers | 拖拽 | FileReader | canvas操作 | 弧度与角度转换
165 0
【网页特性】geolocation | video | Web Workers | 拖拽 | FileReader | canvas操作 | 弧度与角度转换
|
前端开发 算法 JavaScript
不借助 Javascript,利用 SVG 快速构建马赛克效果
不借助 Javascript,利用 SVG 快速构建马赛克效果
137 0
不借助 Javascript,利用 SVG 快速构建马赛克效果
|
前端开发 JavaScript
《JS原理、方法与实践》- canvas作图(七)- 缩放
《JS原理、方法与实践》- canvas作图(七)- 缩放
141 0
|
数据安全/隐私保护 iOS开发 开发者
iOS开发CoreGraphics核心图形框架之九——PDF文件的渲染与创建(二)
iOS开发CoreGraphics核心图形框架之九——PDF文件的渲染与创建
284 0
iOS开发CoreGraphics核心图形框架之九——PDF文件的渲染与创建(二)