maptalks 开发GIS地图(13)maptalks.three.06 bars

1. 说明

使用柱状图,并根据音乐节奏显示动画效果。

 

2. 初始化地图并添加threelayer

 1   var map = new maptalks.Map("map", {
 2             center: [19.06325670775459, 42.16842479475318],
 3             zoom: 3,
 4             pitch: 60,
 5             // bearing: 180,
 6 
 7             centerCross: true,
 8             doubleClickZoom: false,
 9             // baseLayer: new maptalks.TileLayer('tile', {
10             //     urlTemplate: 'https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}.png',
11             //     subdomains: ['a', 'b', 'c', 'd'],
12             //     attribution: '&copy; <a href="http://osm.org">OpenStreetMap</a> contributors, &copy; <a href="https://carto.com/">CARTO</a>'
13             // })
14         });
15 
16         // the ThreeLayer to draw buildings
17         var threeLayer = new maptalks.ThreeLayer('t', {
18             forceRenderOnMoving: true,
19             forceRenderOnRotating: true
20             // animation: true
21         });
22         threeLayer.prepareToDraw = function (gl, scene, camera) {
23             stats = new Stats();
24             stats.domElement.style.zIndex = 100;
25             document.getElementById('map').appendChild(stats.domElement);
26 
27             var light = new THREE.DirectionalLight(0xffffff);
28             light.position.set(0, -10, 10).normalize();
29             scene.add(light);
30 
31             scene.add(new THREE.AmbientLight(0xffffff, 0.2));
32 
33             // camera.add(new THREE.PointLight(0xffffff, 1));
34 
35             addBars(scene);
36 
37         };
38         threeLayer.addTo(map);

 

3. 添加数据

  1 function addBars(scene) {
  2             fetch('./data/population.json').then((function (res) {
  3                 return res.json();
  4             })).then(function (json) {
  5                 const data = json.filter(function (dataItem) {
  6                     return dataItem[2] > 0;
  7                 }).map(function (dataItem) {
  8                     dataItem[2] *= 400;
  9                     min = Math.min(min, dataItem[2]);
 10                     max = Math.max(max, dataItem[2]);
 11                     return {
 12                         coordinate: dataItem.slice(0, 2),
 13                         height: dataItem[2],
 14                         radius: 15000,
 15                         // topColor: '#fff'
 16                     }
 17                 }).slice(0, Infinity);
 18                 const colorMap = {};
 19                 data.forEach(d => {
 20                     const { height } = d;
 21                     const color = getColor(height);
 22                     if (!colorMap[color]) {
 23                         const m = material.clone();
 24                         m.color.set(color);
 25                         colorMap[color] = {
 26                             data: [],
 27                             material: m
 28                         }
 29                     }
 30                     colorMap[color].data.push(d);
 31                 });
 32                 console.log(colorMap);
 33                 const time = 'time';
 34                 console.time(time);
 35                 for (let color in colorMap) {
 36                     const { data, material } = colorMap[color];
 37                     const mesh = threeLayer.toBars(data, { interactive: false }, material);
 38                     bars.push(mesh);
 39                 }
 40                 console.timeEnd(time);
 41                 bars.forEach(mesh => {
 42                     mesh.setToolTip('hello', {
 43                         showTimeout: 0,
 44                         eventsPropagation: true,
 45                         dx: 10
 46                     });
 47 
 48                     //infowindow test
 49                     mesh.setInfoWindow({
 50                         content: 'hello world',
 51                         title: 'message',
 52                         animationDuration: 0,
 53                         autoOpenOn: false
 54                     });
 55 
 56                     //event test
 57                     ['click', 'mousemove', 'empty', 'mouseout', 'mouseover', 'mousedown', 'mouseup', 'dblclick', 'contextmenu'].forEach(function (eventType) {
 58                         mesh.on(eventType, function (e) {
 59                             // console.log(e.type);
 60                             const select = e.selectMesh;
 61                             if (e.type === 'empty' && selectMesh.length) {
 62                                 threeLayer.removeMesh(selectMesh);
 63                                 selectMesh = [];
 64                             }
 65 
 66                             let data, baseObject;
 67                             if (select) {
 68                                 data = select.data;
 69                                 baseObject = select.baseObject;
 70                                 if (baseObject && !baseObject.isAdd) {
 71                                     baseObject.setSymbol(highlightmaterial);
 72                                     threeLayer.addMesh(baseObject);
 73                                     selectMesh.push(baseObject);
 74                                 }
 75                             }
 76 
 77 
 78                             if (selectMesh.length > 20) {
 79                                 threeLayer.removeMesh(selectMesh);
 80                                 selectMesh = [];
 81                             }
 82 
 83 
 84                             // override tooltip
 85                             if (e.type === 'mousemove' && data) {
 86                                 const height = data.height;
 87                                 const tooltip = this.getToolTip();
 88                                 tooltip._content = `height:${height}`;
 89                             }
 90                             //override infowindow
 91                             if (e.type === 'click' && data) {
 92                                 const height = data.height;
 93                                 const infoWindow = this.getInfoWindow();
 94                                 infoWindow.setContent(`height:${height}`);
 95                                 if (infoWindow && (!infoWindow._owner)) {
 96                                     infoWindow.addTo(this);
 97                                 }
 98                                 this.openInfoWindow(e.coordinate);
 99 
100                             }
101                         });
102                     });
103                 });
104                 console.log(bars);
105                 threeLayer.addMesh(bars);
106                 initGui();
107                 animation();
108             });
109         }

 

4. 数据使用的是 ./data/population.json

这里的是数据原始格式:

 

 

下面的这段代码,将这个数据重新生成了一次,把前两个数据作为 coordinate,将最后一个数据乘以 400 作为高度。

然后将 15000 作为了圆柱的半径。

1  dataItem[2] *= 400;
2  min = Math.min(min, dataItem[2]);
3  max = Math.max(max, dataItem[2]);
4  return {
5        coordinate: dataItem.slice(0, 2),
6        height: dataItem[2],
7        radius: 15000,
8        // topColor: '#fff'
9 }

 

最终的数据变为了下面的样式。

别问我那个数据为啥是 440.00000000000006 😭

 

 

5. 显示效果

效果还是不错的。

 

 

 

6. 源码参考

https://github.com/WhatGIS/maptalkMap

 

posted @ 2021-04-30 15:51  googlegis  阅读(349)  评论(0编辑  收藏  举报

坐标合肥,非典型GIS开发人员 GitHub