diff --git a/demos/03_choropleths_polygon.html b/demos/03_choropleths_polygon.html
index a9c6ba4da4..0700fcf2b9 100644
--- a/demos/03_choropleths_polygon.html
+++ b/demos/03_choropleths_polygon.html
@@ -81,6 +81,7 @@ scene.on('loaded', () => {
}
})
.shape('fill')
+ .pattern('id1')
.active(true)
.style({
opacity: 1
diff --git a/demos/polygon_jsondata.html b/demos/polygon_jsondata.html
new file mode 100644
index 0000000000..cca750f0ca
--- /dev/null
+++ b/demos/polygon_jsondata.html
@@ -0,0 +1,144 @@
+
+
+
+
+
+
+
+
+
+ extrude Polygon
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/package.json b/package.json
index cdac246bef..7d647aaafa 100755
--- a/package.json
+++ b/package.json
@@ -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",
diff --git a/src/attr/filter.js b/src/attr/filter.js
index 6a0b29f650..4e2b24ea1b 100644
--- a/src/attr/filter.js
+++ b/src/attr/filter.js
@@ -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) {
diff --git a/src/attr/index.js b/src/attr/index.js
index eb4d45ba47..ef233b0018 100644
--- a/src/attr/index.js
+++ b/src/attr/index.js
@@ -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;
diff --git a/src/attr/pattern.js b/src/attr/pattern.js
new file mode 100644
index 0000000000..be4b34d29f
--- /dev/null
+++ b/src/attr/pattern.js
@@ -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;
diff --git a/src/core/controller/tile_mapping.js b/src/core/controller/tile_mapping.js
new file mode 100644
index 0000000000..f8e70c1b3c
--- /dev/null
+++ b/src/core/controller/tile_mapping.js
@@ -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 ];
+ }
+}
diff --git a/src/core/layer.js b/src/core/layer.js
index ad705463f3..6bec477731 100644
--- a/src/core/layer.js
+++ b/src/core/layer.js
@@ -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 是否允许激活开关
diff --git a/src/core/scene.js b/src/core/scene.js
index efc46c4976..bb6498cb66 100644
--- a/src/core/scene.js
+++ b/src/core/scene.js
@@ -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) {
diff --git a/src/geom/buffer/factory.js b/src/geom/buffer/factory.js
new file mode 100644
index 0000000000..25c0afb52c
--- /dev/null
+++ b/src/geom/buffer/factory.js
@@ -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;
+};
diff --git a/src/global.js b/src/global.js
index 4336336627..1f9e5309e9 100644
--- a/src/global.js
+++ b/src/global.js
@@ -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' ],
diff --git a/src/map/AMap.js b/src/map/AMap.js
index aa7a1a1719..a6a101e7ce 100644
--- a/src/map/AMap.js
+++ b/src/map/AMap.js
@@ -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();
});
}
diff --git a/src/source/parser/geojson.js b/src/source/parser/geojson.js
index 67b3c89db6..c0500d23ca 100644
--- a/src/source/parser/geojson.js
+++ b/src/source/parser/geojson.js
@@ -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 => {
diff --git a/src/source/parser/json.js b/src/source/parser/json.js
index 37128bebce..2f0f8fb029 100644
--- a/src/source/parser/json.js
+++ b/src/source/parser/json.js
@@ -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);