mirror of https://gitee.com/antv-l7/antv-l7
feat(layer): add controller
This commit is contained in:
parent
1491a7b0aa
commit
d562f86251
|
@ -57,7 +57,6 @@ scene.on('loaded', () => {
|
|||
type:'log'
|
||||
}
|
||||
})
|
||||
// cylinder
|
||||
.shape('hexagon')
|
||||
.size(2)
|
||||
.active({fill:'red'})
|
||||
|
@ -73,10 +72,6 @@ scene.on('loaded', () => {
|
|||
})
|
||||
console.log(layer);
|
||||
});
|
||||
//OBJECTID',(id)=>{
|
||||
// const index = id % 8;
|
||||
//return ['#9e0142','#d53e4f','#f46d43','#fdae61','#fee08b','#ffffbf','#e6f598','#abdda4','#66c2a5','#3288bd','#5e4fa2'][index];
|
||||
//}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -52,8 +52,9 @@ scene.on('loaded', () => {
|
|||
maxZoom: 17,
|
||||
}
|
||||
})
|
||||
//.scale()
|
||||
// cylinder
|
||||
.filter('province',name =>{
|
||||
return name =='山东省'
|
||||
})
|
||||
.shape('fill')
|
||||
.size(2)
|
||||
.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 Mapping from './mapping';
|
||||
import Picking from './pick';
|
||||
import Interaction from './interaction';
|
||||
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 Controller from './controller/index';
|
||||
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 { updateObjecteUniform } from '../util/object3d-util';
|
||||
import Util from '../util';
|
||||
|
@ -24,7 +21,6 @@ function parseFields(field) {
|
|||
}
|
||||
return [ field ];
|
||||
}
|
||||
|
||||
export default class Layer extends Base {
|
||||
getDefaultCfg() {
|
||||
return {
|
||||
|
@ -110,7 +106,8 @@ export default class Layer extends Base {
|
|||
};
|
||||
this._object3D.add(object);
|
||||
if (type === 'fill') {
|
||||
this._addPickMesh(object);// 不对边界线进行拾取
|
||||
this.get('pickingController').addPickMesh(object);
|
||||
// this._addPickMesh(object);// 不对边界线进行拾取
|
||||
}
|
||||
setTimeout(() => this.scene._engine.update(), 500);
|
||||
}
|
||||
|
@ -302,26 +299,14 @@ export default class Layer extends Base {
|
|||
this._setAttrOptions(attrName, attrCfg);
|
||||
}
|
||||
_initControllers() {
|
||||
const scales = this.get('scaleOptions');
|
||||
const scaleController = new Controller.Scale({
|
||||
defs: {
|
||||
...scales
|
||||
}
|
||||
});
|
||||
this.set('scaleController', scaleController);
|
||||
const mappingCtr = new Controller.Mapping({ layer: this });
|
||||
const pickCtr = new Controller.Picking({ layer: this });
|
||||
const interactionCtr = new Controller.Interaction({ layer: this });
|
||||
this.set('mappingController', mappingCtr);
|
||||
this.set('pickingController', pickCtr);
|
||||
this.set('interacionController', interactionCtr);
|
||||
}
|
||||
|
||||
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() {
|
||||
this.init();
|
||||
this.scene._engine.update();
|
||||
|
@ -331,19 +316,19 @@ export default class Layer extends Base {
|
|||
repaint() {
|
||||
this.set('scales', {});
|
||||
this._initControllers();
|
||||
this._initAttrs();
|
||||
this._mapping();
|
||||
// this._initAttrs();
|
||||
// this._mapping();
|
||||
this.redraw();
|
||||
}
|
||||
// 初始化图层
|
||||
init() {
|
||||
this._initControllers();
|
||||
this._initAttrs();
|
||||
// this._initAttrs();
|
||||
this._updateDraw();
|
||||
}
|
||||
_initInteraction() {
|
||||
if (this.get('allowActive')) {
|
||||
this.interaction('active');
|
||||
this.get('interacionController').addInteraction('active');
|
||||
}
|
||||
}
|
||||
_initMapEvent() {
|
||||
|
@ -389,16 +374,6 @@ export default class Layer extends Base {
|
|||
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() {
|
||||
const nextAttrs = this.get('attrOptions');
|
||||
const nextStyle = this.get('styleOptions');
|
||||
|
@ -411,7 +386,7 @@ export default class Layer extends Base {
|
|||
const preStyle = this.get('preStyleOption');
|
||||
const nextStyle = this.get('styleOptions');
|
||||
if (preAttrs === undefined && preStyle === undefined) { // 首次渲染
|
||||
this._mapping();
|
||||
// this._mapping();
|
||||
this._setPreOption();
|
||||
this._scaleByZoom();
|
||||
this._initInteraction();
|
||||
|
@ -449,28 +424,6 @@ export default class Layer extends Base {
|
|||
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) {
|
||||
const sizeOption = this.get('attrOptions').size;
|
||||
const fields = parseFields(sizeOption.field);
|
||||
|
@ -495,96 +448,6 @@ export default class Layer extends Base {
|
|||
}
|
||||
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() {
|
||||
if (this._zoomScale) {
|
||||
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() {
|
||||
this.scene.on('pick-' + this.layerId, e => {
|
||||
let { featureId, point2d, type } = e;
|
||||
|
@ -656,7 +495,7 @@ export default class Layer extends Base {
|
|||
* @param {*} object 更新颜色和数据过滤
|
||||
*/
|
||||
_updateAttributes(object) {
|
||||
this._updateMaping();
|
||||
this.get('mappingController').update();
|
||||
const filterData = this.layerData;
|
||||
this._activeIds = null; // 清空选中元素
|
||||
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() {
|
||||
|
||||
}
|
||||
|
|
|
@ -2,21 +2,9 @@ import * as THREE from '../../core/three';
|
|||
import Base from '../../core/base';
|
||||
import { destoryObject } from '../../util/object3d-util';
|
||||
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';
|
||||
const r2d = 180 / Math.PI;
|
||||
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 {
|
||||
constructor(key, url, layer) {
|
||||
super({
|
||||
|
@ -40,127 +28,15 @@ export default class Tile extends Base {
|
|||
this.requestTileAsync(data => this._init(data));
|
||||
}
|
||||
_init(data) {
|
||||
this._initControllers();
|
||||
this._creatSource(data);
|
||||
this._initTileAttrs();
|
||||
this._mapping();
|
||||
this._initControllers();
|
||||
this._createMesh();
|
||||
}
|
||||
_initControllers() {
|
||||
const scales = this.layer.get('scaleOptions');
|
||||
const scaleController = new Controller.Scale({
|
||||
defs: {
|
||||
...scales
|
||||
}
|
||||
this.mapping = new Controller.Mapping({
|
||||
layer: this.layer,
|
||||
mesh: this
|
||||
});
|
||||
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() {}
|
||||
_getTileURL(urlParams) {
|
||||
|
@ -223,6 +99,9 @@ export default class Tile extends Base {
|
|||
return false;
|
||||
}
|
||||
_preRender() {
|
||||
}
|
||||
repaint() {
|
||||
|
||||
}
|
||||
destroy() {
|
||||
super.destroy();
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import Layer from '../../core/layer';
|
||||
import source from '../../core/source';
|
||||
import * as THREE from '../../core/three';
|
||||
import Controller from '../../core/controller/index';
|
||||
import Global from '../../global';
|
||||
const { pointShape } = Global;
|
||||
import TileCache from './tileCache';
|
||||
import pickingFragmentShader from '../../core/engine/picking/picking_frag.glsl';
|
||||
import { throttle, deepMix } from '@antv/util';
|
||||
import { toLngLat, Bounds, Point } from '@antv/geo-coord';
|
||||
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._crs = epsg3857;
|
||||
this._tiles = new THREE.Object3D();
|
||||
this._pickTiles = new THREE.Object3D();
|
||||
this._pickTiles.name = this.layerId;
|
||||
this.scene._engine._picking.add(this._pickTiles);
|
||||
// this._pickTiles = new THREE.Object3D();
|
||||
// this._pickTiles.name = this.layerId;
|
||||
// this.scene._engine._picking.add(this._pickTiles);
|
||||
this._tiles.frustumCulled = false;
|
||||
this._tileKeys = [];
|
||||
this.tileList = {};
|
||||
|
@ -50,8 +50,14 @@ export default class TileLayer extends Layer {
|
|||
deepMix(tileSourceCfg, this.sourceCfg, cfg);
|
||||
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() {
|
||||
// this._initControllers();
|
||||
this._initControllers();
|
||||
this._initMapEvent();
|
||||
// this._initAttrs();
|
||||
this._initInteraction();
|
||||
|
@ -84,6 +90,13 @@ export default class TileLayer extends Layer {
|
|||
* 需要显示 current
|
||||
* 是否保留 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 = [];
|
||||
const zoom = Math.round(this.scene.getZoom()) - 1;
|
||||
const center = this.scene.getCenter();
|
||||
|
@ -207,17 +220,9 @@ export default class TileLayer extends Layer {
|
|||
}
|
||||
}
|
||||
_addPickTile(meshobj) {
|
||||
const pickCtr = this.get('pickingController');
|
||||
const mesh = meshobj.children[0];
|
||||
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();
|
||||
pickingMesh.material.setUniformsValue('u_zoom', zoom);
|
||||
};
|
||||
this._pickTiles.add(pickingMesh);
|
||||
|
||||
pickCtr.addPickMesh(mesh);
|
||||
}
|
||||
// 根据距离优先级查找
|
||||
getSelectFeature(id, lnglat) {
|
||||
|
@ -374,6 +379,10 @@ export default class TileLayer extends Layer {
|
|||
tile.destroy();
|
||||
tile = null;
|
||||
}
|
||||
_updateAttributes() {
|
||||
// 更新mapping
|
||||
// 更新attribute
|
||||
}
|
||||
destroy() {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,17 +32,18 @@ export default class VectorTile extends Tile {
|
|||
});
|
||||
}
|
||||
_creatSource(data) {
|
||||
this.source = this.layer.tileSource(data, {
|
||||
this.layerSource = this.layer.tileSource(data, {
|
||||
parser: {
|
||||
tile: this._tile
|
||||
}
|
||||
});
|
||||
}
|
||||
_createMesh() {
|
||||
const layerData = this.layerData;
|
||||
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') { // 热力图的情况
|
||||
this.mesh.onBeforeRender = renderer => {
|
||||
this._renderMask(renderer);
|
||||
|
@ -114,9 +115,9 @@ export default class VectorTile extends Tile {
|
|||
this.xhrRequest.abort();
|
||||
}
|
||||
getSelectFeature(id) {
|
||||
const featureIndex = this.source.originData.featureKeys[id];
|
||||
const featureIndex = this.layerSource.originData.featureKeys[id];
|
||||
if (featureIndex) {
|
||||
return this.source.originData.dataArray[featureIndex];
|
||||
return this.layerSource.originData.dataArray[featureIndex];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -126,7 +127,7 @@ export default class VectorTile extends Tile {
|
|||
this._object3D = null;
|
||||
this.maskScene = null;
|
||||
this.layerData = null;
|
||||
this.source.destroy();
|
||||
this.source = null;
|
||||
this.layerSource.destroy();
|
||||
this.layerSource = null;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue