mirror of https://gitee.com/antv-l7/antv-l7
feat(layer): add controller
This commit is contained in:
parent
5e4bddf7db
commit
55cf7a0dda
|
@ -57,7 +57,6 @@ scene.on('loaded', () => {
|
||||||
type:'log'
|
type:'log'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
// cylinder
|
|
||||||
.shape('hexagon')
|
.shape('hexagon')
|
||||||
.size(2)
|
.size(2)
|
||||||
.active({fill:'red'})
|
.active({fill:'red'})
|
||||||
|
@ -73,10 +72,6 @@ scene.on('loaded', () => {
|
||||||
})
|
})
|
||||||
console.log(layer);
|
console.log(layer);
|
||||||
});
|
});
|
||||||
//OBJECTID',(id)=>{
|
|
||||||
// const index = id % 8;
|
|
||||||
//return ['#9e0142','#d53e4f','#f46d43','#fdae61','#fee08b','#ffffbf','#e6f598','#abdda4','#66c2a5','#3288bd','#5e4fa2'][index];
|
|
||||||
//}
|
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -52,8 +52,9 @@ scene.on('loaded', () => {
|
||||||
maxZoom: 17,
|
maxZoom: 17,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
//.scale()
|
.filter('province',name =>{
|
||||||
// cylinder
|
return name =='山东省'
|
||||||
|
})
|
||||||
.shape('fill')
|
.shape('fill')
|
||||||
.size(2)
|
.size(2)
|
||||||
.active({fill:'red'})
|
.active({fill:'red'})
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
import Util from '../../util';
|
||||||
|
export default class EventContoller {
|
||||||
|
constructor(cfg) {
|
||||||
|
Util.assign(this, cfg);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,10 @@
|
||||||
import Scale from './scale';
|
import Scale from './scale';
|
||||||
|
import Mapping from './mapping';
|
||||||
|
import Picking from './pick';
|
||||||
|
import Interaction from './interaction';
|
||||||
export default {
|
export default {
|
||||||
Scale
|
Scale,
|
||||||
|
Mapping,
|
||||||
|
Picking,
|
||||||
|
Interaction
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
import Util from '../../util';
|
||||||
|
import { getInteraction } from '../../interaction/index';
|
||||||
|
export default class InteractionController {
|
||||||
|
constructor(cfg) {
|
||||||
|
// defs 列定义
|
||||||
|
Util.assign(this, cfg);
|
||||||
|
}
|
||||||
|
// interaction 方法
|
||||||
|
clearAllInteractions() {
|
||||||
|
const interactions = this.layer.get('interactions');
|
||||||
|
Util.each(interactions, (interaction, key) => {
|
||||||
|
interaction.destory();
|
||||||
|
delete interactions[key];
|
||||||
|
});
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
clearInteraction(type) {
|
||||||
|
const interactions = this.layer.get('interactions');
|
||||||
|
if (interactions[type]) {
|
||||||
|
interactions[type].destory();
|
||||||
|
delete interactions[type];
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
addInteraction(type, cfg = {}) {
|
||||||
|
cfg.layer = this.layer;
|
||||||
|
const Ctor = getInteraction(type);
|
||||||
|
const interaction = new Ctor(cfg);
|
||||||
|
this._setInteraction(type, interaction);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
_setInteraction(type, interaction) {
|
||||||
|
const interactions = this.layer.get('interactions');
|
||||||
|
if (interactions[type]) {
|
||||||
|
interactions[type].destory();
|
||||||
|
}
|
||||||
|
interactions[type] = interaction;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,183 @@
|
||||||
|
import Util from '../../util';
|
||||||
|
import Global from '../../global';
|
||||||
|
import ScaleController from './scale';
|
||||||
|
import Attr from '../../attr/index';
|
||||||
|
export default class Mapping {
|
||||||
|
/** 初始化mapping
|
||||||
|
* 初始化mapping
|
||||||
|
* @param {*} cfg 配置
|
||||||
|
* @param {*} cfg.layer layer对象
|
||||||
|
* @param {*} cfg.mesh mesh对象
|
||||||
|
*/
|
||||||
|
constructor(cfg) {
|
||||||
|
Util.assign(this, cfg);
|
||||||
|
if (!this.mesh) this.mesh = this.layer;
|
||||||
|
this._init();
|
||||||
|
}
|
||||||
|
_init() {
|
||||||
|
this._initControllers();
|
||||||
|
this._initTileAttrs();
|
||||||
|
this._mapping();
|
||||||
|
}
|
||||||
|
update() {
|
||||||
|
this._updateMaping();
|
||||||
|
}
|
||||||
|
_initControllers() {
|
||||||
|
const scales = this.layer.get('scaleOptions');
|
||||||
|
const scaleController = new ScaleController({
|
||||||
|
defs: {
|
||||||
|
...scales
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.mesh.set('scaleController', scaleController);
|
||||||
|
}
|
||||||
|
_createScale(field) {
|
||||||
|
// TODO scale更新
|
||||||
|
const scales = this.mesh.get('scales');
|
||||||
|
let scale = scales[field];
|
||||||
|
if (!scale) {
|
||||||
|
scale = this.createScale(field);
|
||||||
|
scales[field] = scale;
|
||||||
|
}
|
||||||
|
return scale;
|
||||||
|
}
|
||||||
|
createScale(field) {
|
||||||
|
const data = this.mesh.layerSource.data.dataArray;
|
||||||
|
const scales = this.mesh.get('scales');
|
||||||
|
let scale = scales[field];
|
||||||
|
const scaleController = this.mesh.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.mesh.get('attrs');
|
||||||
|
const mappedData = [];
|
||||||
|
const data = this.mesh.layerSource.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 => {
|
||||||
|
item.filter === false && (item.color[3] = 0);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.mesh.layerData = mappedData;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新数据maping
|
||||||
|
* @param {*} layerSource 数据源
|
||||||
|
* @param {*} layer map
|
||||||
|
*/
|
||||||
|
_updateMaping() {
|
||||||
|
const attrs = this.mesh.get('attrs');
|
||||||
|
|
||||||
|
const data = this.mesh.layerSource.data.dataArray;
|
||||||
|
const layerData = this.mesh.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.layer.get('attrOptions');
|
||||||
|
for (const type in attrOptions) {
|
||||||
|
if (attrOptions.hasOwnProperty(type)) {
|
||||||
|
this._updateTileAttr(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_updateTileAttr(type) {
|
||||||
|
const self = this;
|
||||||
|
const attrs = this.mesh.get('attrs');
|
||||||
|
const attrOptions = this.layer.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 ];
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
import Util from '../../util';
|
||||||
|
import * as THREE from '../three';
|
||||||
|
import pickingFragmentShader from '../engine/picking/picking_frag.glsl';
|
||||||
|
import { updateObjecteUniform } from '../../util/object3d-util';
|
||||||
|
export default class PickContoller {
|
||||||
|
constructor(cfg) {
|
||||||
|
Util.assign(this, cfg);
|
||||||
|
this.pickObject3D = new THREE.Object3D();
|
||||||
|
this.addToPicking(this.pickObject3D);
|
||||||
|
}
|
||||||
|
getPickingId() {
|
||||||
|
return this.layer.scene._engine._picking.getNextId();
|
||||||
|
}
|
||||||
|
addToPicking(object) {
|
||||||
|
object.name = this.layer.layerId;
|
||||||
|
this.layer.scene._engine._picking.add(object);
|
||||||
|
}
|
||||||
|
removePickingObject(object) {
|
||||||
|
this.layer.scene._engine._picking.remove(object);
|
||||||
|
}
|
||||||
|
removePickingMesh(mesh) {
|
||||||
|
this.Object3D.remove(mesh);
|
||||||
|
}
|
||||||
|
addPickMesh(mesh) {
|
||||||
|
const pickmaterial = mesh.material.clone();
|
||||||
|
pickmaterial.fragmentShader = pickingFragmentShader;
|
||||||
|
const pickingMesh = new THREE[mesh.type](mesh.geometry, pickmaterial);
|
||||||
|
pickingMesh.name = this.layerId;
|
||||||
|
pickingMesh.onBeforeRender = () => {
|
||||||
|
const zoom = this.layer.scene.getZoom();
|
||||||
|
updateObjecteUniform(pickingMesh, { u_zoom: zoom });
|
||||||
|
};
|
||||||
|
this.pickObject3D.add(pickingMesh);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,9 +7,6 @@ import * as THREE from './three';
|
||||||
import ColorUtil from '../attr/color-util';
|
import ColorUtil from '../attr/color-util';
|
||||||
import Controller from './controller/index';
|
import Controller from './controller/index';
|
||||||
import source from './source';
|
import source from './source';
|
||||||
import pickingFragmentShader from '../core/engine/picking/picking_frag.glsl';
|
|
||||||
import { getInteraction } from '../interaction/index';
|
|
||||||
import Attr from '../attr/index';
|
|
||||||
import diff from '../util/diff';
|
import diff from '../util/diff';
|
||||||
import { updateObjecteUniform } from '../util/object3d-util';
|
import { updateObjecteUniform } from '../util/object3d-util';
|
||||||
import Util from '../util';
|
import Util from '../util';
|
||||||
|
@ -24,7 +21,6 @@ function parseFields(field) {
|
||||||
}
|
}
|
||||||
return [ field ];
|
return [ field ];
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class Layer extends Base {
|
export default class Layer extends Base {
|
||||||
getDefaultCfg() {
|
getDefaultCfg() {
|
||||||
return {
|
return {
|
||||||
|
@ -110,7 +106,8 @@ export default class Layer extends Base {
|
||||||
};
|
};
|
||||||
this._object3D.add(object);
|
this._object3D.add(object);
|
||||||
if (type === 'fill') {
|
if (type === 'fill') {
|
||||||
this._addPickMesh(object);// 不对边界线进行拾取
|
this.get('pickingController').addPickMesh(object);
|
||||||
|
// this._addPickMesh(object);// 不对边界线进行拾取
|
||||||
}
|
}
|
||||||
setTimeout(() => this.scene._engine.update(), 500);
|
setTimeout(() => this.scene._engine.update(), 500);
|
||||||
}
|
}
|
||||||
|
@ -302,26 +299,14 @@ export default class Layer extends Base {
|
||||||
this._setAttrOptions(attrName, attrCfg);
|
this._setAttrOptions(attrName, attrCfg);
|
||||||
}
|
}
|
||||||
_initControllers() {
|
_initControllers() {
|
||||||
const scales = this.get('scaleOptions');
|
const mappingCtr = new Controller.Mapping({ layer: this });
|
||||||
const scaleController = new Controller.Scale({
|
const pickCtr = new Controller.Picking({ layer: this });
|
||||||
defs: {
|
const interactionCtr = new Controller.Interaction({ layer: this });
|
||||||
...scales
|
this.set('mappingController', mappingCtr);
|
||||||
}
|
this.set('pickingController', pickCtr);
|
||||||
});
|
this.set('interacionController', interactionCtr);
|
||||||
this.set('scaleController', scaleController);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
createScale(field) {
|
|
||||||
const data = this.layerSource ? this.layerSource.data.dataArray : null;
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
render() {
|
render() {
|
||||||
this.init();
|
this.init();
|
||||||
this.scene._engine.update();
|
this.scene._engine.update();
|
||||||
|
@ -331,19 +316,19 @@ export default class Layer extends Base {
|
||||||
repaint() {
|
repaint() {
|
||||||
this.set('scales', {});
|
this.set('scales', {});
|
||||||
this._initControllers();
|
this._initControllers();
|
||||||
this._initAttrs();
|
// this._initAttrs();
|
||||||
this._mapping();
|
// this._mapping();
|
||||||
this.redraw();
|
this.redraw();
|
||||||
}
|
}
|
||||||
// 初始化图层
|
// 初始化图层
|
||||||
init() {
|
init() {
|
||||||
this._initControllers();
|
this._initControllers();
|
||||||
this._initAttrs();
|
// this._initAttrs();
|
||||||
this._updateDraw();
|
this._updateDraw();
|
||||||
}
|
}
|
||||||
_initInteraction() {
|
_initInteraction() {
|
||||||
if (this.get('allowActive')) {
|
if (this.get('allowActive')) {
|
||||||
this.interaction('active');
|
this.get('interacionController').addInteraction('active');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_initMapEvent() {
|
_initMapEvent() {
|
||||||
|
@ -389,16 +374,6 @@ export default class Layer extends Base {
|
||||||
updateObjecteUniform(this._object3D, { u_activeId: featureId });
|
updateObjecteUniform(this._object3D, { u_activeId: featureId });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
_initAttrs() {
|
|
||||||
// 对比 options变化判断如何更新
|
|
||||||
const attrOptions = this.get('attrOptions');
|
|
||||||
for (const type in attrOptions) {
|
|
||||||
if (attrOptions.hasOwnProperty(type)) {
|
|
||||||
this._updateAttr(type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_setPreOption() {
|
_setPreOption() {
|
||||||
const nextAttrs = this.get('attrOptions');
|
const nextAttrs = this.get('attrOptions');
|
||||||
const nextStyle = this.get('styleOptions');
|
const nextStyle = this.get('styleOptions');
|
||||||
|
@ -411,7 +386,7 @@ export default class Layer extends Base {
|
||||||
const preStyle = this.get('preStyleOption');
|
const preStyle = this.get('preStyleOption');
|
||||||
const nextStyle = this.get('styleOptions');
|
const nextStyle = this.get('styleOptions');
|
||||||
if (preAttrs === undefined && preStyle === undefined) { // 首次渲染
|
if (preAttrs === undefined && preStyle === undefined) { // 首次渲染
|
||||||
this._mapping();
|
// this._mapping();
|
||||||
this._setPreOption();
|
this._setPreOption();
|
||||||
this._scaleByZoom();
|
this._scaleByZoom();
|
||||||
this._initInteraction();
|
this._initInteraction();
|
||||||
|
@ -449,28 +424,6 @@ export default class Layer extends Base {
|
||||||
this._setPreOption();
|
this._setPreOption();
|
||||||
}
|
}
|
||||||
|
|
||||||
_updateAttr(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 = 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;
|
|
||||||
}
|
|
||||||
_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);
|
||||||
|
@ -495,96 +448,6 @@ export default class Layer extends Base {
|
||||||
}
|
}
|
||||||
updateObjecteUniform(this._object3D, newOption);
|
updateObjecteUniform(this._object3D, newOption);
|
||||||
}
|
}
|
||||||
_mapping(source) {
|
|
||||||
const self = this;
|
|
||||||
const attrs = self.get('attrs');
|
|
||||||
const mappedData = [];
|
|
||||||
// const data = this.layerSource.propertiesData;
|
|
||||||
let data;
|
|
||||||
source ? data = source.data.dataArray : data = this.layerSource.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 = self._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 => {
|
|
||||||
item.filter === false && (item.color[3] = 0);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
this.layerData = mappedData;
|
|
||||||
return mappedData;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 更新地图映射
|
|
||||||
_updateMaping(source, layer) {
|
|
||||||
const self = this;
|
|
||||||
const attrs = self.get('attrs');
|
|
||||||
|
|
||||||
const data = source ? source.data.dataArray : this.layerSource.data.dataArray;
|
|
||||||
const layerData = layer || 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 = self._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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取属性映射的值
|
|
||||||
_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;
|
|
||||||
}
|
|
||||||
_scaleByZoom() {
|
_scaleByZoom() {
|
||||||
if (this._zoomScale) {
|
if (this._zoomScale) {
|
||||||
this.map.on('zoomend', () => {
|
this.map.on('zoomend', () => {
|
||||||
|
@ -594,30 +457,6 @@ export default class Layer extends Base {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getPickingId() {
|
|
||||||
return this.scene._engine._picking.getNextId();
|
|
||||||
}
|
|
||||||
addToPicking(object) {
|
|
||||||
this.scene._engine._picking.add(object);
|
|
||||||
}
|
|
||||||
removeFromPicking(object) {
|
|
||||||
this.scene._engine._picking.remove(object);
|
|
||||||
}
|
|
||||||
_addPickMesh(mesh) {
|
|
||||||
this._pickingMesh = new THREE.Object3D();
|
|
||||||
this._pickingMesh.name = this.layerId;
|
|
||||||
this.addToPicking(this._pickingMesh);
|
|
||||||
const pickmaterial = mesh.material.clone();
|
|
||||||
pickmaterial.fragmentShader = pickingFragmentShader;
|
|
||||||
const pickingMesh = new THREE[mesh.type](mesh.geometry, pickmaterial);
|
|
||||||
pickingMesh.name = this.layerId;
|
|
||||||
pickingMesh.onBeforeRender = () => {
|
|
||||||
const zoom = this.scene.getZoom();
|
|
||||||
updateObjecteUniform(pickingMesh, { u_zoom: zoom });
|
|
||||||
};
|
|
||||||
this._pickingMesh.add(pickingMesh);
|
|
||||||
|
|
||||||
}
|
|
||||||
_initEvents() {
|
_initEvents() {
|
||||||
this.scene.on('pick-' + this.layerId, e => {
|
this.scene.on('pick-' + this.layerId, e => {
|
||||||
let { featureId, point2d, type } = e;
|
let { featureId, point2d, type } = e;
|
||||||
|
@ -656,7 +495,7 @@ export default class Layer extends Base {
|
||||||
* @param {*} object 更新颜色和数据过滤
|
* @param {*} object 更新颜色和数据过滤
|
||||||
*/
|
*/
|
||||||
_updateAttributes(object) {
|
_updateAttributes(object) {
|
||||||
this._updateMaping();
|
this.get('mappingController').update();
|
||||||
const filterData = this.layerData;
|
const filterData = this.layerData;
|
||||||
this._activeIds = null; // 清空选中元素
|
this._activeIds = null; // 清空选中元素
|
||||||
const colorAttr = object.geometry.attributes.a_color;
|
const colorAttr = object.geometry.attributes.a_color;
|
||||||
|
@ -720,37 +559,6 @@ export default class Layer extends Base {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// interaction 方法
|
|
||||||
clearAllInteractions() {
|
|
||||||
const interactions = this.get('interactions');
|
|
||||||
Util.each(interactions, (interaction, key) => {
|
|
||||||
interaction.destory();
|
|
||||||
delete interactions[key];
|
|
||||||
});
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
clearInteraction(type) {
|
|
||||||
const interactions = this.get('interactions');
|
|
||||||
if (interactions[type]) {
|
|
||||||
interactions[type].destory();
|
|
||||||
delete interactions[type];
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
interaction(type, cfg = {}) {
|
|
||||||
cfg.layer = this;
|
|
||||||
const Ctor = getInteraction(type);
|
|
||||||
const interaction = new Ctor(cfg);
|
|
||||||
this._setInteraction(type, interaction);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
_setInteraction(type, interaction) {
|
|
||||||
const interactions = this.get('interactions');
|
|
||||||
if (interactions[type]) {
|
|
||||||
interactions[type].destory();
|
|
||||||
}
|
|
||||||
interactions[type] = interaction;
|
|
||||||
}
|
|
||||||
styleCfg() {
|
styleCfg() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,21 +2,9 @@ import * as THREE from '../../core/three';
|
||||||
import Base from '../../core/base';
|
import Base from '../../core/base';
|
||||||
import { destoryObject } from '../../util/object3d-util';
|
import { destoryObject } from '../../util/object3d-util';
|
||||||
import Controller from '../../core/controller/index';
|
import Controller from '../../core/controller/index';
|
||||||
import Util from '../../util';
|
|
||||||
import Global from '../../global';
|
|
||||||
import Attr from '../../attr/index';
|
|
||||||
import { toLngLatBounds, toBounds } from '@antv/geo-coord';
|
import { toLngLatBounds, toBounds } from '@antv/geo-coord';
|
||||||
const r2d = 180 / Math.PI;
|
const r2d = 180 / Math.PI;
|
||||||
const tileURLRegex = /\{([zxy])\}/g;
|
const tileURLRegex = /\{([zxy])\}/g;
|
||||||
function parseFields(field) {
|
|
||||||
if (Util.isArray(field)) {
|
|
||||||
return field;
|
|
||||||
}
|
|
||||||
if (Util.isString(field)) {
|
|
||||||
return field.split('*');
|
|
||||||
}
|
|
||||||
return [ field ];
|
|
||||||
}
|
|
||||||
export default class Tile extends Base {
|
export default class Tile extends Base {
|
||||||
constructor(key, url, layer) {
|
constructor(key, url, layer) {
|
||||||
super({
|
super({
|
||||||
|
@ -40,127 +28,15 @@ export default class Tile extends Base {
|
||||||
this.requestTileAsync(data => this._init(data));
|
this.requestTileAsync(data => this._init(data));
|
||||||
}
|
}
|
||||||
_init(data) {
|
_init(data) {
|
||||||
this._initControllers();
|
|
||||||
this._creatSource(data);
|
this._creatSource(data);
|
||||||
this._initTileAttrs();
|
this._initControllers();
|
||||||
this._mapping();
|
|
||||||
this._createMesh();
|
this._createMesh();
|
||||||
}
|
}
|
||||||
_initControllers() {
|
_initControllers() {
|
||||||
const scales = this.layer.get('scaleOptions');
|
this.mapping = new Controller.Mapping({
|
||||||
const scaleController = new Controller.Scale({
|
layer: this.layer,
|
||||||
defs: {
|
mesh: this
|
||||||
...scales
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
this.set('scaleController', scaleController);
|
|
||||||
}
|
|
||||||
_createScale(field) {
|
|
||||||
// TODO scale更新
|
|
||||||
const scales = this.get('scales');
|
|
||||||
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.layerSource.propertiesData;
|
|
||||||
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 => {
|
|
||||||
item.filter === false && (item.color[3] = 0);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
this.layerData = mappedData;
|
|
||||||
}
|
|
||||||
_initTileAttrs() {
|
|
||||||
const attrOptions = this.layer.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.layer.get('attrOptions');
|
|
||||||
const option = attrOptions[type];
|
|
||||||
option.neadUpdate = true;
|
|
||||||
const className = Util.upperFirst(type);
|
|
||||||
const fields = 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;
|
|
||||||
}
|
}
|
||||||
_createMesh() {}
|
_createMesh() {}
|
||||||
_getTileURL(urlParams) {
|
_getTileURL(urlParams) {
|
||||||
|
@ -223,6 +99,9 @@ export default class Tile extends Base {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
_preRender() {
|
_preRender() {
|
||||||
|
}
|
||||||
|
repaint() {
|
||||||
|
|
||||||
}
|
}
|
||||||
destroy() {
|
destroy() {
|
||||||
super.destroy();
|
super.destroy();
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import Layer from '../../core/layer';
|
import Layer from '../../core/layer';
|
||||||
import source from '../../core/source';
|
import source from '../../core/source';
|
||||||
import * as THREE from '../../core/three';
|
import * as THREE from '../../core/three';
|
||||||
|
import Controller from '../../core/controller/index';
|
||||||
import Global from '../../global';
|
import Global from '../../global';
|
||||||
const { pointShape } = Global;
|
const { pointShape } = Global;
|
||||||
import TileCache from './tileCache';
|
import TileCache from './tileCache';
|
||||||
import pickingFragmentShader from '../../core/engine/picking/picking_frag.glsl';
|
|
||||||
import { throttle, deepMix } from '@antv/util';
|
import { throttle, deepMix } from '@antv/util';
|
||||||
import { toLngLat, Bounds, Point } from '@antv/geo-coord';
|
import { toLngLat, Bounds, Point } from '@antv/geo-coord';
|
||||||
import { wrapNum } from '@antv/geo-coord/lib/util/index';
|
import { wrapNum } from '@antv/geo-coord/lib/util/index';
|
||||||
|
@ -18,9 +18,9 @@ export default class TileLayer extends Layer {
|
||||||
this._tileCache = new TileCache(100, this._destroyTile);
|
this._tileCache = new TileCache(100, this._destroyTile);
|
||||||
this._crs = epsg3857;
|
this._crs = epsg3857;
|
||||||
this._tiles = new THREE.Object3D();
|
this._tiles = new THREE.Object3D();
|
||||||
this._pickTiles = new THREE.Object3D();
|
// this._pickTiles = new THREE.Object3D();
|
||||||
this._pickTiles.name = this.layerId;
|
// this._pickTiles.name = this.layerId;
|
||||||
this.scene._engine._picking.add(this._pickTiles);
|
// this.scene._engine._picking.add(this._pickTiles);
|
||||||
this._tiles.frustumCulled = false;
|
this._tiles.frustumCulled = false;
|
||||||
this._tileKeys = [];
|
this._tileKeys = [];
|
||||||
this.tileList = {};
|
this.tileList = {};
|
||||||
|
@ -50,8 +50,14 @@ export default class TileLayer extends Layer {
|
||||||
deepMix(tileSourceCfg, this.sourceCfg, cfg);
|
deepMix(tileSourceCfg, this.sourceCfg, cfg);
|
||||||
return new source(tileSourceCfg);
|
return new source(tileSourceCfg);
|
||||||
}
|
}
|
||||||
|
_initControllers() {
|
||||||
|
const pickCtr = new Controller.Picking({ layer: this });
|
||||||
|
const interactionCtr = new Controller.Interaction({ layer: this });
|
||||||
|
this.set('pickingController', pickCtr);
|
||||||
|
this.set('interacionController', interactionCtr);
|
||||||
|
}
|
||||||
render() {
|
render() {
|
||||||
// this._initControllers();
|
this._initControllers();
|
||||||
this._initMapEvent();
|
this._initMapEvent();
|
||||||
// this._initAttrs();
|
// this._initAttrs();
|
||||||
this._initInteraction();
|
this._initInteraction();
|
||||||
|
@ -84,6 +90,13 @@ export default class TileLayer extends Layer {
|
||||||
* 需要显示 current
|
* 需要显示 current
|
||||||
* 是否保留 retain
|
* 是否保留 retain
|
||||||
*/
|
*/
|
||||||
|
const minZoom = this.get('minZoom');
|
||||||
|
const maxZoom = this.get('maxZoom');
|
||||||
|
const currentZoom = this.scene.getZoom();
|
||||||
|
if (currentZoom < minZoom || currentZoom > maxZoom) {
|
||||||
|
this._removeOutTiles();
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.updateTileList = [];
|
this.updateTileList = [];
|
||||||
const zoom = Math.round(this.scene.getZoom()) - 1;
|
const zoom = Math.round(this.scene.getZoom()) - 1;
|
||||||
const center = this.scene.getCenter();
|
const center = this.scene.getCenter();
|
||||||
|
@ -207,17 +220,9 @@ export default class TileLayer extends Layer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_addPickTile(meshobj) {
|
_addPickTile(meshobj) {
|
||||||
|
const pickCtr = this.get('pickingController');
|
||||||
const mesh = meshobj.children[0];
|
const mesh = meshobj.children[0];
|
||||||
const pickmaterial = mesh.material.clone();
|
pickCtr.addPickMesh(mesh);
|
||||||
pickmaterial.fragmentShader = pickingFragmentShader;
|
|
||||||
const pickingMesh = new THREE[mesh.type](mesh.geometry, pickmaterial);
|
|
||||||
pickingMesh.name = this.layerId;
|
|
||||||
pickingMesh.onBeforeRender = () => {
|
|
||||||
const zoom = this.scene.getZoom();
|
|
||||||
pickingMesh.material.setUniformsValue('u_zoom', zoom);
|
|
||||||
};
|
|
||||||
this._pickTiles.add(pickingMesh);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
// 根据距离优先级查找
|
// 根据距离优先级查找
|
||||||
getSelectFeature(id, lnglat) {
|
getSelectFeature(id, lnglat) {
|
||||||
|
@ -374,6 +379,10 @@ export default class TileLayer extends Layer {
|
||||||
tile.destroy();
|
tile.destroy();
|
||||||
tile = null;
|
tile = null;
|
||||||
}
|
}
|
||||||
|
_updateAttributes() {
|
||||||
|
// 更新mapping
|
||||||
|
// 更新attribute
|
||||||
|
}
|
||||||
destroy() {
|
destroy() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,17 +32,18 @@ export default class VectorTile extends Tile {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
_creatSource(data) {
|
_creatSource(data) {
|
||||||
this.source = this.layer.tileSource(data, {
|
this.layerSource = this.layer.tileSource(data, {
|
||||||
parser: {
|
parser: {
|
||||||
tile: this._tile
|
tile: this._tile
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
_createMesh() {
|
_createMesh() {
|
||||||
|
const layerData = this.layerData;
|
||||||
if (this.layer.get('layerType') === 'point') {
|
if (this.layer.get('layerType') === 'point') {
|
||||||
this.layer.shape = this.layer._getShape(this.layerData);
|
this.layer.shape = this.layer._getShape(layerData);
|
||||||
}
|
}
|
||||||
this.mesh = getRender(this.layer.get('layerType'), this.layer.shape)(this.layerData, this.layer);
|
this.mesh = getRender(this.layer.get('layerType'), this.layer.shape)(layerData, this.layer);
|
||||||
if (this.mesh.type !== 'composer') { // 热力图的情况
|
if (this.mesh.type !== 'composer') { // 热力图的情况
|
||||||
this.mesh.onBeforeRender = renderer => {
|
this.mesh.onBeforeRender = renderer => {
|
||||||
this._renderMask(renderer);
|
this._renderMask(renderer);
|
||||||
|
@ -114,9 +115,9 @@ export default class VectorTile extends Tile {
|
||||||
this.xhrRequest.abort();
|
this.xhrRequest.abort();
|
||||||
}
|
}
|
||||||
getSelectFeature(id) {
|
getSelectFeature(id) {
|
||||||
const featureIndex = this.source.originData.featureKeys[id];
|
const featureIndex = this.layerSource.originData.featureKeys[id];
|
||||||
if (featureIndex) {
|
if (featureIndex) {
|
||||||
return this.source.originData.dataArray[featureIndex];
|
return this.layerSource.originData.dataArray[featureIndex];
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -126,7 +127,7 @@ export default class VectorTile extends Tile {
|
||||||
this._object3D = null;
|
this._object3D = null;
|
||||||
this.maskScene = null;
|
this.maskScene = null;
|
||||||
this.layerData = null;
|
this.layerData = null;
|
||||||
this.source.destroy();
|
this.layerSource.destroy();
|
||||||
this.source = null;
|
this.layerSource = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue