merge master

This commit is contained in:
thinkinggis 2019-07-10 14:57:17 +08:00
commit 55c8a799a9
14 changed files with 393 additions and 14 deletions

View File

@ -81,6 +81,7 @@ scene.on('loaded', () => {
}
})
.shape('fill')
.pattern('id1')
.active(true)
.style({
opacity: 1

144
demos/polygon_jsondata.html Normal file
View File

@ -0,0 +1,144 @@
<!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>extrude Polygon</title>
<style>
#map { position:absolute; top:0; bottom:0; width:100%; }
</style>
</head>
<body>
<div id = 'gui' style="position:absolute;top:0px;right:0px;z-index:2;"></div>
<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>
var mapinstance = new AMap.Map('map',{
center: [121.576757,31.279873 ],
viewMode: '3D',
pitch: 0,
zoom: 12,
maxZoom:20,
minZoom:0,
});
const scene = new L7.Scene({
map:mapinstance,
//mapStyle: 'dark', // 样式URL
});
const testdata = [
{
"areaGeometry": "121.576757,31.279873;121.576904,31.279129;121.577422,31.279135;121.577425,31.279401;121.577604,31.279486;121.577873,31.279668;121.577854,31.280147;121.577873,31.280517;121.577713,31.280483;121.577604,31.280365;121.577051,31.279928;121.576757,31.279873;121.576757,31.279873"
},
{
"areaGeometry": "121.588443,31.260267;121.587893,31.260332;121.587385,31.260387;121.586751,31.26045;121.586099,31.260505;121.585549,31.260584;121.585499,31.260641;121.585475,31.260702;121.585469,31.26076;121.585473,31.260797;121.585721,31.261172;121.585957,31.261529;121.58623,31.261987;121.586426,31.26235;121.586646,31.262795;121.586791,31.263137;121.586924,31.263478;121.587054,31.263788;121.587256,31.264224;121.587319,31.264276;121.587421,31.264337;121.587503,31.264368;121.587542,31.264373;121.588431,31.264357;121.589115,31.264355;121.589253,31.264357;121.589339,31.264331;121.589409,31.264288;121.589547,31.264049;121.589752,31.263696;121.589973,31.263313;121.590156,31.262965;121.59029,31.262682;121.590285,31.262557;121.590257,31.262498;121.5902,31.262459;121.589712,31.262265;121.589543,31.262197;121.5895,31.262125;121.589484,31.262072;121.589499,31.262005;121.589638,31.261714;121.589709,31.261579;121.589911,31.261242;121.590037,31.261031;121.590413,31.261176;121.591041,31.26141;121.591095,31.261317;121.59128,31.26097;121.59132,31.260872;121.591495,31.26061;121.591573,31.260552;121.591628,31.26051;121.591846,31.260295;121.592266,31.259879;121.592656,31.259516;121.592781,31.259401;121.5928,31.259343;121.592801,31.259301;121.592789,31.259261;121.592718,31.259196;121.592689,31.259156;121.592266,31.25884;121.591889,31.258548;121.591681,31.258396;121.591423,31.258196;121.590993,31.257889;121.59091,31.257892;121.590849,31.257903;121.590782,31.257971;121.590504,31.25835;121.590177,31.258758;121.589896,31.259137;121.589722,31.259395;121.589449,31.259807;121.58932,31.260028;121.589223,31.26024;121.588443,31.260267;121.588443,31.260267"
}
]
const data2 = {
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
118.48068237304686,
32.120964197033615
],
[
118.49578857421874,
32.037184191435145
],
[
118.57131958007811,
32.061627957476404
],
[
118.57131958007811,
32.13492006367728
],
[
118.48068237304686,
32.120964197033615
]
]
]
}
},
{
"type": "Feature",
"properties": {},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
118.71414184570311,
31.966143862120095
],
[
118.67156982421875,
31.811062019751912
],
[
118.77044677734375,
31.75502854729287
],
[
118.85696411132814,
31.927689274849715
],
[
118.71414184570311,
31.966143862120095
]
]
]
}
}
]
}
scene.on('loaded', () => {
const data = testdata.map(item=>{
const coordStr = item.areaGeometry;
coordStr.split(';');
const coordinates = coordStr.split(';').map(lnglat=>{
return lnglat.split(',');
})
item.areaGeometry = [coordinates];
return item;
})
citylayer = scene.PolygonLayer()
.source(data,{
parser:{
type:'json',
coordinates:'areaGeometry'
}
})
.color('red')
.shape('extrude')
.size(1000)
.active(true)
.style({
opacity: 1.0
})
.render();
});
</script>
</body>
</html>

View File

@ -1,6 +1,6 @@
{
"name": "@antv/l7",
"version": "1.2.0-beta.0",
"version": "1.2.0-beta.3",
"description": "Large-scale WebGL-powered Geospatial Data Visualization",
"main": "build/l7.js",
"browser": "build/l7.js",
@ -109,6 +109,7 @@
"@antv/g": "^3.1.3",
"@antv/geo-coord": "^1.0.8",
"@antv/util": "~2.0.1",
"@mapbox/geojson-rewind": "^0.4.0",
"@mapbox/tiny-sdf": "^1.1.0",
"@mapbox/vector-tile": "^1.3.1",
"@turf/bbox": "^6.0.1",
@ -119,6 +120,7 @@
"d3-hexbin": "^0.2.2",
"earcut": "^2.1.3",
"fecha": "^2.3.3",
"geojson-rewind": "^0.3.1",
"gl-matrix": "^2.4.1",
"gl-vec2": "^1.3.0",
"lodash": "^4.17.5",

View File

@ -1,15 +1,15 @@
/*
* @Author: ThinkGIS
* @Date: 2018-06-14 20:13:18
* @Last Modified by: ThinkGIS
* @Last Modified time: 2018-07-15 17:26:40
* @Last Modified by: mikey.zhaopeng
* @Last Modified time: 2019-07-08 15:46:28
*/
import Base from './base';
/**
* 视觉通道 symbol
* @class Attr.symbol
* 视觉通道 filter
* @class Attr.filter
*/
class Filter extends Base {
constructor(cfg) {

View File

@ -7,6 +7,7 @@ import Shape from './shape';
import Position from './position';
import Symbol from './symbol';
import Filter from './filter';
import Pattern from './pattern';
Base.Color = Color;
Base.Size = Size;
@ -15,5 +16,6 @@ Base.Shape = Shape;
Base.Position = Position;
Base.Symbol = Symbol;
Base.Filter = Filter;
Base.Pattern = Pattern;
export default Base;

16
src/attr/pattern.js Normal file
View File

@ -0,0 +1,16 @@
import Base from './base';
/**
* 视觉通道 pattern
* @class Attr.pattern
*/
class Pattern extends Base {
constructor(cfg) {
super(cfg);
this.names = [ 'pattern' ];
this.type = 'pattern';
this.gradient = null;
}
}
export default Pattern;

View File

@ -0,0 +1,183 @@
import Util from '../../util';
import Global from '../../global';
import ScaleController from './scale';
import Base from '../base';
import Attr from '../../attr/index';
export default class TileMapping extends Base {
constructor(source, cfg) {
super(cfg);
this.source = source;
this._init();
}
_init() {
this._initControllers();
this._initTileAttrs();
this._mapping();
}
update() {
this.set('scales', {});
this._initTileAttrs();
this._updateMaping();
}
_initControllers() {
const scalesOption = this.get('scaleOptions');
const scaleController = new ScaleController({
defs: {
...scalesOption
}
});
this.set('scaleController', scaleController);
}
_createScale(field) {
const scales = this.get('scales');
this._initControllers(); // scale更新
let scale = scales[field];
if (!scale) {
scale = this.createScale(field);
scales[field] = scale;
}
return scale;
}
createScale(field) {
const data = this.source.data.dataArray;
const scales = this.get('scales');
let scale = scales[field];
const scaleController = this.get('scaleController');
if (!scale) {
scale = scaleController.createScale(field, data);
scales[field] = scale;
}
return scale;
}
// 获取属性映射的值
_getAttrValues(attr, record) {
const scales = attr.scales;
const params = [];
for (let i = 0; i < scales.length; i++) {
const scale = scales[i];
const field = scale.field;
if (scale.type === 'identity') {
params.push(scale.value);
} else {
params.push(record[field]);
}
}
const indexZoom = params.indexOf('zoom');
indexZoom !== -1 ? params[indexZoom] = attr.zoom : null;
const values = attr.mapping(...params);
return values;
}
_mapping() {
const attrs = this.get('attrs');
const mappedData = [];
const data = this.source.data.dataArray;
for (let i = 0; i < data.length; i++) {
const record = data[i];
const newRecord = {};
newRecord.id = data[i]._id;
for (const k in attrs) {
if (attrs.hasOwnProperty(k)) {
const attr = attrs[k];
const names = attr.names;
const values = this._getAttrValues(attr, record);
if (names.length > 1) { // position 之类的生成多个字段的属性
for (let j = 0; j < values.length; j++) {
const val = values[j];
const name = names[j];
newRecord[name] = (Util.isArray(val) && val.length === 1) ? val[0] : val; // 只有一个值时返回第一个属性值
}
} else {
newRecord[names[0]] = values.length === 1 ? values[0] : values;
}
}
}
newRecord.coordinates = record.coordinates;
mappedData.push(newRecord);
}
// 通过透明度过滤数据
if (attrs.hasOwnProperty('filter')) {
mappedData.forEach(item => {
if (item.filter === false) {
(item.color[3] = 0);
item.id = -item.id;
}
});
}
this.layerData = mappedData;
}
/**
* 更新数据maping
* @param {*} layerSource 数据源
* @param {*} layer map
*/
_updateMaping() {
const attrs = this.get('attrs');
const data = this.source.data.dataArray;
const layerData = this.layerData;
for (let i = 0; i < data.length; i++) {
const record = data[i];
for (const attrName in attrs) {
if (attrs.hasOwnProperty(attrName) && attrs[attrName].neadUpdate) {
const attr = attrs[attrName];
const names = attr.names;
const values = this._getAttrValues(attr, record);
if (names.length > 1) { // position 之类的生成多个字段的属性
for (let j = 0; j < values.length; j++) {
const val = values[j];
const name = names[j];
layerData[i][name] = (Util.isArray(val) && val.length === 1) ? val[0] : val; // 只有一个值时返回第一个属性值
}
} else {
layerData[i][names[0]] = values.length === 1 ? values[0] : values;
}
attr.neadUpdate = true;
}
}
}
}
_initTileAttrs() {
const attrOptions = this.get('attrOptions');
for (const type in attrOptions) {
if (attrOptions.hasOwnProperty(type)) {
this._updateTileAttr(type);
}
}
}
_updateTileAttr(type) {
const self = this;
const attrs = this.get('attrs');
const attrOptions = this.get('attrOptions');
const option = attrOptions[type];
option.neadUpdate = true;
const className = Util.upperFirst(type);
const fields = this._parseFields(option.field);
const scales = [];
for (let i = 0; i < fields.length; i++) {
const field = fields[i];
const scale = self._createScale(field);
if (type === 'color' && Util.isNil(option.values)) { // 设置 color 的默认色值
option.values = Global.colors;
}
scales.push(scale);
}
option.scales = scales;
const attr = new Attr[className](option);
attrs[type] = attr;
}
_parseFields(field) {
if (Util.isArray(field)) {
return field;
}
if (Util.isString(field)) {
return field.split('*');
}
return [ field ];
}
}

View File

@ -110,7 +110,8 @@ export default class Layer extends Base {
if (type === 'fill') {
this.get('pickingController').addPickMesh(object);
}
setTimeout(() => this.scene._engine.update(), 500);
this.scene._engine.update();
// setTimeout(() => this.scene._engine.update(), 200);
}
remove(object) {
if (object.type === 'composer') {
@ -184,6 +185,10 @@ export default class Layer extends Base {
this._createAttrOption('shape', field, values, Global.shape);
return this;
}
pattern(field, values) {
this._createAttrOption('pattern', field, values, Global.pattern);
return this;
}
/**
* 是否允许使用默认的图形激活交互
* @param {Boolean} enable 是否允许激活开关

View File

@ -42,7 +42,6 @@ export default class Scene extends Base {
const Map = new MapProvider(this._attrs);
Map.mixMap(this);
this._container = Map.container;
// const Map = new MapProvider(this.mapContainer, this._attrs);
Map.on('mapLoad', () => {
this.map = Map.map;
this._initEngine(Map.renderDom);
@ -57,8 +56,8 @@ export default class Scene extends Base {
}
this.style = new Style(this, {});
this.emit('loaded');
this._engine.update();
});
}
initLayer() {
for (const key in LAYER_MAP) {

View File

@ -0,0 +1,12 @@
export const Buffer_MAP = {};
export const getBuffer = (bufferType, shapeType) => {
return Buffer_MAP[bufferType.toLowerCase()] && Buffer_MAP[bufferType.toLowerCase()][shapeType.toLowerCase()];
};
export const registerBuffer = (bufferType, shapeType, render) => {
if (getBuffer(bufferType, shapeType)) {
throw new Error(`Render shapeType '${shapeType}' existed.`);
}
// 存储到 map 中
if (!Buffer_MAP[bufferType.toLowerCase()]) Buffer_MAP[bufferType.toLowerCase()] = {};
Buffer_MAP[bufferType.toLowerCase()][shapeType.toLowerCase()] = render;
};

View File

@ -22,6 +22,7 @@ const Global = {
colors: [ 'rgb(103,0,31)', 'rgb(178,24,43)', 'rgb(214,96,77)', 'rgb(244,165,130)', 'rgb(253,219,199)', 'rgb(247,247,247)', 'rgb(209,229,240)', 'rgb(146,197,222)', 'rgb(67,147,195)', 'rgb(33,102,172)', 'rgb(5,48,97)' ],
size: 10000,
shape: 'circle',
pattern: '',
snapArray: [ 0, 1, 2, 4, 5, 10 ],
pointShape: {
'2d': [ 'circle', 'triangle', 'square', 'pentagon', 'hexagon', 'octogon', 'hexagram', 'rhombus', 'vesica' ],

View File

@ -55,7 +55,7 @@ export default class GaodeMap extends Base {
if (map instanceof AMap.Map) {
this.map = map;
this.container = map.getContainer();
this.map.setMapStyle(this.get('mapStyle'));
this.get('mapStyle') && this.map.setMapStyle(this.get('mapStyle'));
} else {
this.map = new AMap.Map(this.container, this._attrs);
}
@ -82,6 +82,7 @@ export default class GaodeMap extends Base {
camera.lookAt(0, 0, 0);
camera.position.x += e.camera.position.x;
camera.position.y += -e.camera.position.y;
this._engine.update();
});
}

View File

@ -1,7 +1,9 @@
import * as turfMeta from '@turf/meta';
import { getCoords } from '@turf/invariant';
import { djb2hash } from '../../util/bkdr-hash';
import rewind from '@mapbox/geojson-rewind';
export default function geoJSON(data, cfg) {
rewind(data, true);
const resultData = [];
const featureKeys = {};
data.features = data.features.filter(item => {

View File

@ -1,16 +1,27 @@
import rewind from '@mapbox/geojson-rewind';
export default function json(data, cfg) {
const { x, y, x1, y1 } = cfg;
const { x, y, x1, y1, coordinates } = cfg;
const resultdata = [];
data.forEach((col, featureIndex) => {
let coordinates = [];
if (x && y) { coordinates = [ col[x], col[y] ]; } // 点数据
let coords = [];
if (x && y) { coords = [ col[x], col[y] ]; } // 点数据
if (x1 && y1) { // 弧线 或者线段
coordinates = [[ col[x], col[y] ], [ col[x1], col[y1] ]];
coords = [[ col[x], col[y] ], [ col[x1], col[y1] ]];
}
if (coordinates) {
const geometry = {
type: 'Polygon',
coordinates: col[coordinates]
};
rewind(geometry, true);
coords = geometry.coordinates;
delete col[coordinates];
}
col._id = featureIndex + 1;
const dataItem = {
...col,
coordinates
coordinates: coords
};
resultdata.push(dataItem);