mirror of https://gitee.com/antv-l7/antv-l7
refactor(source): source
This commit is contained in:
parent
99e128d11d
commit
6e583a1ec7
|
@ -10,6 +10,9 @@
|
|||
<title>point_circle</title>
|
||||
<style>
|
||||
#map { position:absolute; top:0; bottom:0; width:100%; }
|
||||
.amap-maps {
|
||||
cursor: auto !important
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
|
@ -55,15 +58,15 @@ scene.on('loaded', () => {
|
|||
.shape('2d:circle')
|
||||
.size('value', [ 2, 80]) // default 1
|
||||
//.size('value', [ 10, 300]) // default 1
|
||||
.active(false)
|
||||
.active(true)
|
||||
.filter('value', field_8 => {
|
||||
return field_8 * 1 > 500;
|
||||
})
|
||||
.color('type', colorObj.red)
|
||||
.color('type', colorObj.blue)
|
||||
.style({
|
||||
stroke: 'rgb(255,255,255)',
|
||||
strokeWidth: 1,
|
||||
opacity: 0.9
|
||||
opacity: 1.
|
||||
})
|
||||
.render();
|
||||
|
||||
|
|
|
@ -34,9 +34,11 @@ scene.on('loaded', () => {
|
|||
zIndex: 2
|
||||
})
|
||||
.source(data.list, {
|
||||
type: 'array',
|
||||
parser:{
|
||||
type: 'json',
|
||||
x: 'j',
|
||||
y: 'w',
|
||||
}
|
||||
})
|
||||
.shape('cylinder')
|
||||
.size('t',(level)=> {
|
||||
|
|
|
@ -34,9 +34,11 @@ scene.on('loaded', () => {
|
|||
zIndex: 2
|
||||
})
|
||||
.source(data, {
|
||||
parser:{
|
||||
type: 'csv',
|
||||
y: 'lat',
|
||||
x: 'lng'
|
||||
}
|
||||
})
|
||||
.size(1.0)
|
||||
.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', () => {
|
||||
const imageLayer = scene.ImageLayer().
|
||||
source('https://gw.alipayobjects.com/zos/rmsportal/FnHFeFklTzKDdUESRNDv.jpg',{
|
||||
|
||||
parser:{
|
||||
type:'image',
|
||||
extent: [ 121.1680, 30.2828, 121.3840, 30.4219 ]
|
||||
}
|
||||
|
||||
})
|
||||
.style({
|
||||
opacity:1.0,
|
||||
|
|
|
@ -48,13 +48,14 @@ scene.on('loaded', () => {
|
|||
|
||||
const layer = scene.RasterLayer({ zIndex: 2 }).
|
||||
source(values, {
|
||||
parser: {
|
||||
type: 'raster',
|
||||
width: n,
|
||||
height: m,
|
||||
min: 0,
|
||||
max: 8000,
|
||||
extent: [ 73.482190241, 3.82501784112, 135.106618732, 57.6300459963 ]
|
||||
|
||||
}
|
||||
})
|
||||
.style({
|
||||
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>
|
||||
|
|
@ -107,6 +107,7 @@
|
|||
"lodash": "^4.17.5",
|
||||
"polyline-normals": "^2.0.2",
|
||||
"rbush": "^2.0.2",
|
||||
"simple-statistics": "^7.0.1",
|
||||
"three": "^0.96.0",
|
||||
"venn.js": "^0.2.20",
|
||||
"viewport-mercator-project": "^5.2.0",
|
||||
|
|
|
@ -42,7 +42,7 @@ class Picking {
|
|||
// this._world._container.addEventListener('mousemove', this._onWorldMove.bind(this), false);
|
||||
}
|
||||
pickdata(event) {
|
||||
const point = { x: event.clientX, y: event.clientY, type: event.type };
|
||||
const point = { x: event.offsetX, y: event.offsetY, type: event.type };
|
||||
const normalisedPoint = { x: 0, y: 0 };
|
||||
normalisedPoint.x = (point.x / this._width) * 2 - 1;
|
||||
normalisedPoint.y = -(point.y / this._height) * 2 + 1;
|
||||
|
@ -53,7 +53,6 @@ class Picking {
|
|||
// if (event.button !== 0) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
const point = { x: event.clientX, y: event.clientY, type: event.type };
|
||||
const normalisedPoint = { x: 0, y: 0 };
|
||||
normalisedPoint.x = (point.x / this._width) * 2 - 1;
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
import Base from './base';
|
||||
import * as THREE from './three';
|
||||
import ColorUtil from '../attr/color-util';
|
||||
import * as source from '../source/index';
|
||||
import source from './source';
|
||||
import PickingMaterial from '../core/engine/picking/pickingMaterial';
|
||||
import Attr from '../attr/index';
|
||||
import Util from '../util';
|
||||
|
@ -106,12 +106,10 @@ export default class Layer extends Base {
|
|||
this._object3D.visible = this.get('visible');
|
||||
}
|
||||
source(data, cfg = {}) {
|
||||
const dataType = this._getDataType(data);
|
||||
const { type = dataType } = cfg;
|
||||
cfg.data = data;
|
||||
cfg.mapType = this.get('mapType');
|
||||
|
||||
this.layerSource = new source[type](cfg);
|
||||
this.layerSource = new source(cfg);
|
||||
// this.scene.workerPool.runTask({
|
||||
// command: 'geojson',
|
||||
// data: cfg
|
||||
|
@ -279,10 +277,10 @@ export default class Layer extends Base {
|
|||
const { featureId } = e;
|
||||
if (featureId < 0) return;
|
||||
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; }
|
||||
const style = Util.assign({}, this.StyleData[featureId]);
|
||||
if (this.layerData[featureId].hasOwnProperty('filter') && this.layerData[featureId].filter === false) { return; }
|
||||
const style = Util.assign({}, this.layerData[featureId]);
|
||||
style.color = ColorUtil.toRGB(activeStyle.fill).map(e => e / 255);
|
||||
this.updateStyle([ featureId ], style);
|
||||
}
|
||||
|
@ -321,7 +319,7 @@ export default class Layer extends Base {
|
|||
_updateSize(zoom) {
|
||||
const sizeOption = this.get('attrOptions').size;
|
||||
const fields = parseFields(sizeOption.field);
|
||||
const data = this.layerSource.propertiesData;
|
||||
const data = this.layerSource.data.dataArray;
|
||||
if (!this.zoomSizeCache) this.zoomSizeCache = {};
|
||||
if (!this.zoomSizeCache[zoom]) {
|
||||
this.zoomSizeCache[zoom] = [];
|
||||
|
@ -339,7 +337,8 @@ export default class Layer extends Base {
|
|||
const self = this;
|
||||
const attrs = self.get('attrs');
|
||||
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++) {
|
||||
const record = data[i];
|
||||
const newRecord = {};
|
||||
|
@ -362,18 +361,17 @@ export default class Layer extends Base {
|
|||
}
|
||||
}
|
||||
}
|
||||
newRecord.coordinates = record.coordinates;
|
||||
mappedData.push(newRecord);
|
||||
}
|
||||
|
||||
this.StyleData = mappedData;
|
||||
return mappedData;
|
||||
this.layerData = mappedData;
|
||||
}
|
||||
// 更新地图映射
|
||||
_updateMaping() {
|
||||
const self = this;
|
||||
const attrs = self.get('attrs');
|
||||
|
||||
const data = this.layerSource.propertiesData;
|
||||
const data = this.layerSource.data.dataArray;
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
const record = data[i];
|
||||
for (const attrName in attrs) {
|
||||
|
@ -385,10 +383,10 @@ export default class Layer extends Base {
|
|||
for (let j = 0; j < values.length; j++) {
|
||||
const val = values[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 {
|
||||
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;
|
||||
|
@ -468,6 +466,7 @@ export default class Layer extends Base {
|
|||
pickingMesh.material.setUniformsValue('u_zoom', zoom);
|
||||
};
|
||||
this._pickingMesh.add(pickingMesh);
|
||||
|
||||
}
|
||||
_setPickingId() {
|
||||
this._pickingId = this.getPickingId();
|
||||
|
@ -532,13 +531,13 @@ export default class Layer extends Base {
|
|||
*/
|
||||
_updateFilter(object) {
|
||||
this._updateMaping();
|
||||
const filterData = this.StyleData;
|
||||
const filterData = this.layerData;
|
||||
this._activeIds = null; // 清空选中元素
|
||||
const colorAttr = object.geometry.attributes.a_color;
|
||||
const pickAttr = object.geometry.attributes.pickingId;
|
||||
pickAttr.array.forEach((id, index) => {
|
||||
id = Math.abs(id);
|
||||
const color = [ ...this.StyleData[id - 1].color ];
|
||||
const color = [ ...this.layerData[id - 1].color ];
|
||||
id = Math.abs(id);
|
||||
const item = filterData[id - 1];
|
||||
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 colorAttr = this.layerMesh.geometry.attributes.a_color;
|
||||
this._activeIds.forEach(index => {
|
||||
const color = this.StyleData[index].color;
|
||||
const color = this.layerData[index].color;
|
||||
const firstId = pickingId.indexOf(index + 1);
|
||||
for (let i = firstId; i < pickingId.length; i++) {
|
||||
if (pickingId[i] === index + 1) {
|
||||
|
|
|
@ -2,16 +2,19 @@
|
|||
* @Author: ThinkGIS
|
||||
* @Date: 2018-06-08 11:19:06
|
||||
* @Last Modified by: mikey.zhaopeng
|
||||
* @Last Modified time: 2018-11-01 11:50:43
|
||||
* @Last Modified time: 2019-02-25 20:58:08
|
||||
*/
|
||||
import Base from './base';
|
||||
const Controller = require('./controller/index');
|
||||
import { aProjectFlat } from '../geo/project';
|
||||
import { getTransform, getParser } from '../source';
|
||||
export default class Source extends Base {
|
||||
getDefaultCfg() {
|
||||
return {
|
||||
data: null,
|
||||
defs: {},
|
||||
parser: {},
|
||||
transforms: [],
|
||||
scales: {
|
||||
},
|
||||
options: {}
|
||||
|
@ -19,26 +22,40 @@ export default class Source extends Base {
|
|||
}
|
||||
constructor(cfg) {
|
||||
super(cfg);
|
||||
|
||||
const transform = this.get('transforms');
|
||||
this._transforms = transform || [];
|
||||
this._initControllers();
|
||||
this.prepareData();
|
||||
// 数据解析
|
||||
this._excuteParser();
|
||||
// 数据转换 统计,聚合,分类
|
||||
this._executeTrans();
|
||||
// 坐标转换
|
||||
this._projectCoords();
|
||||
}
|
||||
|
||||
// 标准化数据
|
||||
prepareData() {
|
||||
_excuteParser() {
|
||||
const parser = this.get('parser');
|
||||
const { type = 'geojson' } = parser;
|
||||
const data = this.get('data');
|
||||
this.propertiesData = [];// 临时使用
|
||||
this.geoData = [];
|
||||
|
||||
data.coordinates.forEach(geo => {
|
||||
const coord = this._coordProject(geo);
|
||||
this.geoData.push(coord);
|
||||
this.propertiesData.push([]);
|
||||
this.data = getParser(type)(data, parser);
|
||||
}
|
||||
/**
|
||||
* 数据统计
|
||||
*/
|
||||
_executeTrans() {
|
||||
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) {
|
||||
const data = this.propertiesData;
|
||||
const data = this.data.dataArray;
|
||||
const scales = this.get('scales');
|
||||
let scale = scales[field];
|
||||
const scaleController = this.get('scaleController');
|
||||
|
@ -87,5 +104,10 @@ export default class Source extends Base {
|
|||
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];
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
geometryBuffer() {
|
||||
const coordinates = this.get('coordinates');
|
||||
const images = this.get('image');
|
||||
const layerData = this.get('layerData');
|
||||
const coordinates = layerData[0].coordinates;
|
||||
const images = layerData[0].images;
|
||||
const positions = [ ...coordinates[0],
|
||||
coordinates[1][0], coordinates[0][1], 0,
|
||||
...coordinates[1],
|
||||
|
|
|
@ -3,8 +3,7 @@ import { lineShape } from '../shape';
|
|||
|
||||
export default class LineBuffer extends BufferBase {
|
||||
geometryBuffer() {
|
||||
const coordinates = this.get('coordinates');
|
||||
const properties = this.get('properties');
|
||||
const layerData = this.get('layerData');
|
||||
const shapeType = this.shapeType = this.get('shapeType');
|
||||
const positions = [];
|
||||
const positionsIndex = [];
|
||||
|
@ -16,16 +15,16 @@ export default class LineBuffer extends BufferBase {
|
|||
this.attributes = this._getArcLineAttributes();
|
||||
return;
|
||||
}
|
||||
coordinates.forEach((geo, index) => {
|
||||
const props = properties[index];
|
||||
const attrData = this._getShape(geo, props, index);
|
||||
layerData.forEach((item, index) => {
|
||||
const props = item;
|
||||
const attrData = this._getShape(item.coordinates, props, index);
|
||||
positions.push(...attrData.positions);
|
||||
positionsIndex.push(...attrData.indexes);
|
||||
if (attrData.hasOwnProperty('instances')) {
|
||||
instances.push(...attrData.instances);
|
||||
}
|
||||
});
|
||||
this.bufferStruct.style = properties;
|
||||
this.bufferStruct.style = layerData;
|
||||
this.bufferStruct.verts = positions;
|
||||
this.bufferStruct.indexs = positionsIndex;
|
||||
if (instances.length > 0) {
|
||||
|
@ -50,17 +49,16 @@ export default class LineBuffer extends BufferBase {
|
|||
|
||||
}
|
||||
_getArcLineAttributes() {
|
||||
const coordinates = this.get('coordinates');
|
||||
const properties = this.get('properties');
|
||||
const layerData = this.get('layerData');
|
||||
const positions = [];
|
||||
const colors = [];
|
||||
const indexArray = [];
|
||||
const sizes = [];
|
||||
const instances = [];
|
||||
coordinates.forEach((geo, index) => {
|
||||
const props = properties[index];
|
||||
layerData.forEach(item => {
|
||||
const props = item;
|
||||
const positionCount = positions.length / 3;
|
||||
const attrData = this._getShape(geo, props, positionCount);
|
||||
const attrData = this._getShape(item.coordinates, props, positionCount);
|
||||
positions.push(...attrData.positions);
|
||||
colors.push(...attrData.colors);
|
||||
indexArray.push(...attrData.indexArray);
|
||||
|
@ -76,8 +74,7 @@ export default class LineBuffer extends BufferBase {
|
|||
};
|
||||
}
|
||||
_getMeshLineAttributes() {
|
||||
const coordinates = this.get('coordinates');
|
||||
const properties = this.get('properties');
|
||||
const layerData = this.get('layerData');
|
||||
const { lineType } = this.get('style');
|
||||
const positions = [];
|
||||
const pickingIds = [];
|
||||
|
@ -87,10 +84,10 @@ export default class LineBuffer extends BufferBase {
|
|||
const indexArray = [];
|
||||
const sizes = [];
|
||||
const attrDistance = [];
|
||||
coordinates.forEach((geo, index) => {
|
||||
const props = properties[index];
|
||||
layerData.forEach(item => {
|
||||
const props = item;
|
||||
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);
|
||||
normal.push(...attr.normal);
|
||||
miter.push(...attr.miter);
|
||||
|
|
|
@ -3,7 +3,7 @@ import * as THREE from '../../../core/three';
|
|||
import * as polygonShape from '../../shape/polygon';
|
||||
import * as polygonPath from '../../shape/path';
|
||||
import Util from '../../../util';
|
||||
export default function fillBuffer(coordinates, properties) {
|
||||
export default function fillBuffer(layerData) {
|
||||
const attribute = {
|
||||
vertices: [],
|
||||
normals: [],
|
||||
|
@ -14,8 +14,8 @@ export default function fillBuffer(coordinates, properties) {
|
|||
faceUv: []
|
||||
|
||||
};
|
||||
coordinates.forEach((geo, index) => {
|
||||
let { size, shape, color, id } = properties[index];
|
||||
layerData.forEach(item => {
|
||||
let { size, shape, color, id, coordinates } = item;
|
||||
let polygon = null;
|
||||
const path = polygonPath[shape]();
|
||||
if (pointShape['2d'].indexOf(shape) !== -1) {
|
||||
|
@ -27,7 +27,7 @@ export default function fillBuffer(coordinates, properties) {
|
|||
} else {
|
||||
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;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
export default function ImageBuffer(coordinates, properties, opt) {
|
||||
export default function ImageBuffer(layerData, opt) {
|
||||
const attributes = {
|
||||
vertices: [],
|
||||
colors: [],
|
||||
|
@ -7,10 +7,10 @@ export default function ImageBuffer(coordinates, properties, opt) {
|
|||
pickingIds: [],
|
||||
uv: []
|
||||
};
|
||||
coordinates.forEach((pos, index) => {
|
||||
const { color, size, id, shape } = properties[index];
|
||||
layerData.forEach(item => {
|
||||
const { color, size, id, shape, coordinates } = item;
|
||||
const { x, y } = opt.imagePos[shape];
|
||||
attributes.vertices.push(...pos);
|
||||
attributes.vertices.push(...coordinates);
|
||||
attributes.colors.push(...color);
|
||||
attributes.pickingIds.push(id);
|
||||
attributes.sizes.push(size * window.devicePixelRatio); //
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
export default function NormalBuffer(coordinates, properties) {
|
||||
export default function NormalBuffer(layerData) {
|
||||
const attributes = {
|
||||
vertices: [],
|
||||
colors: [],
|
||||
sizes: [],
|
||||
pickingIds: []
|
||||
};
|
||||
coordinates.forEach((pos, index) => {
|
||||
const { color, size, id } = properties[index];
|
||||
attributes.vertices.push(...pos);
|
||||
layerData.forEach(item => {
|
||||
const { color, size, id, coordinates} = item;
|
||||
attributes.vertices.push(...coordinates);
|
||||
attributes.colors.push(...color);
|
||||
attributes.pickingIds.push(id);
|
||||
attributes.sizes.push(size);
|
||||
|
|
|
@ -3,7 +3,7 @@ import * as polygonShape from '../../shape/polygon';
|
|||
import * as lineShape from '../../shape/line';
|
||||
import { pointShape } from '../../../global';
|
||||
import Util from '../../../util';
|
||||
export default function StrokeBuffer(coordinates, properties, style) {
|
||||
export default function StrokeBuffer(layerData, style) {
|
||||
const attribute = {
|
||||
shapes: [],
|
||||
normal: [],
|
||||
|
@ -15,8 +15,8 @@ export default function StrokeBuffer(coordinates, properties, style) {
|
|||
colors: []
|
||||
};
|
||||
const { stroke, strokeWidth } = style;
|
||||
coordinates.forEach((geo, index) => {
|
||||
let { size, shape, id } = properties[index];
|
||||
layerData.forEach(item => {
|
||||
let { size, shape, id, coordinates } = item;
|
||||
const path = polygonPath[shape]();
|
||||
const positionsIndex = attribute.miter.length;
|
||||
let polygon = null;
|
||||
|
@ -33,7 +33,7 @@ export default function StrokeBuffer(coordinates, properties, style) {
|
|||
} else {
|
||||
throw new Error('Invalid shape type: ' + shape);
|
||||
}
|
||||
polygonLineBuffer(polygon, geo, size, attribute);
|
||||
polygonLineBuffer(polygon, coordinates, size, attribute);
|
||||
|
||||
});
|
||||
return attribute;
|
||||
|
|
|
@ -9,7 +9,7 @@ const metrics = {
|
|||
family: 'ios9',
|
||||
size: 24
|
||||
};
|
||||
export default function TextBuffer(coordinates, properties, style) {
|
||||
export default function TextBuffer(layerData, style) {
|
||||
EventEmitter.call(this);
|
||||
const attributes = {
|
||||
originPoints: [],
|
||||
|
@ -21,7 +21,7 @@ export default function TextBuffer(coordinates, properties, style) {
|
|||
const { textOffset = [ 0, 0 ] } = style;
|
||||
const chars = [];
|
||||
const textChars = {};
|
||||
properties.forEach(element => {
|
||||
layerData.forEach(element => {
|
||||
let text = element.shape || '';
|
||||
text = text.toString();
|
||||
for (let j = 0; j < text.length; j++) {
|
||||
|
@ -33,9 +33,9 @@ export default function TextBuffer(coordinates, properties, style) {
|
|||
}
|
||||
});
|
||||
loadTextInfo(chars, (chars, texture) => {
|
||||
properties.forEach((element, index) => {
|
||||
layerData.forEach(element => {
|
||||
const size = element.size;
|
||||
const pos = coordinates[index];
|
||||
const pos = layerData.coordinates;
|
||||
const pen = { x: textOffset[0], y: textOffset[1] };
|
||||
let text = element.shape || '';
|
||||
text = text.toString();
|
||||
|
|
|
@ -3,22 +3,21 @@ import BufferBase from './bufferBase';
|
|||
export default class PolygonBuffer extends BufferBase {
|
||||
|
||||
geometryBuffer() {
|
||||
const coordinates = this.get('coordinates');
|
||||
const properties = this.get('properties');
|
||||
const layerData = this.get('layerData');
|
||||
const shape = this.get('shape');
|
||||
const positions = [];
|
||||
const faceUv = [];
|
||||
const sizes = [];
|
||||
const positionsIndex = [];
|
||||
let indexCount = 0;
|
||||
this.bufferStruct.style = properties;
|
||||
const isExtrude = properties[0].hasOwnProperty('size');
|
||||
this.bufferStruct.style = layerData;
|
||||
const isExtrude = layerData[0].hasOwnProperty('size');
|
||||
// indices, normals, colors, UVs
|
||||
coordinates.forEach((geo, index) => {
|
||||
const heightValue = properties[index].size;
|
||||
let extrudeData = polygonShape[shape](geo);
|
||||
layerData.forEach(item => {
|
||||
const heightValue = item.size;
|
||||
let extrudeData = polygonShape[shape](item.coordinates);
|
||||
if (isExtrude && shape === 'extrude') {
|
||||
extrudeData = polygonShape.extrude(geo);
|
||||
extrudeData = polygonShape.extrude(item.coordinates);
|
||||
extrudeData.positions = extrudeData.positions.map(pos => {
|
||||
pos[2] *= heightValue;
|
||||
return pos;
|
||||
|
@ -48,7 +47,7 @@ export default class PolygonBuffer extends BufferBase {
|
|||
this.bufferStruct.indices = positionsIndex;
|
||||
this.bufferStruct.position = positions;
|
||||
this.bufferStruct.indexCount = indexCount;
|
||||
this.bufferStruct.style = properties;
|
||||
this.bufferStruct.style = layerData;
|
||||
this.bufferStruct.faceUv = faceUv;
|
||||
this.bufferStruct.sizes = sizes;
|
||||
if (shape !== 'line') {
|
||||
|
|
|
@ -3,8 +3,8 @@ import { colorScales } from '../../attr/colorscales';
|
|||
import * as THREE from '../../core/three';
|
||||
export class RasterBuffer extends BufferBase {
|
||||
geometryBuffer() {
|
||||
const coordinates = this.get('coordinates');
|
||||
|
||||
const layerData = this.get('layerData');
|
||||
const { coordinates, width, data, height } = layerData.dataArray[0];
|
||||
const positions = [
|
||||
...coordinates[0],
|
||||
coordinates[1][0], coordinates[0][1], 0,
|
||||
|
@ -14,9 +14,8 @@ export class RasterBuffer extends BufferBase {
|
|||
coordinates[0][0], coordinates[1][1], 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 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.needsUpdate = true;
|
||||
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_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 = {
|
||||
vertices: new Float32Array(triangles.vertices),
|
||||
uvs: new Float32Array(triangles.uvs),
|
||||
|
@ -78,9 +77,8 @@ export class RasterBuffer extends BufferBase {
|
|||
texture1.needsUpdate = true;
|
||||
return texture1;
|
||||
}
|
||||
_buildTriangles(raster, size = 1, extent) {
|
||||
_buildTriangles(width, height, size = 1, extent) {
|
||||
// const extent = [ 73.482190241, 3.82501784112, 135.106618732, 57.6300459963 ]
|
||||
const { width, height } = raster;
|
||||
const indices = [];
|
||||
const vertices = [];
|
||||
const uvs = [];
|
||||
|
|
|
@ -13,12 +13,11 @@ export default class TextBuffer extends BufferBase {
|
|||
family: 'ios9',
|
||||
size: 24
|
||||
};
|
||||
const coordinates = this.get('coordinates');
|
||||
const properties = this.get('properties');
|
||||
const layerData = this.get('layerData');
|
||||
const { textOffset = [ 0, 0 ] } = this.get('style');
|
||||
const chars = [];
|
||||
const textChars = {};
|
||||
properties.forEach(element => {
|
||||
layerData.forEach(element => {
|
||||
let text = element.shape || '';
|
||||
text = text.toString();
|
||||
for (let j = 0; j < text.length; j++) {
|
||||
|
@ -39,9 +38,9 @@ export default class TextBuffer extends BufferBase {
|
|||
const originPoints = [];
|
||||
const textSizes = [];
|
||||
const textOffsets = [];
|
||||
properties.forEach((element, index) => {
|
||||
layerData.forEach(element => {
|
||||
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: textOffset[0], y: textOffset[1] };
|
||||
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.bufferStruct.style = properties;
|
||||
this.bufferStruct.style = layerData;
|
||||
this.attributes = {
|
||||
originPoints,
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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 * as THREE from '../core/three';
|
||||
import imageSource from '../source/imageSource';
|
||||
import ImageBuffer from '../geom/buffer/image';
|
||||
// import ImageGeometry from '../geom/bufferGeometry/image';
|
||||
import ImageMaterial from '../geom/material/imageMaterial';
|
||||
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() {
|
||||
this.init();
|
||||
this.type = 'image';
|
||||
const source = this.layerSource;
|
||||
const { opacity } = this.get('styleOptions');
|
||||
// 加载 完成事件
|
||||
source.on('imageLoaded', () => {
|
||||
source.data.images.then(images => {
|
||||
this.layerData[0].images = images;
|
||||
const buffer = new ImageBuffer({
|
||||
coordinates: source.geoData,
|
||||
image: source.image
|
||||
layerData: this.layerData
|
||||
});
|
||||
this.initGeometry(buffer.attributes);
|
||||
const material = new ImageMaterial({
|
||||
|
|
|
@ -4,17 +4,14 @@ import PointLayer from './pointLayer';
|
|||
import LineLayer from './lineLayer';
|
||||
import ImageLayer from './imageLayer';
|
||||
import RasterLayer from './rasterLayer';
|
||||
import HeatMapLayer from './heatmap';
|
||||
|
||||
registerLayer('PolygonLayer', PolygonLayer);
|
||||
registerLayer('PointLayer', PointLayer);
|
||||
registerLayer('LineLayer', LineLayer);
|
||||
registerLayer('ImageLayer', ImageLayer);
|
||||
registerLayer('RasterLayer', RasterLayer);
|
||||
registerLayer('HeatMapLayer', HeatMapLayer);
|
||||
|
||||
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.init();
|
||||
const source = this.layerSource;
|
||||
const StyleData = this.StyleData;
|
||||
const layerData = this.layerData;
|
||||
const style = this.get('styleOptions');
|
||||
const buffer = this._buffer = new LineBuffer({
|
||||
coordinates: source.geoData,
|
||||
properties: StyleData,
|
||||
layerData,
|
||||
shapeType: this.shapeType,
|
||||
style
|
||||
});
|
||||
|
|
|
@ -46,12 +46,12 @@ export default class PointLayer extends Layer {
|
|||
case 'fill' :// 填充图形
|
||||
{
|
||||
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'));
|
||||
this.add(meshfill);
|
||||
}
|
||||
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'));
|
||||
this.add(meshStroke, 'line');
|
||||
}
|
||||
|
@ -59,14 +59,14 @@ export default class PointLayer extends Layer {
|
|||
}
|
||||
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 });
|
||||
this.add(imageMesh);
|
||||
break;
|
||||
}
|
||||
case 'normal' : // 原生点
|
||||
{
|
||||
const normalAttribute = PointBuffer.NormalBuffer(source.geoData, this.StyleData, style);
|
||||
const normalAttribute = PointBuffer.NormalBuffer(this.layerData, style);
|
||||
const normalPointMesh = drawPoint.DrawNormal(normalAttribute, style);
|
||||
this.add(normalPointMesh);
|
||||
break;
|
||||
|
@ -78,11 +78,11 @@ export default class PointLayer extends Layer {
|
|||
|
||||
_getShape() {
|
||||
let shape = null;
|
||||
if (!this.StyleData[0].hasOwnProperty('shape')) {
|
||||
if (!this.layerData[0].hasOwnProperty('shape')) {
|
||||
return 'normal';
|
||||
}
|
||||
for (let i = 0; i < this.StyleData.length; i++) {
|
||||
shape = this.StyleData[i].shape;
|
||||
for (let i = 0; i < this.layerData.length; i++) {
|
||||
shape = this.layerData[i].shape;
|
||||
if (shape !== undefined) {
|
||||
break;
|
||||
}
|
||||
|
@ -103,8 +103,7 @@ export default class PointLayer extends Layer {
|
|||
const styleOptions = this.get('styleOptions');
|
||||
const buffer = new TextBuffer({
|
||||
type: this.shapeType,
|
||||
coordinates: source.geoData,
|
||||
properties: this.StyleData,
|
||||
layerData: this.layerData,
|
||||
style: this.get('styleOptions')
|
||||
});
|
||||
|
||||
|
|
|
@ -21,11 +21,9 @@ export default class PolygonLayer extends Layer {
|
|||
_prepareRender() {
|
||||
this.init();
|
||||
this.type = 'polygon';
|
||||
const source = this.layerSource;
|
||||
this._buffer = new PolygonBuffer({
|
||||
shape: this.shape,
|
||||
coordinates: source.geoData,
|
||||
properties: this.StyleData
|
||||
layerData: this.layerData
|
||||
});
|
||||
this.add(this._getLayerRender());
|
||||
}
|
||||
|
|
|
@ -1,16 +1,10 @@
|
|||
import Layer from '../core/layer';
|
||||
import * as THREE from '../core/three';
|
||||
import RasterSource from '../source/rasterSource';
|
||||
import RasterMaterial from '../geom/material/rasterMaterial';
|
||||
import { RasterBuffer } from '../geom/buffer/raster';
|
||||
|
||||
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() {
|
||||
this.type = 'raster';
|
||||
this.init();
|
||||
|
@ -18,18 +12,18 @@ export default class RasterLayer extends Layer {
|
|||
// 加载 完成事件
|
||||
const styleOptions = this.get('styleOptions');
|
||||
const buffer = new RasterBuffer({
|
||||
coordinates: source.geoData,
|
||||
raster: source.rasterData,
|
||||
layerData: source.data,
|
||||
rampColors: styleOptions.rampColors
|
||||
});
|
||||
this.initGeometry(buffer.attributes);
|
||||
const rasterConfig = source.data.dataArray[0];
|
||||
const material = new RasterMaterial({
|
||||
u_texture: buffer.bufferStruct.u_raster,
|
||||
u_colorTexture: buffer.bufferStruct.u_colorTexture,
|
||||
u_opacity: 1.0,
|
||||
u_extent: buffer.bufferStruct.u_extent,
|
||||
u_min: source.rasterData.min,
|
||||
u_max: source.rasterData.max,
|
||||
u_min: rasterConfig.min,
|
||||
u_max: rasterConfig.max,
|
||||
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,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,47 +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;
|
||||
/* eslint-disable */
|
||||
turfMeta.flattenEach(data, (currentFeature, featureIndex, multiFeatureIndex) => {
|
||||
/* eslint-disable */
|
||||
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';
|
||||
export { default as csv } from './csvSource';
|
||||
export { default as array } from './csvSource';
|
||||
export { default as basic } from '../core/source';
|
||||
export { default as imageSource } from './imageSource';
|
||||
// source parser
|
||||
|
||||
import geojson from './parser/geojson';
|
||||
import image from './parser/image';
|
||||
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-aggregator';
|
||||
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,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';
|
||||
|
Loading…
Reference in New Issue