mirror of https://gitee.com/antv-l7/antv-l7
Merge branch 'grid-heatMap' into 'master'
Grid heat map 增加mapbox 增加多边形热力图 See merge request !5
This commit is contained in:
commit
e611930470
|
@ -69,7 +69,6 @@ lib
|
||||||
|
|
||||||
*.sw*
|
*.sw*
|
||||||
*.un~
|
*.un~
|
||||||
demos/mapbox.html
|
|
||||||
demos/gd.html
|
demos/gd.html
|
||||||
demos/data
|
demos/data
|
||||||
demos/image
|
demos/image
|
||||||
|
|
|
@ -10,6 +10,9 @@
|
||||||
<title>point_circle</title>
|
<title>point_circle</title>
|
||||||
<style>
|
<style>
|
||||||
#map { position:absolute; top:0; bottom:0; width:100%; }
|
#map { position:absolute; top:0; bottom:0; width:100%; }
|
||||||
|
.amap-maps {
|
||||||
|
cursor: auto !important
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
@ -55,15 +58,15 @@ scene.on('loaded', () => {
|
||||||
.shape('2d:circle')
|
.shape('2d:circle')
|
||||||
.size('value', [ 2, 80]) // default 1
|
.size('value', [ 2, 80]) // default 1
|
||||||
//.size('value', [ 10, 300]) // default 1
|
//.size('value', [ 10, 300]) // default 1
|
||||||
.active(false)
|
.active(true)
|
||||||
.filter('value', field_8 => {
|
.filter('value', field_8 => {
|
||||||
return field_8 * 1 > 500;
|
return field_8 * 1 > 500;
|
||||||
})
|
})
|
||||||
.color('type', colorObj.red)
|
.color('type', colorObj.blue)
|
||||||
.style({
|
.style({
|
||||||
stroke: 'rgb(255,255,255)',
|
stroke: 'rgb(255,255,255)',
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
opacity: 0.9
|
opacity: 1.
|
||||||
})
|
})
|
||||||
.render();
|
.render();
|
||||||
|
|
||||||
|
|
|
@ -34,9 +34,11 @@ scene.on('loaded', () => {
|
||||||
zIndex: 2
|
zIndex: 2
|
||||||
})
|
})
|
||||||
.source(data.list, {
|
.source(data.list, {
|
||||||
type: 'array',
|
parser:{
|
||||||
x: 'j',
|
type: 'json',
|
||||||
y: 'w',
|
x: 'j',
|
||||||
|
y: 'w',
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.shape('cylinder')
|
.shape('cylinder')
|
||||||
.size('t',(level)=> {
|
.size('t',(level)=> {
|
||||||
|
|
|
@ -34,9 +34,11 @@ scene.on('loaded', () => {
|
||||||
zIndex: 2
|
zIndex: 2
|
||||||
})
|
})
|
||||||
.source(data, {
|
.source(data, {
|
||||||
type: 'csv',
|
parser:{
|
||||||
y: 'lat',
|
type: 'csv',
|
||||||
x: 'lng'
|
y: 'lat',
|
||||||
|
x: 'lng'
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.size(1.0)
|
.size(1.0)
|
||||||
.color('#0D408C')
|
.color('#0D408C')
|
||||||
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||||
|
<meta name="geometry" content="diagram">
|
||||||
|
<link rel="stylesheet" href="./assets/common.css">
|
||||||
|
<link rel="stylesheet" href="./assets/info.css">
|
||||||
|
<title>point_circle</title>
|
||||||
|
<style>
|
||||||
|
#map { position:absolute; top:0; bottom:0; width:100%; }
|
||||||
|
.amap-maps {
|
||||||
|
cursor: auto !important
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="map"></div>
|
||||||
|
<script src="https://webapi.amap.com/maps?v=1.4.8&key=15cd8a57710d40c9b7c0e3cc120f1200&plugin=Map3D"></script>
|
||||||
|
<script src="./assets/jquery-3.2.1.min.js"></script>
|
||||||
|
<script src="./assets/dat.gui.min.js"></script>
|
||||||
|
<script src="../build/L7.js"></script>
|
||||||
|
<script>
|
||||||
|
const colorObj ={
|
||||||
|
blue: ["#E8FCFF", "#CFF6FF", "#A1E9ff", "#65CEF7", "#3CB1F0", "#2894E0", "#1772c2", "#105CB3", "#0D408C", "#002466"].reverse(),
|
||||||
|
red: ["#FFF4F2", "#FFDFDB", "#FAADAA", "#F77472", "#F04850", "#D63147", "#BD223E", "#A81642", "#820C37", "#5C0023"].reverse(),
|
||||||
|
orange:["#FFF7EB", "#FFECD4", "#FAD09D", "#F7B16A", "#F08D41", "#DB6C2C", "#C2491D", "#AD2B11", "#871D0C", "#610800"].reverse(),
|
||||||
|
green:["#FAFFF0", "#EBF7D2", "#C8E695", "#A5D660", "#7DC238", "#59A616", "#3F8C0B", "#237804", "#125200", "#082B00"].reverse(),
|
||||||
|
yellow:["#FFFFE8", "#FFFECC", "#FAF896", "#F7E463", "#F0CE3A", "#DBB125", "#C29117", "#AD7410", "#87500C", "#613000"].reverse(),
|
||||||
|
purple:["#FCF2FF", "#F5DEFF", "#DDB3F2", "#BE7BE3", "#9B4ECF", "#7737B3", "#5B2899", "#411C85", "#270F5E", "#100338"].reverse()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const scene = new L7.Scene({
|
||||||
|
id: 'map',
|
||||||
|
mapStyle: 'light', // 样式URL
|
||||||
|
center: [ 120.19382669582967, 30.258134 ],
|
||||||
|
pitch: 0,
|
||||||
|
zoom: 4,
|
||||||
|
maxZoom:14,
|
||||||
|
minZoom:4,
|
||||||
|
});
|
||||||
|
window.scene = scene;
|
||||||
|
scene.on('loaded', () => {
|
||||||
|
$.get('https://gw.alipayobjects.com/os/basement_prod/7359a5e9-3c5e-453f-b207-bc892fb23b84.csv', data => {
|
||||||
|
|
||||||
|
|
||||||
|
const circleLayer = scene.PointLayer({
|
||||||
|
zIndex: 2
|
||||||
|
})
|
||||||
|
.source(data,{
|
||||||
|
type: 'csv',
|
||||||
|
x: 'lng',
|
||||||
|
y: 'lat',
|
||||||
|
})
|
||||||
|
.size(1.0)
|
||||||
|
.color('#0D408C')
|
||||||
|
.style({
|
||||||
|
stroke: 'rgb(255,255,255)',
|
||||||
|
strokeWidth: 1,
|
||||||
|
opacity: 1.
|
||||||
|
})
|
||||||
|
.render();
|
||||||
|
|
||||||
|
circleLayer.on('click',(e)=>{
|
||||||
|
console.log(e);
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
|
@ -33,8 +33,11 @@ const scene = new L7.Scene({
|
||||||
scene.on('loaded', () => {
|
scene.on('loaded', () => {
|
||||||
const imageLayer = scene.ImageLayer().
|
const imageLayer = scene.ImageLayer().
|
||||||
source('https://gw.alipayobjects.com/zos/rmsportal/FnHFeFklTzKDdUESRNDv.jpg',{
|
source('https://gw.alipayobjects.com/zos/rmsportal/FnHFeFklTzKDdUESRNDv.jpg',{
|
||||||
|
parser:{
|
||||||
|
type:'image',
|
||||||
|
extent: [ 121.1680, 30.2828, 121.3840, 30.4219 ]
|
||||||
|
}
|
||||||
|
|
||||||
extent: [ 121.1680, 30.2828, 121.3840, 30.4219 ]
|
|
||||||
})
|
})
|
||||||
.style({
|
.style({
|
||||||
opacity:1.0,
|
opacity:1.0,
|
||||||
|
|
|
@ -48,13 +48,14 @@ scene.on('loaded', () => {
|
||||||
|
|
||||||
const layer = scene.RasterLayer({ zIndex: 2 }).
|
const layer = scene.RasterLayer({ zIndex: 2 }).
|
||||||
source(values, {
|
source(values, {
|
||||||
type: 'raster',
|
parser: {
|
||||||
width: n,
|
type: 'raster',
|
||||||
height: m,
|
width: n,
|
||||||
min: 0,
|
height: m,
|
||||||
max: 8000,
|
min: 0,
|
||||||
extent: [ 73.482190241, 3.82501784112, 135.106618732, 57.6300459963 ]
|
max: 8000,
|
||||||
|
extent: [ 73.482190241, 3.82501784112, 135.106618732, 57.6300459963 ]
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.style({
|
.style({
|
||||||
rampColors: {
|
rampColors: {
|
||||||
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||||
|
<meta name="geometry" content="diagram">
|
||||||
|
<link rel="stylesheet" href="./assets/common.css">
|
||||||
|
<title>point_circle</title>
|
||||||
|
<style>
|
||||||
|
#map { position:absolute; top:0; bottom:0; width:100%; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="map"></div>
|
||||||
|
<script src="https://webapi.amap.com/maps?v=1.4.8&key=15cd8a57710d40c9b7c0e3cc120f1200&plugin=Map3D"></script>
|
||||||
|
<script src="./assets/jquery-3.2.1.min.js"></script>
|
||||||
|
<script src="./assets/dat.gui.min.js"></script>
|
||||||
|
<script src="../build/L7.js"></script>
|
||||||
|
<script>
|
||||||
|
|
||||||
|
const scene = new L7.Scene({
|
||||||
|
id: 'map',
|
||||||
|
mapStyle: 'dark', // 样式URL
|
||||||
|
center: [120.132624,30.281774],
|
||||||
|
pitch: 0,
|
||||||
|
zoom: 3.88
|
||||||
|
});
|
||||||
|
scene.on('loaded', () => {
|
||||||
|
$.get('https://gw.alipayobjects.com/os/basement_prod/7359a5e9-3c5e-453f-b207-bc892fb23b84.csv', data => {
|
||||||
|
var layer = scene.HeatMapLayer({
|
||||||
|
zIndex: 2
|
||||||
|
})
|
||||||
|
.source(data, {
|
||||||
|
parser: {
|
||||||
|
type: 'csv',
|
||||||
|
x: 'lng',
|
||||||
|
y: 'lat'
|
||||||
|
},
|
||||||
|
transforms:[
|
||||||
|
{
|
||||||
|
type: 'map',
|
||||||
|
callback:function(item){
|
||||||
|
const [x, y] = item.coordinates;
|
||||||
|
item.lat = item.lat*1;
|
||||||
|
item.lng = item.lng*1;
|
||||||
|
item.v = item.v *1;
|
||||||
|
item.coordinates = [x*1,y*1];
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'grid',
|
||||||
|
size: 15000,
|
||||||
|
field:'v',
|
||||||
|
method:'sum'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
.shape('gird')
|
||||||
|
.style({
|
||||||
|
coverage: 0.8
|
||||||
|
})
|
||||||
|
.color('count', ["#002466","#105CB3","#2894E0","#CFF6FF","#FFF5B8","#FFAB5C","#F27049","#730D1C"])
|
||||||
|
.render();
|
||||||
|
console.log(layer);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
|
@ -0,0 +1,93 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||||
|
<meta name="geometry" content="diagram">
|
||||||
|
<link rel="stylesheet" href="./assets/common.css">
|
||||||
|
<link rel="stylesheet" href="./assets/info.css">
|
||||||
|
<title>point_circle</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
margin:0;
|
||||||
|
padding:0;
|
||||||
|
}
|
||||||
|
#map { position:absolute; top:0; bottom:0; width:100%; margin:0; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="map"></div>
|
||||||
|
<script src='https://api.tiles.mapbox.com/mapbox-gl-js/v0.34.0/mapbox-gl.js'></script>
|
||||||
|
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.34.0/mapbox-gl.css' rel='stylesheet' />
|
||||||
|
<script src="./assets/jquery-3.2.1.min.js"></script>
|
||||||
|
<script src="./assets/dat.gui.min.js"></script>
|
||||||
|
<script src="../build/L7.js"></script>
|
||||||
|
<script>
|
||||||
|
const colorObj ={
|
||||||
|
blue: ["#E8FCFF", "#CFF6FF", "#A1E9ff", "#65CEF7", "#3CB1F0", "#2894E0", "#1772c2", "#105CB3", "#0D408C", "#002466"].reverse(),
|
||||||
|
red: ["#FFF4F2", "#FFDFDB", "#FAADAA", "#F77472", "#F04850", "#D63147", "#BD223E", "#A81642", "#820C37", "#5C0023"].reverse(),
|
||||||
|
orange:["#FFF7EB", "#FFECD4", "#FAD09D", "#F7B16A", "#F08D41", "#DB6C2C", "#C2491D", "#AD2B11", "#871D0C", "#610800"].reverse(),
|
||||||
|
green:["#FAFFF0", "#EBF7D2", "#C8E695", "#A5D660", "#7DC238", "#59A616", "#3F8C0B", "#237804", "#125200", "#082B00"].reverse(),
|
||||||
|
yellow:["#FFFFE8", "#FFFECC", "#FAF896", "#F7E463", "#F0CE3A", "#DBB125", "#C29117", "#AD7410", "#87500C", "#613000"].reverse(),
|
||||||
|
purple:["#FCF2FF", "#F5DEFF", "#DDB3F2", "#BE7BE3", "#9B4ECF", "#7737B3", "#5B2899", "#411C85", "#270F5E", "#100338"].reverse()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const scene = new L7.Scene({
|
||||||
|
container: 'map',
|
||||||
|
mapType:'mapbox',
|
||||||
|
style: 'mapbox://styles/mapbox/streets-v9', // stylesheet location
|
||||||
|
center: [ 120.19382669582967, 30.258134 ],
|
||||||
|
pitch: 0,
|
||||||
|
hash:true,
|
||||||
|
zoom: 1,
|
||||||
|
});
|
||||||
|
window.scene = scene;
|
||||||
|
scene.on('loaded', () => {
|
||||||
|
var colors = ["#FFF5B8","#FFDC7D","#FFAB5C","#F27049","#D42F31","#730D1C"];
|
||||||
|
$.getJSON('https://gw.alipayobjects.com/os/rmsportal/JToMOWvicvJOISZFCkEI.json', city => {
|
||||||
|
const citylayer = scene.PolygonLayer()
|
||||||
|
.source(city)
|
||||||
|
//.color('pm2_5_24h',["#FFF5B8","#FFDC7D","#FFAB5C","#F27049","#D42F31","#730D1C"])
|
||||||
|
.color('pm2_5_24h',(p)=>{
|
||||||
|
if(p>120){
|
||||||
|
return colors[5];
|
||||||
|
} else if(p>65){
|
||||||
|
return colors[4];
|
||||||
|
} else if(p>30) {
|
||||||
|
return colors[3];
|
||||||
|
} else if(p>15){
|
||||||
|
return colors[2];
|
||||||
|
} else if(p>8){
|
||||||
|
return colors[1];
|
||||||
|
}else {
|
||||||
|
return colors[0];
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.shape('fill')
|
||||||
|
.active(true)
|
||||||
|
.style({
|
||||||
|
opacity: 1
|
||||||
|
})
|
||||||
|
.render();
|
||||||
|
console.log('success');
|
||||||
|
});
|
||||||
|
$.get('https://gw.alipayobjects.com/os/rmsportal/ggFwDClGjjvpSMBIrcEx.json', data => {
|
||||||
|
citylayer = scene.PolygonLayer({
|
||||||
|
zIndex: 2
|
||||||
|
})
|
||||||
|
.source(data)
|
||||||
|
.shape('extrude')
|
||||||
|
.active({fill:'red'})
|
||||||
|
.size('floor',[0.1,1])
|
||||||
|
.color('#aaa')
|
||||||
|
.render();
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
|
@ -101,12 +101,14 @@
|
||||||
"@turf/invariant": "^6.1.2",
|
"@turf/invariant": "^6.1.2",
|
||||||
"@turf/meta": "^6.0.2",
|
"@turf/meta": "^6.0.2",
|
||||||
"d3-dsv": "^1.0.10",
|
"d3-dsv": "^1.0.10",
|
||||||
|
"d3-hexbin": "^0.2.2",
|
||||||
"earcut": "^2.1.3",
|
"earcut": "^2.1.3",
|
||||||
"fecha": "^2.3.3",
|
"fecha": "^2.3.3",
|
||||||
"gl-matrix": "^2.4.1",
|
"gl-matrix": "^2.4.1",
|
||||||
"lodash": "^4.17.5",
|
"lodash": "^4.17.5",
|
||||||
"polyline-normals": "^2.0.2",
|
"polyline-normals": "^2.0.2",
|
||||||
"rbush": "^2.0.2",
|
"rbush": "^2.0.2",
|
||||||
|
"simple-statistics": "^7.0.1",
|
||||||
"three": "^0.96.0",
|
"three": "^0.96.0",
|
||||||
"venn.js": "^0.2.20",
|
"venn.js": "^0.2.20",
|
||||||
"viewport-mercator-project": "^5.2.0",
|
"viewport-mercator-project": "^5.2.0",
|
||||||
|
|
|
@ -1,36 +0,0 @@
|
||||||
import geom from '../../geom/geom';
|
|
||||||
import { GeoBuffer, bufferGeometry, Material } from '../../geom/index';
|
|
||||||
|
|
||||||
|
|
||||||
// geom shape buffer geometry material
|
|
||||||
// shape name type()
|
|
||||||
// buffer 1:n geometry
|
|
||||||
// geometry
|
|
||||||
//
|
|
||||||
export default function polygonGeom(shape, coordinates, properties, layerid) {
|
|
||||||
const polygongeom = geom.polygon;
|
|
||||||
const { buffer, geometry, material } = polygongeom[shape];// polygon 映射表
|
|
||||||
const bufferData = new GeoBuffer[buffer]({
|
|
||||||
coordinates,
|
|
||||||
properties,
|
|
||||||
shape
|
|
||||||
});
|
|
||||||
bufferData.bufferStruct.name = layerid;
|
|
||||||
const bg = new bufferGeometry[geometry](bufferData.bufferStruct);
|
|
||||||
const mtl = Material[material]();
|
|
||||||
return {
|
|
||||||
geometry: bg,
|
|
||||||
mtl
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function pointGeom(shape, bufferData) {
|
|
||||||
const pointgeom = geom.point;
|
|
||||||
const { geometry, material } = pointgeom[shape];
|
|
||||||
const bg = new bufferGeometry[geometry](bufferData.bufferStruct);
|
|
||||||
const mtl = Material[material]();
|
|
||||||
return {
|
|
||||||
geometry: bg,
|
|
||||||
mtl
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
|
||||||
|
import { getMap } from '../../map';
|
||||||
|
import Base from '../base';
|
||||||
|
export default class MapContorller extends Base {
|
||||||
|
constructor(cfg, engine, scene) {
|
||||||
|
super(cfg);
|
||||||
|
this._engine = engine;
|
||||||
|
this.scene = scene;
|
||||||
|
}
|
||||||
|
_init() {
|
||||||
|
const mapType = this.get('mapType');
|
||||||
|
const mapCfg = this.get('mapCfg');
|
||||||
|
this.map = new getMap(mapType)(mapCfg);
|
||||||
|
this.map('mapLoad', this._mapload.bind(this));
|
||||||
|
}
|
||||||
|
_mapload() {
|
||||||
|
this.map.asyncCamera(this._engine);
|
||||||
|
this.emit('loaded');
|
||||||
|
}
|
||||||
|
_bindMapMethod() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -11,6 +11,9 @@ export default class Engine extends EventEmitter {
|
||||||
this._camera = new Camera(container).camera;
|
this._camera = new Camera(container).camera;
|
||||||
this._renderer = new Renderer(container).renderer;
|
this._renderer = new Renderer(container).renderer;
|
||||||
this._world = world;
|
this._world = world;
|
||||||
|
// for MapBox
|
||||||
|
this.world = new THREE.Group();
|
||||||
|
this._scene.add(this.world);
|
||||||
this._picking = Picking(this._world, this._renderer, this._camera, this._scene);
|
this._picking = Picking(this._world, this._renderer, this._camera, this._scene);
|
||||||
this.clock = new THREE.Clock();
|
this.clock = new THREE.Clock();
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,8 @@ class Picking {
|
||||||
this.scene = scene;
|
this.scene = scene;
|
||||||
this._raycaster.linePrecision = 10;
|
this._raycaster.linePrecision = 10;
|
||||||
this._pickingScene = PickingScene;
|
this._pickingScene = PickingScene;
|
||||||
|
this.world = new THREE.Group();
|
||||||
|
this._pickingScene.add(this.world);
|
||||||
const size = this._renderer.getSize();
|
const size = this._renderer.getSize();
|
||||||
this._width = size.width;
|
this._width = size.width;
|
||||||
this._height = size.height;
|
this._height = size.height;
|
||||||
|
@ -34,8 +36,7 @@ class Picking {
|
||||||
window.addEventListener('resize', this._resizeHandler, false);
|
window.addEventListener('resize', this._resizeHandler, false);
|
||||||
}
|
}
|
||||||
pickdata(event) {
|
pickdata(event) {
|
||||||
const point = { x: event.pixel.x, y: event.pixel.y, type: event.type };
|
const point = { x: event.offsetX, y: event.offsetY, type: event.type };
|
||||||
|
|
||||||
const normalisedPoint = { x: 0, y: 0 };
|
const normalisedPoint = { x: 0, y: 0 };
|
||||||
normalisedPoint.x = (point.x / this._width) * 2 - 1;
|
normalisedPoint.x = (point.x / this._width) * 2 - 1;
|
||||||
normalisedPoint.y = -(point.y / this._height) * 2 + 1;
|
normalisedPoint.y = -(point.y / this._height) * 2 + 1;
|
||||||
|
@ -61,12 +62,12 @@ class Picking {
|
||||||
|
|
||||||
}
|
}
|
||||||
_filterObject(id) {
|
_filterObject(id) {
|
||||||
this._pickingScene.children.forEach((object, index) => {
|
this.world.children.forEach((object, index) => {
|
||||||
index === id ? object.visible = true : object.visible = false;
|
index === id ? object.visible = true : object.visible = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
_pickAllObject(point, normalisedPoint) {
|
_pickAllObject(point, normalisedPoint) {
|
||||||
this._pickingScene.children.forEach((object, index) => {
|
this.world.children.forEach((object, index) => {
|
||||||
this._filterObject(index);
|
this._filterObject(index);
|
||||||
const item = this._pick(point, normalisedPoint, object.name);
|
const item = this._pick(point, normalisedPoint, object.name);
|
||||||
item.type = point.type;
|
item.type = point.type;
|
||||||
|
@ -86,7 +87,6 @@ class Picking {
|
||||||
id = -999;
|
id = -999;
|
||||||
// return;
|
// return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this._raycaster.setFromCamera(normalisedPoint, this._camera);
|
this._raycaster.setFromCamera(normalisedPoint, this._camera);
|
||||||
|
|
||||||
const intersects = this._raycaster.intersectObjects(this._pickingScene.children, true);
|
const intersects = this._raycaster.intersectObjects(this._pickingScene.children, true);
|
||||||
|
@ -111,13 +111,14 @@ class Picking {
|
||||||
//
|
//
|
||||||
// Picking ID should already be added as an attribute
|
// Picking ID should already be added as an attribute
|
||||||
add(mesh) {
|
add(mesh) {
|
||||||
this._pickingScene.add(mesh);
|
this.world.add(mesh);
|
||||||
|
|
||||||
this._needUpdate = true;
|
this._needUpdate = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove mesh from picking scene
|
// Remove mesh from picking scene
|
||||||
remove(mesh) {
|
remove(mesh) {
|
||||||
this._pickingScene.remove(mesh);
|
this.world.remove(mesh);
|
||||||
this._needUpdate = true;
|
this._needUpdate = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
import Base from './base';
|
import Base from './base';
|
||||||
import * as THREE from './three';
|
import * as THREE from './three';
|
||||||
import ColorUtil from '../attr/color-util';
|
import ColorUtil from '../attr/color-util';
|
||||||
import * as source from '../source/index';
|
import source from './source';
|
||||||
import PickingMaterial from '../core/engine/picking/pickingMaterial';
|
import PickingMaterial from '../core/engine/picking/pickingMaterial';
|
||||||
import Attr from '../attr/index';
|
import Attr from '../attr/index';
|
||||||
import Util from '../util';
|
import Util from '../util';
|
||||||
|
@ -63,7 +63,8 @@ export default class Layer extends Base {
|
||||||
const layerId = this._getUniqueId();
|
const layerId = this._getUniqueId();
|
||||||
this.layerId = layerId;
|
this.layerId = layerId;
|
||||||
this._activeIds = null;
|
this._activeIds = null;
|
||||||
scene._engine._scene.add(this._object3D);
|
const world = scene._engine.world;
|
||||||
|
world.add(this._object3D);
|
||||||
this.layerMesh = null;
|
this.layerMesh = null;
|
||||||
this.layerLineMesh = null;
|
this.layerLineMesh = null;
|
||||||
this._initEvents();
|
this._initEvents();
|
||||||
|
@ -106,12 +107,9 @@ export default class Layer extends Base {
|
||||||
this._object3D.visible = this.get('visible');
|
this._object3D.visible = this.get('visible');
|
||||||
}
|
}
|
||||||
source(data, cfg = {}) {
|
source(data, cfg = {}) {
|
||||||
const dataType = this._getDataType(data);
|
|
||||||
const { type = dataType } = cfg;
|
|
||||||
cfg.data = data;
|
cfg.data = data;
|
||||||
cfg.mapType = this.get('mapType');
|
cfg.mapType = this.scene.mapType;
|
||||||
|
this.layerSource = new source(cfg);
|
||||||
this.layerSource = new source[type](cfg);
|
|
||||||
// this.scene.workerPool.runTask({
|
// this.scene.workerPool.runTask({
|
||||||
// command: 'geojson',
|
// command: 'geojson',
|
||||||
// data: cfg
|
// data: cfg
|
||||||
|
@ -279,10 +277,10 @@ export default class Layer extends Base {
|
||||||
const { featureId } = e;
|
const { featureId } = e;
|
||||||
if (featureId < 0) return;
|
if (featureId < 0) return;
|
||||||
const activeStyle = this.get('activedOptions');
|
const activeStyle = this.get('activedOptions');
|
||||||
const selectFeatureIds = this.layerSource.getSelectFeatureId(featureId);
|
// const selectFeatureIds = this.layerSource.getSelectFeatureId(featureId);
|
||||||
// 如果数据不显示状态则不进行高亮
|
// 如果数据不显示状态则不进行高亮
|
||||||
if (this.StyleData[selectFeatureIds[0]].hasOwnProperty('filter') && this.StyleData[selectFeatureIds[0]].filter === false) { return; }
|
if (this.layerData[featureId].hasOwnProperty('filter') && this.layerData[featureId].filter === false) { return; }
|
||||||
const style = Util.assign({}, this.StyleData[featureId]);
|
const style = Util.assign({}, this.layerData[featureId]);
|
||||||
style.color = ColorUtil.toRGB(activeStyle.fill).map(e => e / 255);
|
style.color = ColorUtil.toRGB(activeStyle.fill).map(e => e / 255);
|
||||||
this.updateStyle([ featureId ], style);
|
this.updateStyle([ featureId ], style);
|
||||||
}
|
}
|
||||||
|
@ -321,7 +319,7 @@ export default class Layer extends Base {
|
||||||
_updateSize(zoom) {
|
_updateSize(zoom) {
|
||||||
const sizeOption = this.get('attrOptions').size;
|
const sizeOption = this.get('attrOptions').size;
|
||||||
const fields = parseFields(sizeOption.field);
|
const fields = parseFields(sizeOption.field);
|
||||||
const data = this.layerSource.propertiesData;
|
const data = this.layerSource.data.dataArray;
|
||||||
if (!this.zoomSizeCache) this.zoomSizeCache = {};
|
if (!this.zoomSizeCache) this.zoomSizeCache = {};
|
||||||
if (!this.zoomSizeCache[zoom]) {
|
if (!this.zoomSizeCache[zoom]) {
|
||||||
this.zoomSizeCache[zoom] = [];
|
this.zoomSizeCache[zoom] = [];
|
||||||
|
@ -339,7 +337,8 @@ export default class Layer extends Base {
|
||||||
const self = this;
|
const self = this;
|
||||||
const attrs = self.get('attrs');
|
const attrs = self.get('attrs');
|
||||||
const mappedData = [];
|
const mappedData = [];
|
||||||
const data = this.layerSource.propertiesData;
|
// const data = this.layerSource.propertiesData;
|
||||||
|
const data = this.layerSource.data.dataArray;
|
||||||
for (let i = 0; i < data.length; i++) {
|
for (let i = 0; i < data.length; i++) {
|
||||||
const record = data[i];
|
const record = data[i];
|
||||||
const newRecord = {};
|
const newRecord = {};
|
||||||
|
@ -362,18 +361,17 @@ export default class Layer extends Base {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
newRecord.coordinates = record.coordinates;
|
||||||
mappedData.push(newRecord);
|
mappedData.push(newRecord);
|
||||||
}
|
}
|
||||||
|
this.layerData = mappedData;
|
||||||
this.StyleData = mappedData;
|
|
||||||
return mappedData;
|
|
||||||
}
|
}
|
||||||
// 更新地图映射
|
// 更新地图映射
|
||||||
_updateMaping() {
|
_updateMaping() {
|
||||||
const self = this;
|
const self = this;
|
||||||
const attrs = self.get('attrs');
|
const attrs = self.get('attrs');
|
||||||
|
|
||||||
const data = this.layerSource.propertiesData;
|
const data = this.layerSource.data.dataArray;
|
||||||
for (let i = 0; i < data.length; i++) {
|
for (let i = 0; i < data.length; i++) {
|
||||||
const record = data[i];
|
const record = data[i];
|
||||||
for (const attrName in attrs) {
|
for (const attrName in attrs) {
|
||||||
|
@ -385,10 +383,10 @@ export default class Layer extends Base {
|
||||||
for (let j = 0; j < values.length; j++) {
|
for (let j = 0; j < values.length; j++) {
|
||||||
const val = values[j];
|
const val = values[j];
|
||||||
const name = names[j];
|
const name = names[j];
|
||||||
this.StyleData[i][name] = (Util.isArray(val) && val.length === 1) ? val[0] : val; // 只有一个值时返回第一个属性值
|
this.layerData[i][name] = (Util.isArray(val) && val.length === 1) ? val[0] : val; // 只有一个值时返回第一个属性值
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.StyleData[i][names[0]] = values.length === 1 ? values[0] : values;
|
this.layerData[i][names[0]] = values.length === 1 ? values[0] : values;
|
||||||
|
|
||||||
}
|
}
|
||||||
attr.neadUpdate = true;
|
attr.neadUpdate = true;
|
||||||
|
@ -468,6 +466,7 @@ export default class Layer extends Base {
|
||||||
pickingMesh.material.setUniformsValue('u_zoom', zoom);
|
pickingMesh.material.setUniformsValue('u_zoom', zoom);
|
||||||
};
|
};
|
||||||
this._pickingMesh.add(pickingMesh);
|
this._pickingMesh.add(pickingMesh);
|
||||||
|
|
||||||
}
|
}
|
||||||
_setPickingId() {
|
_setPickingId() {
|
||||||
this._pickingId = this.getPickingId();
|
this._pickingId = this.getPickingId();
|
||||||
|
@ -532,13 +531,13 @@ export default class Layer extends Base {
|
||||||
*/
|
*/
|
||||||
_updateFilter(object) {
|
_updateFilter(object) {
|
||||||
this._updateMaping();
|
this._updateMaping();
|
||||||
const filterData = this.StyleData;
|
const filterData = this.layerData;
|
||||||
this._activeIds = null; // 清空选中元素
|
this._activeIds = null; // 清空选中元素
|
||||||
const colorAttr = object.geometry.attributes.a_color;
|
const colorAttr = object.geometry.attributes.a_color;
|
||||||
const pickAttr = object.geometry.attributes.pickingId;
|
const pickAttr = object.geometry.attributes.pickingId;
|
||||||
pickAttr.array.forEach((id, index) => {
|
pickAttr.array.forEach((id, index) => {
|
||||||
id = Math.abs(id);
|
id = Math.abs(id);
|
||||||
const color = [ ...this.StyleData[id - 1].color ];
|
const color = [ ...this.layerData[id - 1].color ];
|
||||||
id = Math.abs(id);
|
id = Math.abs(id);
|
||||||
const item = filterData[id - 1];
|
const item = filterData[id - 1];
|
||||||
if (item.hasOwnProperty('filter') && item.filter === false) {
|
if (item.hasOwnProperty('filter') && item.filter === false) {
|
||||||
|
@ -584,7 +583,7 @@ export default class Layer extends Base {
|
||||||
const pickingId = this.layerMesh.geometry.attributes.pickingId.array;
|
const pickingId = this.layerMesh.geometry.attributes.pickingId.array;
|
||||||
const colorAttr = this.layerMesh.geometry.attributes.a_color;
|
const colorAttr = this.layerMesh.geometry.attributes.a_color;
|
||||||
this._activeIds.forEach(index => {
|
this._activeIds.forEach(index => {
|
||||||
const color = this.StyleData[index].color;
|
const color = this.layerData[index].color;
|
||||||
const firstId = pickingId.indexOf(index + 1);
|
const firstId = pickingId.indexOf(index + 1);
|
||||||
for (let i = firstId; i < pickingId.length; i++) {
|
for (let i = firstId; i < pickingId.length; i++) {
|
||||||
if (pickingId[i] === index + 1) {
|
if (pickingId[i] === index + 1) {
|
||||||
|
|
|
@ -3,8 +3,8 @@ import { LAYER_MAP } from '../layer';
|
||||||
import Base from './base';
|
import Base from './base';
|
||||||
import LoadImage from './image';
|
import LoadImage from './image';
|
||||||
import WorkerPool from './worker';
|
import WorkerPool from './worker';
|
||||||
import { MapProvider } from '../map/provider';
|
// import { MapProvider } from '../map/AMap';
|
||||||
import GaodeMap from '../map/gaodeMap';
|
import { getMap } from '../map/index';
|
||||||
import Global from '../global';
|
import Global from '../global';
|
||||||
import { compileBuiltinModules } from '../geom/shader';
|
import { compileBuiltinModules } from '../geom/shader';
|
||||||
export default class Scene extends Base {
|
export default class Scene extends Base {
|
||||||
|
@ -31,16 +31,14 @@ export default class Scene extends Base {
|
||||||
}
|
}
|
||||||
_initMap() {
|
_initMap() {
|
||||||
this.mapContainer = this.get('id');
|
this.mapContainer = this.get('id');
|
||||||
this._container = document.getElementById(this.mapContainer);
|
this.mapType = this.get('mapType') || 'amap';
|
||||||
const Map = new MapProvider(this.mapContainer, this._attrs);
|
const MapProvider = getMap(this.mapType);
|
||||||
|
const Map = new MapProvider(this._attrs);
|
||||||
|
Map.mixMap(this);
|
||||||
|
this._container = document.getElementById(Map.container);
|
||||||
|
// const Map = new MapProvider(this.mapContainer, this._attrs);
|
||||||
Map.on('mapLoad', () => {
|
Map.on('mapLoad', () => {
|
||||||
this._initEngine(Map.renderDom);
|
this._initEngine(Map.renderDom);
|
||||||
const sceneMap = new GaodeMap(Map.map);
|
|
||||||
// eslint-disable-next-line
|
|
||||||
Object.getOwnPropertyNames(sceneMap.__proto__).forEach((key)=>{
|
|
||||||
// eslint-disable-next-line
|
|
||||||
if ('key' !== 'constructor') { this.__proto__[key] = sceneMap.__proto__[key]; }
|
|
||||||
});
|
|
||||||
this.map = Map.map;
|
this.map = Map.map;
|
||||||
Map.asyncCamera(this._engine);
|
Map.asyncCamera(this._engine);
|
||||||
this.initLayer();
|
this.initLayer();
|
||||||
|
@ -101,8 +99,10 @@ export default class Scene extends Base {
|
||||||
'dblclick'
|
'dblclick'
|
||||||
];
|
];
|
||||||
events.forEach(event => {
|
events.forEach(event => {
|
||||||
this.map.on(event, e => {
|
|
||||||
|
this._container.addEventListener(event, e => {
|
||||||
// 要素拾取
|
// 要素拾取
|
||||||
|
e.pixel || (e.pixel = e.point);
|
||||||
this._engine._picking.pickdata(e);
|
this._engine._picking.pickdata(e);
|
||||||
}, false);
|
}, false);
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,17 +1,15 @@
|
||||||
/*
|
|
||||||
* @Author: ThinkGIS
|
|
||||||
* @Date: 2018-06-08 11:19:06
|
|
||||||
* @Last Modified by: mikey.zhaopeng
|
|
||||||
* @Last Modified time: 2018-11-01 11:50:43
|
|
||||||
*/
|
|
||||||
import Base from './base';
|
import Base from './base';
|
||||||
const Controller = require('./controller/index');
|
const Controller = require('./controller/index');
|
||||||
import { aProjectFlat } from '../geo/project';
|
import { getTransform, getParser } from '../source';
|
||||||
|
import { getMap } from '../map/index';
|
||||||
export default class Source extends Base {
|
export default class Source extends Base {
|
||||||
getDefaultCfg() {
|
getDefaultCfg() {
|
||||||
return {
|
return {
|
||||||
data: null,
|
data: null,
|
||||||
defs: {},
|
defs: {},
|
||||||
|
parser: {},
|
||||||
|
transforms: [],
|
||||||
scales: {
|
scales: {
|
||||||
},
|
},
|
||||||
options: {}
|
options: {}
|
||||||
|
@ -19,26 +17,40 @@ export default class Source extends Base {
|
||||||
}
|
}
|
||||||
constructor(cfg) {
|
constructor(cfg) {
|
||||||
super(cfg);
|
super(cfg);
|
||||||
|
const transform = this.get('transforms');
|
||||||
|
this._transforms = transform || [];
|
||||||
this._initControllers();
|
this._initControllers();
|
||||||
this.prepareData();
|
// 数据解析
|
||||||
|
this._excuteParser();
|
||||||
|
// 数据转换 统计,聚合,分类
|
||||||
|
this._executeTrans();
|
||||||
|
// 坐标转换
|
||||||
|
this._projectCoords();
|
||||||
}
|
}
|
||||||
|
_excuteParser() {
|
||||||
// 标准化数据
|
const parser = this.get('parser');
|
||||||
prepareData() {
|
const { type = 'geojson' } = parser;
|
||||||
const data = this.get('data');
|
const data = this.get('data');
|
||||||
this.propertiesData = [];// 临时使用
|
this.data = getParser(type)(data, parser);
|
||||||
this.geoData = [];
|
}
|
||||||
|
/**
|
||||||
data.coordinates.forEach(geo => {
|
* 数据统计
|
||||||
const coord = this._coordProject(geo);
|
*/
|
||||||
this.geoData.push(coord);
|
_executeTrans() {
|
||||||
this.propertiesData.push([]);
|
const trans = this._transforms;
|
||||||
|
trans.forEach(tran => {
|
||||||
|
const { type } = tran;
|
||||||
|
this.data = getTransform(type)(this.data, tran);
|
||||||
|
});
|
||||||
|
this._transforms = trans;
|
||||||
|
}
|
||||||
|
_projectCoords() {
|
||||||
|
this.data.dataArray.forEach(data => {
|
||||||
|
data.coordinates = this._coordProject(data.coordinates);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
createScale(field) {
|
createScale(field) {
|
||||||
const data = this.propertiesData;
|
const data = this.data.dataArray;
|
||||||
const scales = this.get('scales');
|
const scales = this.get('scales');
|
||||||
let scale = scales[field];
|
let scale = scales[field];
|
||||||
const scaleController = this.get('scaleController');
|
const scaleController = this.get('scaleController');
|
||||||
|
@ -50,6 +62,8 @@ export default class Source extends Base {
|
||||||
}
|
}
|
||||||
_initControllers() {
|
_initControllers() {
|
||||||
const defs = this.get('defs');
|
const defs = this.get('defs');
|
||||||
|
const mapType = this.get('mapType');
|
||||||
|
this.projectFlat = getMap(mapType).project;
|
||||||
const scaleController = new Controller.Scale({
|
const scaleController = new Controller.Scale({
|
||||||
defs
|
defs
|
||||||
});
|
});
|
||||||
|
@ -83,9 +97,14 @@ export default class Source extends Base {
|
||||||
}
|
}
|
||||||
_coorConvert(geo) {
|
_coorConvert(geo) {
|
||||||
|
|
||||||
const ll = aProjectFlat(geo);
|
const ll = this.projectFlat(geo);
|
||||||
return [ ll.x, -ll.y, geo[2] || 0 ];
|
return [ ll.x, ll.y, geo[2] || 0 ];
|
||||||
|
|
||||||
}
|
}
|
||||||
|
getSelectFeature(featureId) {
|
||||||
|
const data = this.get('data');
|
||||||
|
// 如果是GeoJSON 数据返回原数
|
||||||
|
return data.features ? data.features[featureId] : this.data.dataArray[featureId];
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ export { Scene } from 'three/src/scenes/Scene.js';
|
||||||
export { WebGLRenderer } from 'three/src/renderers/WebGLRenderer.js';
|
export { WebGLRenderer } from 'three/src/renderers/WebGLRenderer.js';
|
||||||
export { CanvasTexture } from 'three/src/textures/CanvasTexture.js';
|
export { CanvasTexture } from 'three/src/textures/CanvasTexture.js';
|
||||||
export { Object3D } from 'three/src/core/Object3D.js';
|
export { Object3D } from 'three/src/core/Object3D.js';
|
||||||
|
export { Group } from 'three/src/objects/Group';
|
||||||
export { Clock } from 'three/src/core/Clock';
|
export { Clock } from 'three/src/core/Clock';
|
||||||
export { Points } from 'three/src/objects/Points.js';
|
export { Points } from 'three/src/objects/Points.js';
|
||||||
export { LineSegments } from 'three/src/objects/LineSegments.js';
|
export { LineSegments } from 'three/src/objects/LineSegments.js';
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -13,5 +13,20 @@ export function aProjectFlat(lnglat) {
|
||||||
d = 0.5;
|
d = 0.5;
|
||||||
x = scale * (a * x + b) - 215440491;
|
x = scale * (a * x + b) - 215440491;
|
||||||
y = scale * (c * y + d) - 106744817;
|
y = scale * (c * y + d) - 106744817;
|
||||||
return { x, y };
|
return { x: parseInt(x), y: parseInt(y) };
|
||||||
|
}
|
||||||
|
export function unProjectFlat(px) {
|
||||||
|
const a = 0.5 / Math.PI,
|
||||||
|
b = 0.5,
|
||||||
|
c = -0.5 / Math.PI;
|
||||||
|
let d = 0.5;
|
||||||
|
const scale = 256 << 20;
|
||||||
|
let [ x, y ] = px;
|
||||||
|
x = ((x + 215440491) / scale - b) / a;
|
||||||
|
y = ((y + 106744817) / scale - d) / c;
|
||||||
|
y = (Math.atan(Math.pow(Math.E, y)) - (Math.PI / 4)) * 2;
|
||||||
|
d = Math.PI / 180;
|
||||||
|
const lat = y / d;
|
||||||
|
const lng = x / d;
|
||||||
|
return [ lng, lat ];
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
export default function gridBuffer(layerData) {
|
||||||
|
const attribute = {
|
||||||
|
vertices: [],
|
||||||
|
miter: [],
|
||||||
|
colors: [],
|
||||||
|
pickingIds: []
|
||||||
|
};
|
||||||
|
layerData.forEach(element => {
|
||||||
|
const { color, id } = element;
|
||||||
|
const [ x, y, z ] = element.coordinates;
|
||||||
|
attribute.vertices.push(x, y, z);
|
||||||
|
attribute.miter.push(-1, -1);
|
||||||
|
attribute.vertices.push(x, y, z);
|
||||||
|
attribute.miter.push(1, 1);
|
||||||
|
attribute.vertices.push(x, y, z);
|
||||||
|
attribute.miter.push(-1, 1);
|
||||||
|
attribute.vertices.push(x, y, z);
|
||||||
|
attribute.miter.push(-1, -1);
|
||||||
|
attribute.vertices.push(x, y, z);
|
||||||
|
attribute.miter.push(1, -1);
|
||||||
|
attribute.vertices.push(x, y, z);
|
||||||
|
attribute.miter.push(1, 1);
|
||||||
|
attribute.colors.push(...color);
|
||||||
|
attribute.colors.push(...color);
|
||||||
|
attribute.colors.push(...color);
|
||||||
|
attribute.colors.push(...color);
|
||||||
|
attribute.colors.push(...color);
|
||||||
|
attribute.colors.push(...color);
|
||||||
|
attribute.pickingIds.push(id, id, id, id, id, id);
|
||||||
|
});
|
||||||
|
return attribute;
|
||||||
|
}
|
|
@ -4,8 +4,9 @@ import * as THREE from '../../core/three';
|
||||||
|
|
||||||
export default class ImageBuffer extends BufferBase {
|
export default class ImageBuffer extends BufferBase {
|
||||||
geometryBuffer() {
|
geometryBuffer() {
|
||||||
const coordinates = this.get('coordinates');
|
const layerData = this.get('layerData');
|
||||||
const images = this.get('image');
|
const coordinates = layerData[0].coordinates;
|
||||||
|
const images = layerData[0].images;
|
||||||
const positions = [ ...coordinates[0],
|
const positions = [ ...coordinates[0],
|
||||||
coordinates[1][0], coordinates[0][1], 0,
|
coordinates[1][0], coordinates[0][1], 0,
|
||||||
...coordinates[1],
|
...coordinates[1],
|
||||||
|
|
|
@ -3,8 +3,7 @@ import { lineShape } from '../shape';
|
||||||
|
|
||||||
export default class LineBuffer extends BufferBase {
|
export default class LineBuffer extends BufferBase {
|
||||||
geometryBuffer() {
|
geometryBuffer() {
|
||||||
const coordinates = this.get('coordinates');
|
const layerData = this.get('layerData');
|
||||||
const properties = this.get('properties');
|
|
||||||
const shapeType = this.shapeType = this.get('shapeType');
|
const shapeType = this.shapeType = this.get('shapeType');
|
||||||
const positions = [];
|
const positions = [];
|
||||||
const positionsIndex = [];
|
const positionsIndex = [];
|
||||||
|
@ -16,16 +15,16 @@ export default class LineBuffer extends BufferBase {
|
||||||
this.attributes = this._getArcLineAttributes();
|
this.attributes = this._getArcLineAttributes();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
coordinates.forEach((geo, index) => {
|
layerData.forEach((item, index) => {
|
||||||
const props = properties[index];
|
const props = item;
|
||||||
const attrData = this._getShape(geo, props, index);
|
const attrData = this._getShape(item.coordinates, props, index);
|
||||||
positions.push(...attrData.positions);
|
positions.push(...attrData.positions);
|
||||||
positionsIndex.push(...attrData.indexes);
|
positionsIndex.push(...attrData.indexes);
|
||||||
if (attrData.hasOwnProperty('instances')) {
|
if (attrData.hasOwnProperty('instances')) {
|
||||||
instances.push(...attrData.instances);
|
instances.push(...attrData.instances);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.bufferStruct.style = properties;
|
this.bufferStruct.style = layerData;
|
||||||
this.bufferStruct.verts = positions;
|
this.bufferStruct.verts = positions;
|
||||||
this.bufferStruct.indexs = positionsIndex;
|
this.bufferStruct.indexs = positionsIndex;
|
||||||
if (instances.length > 0) {
|
if (instances.length > 0) {
|
||||||
|
@ -50,17 +49,16 @@ export default class LineBuffer extends BufferBase {
|
||||||
|
|
||||||
}
|
}
|
||||||
_getArcLineAttributes() {
|
_getArcLineAttributes() {
|
||||||
const coordinates = this.get('coordinates');
|
const layerData = this.get('layerData');
|
||||||
const properties = this.get('properties');
|
|
||||||
const positions = [];
|
const positions = [];
|
||||||
const colors = [];
|
const colors = [];
|
||||||
const indexArray = [];
|
const indexArray = [];
|
||||||
const sizes = [];
|
const sizes = [];
|
||||||
const instances = [];
|
const instances = [];
|
||||||
coordinates.forEach((geo, index) => {
|
layerData.forEach(item => {
|
||||||
const props = properties[index];
|
const props = item;
|
||||||
const positionCount = positions.length / 3;
|
const positionCount = positions.length / 3;
|
||||||
const attrData = this._getShape(geo, props, positionCount);
|
const attrData = this._getShape(item.coordinates, props, positionCount);
|
||||||
positions.push(...attrData.positions);
|
positions.push(...attrData.positions);
|
||||||
colors.push(...attrData.colors);
|
colors.push(...attrData.colors);
|
||||||
indexArray.push(...attrData.indexArray);
|
indexArray.push(...attrData.indexArray);
|
||||||
|
@ -76,8 +74,7 @@ export default class LineBuffer extends BufferBase {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
_getMeshLineAttributes() {
|
_getMeshLineAttributes() {
|
||||||
const coordinates = this.get('coordinates');
|
const layerData = this.get('layerData');
|
||||||
const properties = this.get('properties');
|
|
||||||
const { lineType } = this.get('style');
|
const { lineType } = this.get('style');
|
||||||
const positions = [];
|
const positions = [];
|
||||||
const pickingIds = [];
|
const pickingIds = [];
|
||||||
|
@ -87,10 +84,10 @@ export default class LineBuffer extends BufferBase {
|
||||||
const indexArray = [];
|
const indexArray = [];
|
||||||
const sizes = [];
|
const sizes = [];
|
||||||
const attrDistance = [];
|
const attrDistance = [];
|
||||||
coordinates.forEach((geo, index) => {
|
layerData.forEach(item => {
|
||||||
const props = properties[index];
|
const props = item;
|
||||||
const positionCount = positions.length / 3;
|
const positionCount = positions.length / 3;
|
||||||
const attr = lineShape.Line(geo, props, positionCount, (lineType !== 'soild'));
|
const attr = lineShape.Line(item.coordinates, props, positionCount, (lineType !== 'soild'));
|
||||||
positions.push(...attr.positions);
|
positions.push(...attr.positions);
|
||||||
normal.push(...attr.normal);
|
normal.push(...attr.normal);
|
||||||
miter.push(...attr.miter);
|
miter.push(...attr.miter);
|
||||||
|
|
|
@ -3,7 +3,7 @@ import * as THREE from '../../../core/three';
|
||||||
import * as polygonShape from '../../shape/polygon';
|
import * as polygonShape from '../../shape/polygon';
|
||||||
import * as polygonPath from '../../shape/path';
|
import * as polygonPath from '../../shape/path';
|
||||||
import Util from '../../../util';
|
import Util from '../../../util';
|
||||||
export default function fillBuffer(coordinates, properties) {
|
export default function fillBuffer(layerData) {
|
||||||
const attribute = {
|
const attribute = {
|
||||||
vertices: [],
|
vertices: [],
|
||||||
normals: [],
|
normals: [],
|
||||||
|
@ -14,8 +14,8 @@ export default function fillBuffer(coordinates, properties) {
|
||||||
faceUv: []
|
faceUv: []
|
||||||
|
|
||||||
};
|
};
|
||||||
coordinates.forEach((geo, index) => {
|
layerData.forEach(item => {
|
||||||
let { size, shape, color, id } = properties[index];
|
let { size, shape, color, id, coordinates } = item;
|
||||||
let polygon = null;
|
let polygon = null;
|
||||||
const path = polygonPath[shape]();
|
const path = polygonPath[shape]();
|
||||||
if (pointShape['2d'].indexOf(shape) !== -1) {
|
if (pointShape['2d'].indexOf(shape) !== -1) {
|
||||||
|
@ -27,7 +27,7 @@ export default function fillBuffer(coordinates, properties) {
|
||||||
} else {
|
} else {
|
||||||
throw new Error('Invalid shape type: ' + shape);
|
throw new Error('Invalid shape type: ' + shape);
|
||||||
}
|
}
|
||||||
toPointShapeAttributes(polygon, geo, { size, shape, color, id }, attribute);
|
toPointShapeAttributes(polygon, coordinates, { size, shape, color, id }, attribute);
|
||||||
|
|
||||||
});
|
});
|
||||||
return attribute;
|
return attribute;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
export default function ImageBuffer(coordinates, properties, opt) {
|
export default function ImageBuffer(layerData, opt) {
|
||||||
const attributes = {
|
const attributes = {
|
||||||
vertices: [],
|
vertices: [],
|
||||||
colors: [],
|
colors: [],
|
||||||
|
@ -7,10 +7,10 @@ export default function ImageBuffer(coordinates, properties, opt) {
|
||||||
pickingIds: [],
|
pickingIds: [],
|
||||||
uv: []
|
uv: []
|
||||||
};
|
};
|
||||||
coordinates.forEach((pos, index) => {
|
layerData.forEach(item => {
|
||||||
const { color, size, id, shape } = properties[index];
|
const { color, size, id, shape, coordinates } = item;
|
||||||
const { x, y } = opt.imagePos[shape];
|
const { x, y } = opt.imagePos[shape];
|
||||||
attributes.vertices.push(...pos);
|
attributes.vertices.push(...coordinates);
|
||||||
attributes.colors.push(...color);
|
attributes.colors.push(...color);
|
||||||
attributes.pickingIds.push(id);
|
attributes.pickingIds.push(id);
|
||||||
attributes.sizes.push(size * window.devicePixelRatio); //
|
attributes.sizes.push(size * window.devicePixelRatio); //
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
export default function NormalBuffer(coordinates, properties) {
|
export default function NormalBuffer(layerData) {
|
||||||
const attributes = {
|
const attributes = {
|
||||||
vertices: [],
|
vertices: [],
|
||||||
colors: [],
|
colors: [],
|
||||||
sizes: [],
|
sizes: [],
|
||||||
pickingIds: []
|
pickingIds: []
|
||||||
};
|
};
|
||||||
coordinates.forEach((pos, index) => {
|
layerData.forEach(item => {
|
||||||
const { color, size, id } = properties[index];
|
const { color, size, id, coordinates} = item;
|
||||||
attributes.vertices.push(...pos);
|
attributes.vertices.push(...coordinates);
|
||||||
attributes.colors.push(...color);
|
attributes.colors.push(...color);
|
||||||
attributes.pickingIds.push(id);
|
attributes.pickingIds.push(id);
|
||||||
attributes.sizes.push(size);
|
attributes.sizes.push(size);
|
||||||
|
|
|
@ -3,7 +3,7 @@ import * as polygonShape from '../../shape/polygon';
|
||||||
import * as lineShape from '../../shape/line';
|
import * as lineShape from '../../shape/line';
|
||||||
import { pointShape } from '../../../global';
|
import { pointShape } from '../../../global';
|
||||||
import Util from '../../../util';
|
import Util from '../../../util';
|
||||||
export default function StrokeBuffer(coordinates, properties, style) {
|
export default function StrokeBuffer(layerData, style) {
|
||||||
const attribute = {
|
const attribute = {
|
||||||
shapes: [],
|
shapes: [],
|
||||||
normal: [],
|
normal: [],
|
||||||
|
@ -15,8 +15,8 @@ export default function StrokeBuffer(coordinates, properties, style) {
|
||||||
colors: []
|
colors: []
|
||||||
};
|
};
|
||||||
const { stroke, strokeWidth } = style;
|
const { stroke, strokeWidth } = style;
|
||||||
coordinates.forEach((geo, index) => {
|
layerData.forEach(item => {
|
||||||
let { size, shape, id } = properties[index];
|
let { size, shape, id, coordinates } = item;
|
||||||
const path = polygonPath[shape]();
|
const path = polygonPath[shape]();
|
||||||
const positionsIndex = attribute.miter.length;
|
const positionsIndex = attribute.miter.length;
|
||||||
let polygon = null;
|
let polygon = null;
|
||||||
|
@ -33,7 +33,7 @@ export default function StrokeBuffer(coordinates, properties, style) {
|
||||||
} else {
|
} else {
|
||||||
throw new Error('Invalid shape type: ' + shape);
|
throw new Error('Invalid shape type: ' + shape);
|
||||||
}
|
}
|
||||||
polygonLineBuffer(polygon, geo, size, attribute);
|
polygonLineBuffer(polygon, coordinates, size, attribute);
|
||||||
|
|
||||||
});
|
});
|
||||||
return attribute;
|
return attribute;
|
||||||
|
|
|
@ -9,7 +9,7 @@ const metrics = {
|
||||||
family: 'ios9',
|
family: 'ios9',
|
||||||
size: 24
|
size: 24
|
||||||
};
|
};
|
||||||
export default function TextBuffer(coordinates, properties, style) {
|
export default function TextBuffer(layerData, style) {
|
||||||
EventEmitter.call(this);
|
EventEmitter.call(this);
|
||||||
const attributes = {
|
const attributes = {
|
||||||
originPoints: [],
|
originPoints: [],
|
||||||
|
@ -21,7 +21,7 @@ export default function TextBuffer(coordinates, properties, style) {
|
||||||
const { textOffset = [ 0, 0 ] } = style;
|
const { textOffset = [ 0, 0 ] } = style;
|
||||||
const chars = [];
|
const chars = [];
|
||||||
const textChars = {};
|
const textChars = {};
|
||||||
properties.forEach(element => {
|
layerData.forEach(element => {
|
||||||
let text = element.shape || '';
|
let text = element.shape || '';
|
||||||
text = text.toString();
|
text = text.toString();
|
||||||
for (let j = 0; j < text.length; j++) {
|
for (let j = 0; j < text.length; j++) {
|
||||||
|
@ -33,9 +33,9 @@ export default function TextBuffer(coordinates, properties, style) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
loadTextInfo(chars, (chars, texture) => {
|
loadTextInfo(chars, (chars, texture) => {
|
||||||
properties.forEach((element, index) => {
|
layerData.forEach(element => {
|
||||||
const size = element.size;
|
const size = element.size;
|
||||||
const pos = coordinates[index];
|
const pos = layerData.coordinates;
|
||||||
const pen = { x: textOffset[0], y: textOffset[1] };
|
const pen = { x: textOffset[0], y: textOffset[1] };
|
||||||
let text = element.shape || '';
|
let text = element.shape || '';
|
||||||
text = text.toString();
|
text = text.toString();
|
||||||
|
|
|
@ -3,22 +3,21 @@ import BufferBase from './bufferBase';
|
||||||
export default class PolygonBuffer extends BufferBase {
|
export default class PolygonBuffer extends BufferBase {
|
||||||
|
|
||||||
geometryBuffer() {
|
geometryBuffer() {
|
||||||
const coordinates = this.get('coordinates');
|
const layerData = this.get('layerData');
|
||||||
const properties = this.get('properties');
|
|
||||||
const shape = this.get('shape');
|
const shape = this.get('shape');
|
||||||
const positions = [];
|
const positions = [];
|
||||||
const faceUv = [];
|
const faceUv = [];
|
||||||
const sizes = [];
|
const sizes = [];
|
||||||
const positionsIndex = [];
|
const positionsIndex = [];
|
||||||
let indexCount = 0;
|
let indexCount = 0;
|
||||||
this.bufferStruct.style = properties;
|
this.bufferStruct.style = layerData;
|
||||||
const isExtrude = properties[0].hasOwnProperty('size');
|
const isExtrude = layerData[0].hasOwnProperty('size');
|
||||||
// indices, normals, colors, UVs
|
// indices, normals, colors, UVs
|
||||||
coordinates.forEach((geo, index) => {
|
layerData.forEach(item => {
|
||||||
const heightValue = properties[index].size;
|
const heightValue = item.size;
|
||||||
let extrudeData = polygonShape[shape](geo);
|
let extrudeData = polygonShape[shape](item.coordinates);
|
||||||
if (isExtrude && shape === 'extrude') {
|
if (isExtrude && shape === 'extrude') {
|
||||||
extrudeData = polygonShape.extrude(geo);
|
extrudeData = polygonShape.extrude(item.coordinates);
|
||||||
extrudeData.positions = extrudeData.positions.map(pos => {
|
extrudeData.positions = extrudeData.positions.map(pos => {
|
||||||
pos[2] *= heightValue;
|
pos[2] *= heightValue;
|
||||||
return pos;
|
return pos;
|
||||||
|
@ -48,7 +47,7 @@ export default class PolygonBuffer extends BufferBase {
|
||||||
this.bufferStruct.indices = positionsIndex;
|
this.bufferStruct.indices = positionsIndex;
|
||||||
this.bufferStruct.position = positions;
|
this.bufferStruct.position = positions;
|
||||||
this.bufferStruct.indexCount = indexCount;
|
this.bufferStruct.indexCount = indexCount;
|
||||||
this.bufferStruct.style = properties;
|
this.bufferStruct.style = layerData;
|
||||||
this.bufferStruct.faceUv = faceUv;
|
this.bufferStruct.faceUv = faceUv;
|
||||||
this.bufferStruct.sizes = sizes;
|
this.bufferStruct.sizes = sizes;
|
||||||
if (shape !== 'line') {
|
if (shape !== 'line') {
|
||||||
|
|
|
@ -3,8 +3,8 @@ import { colorScales } from '../../attr/colorscales';
|
||||||
import * as THREE from '../../core/three';
|
import * as THREE from '../../core/three';
|
||||||
export class RasterBuffer extends BufferBase {
|
export class RasterBuffer extends BufferBase {
|
||||||
geometryBuffer() {
|
geometryBuffer() {
|
||||||
const coordinates = this.get('coordinates');
|
const layerData = this.get('layerData');
|
||||||
|
const { coordinates, width, data, height } = layerData.dataArray[0];
|
||||||
const positions = [
|
const positions = [
|
||||||
...coordinates[0],
|
...coordinates[0],
|
||||||
coordinates[1][0], coordinates[0][1], 0,
|
coordinates[1][0], coordinates[0][1], 0,
|
||||||
|
@ -14,9 +14,8 @@ export class RasterBuffer extends BufferBase {
|
||||||
coordinates[0][0], coordinates[1][1], 0
|
coordinates[0][0], coordinates[1][1], 0
|
||||||
];
|
];
|
||||||
const imgPosUv = [ 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0 ];
|
const imgPosUv = [ 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0 ];
|
||||||
const raster = this.get('raster');
|
|
||||||
const size = this.get('size');
|
const size = this.get('size');
|
||||||
const texture = new THREE.DataTexture(new Float32Array(raster.data), raster.width, raster.height, THREE.LuminanceFormat, THREE.FloatType);
|
const texture = new THREE.DataTexture(new Float32Array(data), width, height, THREE.LuminanceFormat, THREE.FloatType);
|
||||||
texture.generateMipmaps = true;
|
texture.generateMipmaps = true;
|
||||||
texture.needsUpdate = true;
|
texture.needsUpdate = true;
|
||||||
const colors = this.get('rampColors');
|
const colors = this.get('rampColors');
|
||||||
|
@ -28,7 +27,7 @@ export class RasterBuffer extends BufferBase {
|
||||||
this.bufferStruct.u_extent = [ coordinates[0][0], coordinates[0][1], coordinates[1][0], coordinates[1][1] ];
|
this.bufferStruct.u_extent = [ coordinates[0][0], coordinates[0][1], coordinates[1][0], coordinates[1][1] ];
|
||||||
|
|
||||||
this.bufferStruct.u_colorTexture = colorTexture; // 颜色表‘=
|
this.bufferStruct.u_colorTexture = colorTexture; // 颜色表‘=
|
||||||
const triangles = this._buildTriangles(raster, size, this.bufferStruct.u_extent);
|
const triangles = this._buildTriangles(width, height, size, this.bufferStruct.u_extent);
|
||||||
const attributes = {
|
const attributes = {
|
||||||
vertices: new Float32Array(triangles.vertices),
|
vertices: new Float32Array(triangles.vertices),
|
||||||
uvs: new Float32Array(triangles.uvs),
|
uvs: new Float32Array(triangles.uvs),
|
||||||
|
@ -78,9 +77,8 @@ export class RasterBuffer extends BufferBase {
|
||||||
texture1.needsUpdate = true;
|
texture1.needsUpdate = true;
|
||||||
return texture1;
|
return texture1;
|
||||||
}
|
}
|
||||||
_buildTriangles(raster, size = 1, extent) {
|
_buildTriangles(width, height, size = 1, extent) {
|
||||||
// const extent = [ 73.482190241, 3.82501784112, 135.106618732, 57.6300459963 ]
|
// const extent = [ 73.482190241, 3.82501784112, 135.106618732, 57.6300459963 ]
|
||||||
const { width, height } = raster;
|
|
||||||
const indices = [];
|
const indices = [];
|
||||||
const vertices = [];
|
const vertices = [];
|
||||||
const uvs = [];
|
const uvs = [];
|
||||||
|
|
|
@ -13,12 +13,11 @@ export default class TextBuffer extends BufferBase {
|
||||||
family: 'ios9',
|
family: 'ios9',
|
||||||
size: 24
|
size: 24
|
||||||
};
|
};
|
||||||
const coordinates = this.get('coordinates');
|
const layerData = this.get('layerData');
|
||||||
const properties = this.get('properties');
|
|
||||||
const { textOffset = [ 0, 0 ] } = this.get('style');
|
const { textOffset = [ 0, 0 ] } = this.get('style');
|
||||||
const chars = [];
|
const chars = [];
|
||||||
const textChars = {};
|
const textChars = {};
|
||||||
properties.forEach(element => {
|
layerData.forEach(element => {
|
||||||
let text = element.shape || '';
|
let text = element.shape || '';
|
||||||
text = text.toString();
|
text = text.toString();
|
||||||
for (let j = 0; j < text.length; j++) {
|
for (let j = 0; j < text.length; j++) {
|
||||||
|
@ -39,9 +38,9 @@ export default class TextBuffer extends BufferBase {
|
||||||
const originPoints = [];
|
const originPoints = [];
|
||||||
const textSizes = [];
|
const textSizes = [];
|
||||||
const textOffsets = [];
|
const textOffsets = [];
|
||||||
properties.forEach((element, index) => {
|
layerData.forEach(element => {
|
||||||
const size = element.size;
|
const size = element.size;
|
||||||
const pos = coordinates[index];
|
const pos = element.coordinates;
|
||||||
// const pen = { x: pos[0] - dimensions.advance / 2, y: pos[1] };
|
// const pen = { x: pos[0] - dimensions.advance / 2, y: pos[1] };
|
||||||
const pen = { x: textOffset[0], y: textOffset[1] };
|
const pen = { x: textOffset[0], y: textOffset[1] };
|
||||||
let text = element.shape || '';
|
let text = element.shape || '';
|
||||||
|
@ -53,7 +52,7 @@ export default class TextBuffer extends BufferBase {
|
||||||
this._drawGlyph(pos, text[i], pen, size, colors, textureElements, originPoints, textSizes, textOffsets, color);
|
this._drawGlyph(pos, text[i], pen, size, colors, textureElements, originPoints, textSizes, textOffsets, color);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.bufferStruct.style = properties;
|
this.bufferStruct.style = layerData;
|
||||||
this.attributes = {
|
this.attributes = {
|
||||||
originPoints,
|
originPoints,
|
||||||
textSizes,
|
textSizes,
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
import grid_frag from '../shader/grid_frag.glsl';
|
||||||
|
import grid_vert from '../shader/grid_vert.glsl';
|
||||||
|
import Material from './material';
|
||||||
|
|
||||||
|
|
||||||
|
export default class GridMaterial extends Material {
|
||||||
|
getDefaultParameters() {
|
||||||
|
return {
|
||||||
|
uniforms: {
|
||||||
|
u_opacity: { value: 1.0 },
|
||||||
|
u_time: { value: 0 },
|
||||||
|
u_xOffset: { value: 0.01 },
|
||||||
|
u_yOffset: { value: 0.01 },
|
||||||
|
u_coverage: { value: 0.8 }
|
||||||
|
},
|
||||||
|
defines: {
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
constructor(_uniforms, _defines, parameters) {
|
||||||
|
super(parameters);
|
||||||
|
const { uniforms, defines } = this.getDefaultParameters();
|
||||||
|
this.uniforms = Object.assign(uniforms, this.setUniform(_uniforms));
|
||||||
|
this.type = 'GridMaterial';
|
||||||
|
this.defines = Object.assign(defines, _defines);
|
||||||
|
this.vertexShader = grid_vert;
|
||||||
|
this.fragmentShader = grid_frag;
|
||||||
|
this.transparent = true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,28 +1,5 @@
|
||||||
import Material from './material';
|
import Material from './material';
|
||||||
import { getModule } from '../../util/shaderModule';
|
import { getModule } from '../../util/shaderModule';
|
||||||
// export default function PolygonMaterial(options) {
|
|
||||||
// const material = new Material({
|
|
||||||
// uniforms: {
|
|
||||||
// u_opacity: { value: options.u_opacity || 1.0 },
|
|
||||||
// u_texture: { value: options.u_texture },
|
|
||||||
// u_time: { value: options.u_time || 0 },
|
|
||||||
// u_zoom: { value: options.u_zoom || 0 },
|
|
||||||
// u_baseColor: { value: options.u_baseColor || [ 1.0, 0, 0, 1.0 ] },
|
|
||||||
// u_brightColor: { value: options.u_brightColor || [ 1.0, 0, 0, 1.0 ] },
|
|
||||||
// u_windowColor: { value: options.u_windowColor || [ 1.0, 0, 0, 1.0 ] },
|
|
||||||
// u_near: { value: options.u_near || 0.0 },
|
|
||||||
// u_far: { value: options.u_far || 1.0 }
|
|
||||||
// },
|
|
||||||
// vertexShader: polygon_vert,
|
|
||||||
// fragmentShader: polygon_frag,
|
|
||||||
// transparent: true,
|
|
||||||
// defines: {
|
|
||||||
// TEXCOORD_0: !!options.u_texture
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// return material;
|
|
||||||
// }
|
|
||||||
|
|
||||||
export default class PolygonMaterial extends Material {
|
export default class PolygonMaterial extends Material {
|
||||||
getDefaultParameters() {
|
getDefaultParameters() {
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
precision highp float;
|
||||||
|
uniform float u_opacity;
|
||||||
|
varying vec4 v_color;
|
||||||
|
void main() {
|
||||||
|
vec4 color = v_color;
|
||||||
|
gl_FragColor = color;
|
||||||
|
gl_FragColor.a =color.a*u_opacity;
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
precision highp float;
|
||||||
|
attribute vec2 miter;
|
||||||
|
attribute vec4 a_color;
|
||||||
|
uniform float u_xOffset;
|
||||||
|
uniform float u_yOffset;
|
||||||
|
uniform float u_coverage;
|
||||||
|
varying vec4 v_color;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
mat4 matModelViewProjection = projectionMatrix * modelViewMatrix;
|
||||||
|
v_color = a_color;
|
||||||
|
float x = position.x + miter.x * u_xOffset * u_coverage;
|
||||||
|
float y = position.y + miter.y * u_yOffset * u_coverage;
|
||||||
|
gl_Position = matModelViewProjection * vec4(x, y, position.z, 1.0);
|
||||||
|
}
|
|
@ -1,7 +1,8 @@
|
||||||
|
|
||||||
precision highp float;
|
precision highp float;
|
||||||
|
|
||||||
#pragma import "common"
|
#define PI 3.14159265359
|
||||||
|
#define TWO_PI 6.28318530718
|
||||||
|
|
||||||
uniform float u_strokeWidth;
|
uniform float u_strokeWidth;
|
||||||
uniform vec4 u_stroke;
|
uniform vec4 u_stroke;
|
||||||
|
|
|
@ -15,7 +15,7 @@ varying float v_size;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
float scale = pow(2.0,(20.0 - u_zoom));
|
float scale = pow(2.0,(20.0 - u_zoom));
|
||||||
mat4 matModelViewProjection = projectionMatrix * modelViewMatrix;
|
mat4 matModelViewProjection = projectionMatrix * modelViewMatrix * 100.;
|
||||||
vec3 newposition = position;
|
vec3 newposition = position;
|
||||||
// newposition.x -= 128.0;
|
// newposition.x -= 128.0;
|
||||||
#ifdef SHAPE
|
#ifdef SHAPE
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
import Layer from '../core/layer';
|
||||||
|
import gridBuffer from '../geom/buffer/heatmap/grid';
|
||||||
|
import DrawGrid from './render/heatmap/gird';
|
||||||
|
|
||||||
|
export default class HeatMapLayer extends Layer {
|
||||||
|
shape(type) {
|
||||||
|
this.shapeType = type;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
this._prepareRender();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
_prepareRender() {
|
||||||
|
this.init();
|
||||||
|
this.type = 'heatmap';
|
||||||
|
const style = this.get('styleOptions');
|
||||||
|
const { xOffset, yOffset } = this.layerSource.data;
|
||||||
|
this._buffer = new gridBuffer(this.layerData);
|
||||||
|
const config = {
|
||||||
|
...style,
|
||||||
|
xOffset,
|
||||||
|
yOffset
|
||||||
|
};
|
||||||
|
const girdMesh = new DrawGrid(this._buffer, config);
|
||||||
|
this.add(girdMesh);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,26 +1,19 @@
|
||||||
import Layer from '../core/layer';
|
import Layer from '../core/layer';
|
||||||
import * as THREE from '../core/three';
|
import * as THREE from '../core/three';
|
||||||
import imageSource from '../source/imageSource';
|
|
||||||
import ImageBuffer from '../geom/buffer/image';
|
import ImageBuffer from '../geom/buffer/image';
|
||||||
// import ImageGeometry from '../geom/bufferGeometry/image';
|
// import ImageGeometry from '../geom/bufferGeometry/image';
|
||||||
import ImageMaterial from '../geom/material/imageMaterial';
|
import ImageMaterial from '../geom/material/imageMaterial';
|
||||||
export default class imageLayer extends Layer {
|
export default class imageLayer extends Layer {
|
||||||
source(data, cfg = {}) {
|
|
||||||
cfg.mapType = this.get('mapType');
|
|
||||||
cfg.data = data;
|
|
||||||
this.layerSource = new imageSource(cfg);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
render() {
|
render() {
|
||||||
this.init();
|
this.init();
|
||||||
this.type = 'image';
|
this.type = 'image';
|
||||||
const source = this.layerSource;
|
const source = this.layerSource;
|
||||||
const { opacity } = this.get('styleOptions');
|
const { opacity } = this.get('styleOptions');
|
||||||
// 加载 完成事件
|
// 加载 完成事件
|
||||||
source.on('imageLoaded', () => {
|
source.data.images.then(images => {
|
||||||
|
this.layerData[0].images = images;
|
||||||
const buffer = new ImageBuffer({
|
const buffer = new ImageBuffer({
|
||||||
coordinates: source.geoData,
|
layerData: this.layerData
|
||||||
image: source.image
|
|
||||||
});
|
});
|
||||||
this.initGeometry(buffer.attributes);
|
this.initGeometry(buffer.attributes);
|
||||||
const material = new ImageMaterial({
|
const material = new ImageMaterial({
|
||||||
|
|
|
@ -4,17 +4,14 @@ import PointLayer from './pointLayer';
|
||||||
import LineLayer from './lineLayer';
|
import LineLayer from './lineLayer';
|
||||||
import ImageLayer from './imageLayer';
|
import ImageLayer from './imageLayer';
|
||||||
import RasterLayer from './rasterLayer';
|
import RasterLayer from './rasterLayer';
|
||||||
|
import HeatMapLayer from './heatmap';
|
||||||
|
|
||||||
registerLayer('PolygonLayer', PolygonLayer);
|
registerLayer('PolygonLayer', PolygonLayer);
|
||||||
registerLayer('PointLayer', PointLayer);
|
registerLayer('PointLayer', PointLayer);
|
||||||
registerLayer('LineLayer', LineLayer);
|
registerLayer('LineLayer', LineLayer);
|
||||||
registerLayer('ImageLayer', ImageLayer);
|
registerLayer('ImageLayer', ImageLayer);
|
||||||
registerLayer('RasterLayer', RasterLayer);
|
registerLayer('RasterLayer', RasterLayer);
|
||||||
|
registerLayer('HeatMapLayer', HeatMapLayer);
|
||||||
|
|
||||||
export { LAYER_MAP } from './factory';
|
export { LAYER_MAP } from './factory';
|
||||||
export { default as PolygonLayer } from './polygonLayer';
|
|
||||||
export { default as PointLayer } from './pointLayer';
|
|
||||||
export { default as LineLayer } from './lineLayer';
|
|
||||||
export { default as ImageLayer } from './imageLayer';
|
|
||||||
export { default as RasterLayer } from './rasterLayer';
|
|
||||||
|
|
||||||
|
|
|
@ -12,11 +12,10 @@ export default class LineLayer extends Layer {
|
||||||
this.type = 'polyline';
|
this.type = 'polyline';
|
||||||
this.init();
|
this.init();
|
||||||
const source = this.layerSource;
|
const source = this.layerSource;
|
||||||
const StyleData = this.StyleData;
|
const layerData = this.layerData;
|
||||||
const style = this.get('styleOptions');
|
const style = this.get('styleOptions');
|
||||||
const buffer = this._buffer = new LineBuffer({
|
const buffer = this._buffer = new LineBuffer({
|
||||||
coordinates: source.geoData,
|
layerData,
|
||||||
properties: StyleData,
|
|
||||||
shapeType: this.shapeType,
|
shapeType: this.shapeType,
|
||||||
style
|
style
|
||||||
});
|
});
|
||||||
|
|
|
@ -45,12 +45,12 @@ export default class PointLayer extends Layer {
|
||||||
case 'fill' :// 填充图形
|
case 'fill' :// 填充图形
|
||||||
{
|
{
|
||||||
if (fill !== 'none') { // 是否填充
|
if (fill !== 'none') { // 是否填充
|
||||||
const attributes = PointBuffer.FillBuffer(source.geoData, this.StyleData, style);
|
const attributes = PointBuffer.FillBuffer(this.layerData, style);
|
||||||
const meshfill = drawPoint.DrawFill(attributes, this.get('styleOptions'));
|
const meshfill = drawPoint.DrawFill(attributes, this.get('styleOptions'));
|
||||||
this.add(meshfill);
|
this.add(meshfill);
|
||||||
}
|
}
|
||||||
if (stroke !== 'none') { // 是否绘制边界
|
if (stroke !== 'none') { // 是否绘制边界
|
||||||
const lineAttribute = PointBuffer.StrokeBuffer(source.geoData, this.StyleData, style);
|
const lineAttribute = PointBuffer.StrokeBuffer(this.layerData, style);
|
||||||
const meshStroke = drawPoint.DrawStroke(lineAttribute, this.get('styleOptions'));
|
const meshStroke = drawPoint.DrawStroke(lineAttribute, this.get('styleOptions'));
|
||||||
this.add(meshStroke, 'line');
|
this.add(meshStroke, 'line');
|
||||||
}
|
}
|
||||||
|
@ -58,14 +58,14 @@ export default class PointLayer extends Layer {
|
||||||
}
|
}
|
||||||
case 'image':// 绘制图片标注
|
case 'image':// 绘制图片标注
|
||||||
{
|
{
|
||||||
const imageAttribute = PointBuffer.ImageBuffer(source.geoData, this.StyleData, { imagePos: this.scene.image.imagePos });
|
const imageAttribute = PointBuffer.ImageBuffer(this.layerData, { imagePos: this.scene.image.imagePos });
|
||||||
const imageMesh = drawPoint.DrawImage(imageAttribute, { ...style, texture: this.scene.image.texture });
|
const imageMesh = drawPoint.DrawImage(imageAttribute, { ...style, texture: this.scene.image.texture });
|
||||||
this.add(imageMesh);
|
this.add(imageMesh);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'normal' : // 原生点
|
case 'normal' : // 原生点
|
||||||
{
|
{
|
||||||
const normalAttribute = PointBuffer.NormalBuffer(source.geoData, this.StyleData, style);
|
const normalAttribute = PointBuffer.NormalBuffer(this.layerData, style);
|
||||||
const normalPointMesh = drawPoint.DrawNormal(normalAttribute, style);
|
const normalPointMesh = drawPoint.DrawNormal(normalAttribute, style);
|
||||||
this.add(normalPointMesh);
|
this.add(normalPointMesh);
|
||||||
break;
|
break;
|
||||||
|
@ -77,11 +77,11 @@ export default class PointLayer extends Layer {
|
||||||
|
|
||||||
_getShape() {
|
_getShape() {
|
||||||
let shape = null;
|
let shape = null;
|
||||||
if (!this.StyleData[0].hasOwnProperty('shape')) {
|
if (!this.layerData[0].hasOwnProperty('shape')) {
|
||||||
return 'normal';
|
return 'normal';
|
||||||
}
|
}
|
||||||
for (let i = 0; i < this.StyleData.length; i++) {
|
for (let i = 0; i < this.layerData.length; i++) {
|
||||||
shape = this.StyleData[i].shape;
|
shape = this.layerData[i].shape;
|
||||||
if (shape !== undefined) {
|
if (shape !== undefined) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -102,8 +102,7 @@ export default class PointLayer extends Layer {
|
||||||
const styleOptions = this.get('styleOptions');
|
const styleOptions = this.get('styleOptions');
|
||||||
const buffer = new TextBuffer({
|
const buffer = new TextBuffer({
|
||||||
type: this.shapeType,
|
type: this.shapeType,
|
||||||
coordinates: source.geoData,
|
layerData: this.layerData,
|
||||||
properties: this.StyleData,
|
|
||||||
style: this.get('styleOptions')
|
style: this.get('styleOptions')
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -21,11 +21,9 @@ export default class PolygonLayer extends Layer {
|
||||||
_prepareRender() {
|
_prepareRender() {
|
||||||
this.init();
|
this.init();
|
||||||
this.type = 'polygon';
|
this.type = 'polygon';
|
||||||
const source = this.layerSource;
|
|
||||||
this._buffer = new PolygonBuffer({
|
this._buffer = new PolygonBuffer({
|
||||||
shape: this.shape,
|
shape: this.shape,
|
||||||
coordinates: source.geoData,
|
layerData: this.layerData
|
||||||
properties: this.StyleData
|
|
||||||
});
|
});
|
||||||
this.add(this._getLayerRender());
|
this.add(this._getLayerRender());
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,10 @@
|
||||||
import Layer from '../core/layer';
|
import Layer from '../core/layer';
|
||||||
import * as THREE from '../core/three';
|
import * as THREE from '../core/three';
|
||||||
import RasterSource from '../source/rasterSource';
|
|
||||||
import RasterMaterial from '../geom/material/rasterMaterial';
|
import RasterMaterial from '../geom/material/rasterMaterial';
|
||||||
import { RasterBuffer } from '../geom/buffer/raster';
|
import { RasterBuffer } from '../geom/buffer/raster';
|
||||||
|
|
||||||
export default class RasterLayer extends Layer {
|
export default class RasterLayer extends Layer {
|
||||||
source(data, cfg = {}) {
|
|
||||||
cfg.mapType = this.get('mapType');
|
|
||||||
cfg.data = data;
|
|
||||||
this.layerSource = new RasterSource(cfg);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
render() {
|
render() {
|
||||||
this.type = 'raster';
|
this.type = 'raster';
|
||||||
this.init();
|
this.init();
|
||||||
|
@ -18,18 +12,18 @@ export default class RasterLayer extends Layer {
|
||||||
// 加载 完成事件
|
// 加载 完成事件
|
||||||
const styleOptions = this.get('styleOptions');
|
const styleOptions = this.get('styleOptions');
|
||||||
const buffer = new RasterBuffer({
|
const buffer = new RasterBuffer({
|
||||||
coordinates: source.geoData,
|
layerData: source.data,
|
||||||
raster: source.rasterData,
|
|
||||||
rampColors: styleOptions.rampColors
|
rampColors: styleOptions.rampColors
|
||||||
});
|
});
|
||||||
this.initGeometry(buffer.attributes);
|
this.initGeometry(buffer.attributes);
|
||||||
|
const rasterConfig = source.data.dataArray[0];
|
||||||
const material = new RasterMaterial({
|
const material = new RasterMaterial({
|
||||||
u_texture: buffer.bufferStruct.u_raster,
|
u_texture: buffer.bufferStruct.u_raster,
|
||||||
u_colorTexture: buffer.bufferStruct.u_colorTexture,
|
u_colorTexture: buffer.bufferStruct.u_colorTexture,
|
||||||
u_opacity: 1.0,
|
u_opacity: 1.0,
|
||||||
u_extent: buffer.bufferStruct.u_extent,
|
u_extent: buffer.bufferStruct.u_extent,
|
||||||
u_min: source.rasterData.min,
|
u_min: rasterConfig.min,
|
||||||
u_max: source.rasterData.max,
|
u_max: rasterConfig.max,
|
||||||
u_dimension: buffer.attributes.dimension
|
u_dimension: buffer.attributes.dimension
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
import * as THREE from '../../../core/three';
|
||||||
|
import GridMaterial from '../../../geom/material/grid';
|
||||||
|
export default function DrawGrid(attributes, style) {
|
||||||
|
const { opacity, xOffset, yOffset, coverage } = style;
|
||||||
|
const geometry = new THREE.BufferGeometry();
|
||||||
|
geometry.addAttribute('position', new THREE.Float32BufferAttribute(attributes.vertices, 3));
|
||||||
|
geometry.addAttribute('miter', new THREE.Float32BufferAttribute(attributes.miter, 2));
|
||||||
|
geometry.addAttribute('a_color', new THREE.Float32BufferAttribute(attributes.colors, 4));
|
||||||
|
geometry.addAttribute('pickingId', new THREE.Float32BufferAttribute(attributes.pickingIds, 1));
|
||||||
|
const material = new GridMaterial({
|
||||||
|
u_opacity: opacity,
|
||||||
|
u_xOffset: xOffset,
|
||||||
|
u_yOffset: yOffset,
|
||||||
|
u_coverage: coverage
|
||||||
|
}, {
|
||||||
|
SHAPE: false
|
||||||
|
});
|
||||||
|
const gridMesh = new THREE.Mesh(geometry, material);
|
||||||
|
return gridMesh;
|
||||||
|
}
|
||||||
|
|
|
@ -1,18 +1,34 @@
|
||||||
import Base from '../core/base';
|
import Base from '../core/base';
|
||||||
|
import { scene } from '../global';
|
||||||
import * as Theme from '../theme/index';
|
import * as Theme from '../theme/index';
|
||||||
import Util from '../util';
|
import Util from '../util';
|
||||||
import { scene } from '../global';
|
|
||||||
const DEG2RAD = Math.PI / 180;
|
const DEG2RAD = Math.PI / 180;
|
||||||
export class MapProvider extends Base {
|
export default class GaodeMap extends Base {
|
||||||
getDefaultCfg() {
|
getDefaultCfg() {
|
||||||
return Util.assign(scene, {
|
return Util.assign(scene, {
|
||||||
resizeEnable: true,
|
resizeEnable: true,
|
||||||
viewMode: '3D'
|
viewMode: '3D'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
constructor(container, cfg) {
|
static project(lnglat) {
|
||||||
|
const maxs = 85.0511287798;
|
||||||
|
const lat = Math.max(Math.min(maxs, lnglat[1]), -maxs);
|
||||||
|
const scale = 256 << 20;
|
||||||
|
let d = Math.PI / 180;
|
||||||
|
let x = lnglat[0] * d;
|
||||||
|
let y = lat * d;
|
||||||
|
y = Math.log(Math.tan((Math.PI / 4) + (y / 2)));
|
||||||
|
const a = 0.5 / Math.PI,
|
||||||
|
b = 0.5,
|
||||||
|
c = -0.5 / Math.PI;
|
||||||
|
d = 0.5;
|
||||||
|
x = scale * (a * x + b) - 215440491;
|
||||||
|
y = -(scale * (c * y + d) - 106744817);
|
||||||
|
return { x, y };
|
||||||
|
}
|
||||||
|
constructor(cfg) {
|
||||||
super(cfg);
|
super(cfg);
|
||||||
this.container = container;
|
this.container = this.get('id');
|
||||||
this.initMap();
|
this.initMap();
|
||||||
this.addOverLayer();
|
this.addOverLayer();
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
@ -85,4 +101,31 @@ export class MapProvider extends Base {
|
||||||
this.renderDom.id = 'l7_canvaslayer';
|
this.renderDom.id = 'l7_canvaslayer';
|
||||||
canvasContainer.appendChild(this.renderDom);
|
canvasContainer.appendChild(this.renderDom);
|
||||||
}
|
}
|
||||||
|
mixMap(scene) {
|
||||||
|
const map = this.map;
|
||||||
|
scene.getZoom = () => { return map.getZoom(); };
|
||||||
|
scene.getCenter = () => { return map.getCenter(); };
|
||||||
|
scene.getSize = () => { return map.getSize(); };
|
||||||
|
scene.getPitch = () => { return map.getPitch(); };
|
||||||
|
scene.getRotation = () => { return map.getRotation(); };
|
||||||
|
scene.getStatus = () => { return map.getStatus(); };
|
||||||
|
scene.getScale = () => { return map.getScale(); };
|
||||||
|
scene.getZoom = () => { return map.getZoom(); };
|
||||||
|
scene.setZoom = () => { return map.setZoom(); };
|
||||||
|
scene.setBounds = () => { return map.setBounds(); };
|
||||||
|
scene.setRotation = () => { return map.setRotation(); };
|
||||||
|
scene.zoomIn = () => { return map.zoomIn(); };
|
||||||
|
scene.setRotation = () => { return map.setRotation(); };
|
||||||
|
scene.zoomOut = () => { return map.zoomOut(); };
|
||||||
|
scene.panTo = () => { return map.panTo(); };
|
||||||
|
scene.panBy = () => { return map.panBy(); };
|
||||||
|
scene.setPitch = () => { return map.setPitch(); };
|
||||||
|
scene.pixelToLngLat = () => { return map.pixelToLngLat(); };
|
||||||
|
scene.lngLatToPixel = () => { return map.lngLatToPixel(); };
|
||||||
|
scene.setMapStyle = () => { return map.setMapStyle(); };
|
||||||
|
scene.containerToLngLat = pixel => {
|
||||||
|
const ll = new AMap.Pixel(pixel.x, pixel.y);
|
||||||
|
return map.containerToLngLat(ll);
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -21,7 +21,7 @@ export default class GaodeMap {
|
||||||
return this.map.getStatus();
|
return this.map.getStatus();
|
||||||
}
|
}
|
||||||
getScale() {
|
getScale() {
|
||||||
return this.getScale();
|
return this.map.getScale();
|
||||||
}
|
}
|
||||||
setZoom(zoom) {
|
setZoom(zoom) {
|
||||||
return this.map.setZoom(zoom);
|
return this.map.setZoom(zoom);
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
import MapBox from './mapbox';
|
||||||
|
import { default as AMap } from './AMap';
|
||||||
|
export {
|
||||||
|
AMap,
|
||||||
|
MapBox
|
||||||
|
};
|
||||||
|
const MapType = {
|
||||||
|
amap: AMap,
|
||||||
|
mapbox: MapBox
|
||||||
|
};
|
||||||
|
export const getMap = type => {
|
||||||
|
return MapType[type.toLowerCase()];
|
||||||
|
};
|
||||||
|
|
||||||
|
export const registerMap = (type, map) => {
|
||||||
|
if (getMap(type)) {
|
||||||
|
throw new Error(`Map type '${type}' existed.`);
|
||||||
|
}
|
||||||
|
map.type = type;
|
||||||
|
// 存储到 map 中
|
||||||
|
MapType[type.toLowerCase()] = map;
|
||||||
|
};
|
|
@ -0,0 +1,154 @@
|
||||||
|
import Base from '../core/base';
|
||||||
|
import Util from '../util';
|
||||||
|
import { scene } from '../global';
|
||||||
|
import * as THREE from '../core/three';
|
||||||
|
const WORLD_SIZE = 512;
|
||||||
|
const MERCATOR_A = 6378137.0;
|
||||||
|
const WORLD_SCALE = 1 / 100;
|
||||||
|
const PROJECTION_WORLD_SIZE = WORLD_SIZE / (MERCATOR_A * Math.PI) / 2;
|
||||||
|
export default class MapBox extends Base {
|
||||||
|
getDefaultCfg() {
|
||||||
|
return Util.assign(scene, {
|
||||||
|
resizeEnable: true,
|
||||||
|
viewMode: '3D'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
static project(lnglat) {
|
||||||
|
const d = Math.PI / 180;
|
||||||
|
const x = -MERCATOR_A * lnglat[0] * d * PROJECTION_WORLD_SIZE;
|
||||||
|
const y = -MERCATOR_A * Math.log(Math.tan((Math.PI * 0.25) + (0.5 * lnglat[1] * d))) * PROJECTION_WORLD_SIZE;
|
||||||
|
return { x, y };
|
||||||
|
}
|
||||||
|
constructor(cfg) {
|
||||||
|
super(cfg);
|
||||||
|
this.container = this.get('container');
|
||||||
|
this.initMap();
|
||||||
|
this.addOverLayer();
|
||||||
|
setTimeout(() => {
|
||||||
|
this.emit('mapLoad');
|
||||||
|
}, 100);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
initMap() {
|
||||||
|
mapboxgl.accessToken = 'pk.eyJ1IjoibHp4dWUiLCJhIjoiYnhfTURyRSJ9.Ugm314vAKPHBzcPmY1p4KQ';
|
||||||
|
this.map = new mapboxgl.Map(this._attrs);
|
||||||
|
}
|
||||||
|
asyncCamera(engine) {
|
||||||
|
this.engine = engine;
|
||||||
|
const camera = engine._camera;
|
||||||
|
const scene = engine.world;
|
||||||
|
const pickScene = engine._picking.world;
|
||||||
|
camera.matrixAutoUpdate = false;
|
||||||
|
scene.position.x = scene.position.y = WORLD_SIZE / 2;
|
||||||
|
scene.matrixAutoUpdate = false;
|
||||||
|
pickScene.position.x = pickScene.position.y = WORLD_SIZE / 2;
|
||||||
|
pickScene.matrixAutoUpdate = false;
|
||||||
|
this.updateCamera();
|
||||||
|
this.map.on('move', () => {
|
||||||
|
this.updateCamera();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
updateCamera() {
|
||||||
|
const engine = this.engine;
|
||||||
|
const scene = engine.world;
|
||||||
|
const pickScene = engine._picking.world;
|
||||||
|
const camera = engine._camera;
|
||||||
|
// Build a projection matrix, paralleling the code found in Mapbox GL JS
|
||||||
|
const fov = 0.6435011087932844;
|
||||||
|
const cameraToCenterDistance = 0.5 / Math.tan(fov / 2) * this.map.transform.height * WORLD_SCALE;
|
||||||
|
const halfFov = fov / 2;
|
||||||
|
const groundAngle = Math.PI / 2 + this.map.transform._pitch;
|
||||||
|
const topHalfSurfaceDistance = Math.sin(halfFov) * cameraToCenterDistance / Math.sin(Math.PI - groundAngle - halfFov);
|
||||||
|
|
||||||
|
// Calculate z distance of the farthest fragment that should be rendered.
|
||||||
|
const furthestDistance = Math.cos(Math.PI / 2 - this.map.transform._pitch) * topHalfSurfaceDistance + cameraToCenterDistance;
|
||||||
|
|
||||||
|
// Add a bit extra to avoid precision problems when a fragment's distance is exactly `furthestDistance`
|
||||||
|
let farZ = furthestDistance * 1.1;
|
||||||
|
if (this.pitch > 50) {
|
||||||
|
farZ = 1000;
|
||||||
|
}
|
||||||
|
const { x, y } = this.map.transform.point;
|
||||||
|
camera.projectionMatrix = this.makePerspectiveMatrix(fov, this.map.transform.width / this.map.transform.height, 1, farZ);
|
||||||
|
const cameraWorldMatrix = new THREE.Matrix4();
|
||||||
|
const cameraTranslateZ = new THREE.Matrix4().makeTranslation(0, 0, cameraToCenterDistance);
|
||||||
|
const cameraRotateX = new THREE.Matrix4().makeRotationX(this.map.transform._pitch);
|
||||||
|
const cameraRotateZ = new THREE.Matrix4().makeRotationZ(this.map.transform.angle);
|
||||||
|
const cameraTranslateXY = new THREE.Matrix4().makeTranslation(x * WORLD_SCALE, -y * WORLD_SCALE, 0);
|
||||||
|
// const cameraTranslateCenter = new THREE.Matrix4().makeTranslation(0, 0, cameraToCenterDistance);
|
||||||
|
// Unlike the Mapbox GL JS camera, separate camera translation and rotation out into its world matrix
|
||||||
|
// If this is applied directly to the projection matrix, it will work OK but break raycasting
|
||||||
|
cameraWorldMatrix
|
||||||
|
.premultiply(cameraTranslateZ)
|
||||||
|
.premultiply(cameraRotateX)
|
||||||
|
.premultiply(cameraRotateZ)
|
||||||
|
.premultiply(cameraTranslateXY);
|
||||||
|
|
||||||
|
camera.matrixWorld.copy(cameraWorldMatrix);
|
||||||
|
|
||||||
|
const zoomPow = this.map.transform.scale * WORLD_SCALE;
|
||||||
|
// Handle scaling and translation of objects in the map in the world's matrix transform, not the camera
|
||||||
|
const scale = new THREE.Matrix4();
|
||||||
|
const translateCenter = new THREE.Matrix4();
|
||||||
|
const translateMap = new THREE.Matrix4();
|
||||||
|
const rotateMap = new THREE.Matrix4();
|
||||||
|
scale
|
||||||
|
.makeScale(zoomPow, zoomPow, 1.0);
|
||||||
|
translateCenter
|
||||||
|
.makeTranslation(WORLD_SIZE / 2, -WORLD_SIZE / 2, 0);
|
||||||
|
translateMap
|
||||||
|
.makeTranslation(-this.map.transform.x, this.map.transform.y, 0);
|
||||||
|
rotateMap
|
||||||
|
.makeRotationZ(Math.PI);
|
||||||
|
scene.matrix = new THREE.Matrix4();
|
||||||
|
scene.matrix
|
||||||
|
.premultiply(rotateMap)
|
||||||
|
.premultiply(translateCenter)
|
||||||
|
.premultiply(scale);
|
||||||
|
pickScene.matrix = new THREE.Matrix4();
|
||||||
|
pickScene.matrix
|
||||||
|
.premultiply(rotateMap)
|
||||||
|
.premultiply(translateCenter)
|
||||||
|
.premultiply(scale);
|
||||||
|
}
|
||||||
|
makePerspectiveMatrix(fovy, aspect, near, far) {
|
||||||
|
const out = new THREE.Matrix4();
|
||||||
|
const f = 1.0 / Math.tan(fovy / 2),
|
||||||
|
nf = 1 / (near - far);
|
||||||
|
const newMatrix = [
|
||||||
|
f / aspect, 0, 0, 0,
|
||||||
|
0, f, 0, 0,
|
||||||
|
0, 0, (far + near) * nf, -1,
|
||||||
|
0, 0, (2 * far * near) * nf, 0
|
||||||
|
];
|
||||||
|
out.elements = newMatrix;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
projectFlat(lnglat) {
|
||||||
|
return this.map.lngLatToGeodeticCoord(lnglat);
|
||||||
|
}
|
||||||
|
getCenter() {
|
||||||
|
return this.map.getCenter();
|
||||||
|
}
|
||||||
|
getCenterFlat() {
|
||||||
|
return this.projectFlat(this.getCenter());
|
||||||
|
}
|
||||||
|
addOverLayer() {
|
||||||
|
const canvasContainer = document.getElementById(this.container);
|
||||||
|
this.canvasContainer = canvasContainer;
|
||||||
|
this.renderDom = document.createElement('div');
|
||||||
|
this.renderDom.style.cssText += 'position: absolute;top: 0; z-index:10;height: 100%;width: 100%;pointer-events: none;';
|
||||||
|
this.renderDom.id = 'l7_canvaslayer';
|
||||||
|
canvasContainer.appendChild(this.renderDom);
|
||||||
|
}
|
||||||
|
mixMap(scene) {
|
||||||
|
const map = this.map;
|
||||||
|
scene.getZoom = () => { return map.getZoom(); };
|
||||||
|
scene.getCenter = () => { return map.getCenter(); };
|
||||||
|
scene.getPitch = () => { return map.getPitch(); };
|
||||||
|
scene.containerToLngLat = point => { return map.unproject(point); };
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,69 +0,0 @@
|
||||||
import Source from '../core/source';
|
|
||||||
import FeatureIndex from '../geo/featureIndex';
|
|
||||||
import { csvParse } from 'd3-dsv';
|
|
||||||
export default class CSVSource extends Source {
|
|
||||||
prepareData() {
|
|
||||||
this.type = 'csv';
|
|
||||||
const data = this.get('data');
|
|
||||||
const x = this.get('x');
|
|
||||||
const y = this.get('y');
|
|
||||||
const x1 = this.get('x1');
|
|
||||||
const y1 = this.get('y1');
|
|
||||||
const coords = this.get('coordinates');
|
|
||||||
this.propertiesData = [];// 临时使用
|
|
||||||
this.geoData = [];
|
|
||||||
let csvdata = data;
|
|
||||||
Array.isArray(csvdata) || (csvdata = csvParse(data));
|
|
||||||
this.propertiesData = csvdata;
|
|
||||||
csvdata.forEach((col, featureIndex) => {
|
|
||||||
let coordinates = [];
|
|
||||||
if (col.coordinates) {
|
|
||||||
coordinates = col.coordinates;
|
|
||||||
}
|
|
||||||
if (x && y) { coordinates = [ col[x], col[y] ]; } // 点数据
|
|
||||||
if (x1 && y1) { // 弧线 或者线段
|
|
||||||
coordinates = [[ col[x], col[y] ], [ col[x1], col[y1] ]];
|
|
||||||
}
|
|
||||||
if (coords && col.coords) { coordinates = col.coords; }
|
|
||||||
col._id = featureIndex + 1;
|
|
||||||
this._coordProject(coordinates);
|
|
||||||
this.geoData.push(this._coordProject(coordinates));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
featureIndex() {
|
|
||||||
const data = this.get('data');
|
|
||||||
this.featureIndex = new FeatureIndex(data);
|
|
||||||
}
|
|
||||||
getSelectFeatureId(featureId) {
|
|
||||||
return [ featureId ];
|
|
||||||
}
|
|
||||||
getSelectFeature(featureId) {
|
|
||||||
return this.propertiesData[featureId];
|
|
||||||
|
|
||||||
}
|
|
||||||
_getCoord(geo) {
|
|
||||||
if (geo.geometry) {
|
|
||||||
// GeoJSON feature
|
|
||||||
geo = geo.geometry.coordinates;
|
|
||||||
} else if (geo.coordinates) {
|
|
||||||
// GeoJSON geometry
|
|
||||||
geo = geo.coordinates;
|
|
||||||
}
|
|
||||||
return geo;
|
|
||||||
}
|
|
||||||
_coordProject(geo) {
|
|
||||||
if (Array.isArray(geo[0][0])) {
|
|
||||||
return geo.map(coor => {
|
|
||||||
return this._coordProject(coor);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (!Array.isArray(geo[0])) {
|
|
||||||
return this._coorConvert(geo);
|
|
||||||
}
|
|
||||||
return geo.map(coor => {
|
|
||||||
return this._coorConvert(coor);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
|
||||||
|
const TRANSFORMS = {};
|
||||||
|
const PARSERS = {};
|
||||||
|
export const getParser = type => PARSERS[type];
|
||||||
|
export const registerParser = (type, parserFunction) => {
|
||||||
|
PARSERS[type] = parserFunction;
|
||||||
|
};
|
||||||
|
export const getTransform = type => TRANSFORMS[type];
|
||||||
|
export const registerTransform = (type, transFunction) => {
|
||||||
|
TRANSFORMS[type] = transFunction;
|
||||||
|
};
|
|
@ -1,45 +0,0 @@
|
||||||
import Source from '../core/source';
|
|
||||||
import * as turfMeta from '@turf/meta';
|
|
||||||
import { default as cleanCoords } from '@turf/clean-coords';
|
|
||||||
import { getCoords } from '@turf/invariant';
|
|
||||||
import FeatureIndex from '../geo/featureIndex';
|
|
||||||
|
|
||||||
export default class GeojsonSource extends Source {
|
|
||||||
prepareData() {
|
|
||||||
this.type = 'geojson';
|
|
||||||
const data = this.get('data');
|
|
||||||
this.propertiesData = [];
|
|
||||||
this.geoData = [];
|
|
||||||
turfMeta.flattenEach(data, (currentFeature, featureIndex) => {
|
|
||||||
const coord = getCoords(cleanCoords(currentFeature));
|
|
||||||
this.geoData.push(this._coordProject(coord));
|
|
||||||
currentFeature.properties._id = featureIndex + 1;
|
|
||||||
this.propertiesData.push(currentFeature.properties);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
featureIndex() {
|
|
||||||
const data = this.get('data');
|
|
||||||
this.featureIndex = new FeatureIndex(data);
|
|
||||||
}
|
|
||||||
getSelectFeatureId(featureId) {
|
|
||||||
const data = this.get('data');
|
|
||||||
const selectFeatureIds = [];
|
|
||||||
let featureStyleId = 0;
|
|
||||||
turfMeta.flattenEach(data, (currentFeature, featureIndex/* , multiFeatureIndex*/) => {
|
|
||||||
if (featureIndex === (featureId)) {
|
|
||||||
selectFeatureIds.push(featureStyleId);
|
|
||||||
}
|
|
||||||
featureStyleId++;
|
|
||||||
if (featureIndex > featureId) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return selectFeatureIds;
|
|
||||||
|
|
||||||
}
|
|
||||||
getSelectFeature(featureId) {
|
|
||||||
const data = this.get('data');
|
|
||||||
return data.features[featureId];
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,37 +0,0 @@
|
||||||
import Source from '../core/source';
|
|
||||||
import { getImage } from '../util/ajax';
|
|
||||||
export default class ImageSource extends Source {
|
|
||||||
prepareData() {
|
|
||||||
this.type = 'image';
|
|
||||||
const extent = this.get('extent');
|
|
||||||
const lb = this._coorConvert(extent.slice(0, 2));
|
|
||||||
const tr = this._coorConvert(extent.slice(2, 4));
|
|
||||||
this.geoData = [ lb, tr ];
|
|
||||||
this.propertiesData = [];
|
|
||||||
this._loadData();
|
|
||||||
}
|
|
||||||
_loadData() {
|
|
||||||
const url = this.get('data');
|
|
||||||
this.image = [];
|
|
||||||
if (typeof (url) === 'string') {
|
|
||||||
getImage({ url }, (err, img) => {
|
|
||||||
this.image = img;
|
|
||||||
this.emit('imageLoaded');
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
const imageCount = url.length;
|
|
||||||
let imageindex = 0;
|
|
||||||
url.forEach(item => {
|
|
||||||
getImage({ url: item }, (err, img) => {
|
|
||||||
imageindex++;
|
|
||||||
this.image.push(img);
|
|
||||||
if (imageindex === imageCount) {
|
|
||||||
this.emit('imageLoaded');
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,5 +1,23 @@
|
||||||
export { default as geojson } from './geojsonSource';
|
// source parser
|
||||||
export { default as csv } from './csvSource';
|
|
||||||
export { default as array } from './csvSource';
|
import geojson from './parser/geojson';
|
||||||
export { default as basic } from '../core/source';
|
import image from './parser/image';
|
||||||
export { default as imageSource } from './imageSource';
|
import csv from './parser/csv';
|
||||||
|
import json from './parser/json';
|
||||||
|
import raster from './parser/raster';
|
||||||
|
|
||||||
|
import { registerTransform, registerParser } from './factory';
|
||||||
|
import { aggregatorToGrid } from './transform/grid';
|
||||||
|
import { map } from './transform/map';
|
||||||
|
|
||||||
|
registerParser('geojson', geojson);
|
||||||
|
registerParser('image', image);
|
||||||
|
registerParser('csv', csv);
|
||||||
|
registerParser('json', json);
|
||||||
|
registerParser('raster', raster);
|
||||||
|
// 注册transform
|
||||||
|
|
||||||
|
registerTransform('grid', aggregatorToGrid);
|
||||||
|
registerTransform('map', map);
|
||||||
|
|
||||||
|
export { getTransform, registerTransform, getParser, registerParser } from './factory';
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
import { csvParse } from 'd3-dsv';
|
||||||
|
export default function csv(data, cfg) {
|
||||||
|
const { x, y, x1, y1 } = cfg;
|
||||||
|
const csvdata = csvParse(data);
|
||||||
|
const resultdata = [];
|
||||||
|
csvdata.forEach((col, featureIndex) => {
|
||||||
|
let coordinates = [];
|
||||||
|
if (x && y) { coordinates = [ col[x], col[y] ]; } // 点数据
|
||||||
|
if (x1 && y1) { // 弧线 或者线段
|
||||||
|
coordinates = [[ col[x], col[y] ], [ col[x1], col[y1] ]];
|
||||||
|
}
|
||||||
|
col._id = featureIndex + 1;
|
||||||
|
const dataItem = {
|
||||||
|
...col,
|
||||||
|
coordinates
|
||||||
|
|
||||||
|
};
|
||||||
|
resultdata.push(dataItem);
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
dataArray: resultdata
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
import * as turfMeta from '@turf/meta';
|
||||||
|
import { default as cleanCoords } from '@turf/clean-coords';
|
||||||
|
import { getCoords } from '@turf/invariant';
|
||||||
|
|
||||||
|
export default function geoJSON(data) {
|
||||||
|
const resultData = [];
|
||||||
|
turfMeta.flattenEach(data, (currentFeature, featureIndex) => { // 多个polygon 拆成一个
|
||||||
|
const coord = getCoords(cleanCoords(currentFeature));
|
||||||
|
const dataItem = {
|
||||||
|
...currentFeature.properties,
|
||||||
|
coordinates: coord,
|
||||||
|
_id: featureIndex + 1
|
||||||
|
};
|
||||||
|
resultData.push(dataItem);
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
dataArray: resultData
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
import { getImage } from '../../util/ajax';
|
||||||
|
export default function image(data, cfg) {
|
||||||
|
const { extent } = cfg;
|
||||||
|
|
||||||
|
const images = new Promise(resolve => {
|
||||||
|
loadData(data, res => {
|
||||||
|
resolve(res);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
const resultData = {
|
||||||
|
images,
|
||||||
|
_id: 1,
|
||||||
|
dataArray: [{ coordinates: [[ extent[0], extent[1] ], [ extent[2], extent[3] ]] }]
|
||||||
|
};
|
||||||
|
return resultData;
|
||||||
|
}
|
||||||
|
function loadData(data, done) {
|
||||||
|
const url = data;
|
||||||
|
let image = [];
|
||||||
|
if (typeof (url) === 'string') {
|
||||||
|
getImage({ url }, (err, img) => {
|
||||||
|
image = img;
|
||||||
|
done(image);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
const imageCount = url.length;
|
||||||
|
let imageindex = 0;
|
||||||
|
url.forEach(item => {
|
||||||
|
getImage({ url: item }, (err, img) => {
|
||||||
|
imageindex++;
|
||||||
|
image.push(img);
|
||||||
|
if (imageindex === imageCount) {
|
||||||
|
done(image);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
return image;
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
export default function json(data, cfg) {
|
||||||
|
const { x, y, x1, y1 } = cfg;
|
||||||
|
const resultdata = [];
|
||||||
|
data.forEach((col, featureIndex) => {
|
||||||
|
let coordinates = [];
|
||||||
|
if (x && y) { coordinates = [ col[x], col[y] ]; } // 点数据
|
||||||
|
if (x1 && y1) { // 弧线 或者线段
|
||||||
|
coordinates = [[ col[x], col[y] ], [ col[x1], col[y1] ]];
|
||||||
|
}
|
||||||
|
col._id = featureIndex + 1;
|
||||||
|
const dataItem = {
|
||||||
|
...col,
|
||||||
|
coordinates
|
||||||
|
|
||||||
|
};
|
||||||
|
resultdata.push(dataItem);
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
dataArray: resultdata
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
export default function raster(data, cfg) {
|
||||||
|
const { extent, width, height, min, max } = cfg;
|
||||||
|
const resultData = {
|
||||||
|
_id: 1,
|
||||||
|
dataArray: [
|
||||||
|
{
|
||||||
|
data,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
min,
|
||||||
|
max,
|
||||||
|
coordinates: [[ extent[0], extent[1] ], [ extent[2], extent[3] ]] }]
|
||||||
|
};
|
||||||
|
return resultData;
|
||||||
|
}
|
|
@ -1,31 +0,0 @@
|
||||||
import imageSource from './imageSource';
|
|
||||||
export class RainSource extends imageSource {
|
|
||||||
prepareData() {
|
|
||||||
const extent = this.get('extent');
|
|
||||||
const lb = this._coorConvert(extent.slice(0, 2));
|
|
||||||
const tr = this._coorConvert(extent.slice(2, 4));
|
|
||||||
this.extent = [ lb, tr ];
|
|
||||||
this.propertiesData = [];
|
|
||||||
this._genaratePoints();
|
|
||||||
this._loadData();
|
|
||||||
}
|
|
||||||
_genaratePoints() {
|
|
||||||
const numParticles = 512 * 512;
|
|
||||||
|
|
||||||
const particleRes = this.particleRes = Math.ceil(Math.sqrt(numParticles));
|
|
||||||
const numPoints = particleRes * particleRes;
|
|
||||||
const particleState = [];
|
|
||||||
const particleState0 = new Uint8ClampedArray(numPoints * 4);
|
|
||||||
const particleState1 = new Uint8ClampedArray(numPoints * 4);
|
|
||||||
const emptyPixels = new Uint8ClampedArray(numPoints * 4);
|
|
||||||
for (let i = 0; i < particleState0.length; i++) {
|
|
||||||
particleState0[i] = Math.floor(Math.random() * 256); // randomize the initial particle positions
|
|
||||||
}
|
|
||||||
this.particleIndices = new Float32Array(numPoints);
|
|
||||||
for (let i = 0; i < numPoints; i++) this.particleIndices[i] = i;
|
|
||||||
this.particleImage0 = new ImageData(particleState0, particleRes, particleRes);
|
|
||||||
this.particleImage1 = new ImageData(particleState1, particleRes, particleRes);
|
|
||||||
this.backgroundImage = new ImageData(emptyPixels, particleRes, particleRes);
|
|
||||||
this.geoData = particleState;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,20 +0,0 @@
|
||||||
import Source from '../core/source';
|
|
||||||
export default class RasterSource extends Source {
|
|
||||||
prepareData() {
|
|
||||||
this.type = 'raster';
|
|
||||||
const extent = this.get('extent');
|
|
||||||
const lb = this._coorConvert(extent.slice(0, 2));
|
|
||||||
const tr = this._coorConvert(extent.slice(2, 4));
|
|
||||||
this.geoData = [ lb, tr ];
|
|
||||||
this.propertiesData = [];
|
|
||||||
this.rasterData = {
|
|
||||||
data: this.get('data'),
|
|
||||||
width: this.get('width'),
|
|
||||||
height: this.get('height'),
|
|
||||||
min: this.get('min'),
|
|
||||||
max: this.get('max')
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,101 @@
|
||||||
|
/**
|
||||||
|
* 生成四边形热力图
|
||||||
|
*/
|
||||||
|
import * as statistics from './statistics';
|
||||||
|
|
||||||
|
const R_EARTH = 6378000;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计算方格密度图
|
||||||
|
* @param {*} data 经纬度数据 和属性数据
|
||||||
|
* @param {*} size 半径大小 单位 km
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
export function aggregatorToGrid(data, option) {
|
||||||
|
const dataArray = data.dataArray;
|
||||||
|
const { size = 10 } = option;
|
||||||
|
const { gridHash, gridOffset } = _pointsGridHash(dataArray, size);
|
||||||
|
const layerData = _getGridLayerDataFromGridHash(gridHash, gridOffset, option);
|
||||||
|
return {
|
||||||
|
xOffset: gridOffset.xOffset / 360 * (256 << 20) / 2,
|
||||||
|
yOffset: gridOffset.xOffset / 360 * (256 << 20) / 2,
|
||||||
|
dataArray: layerData
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function _pointsGridHash(dataArray, size) {
|
||||||
|
let latMin = Infinity;
|
||||||
|
let latMax = -Infinity;
|
||||||
|
let pLat;
|
||||||
|
for (let index = 0; index < dataArray.length; index++) {
|
||||||
|
const point = dataArray[index];
|
||||||
|
pLat = point.coordinates[1];
|
||||||
|
if (Number.isFinite(pLat)) {
|
||||||
|
latMin = pLat < latMin ? pLat : latMin;
|
||||||
|
latMax = pLat > latMax ? pLat : latMax;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
// const centerLat = (latMin + latMax) / 2;
|
||||||
|
const centerLat = 34.54083;
|
||||||
|
const gridOffset = _calculateGridLatLonOffset(size, centerLat);
|
||||||
|
if (gridOffset.xOffset <= 0 || gridOffset.yOffset <= 0) {
|
||||||
|
return { gridHash: {}, gridOffset };
|
||||||
|
}
|
||||||
|
const gridHash = {};
|
||||||
|
for (let index = 0; index < dataArray.length; index++) {
|
||||||
|
const point = dataArray[index];
|
||||||
|
const lat = point.coordinates[1];
|
||||||
|
const lng = point.coordinates[0];
|
||||||
|
|
||||||
|
if (Number.isFinite(lat) && Number.isFinite(lng)) {
|
||||||
|
const latIdx = Math.floor((lat + 90) / gridOffset.yOffset);
|
||||||
|
const lonIdx = Math.floor((lng + 180) / gridOffset.xOffset);
|
||||||
|
const key = `${latIdx}-${lonIdx}`;
|
||||||
|
|
||||||
|
gridHash[key] = gridHash[key] || { count: 0, points: [] };
|
||||||
|
gridHash[key].count += 1;
|
||||||
|
gridHash[key].points.push(point);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return { gridHash, gridOffset };
|
||||||
|
}
|
||||||
|
// 计算网格偏移量
|
||||||
|
function _calculateGridLatLonOffset(cellSize, latitude) {
|
||||||
|
const yOffset = _calculateLatOffset(cellSize);
|
||||||
|
const xOffset = _calculateLonOffset(latitude, cellSize);
|
||||||
|
return { yOffset, xOffset };
|
||||||
|
}
|
||||||
|
|
||||||
|
function _calculateLatOffset(dy) {
|
||||||
|
return (dy / R_EARTH) * (180 / Math.PI);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _calculateLonOffset(lat, dx) {
|
||||||
|
return ((dx / R_EARTH) * (180 / Math.PI)) / Math.cos((lat * Math.PI) / 180);
|
||||||
|
}
|
||||||
|
function _getGridLayerDataFromGridHash(gridHash, gridOffset, option) {
|
||||||
|
return Object.keys(gridHash).reduce((accu, key, i) => {
|
||||||
|
const idxs = key.split('-');
|
||||||
|
const latIdx = parseInt(idxs[0], 10);
|
||||||
|
const lonIdx = parseInt(idxs[1], 10);
|
||||||
|
const item = {};
|
||||||
|
if (option.field && option.method) {
|
||||||
|
const columns = getColumn(gridHash[key].points, option.field);
|
||||||
|
item[option.method] = statistics[option.method](columns);
|
||||||
|
}
|
||||||
|
Object.assign(item, {
|
||||||
|
_id: i + 1,
|
||||||
|
coordinates: [ -180 + gridOffset.xOffset * lonIdx, -90 + gridOffset.yOffset * latIdx ],
|
||||||
|
count: gridHash[key].count
|
||||||
|
});
|
||||||
|
accu.push(item);
|
||||||
|
return accu;
|
||||||
|
}, []);
|
||||||
|
}
|
||||||
|
function getColumn(data, columnName) {
|
||||||
|
return data.map(item => {
|
||||||
|
return item[columnName];
|
||||||
|
});
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
import { hexbin } from 'd3-hexbin';
|
||||||
|
import { aProjectFlat, unProjectFlat } from '../../geo/project';
|
||||||
|
import * as statistics from './statistics';
|
||||||
|
const R_EARTH = 6378000;
|
||||||
|
export function pointToHexbin(data, option) {
|
||||||
|
const dataArray = data.dataArray;
|
||||||
|
const { size = 10 } = option;
|
||||||
|
const pixlSize = size / (2 * Math.PI * R_EARTH) * (256 << 20) / 2;
|
||||||
|
const screenPoints = dataArray.map(point => {
|
||||||
|
const { x, y } = aProjectFlat(point.coordinates);
|
||||||
|
return {
|
||||||
|
...point,
|
||||||
|
coordinates: [ x, y ]
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const newHexbin = hexbin()
|
||||||
|
.radius(pixlSize)
|
||||||
|
.x(d => d.coordinates[0])
|
||||||
|
.y(d => d.coordinates[1]);
|
||||||
|
const hexbinBins = newHexbin(screenPoints);
|
||||||
|
const result = {
|
||||||
|
size: pixlSize
|
||||||
|
};
|
||||||
|
result.dataArray = hexbinBins.map((hex, index) => {
|
||||||
|
if (option.field && option.method) {
|
||||||
|
const columns = getColumn(hex, option.field);
|
||||||
|
hex[option.method] = statistics[option.method](columns);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
coordinates: unProjectFlat([ hex.x, hex.y ]),
|
||||||
|
id: index + 1
|
||||||
|
};
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
function getColumn(data, columnName) {
|
||||||
|
return data.map(item => {
|
||||||
|
return item[columnName];
|
||||||
|
});
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
export function map(data, options) {
|
||||||
|
const { callback } = options;
|
||||||
|
if (callback) {
|
||||||
|
data.dataArray = data.dataArray.map(callback);
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
/* 支持 'max', 'mean', 'median', 'min', 'mode', 'product', 'standardDeviation',
|
||||||
|
* 'sum', 'sumSimple', 'variance', 'count', 'distinct'
|
||||||
|
*/
|
||||||
|
export { default as min } from 'simple-statistics/src/min';
|
||||||
|
export { default as max } from 'simple-statistics/src/max';
|
||||||
|
export { default as mean } from 'simple-statistics/src/mean';
|
||||||
|
export { default as sum } from 'simple-statistics/src/sum';
|
||||||
|
export { default as median } from 'simple-statistics/src/median';
|
||||||
|
export { default as standardDeviation } from 'simple-statistics/src/standard_deviation';
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,21 @@
|
||||||
|
import { expect } from 'chai';
|
||||||
|
import { pointData } from '../../../asset/data/point';
|
||||||
|
import { pointToHexbin } from '../../../../src/source/transform/hexagon';
|
||||||
|
describe('hexagon Test', function() {
|
||||||
|
|
||||||
|
it('pointToHexbin', function() {
|
||||||
|
const dataArray = pointData.map(item => {
|
||||||
|
const lng = 1e-6 * (250 * item.grid_x + 125),
|
||||||
|
lat = 1e-6 * (250 * item.grid_y + 125);
|
||||||
|
return {
|
||||||
|
v: item.count * 1,
|
||||||
|
coordinates: [ lng, lat ]
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
dataArray
|
||||||
|
};
|
||||||
|
const hexgonGrid = pointToHexbin(data, { size: 100, field: 'count', method: 'sum' });
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue