Merge pull request #16 from antvis/1.3beta.2

1.3beta.2
This commit is contained in:
@thinkinggis 2019-08-22 11:09:32 +08:00 committed by GitHub
commit 4ecbc2ace1
24 changed files with 265 additions and 101 deletions

View File

@ -54,7 +54,7 @@ window.scene = scene;
scene.on('loaded', () => {
$.get('https://gw.alipayobjects.com/os/rmsportal/epnZEheZeDgsiSjSPcCv.json', data => {
console.log(data);
const circleLayer = scene.PointLayer({
const circleLayer = = scene.PointLayer({
zIndex: 0,
})
.source(data,{
@ -76,7 +76,6 @@ scene.on('loaded', () => {
})
.source(circleLayer.layerSource)
.shape('point_count', 'text')
.active(true)
.size('point_count', [ 10, 20, 24 ])
.color('#FFF')
.style({

68
demos/datafilter.html Normal file
View File

@ -0,0 +1,68 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<meta name="geometry" content="diagram">
<link rel="stylesheet" href="./assets/common.css">
<link rel="stylesheet" href="./assets/info.css">
<title>hexagon demo</title>
<style>
body {margin: 0;}
#map { position:absolute; top:0; bottom:0; width:100%; }
</style>
</head>
<body>
<div id="map"></div>
<script src="https://webapi.amap.com/maps?v=1.4.8&key=15cd8a57710d40c9b7c0e3cc120f1200&plugin=Map3D"></script>
<script src="./assets/jquery-3.2.1.min.js"></script>
<script src="./assets/dat.gui.min.js"></script>
<script src="../build/L7.js"></script>
<script>
const scene = new L7.Scene({
id: 'map',
mapStyle: 'dark', // 样式URL
center: [121.5558, 31.2481 ],
pitch: 0,
zoom: 11,
hash:true,
});
window.scene = scene;
scene.on('loaded', () => {
$.getJSON('https://gw.alipayobjects.com/os/basement_prod/7bb614db-bac0-48d7-93e7-9446392d3917.json', city => {
const layer = scene.PolygonLayer()
.source(city)
.color('unit_price',['#b2182b','#ef8a62','#fddbc7','#d1e5f0','#67a9cf','#2166ac'].reverse())
.shape('fill')
.active(false)
.style({
opacity: 1
})
.render()
const highlight = scene.LineLayer()
.source(city)
.color('#fff')
.filter('unit_price', (price)=> { return price > 40000})
.shape('line')
.size(4)
.render()
layer.on('click',(item)=>{
const { feature } = item;
highlight.filter('id',(id)=>{
return feature.properties.id === id;
}).render();
})
})
});
</script>
</body>
</html>

81
demos/point.html Normal file
View File

@ -0,0 +1,81 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="https://gw.alipayobjects.com/os/rmsportal/PqLCOJpqoOUfuPRacUzE.css" />
<title>气泡图</title>
<style> ::-webkit-scrollbar{display:none;}html,body{overflow:hidden;margin:0;}
#map { position:absolute; top:0; bottom:0; width:100%; }
</style>
</head>
<body>
<div id="map"></div>
<script>/*Fixing iframe window.innerHeight 0 issue in Safari*/ document.body.clientHeight; </script>
<script src="https://webapi.amap.com/maps?v=1.4.8&key=15cd8a57710d40c9b7c0e3cc120f1200&plugin=Map3D"></script>
<script src="https://gw.alipayobjects.com/os/antv/assets/lib/jquery-3.2.1.min.js"></script>
<script src="../build/l7.js"></script>
<style>
#map { position:absolute; top:0; bottom:0; width:100%; }
</style>
<script>
var scene = new L7.Scene({
id: 'map',
mapStyle: 'light', // 样式URL
center: [120.19382669582967, 30.258134],
pitch: 0,
minZoom:5,
maxZoom:15,
zoom: 3
});
window.scene = scene;
scene.on('loaded',()=>{
$.getJSON('https://gw.alipayobjects.com/os/basement_prod/1d27c363-af3a-469e-ab5b-7a7e1ce4f311.json', city => {
const labeldata = city.features.map(fe=>{
return fe.properties
})
const layer = scene.PolygonLayer()
.source(city)
.color('unit_price',['#b2182b','#ef8a62','#fddbc7','#d1e5f0','#67a9cf','#2166ac'].reverse())
.shape('fill')
.active(true)
.style({
opacity: 1
})
.render()
const layer2= scene.PolygonLayer()
.source(city)
.color('#fff')
.shape('line')
.style({
opacity: 1
})
.render()
layer.fitBounds();
scene.PointLayer({
zIndex: 5
})
.source(labeldata,{
parser:{
type:'json',
x:'longitude',
y:'latitude'
}
})
.shape('name', 'text')
.size(20)
.color('#000')
.style({
// fontFamily: 'Monaco, monospace', // 字体
fontWeight: 200,
textAnchor: 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left
textOffset: [ 0, 0 ], // 文本相对锚点的偏移量 [水平, 垂直]
spacing: 2, // 字符间距
padding: [ 4, 4 ], // 文本包围盒 padding [水平,垂直],影响碰撞检测结果,避免相邻文本靠的太近
strokeColor: '#fff', // 描边颜色
strokeWidth: 4, // 描边宽度
opacity: 1.0
})
.render();
})
})
</script>

View File

@ -38,18 +38,18 @@ const scene = new L7.Scene({
// 高德数据服务 https://mvt.amap.com/district/CHN2/{z}/{x}/{y}/4096?key=608d75903d29ad471362f8c58c550daf
scene.on('loaded', () => {
const attributeCtr = new L7.Control.Attribution();
attributeCtr.addTo(scene);
scene.addTileSource('test',{
url:' https://mvt.amap.com/district/CHN2/{z}/{x}/{y}/4096?key=608d75903d29ad471362f8c58c550daf',
type:'vector',
minZoom: 0,
maxZoom:9
})
const layer = scene.PolygonLayer({
zIndex:0,
attribution:'高德地图'
})
.source('test',{
parser:{
@ -66,13 +66,20 @@ scene.on('loaded', () => {
opacity:1.0
})
.render();
let id =0;
layer.on('click',(e) => {
const { lnglat, feature } = e;
const popup = new L7.Popup()
console.log(lnglat);
const popup = new L7.Popup({
id:id++
})
.setLnglat([lnglat.lng, lnglat.lat])
.setHTML(feature.properties.NAME_CHN.toString()).addTo(scene);
.setText(feature.properties.NAME_CHN.toString()).addTo(scene);
})
scene.on('click',(e)=>{
console.log(e);
})
const layer2 = scene.LineLayer({
zIndex:10,
})

View File

@ -1,6 +1,6 @@
{
"name": "@antv/l7",
"version": "1.3.0-beta.1",
"version": "1.3.0-beta.4",
"description": "Large-scale WebGL-powered Geospatial Data Visualization",
"main": "build/L7.js",
"browser": "build/L7-min.js",

View File

@ -345,12 +345,12 @@
border-radius: 5px;
}
.l7-control-layers-toggle {
background-image: url(../images/layers.png);
background-image: url(../images/layers.svg);
width: 36px;
height: 36px;
}
.l7-retina .l7-control-layers-toggle {
background-image: url(../images/layers-2x.png);
background-image: url(../images/layers.svg);
background-size: 26px 26px;
}
.l7-touch .l7-control-layers-toggle {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 696 B

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1566292427369" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8341" width="32" height="32" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><style type="text/css"></style></defs><path d="M256 341.333333l256 128 256-128-256-128-256 128z m276.864-208.384l341.034667 173.909334c20.736 10.581333 28.202667 34.56 16.682666 53.632a41.386667 41.386667 0 0 1-16.64 15.317333l-341.077333 173.909333a46.336 46.336 0 0 1-41.728 0L150.101333 375.808c-20.736-10.581333-28.202667-34.56-16.682666-53.632a41.386667 41.386667 0 0 1 16.64-15.317333l341.077333-173.909334c12.970667-6.613333 28.757333-6.613333 41.728 0z m0 587.349334a45.653333 45.653333 0 0 1-41.728 0l-341.034667-176.938667c-20.736-10.752-28.202667-35.157333-16.682666-54.528a41.642667 41.642667 0 0 1 16.64-15.573333 34.901333 34.901333 0 0 1 32.213333 0l308.906667 160.213333c12.928 6.741333 28.714667 6.741333 41.685333 0l308.864-160.213333a34.901333 34.901333 0 0 1 32.170667 0c20.736 10.752 28.202667 35.157333 16.682666 54.528a41.642667 41.642667 0 0 1-16.64 15.573333l-341.077333 176.938667z m0 170.666666a45.653333 45.653333 0 0 1-41.728 0l-341.034667-176.938666c-20.736-10.752-28.202667-35.157333-16.682666-54.528a41.642667 41.642667 0 0 1 16.64-15.573334 34.901333 34.901333 0 0 1 32.213333 0l308.906667 160.213334c12.928 6.741333 28.714667 6.741333 41.685333 0l308.864-160.213334a34.901333 34.901333 0 0 1 32.170667 0c20.736 10.752 28.202667 35.157333 16.682666 54.528a41.642667 41.642667 0 0 1-16.64 15.573334l-341.077333 176.938666z" fill="#000000" p-id="8342"></path></svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -11,15 +11,18 @@ export default class Popup extends Base {
anchor: 'bottom',
...cfg
});
bindAll([ '_update', '_onClickClose', 'remove' ], this);
}
addTo(scene) {
this._scene = scene;
if (this.get('closeOnClick')) {
this._scene.on('click', this._onClickClose);
}
this._scene.on('camerachange', this._update);
this._update();
if (this.get('closeOnClick')) {
setTimeout(() => { // TODO 事件冲突
this._scene.on('click', this._onClickClose);
}, 30);
}
}
setLnglat(lngLat) {
this.lngLat = lngLat;

View File

@ -18,15 +18,20 @@ export default class Mapping {
_init() {
this._initControllers();
this._initTileAttrs();
this._initAttrs();
this._mapping();
}
update() {
this.mesh.set('scales', {});
this._initTileAttrs();
this._initAttrs();
this._updateMaping();
}
reMapping() {
this.mesh.set('scales', {});
this._initAttrs();
this._mapping();
}
_initControllers() {
const scalesOption = this.layer.get('scaleOptions');
@ -144,7 +149,7 @@ export default class Mapping {
}
_initTileAttrs() {
_initAttrs() {
const attrOptions = this.layer.get('attrOptions');
for (const type in attrOptions) {
if (attrOptions.hasOwnProperty(type)) {

View File

@ -20,7 +20,7 @@ class Picking {
depthBuffer: true
};
this._pickingTexture = new THREE.WebGLRenderTarget(this._width, this._height, parameters);
this._pickingTexture = new THREE.WebGLRenderTarget(this._width / 10, this._height / 10, parameters);
this._nextId = 1;

View File

@ -81,16 +81,15 @@ export default class Layer extends Base {
/**
* 将图层添加加到 Object
* @param {*} object three 物体
* @param {*} type mesh类型是区别是填充还是边线
*/
add(object, type = 'fill') {
add(object) {
// composer合图层绘制
if (object.type === 'composer') {
this._object3D = object;
this.scene._engine.composerLayers.push(object);
return;
}
type === 'fill' ? this.layerMesh = object : this.layerLineMesh = object;
this.layerMesh = object;
this._visibleWithZoom();
object.onBeforeRender = () => { // 每次渲染前改变状态
const zoom = this.scene.getZoom();
@ -105,9 +104,8 @@ export default class Layer extends Base {
this.afterRender();
};
this._object3D.add(object);
if (type === 'fill') {
this.get('pickingController').addPickMesh(object);
}
this.get('pickingController').addPickMesh(object);
}
remove(object) {
if (object.type === 'composer') {
@ -279,6 +277,7 @@ export default class Layer extends Base {
setData(data, cfg) {
this.layerSource.setData(data, cfg);
this.repaint();
this.scene._engine.update();
}
_createScale(field) {
// TODO scale更新
@ -331,7 +330,7 @@ export default class Layer extends Base {
this.scene.style.update(this._attrs);
return this;
}
this.init();
this._updateDraw();
this.scene._engine.update();
return this;
}
@ -345,7 +344,6 @@ export default class Layer extends Base {
init() {
this._initControllers();
this._mapping();
this._updateDraw();
}
_initInteraction() {
if (this.get('allowActive')) {
@ -379,6 +377,7 @@ export default class Layer extends Base {
setActive(id, color) {
this._activeIds = id;
if (!color) color = Global.activeColor;
if (!Array.isArray(color)) {
color = ColorUtil.color2RGBA(color);
}
@ -407,31 +406,35 @@ export default class Layer extends Base {
const preStyle = this.get('preStyleOption');
const nextStyle = this.get('styleOptions');
if (preAttrs === undefined && preStyle === undefined) { // 首次渲染
// this._mapping();
// this._scaleByZoom();
this._setPreOption();
this.init();
this._initInteraction();
this._initMapEvent();
if (this.layerData.length === 0) {
return;
}
this.draw();
return;
}
if (!Util.isEqual(preAttrs.color, nextAttrs.color)) {
this._updateAttributes(this.layerMesh);
}
// 更新数据过滤 filter
if (!Util.isEqual(preAttrs.filter, nextAttrs.filter)) {
// 更新color
this.repaint();
this._setPreOption();
return;
}
if (!Util.isEqual(preAttrs.color, nextAttrs.color)) {
this._updateAttributes(this.layerMesh);
}
// 更新Size
if (!Util.isEqual(preAttrs.size, nextAttrs.size)) {
// 更新color
this._updateSize();
this.repaint();
}
// 更新形状
if (!Util.isEqual(preAttrs.shape, nextAttrs.shape)) {
// 更新color
this._updateShape();
this.repaint();
}
if (!Util.isEqual(preStyle, nextStyle)) {
// 判断新增,修改,删除
@ -442,7 +445,6 @@ export default class Layer extends Base {
});
this._updateStyle(newStyle);
}
this._setPreOption();
}
_updateSize(zoom) {
@ -525,6 +527,9 @@ export default class Layer extends Base {
style
};
}
_updateFilter() {
this.get('mappingController').reMapping();
}
/**
* 用于过滤数据
* @param {*} object 更新颜色和数据过滤

View File

@ -3,7 +3,6 @@ import { LAYER_MAP } from '../layer';
import Base from './base';
import LoadImage from './image';
import FontAtlasManager from './atlas/font-manager';
// import { MapProvider } from '../map/AMap';
import { getMap } from '../map/index';
import Global from '../global';
import { getInteraction } from '../interaction/index';
@ -42,6 +41,9 @@ export default class Scene extends Base {
if (this.get('scaleControl')) {
new Control.Scale().addTo(this);
}
if (this.get('attributionControl')) {
new Control.Attribution().addTo(this);
}
}
// 为pickup场景添加 object 对象
addPickMesh(object) {
@ -145,9 +147,7 @@ export default class Scene extends Base {
// 要素拾取
if (e.target.nodeName !== 'CANVAS') return;
e.pixel || (e.pixel = e.point);
requestAnimationFrame(() => {
this._engine._picking.pickdata(e);
});
this._engine._picking.pickdata(e);
}, true);
});
}

View File

@ -40,6 +40,7 @@ export default class Source extends Base {
this._transforms = transform || [];
this.set('data', data);
this._init();
this.emit('SourceUpdate');
}
// 数据更新
updateTransfrom(cfg) {

View File

@ -6,7 +6,8 @@ export default function TextMaterial(_uniforms) {
const { vs, fs, uniforms } = getModule('text');
const material = new Material({
defines: {
DEVICE_PIXEL_RATIO: window.devicePixelRatio
SDF_PX: '8.0',
EDGE_GAMMA: 0.105 / window.devicePixelRatio
},
uniforms: wrapUniforms(merge(uniforms, _uniforms)),
vertexShader: vs,

View File

@ -56,7 +56,6 @@ void main() {
float segmentRatio = getSegmentRatio(segmentIndex);
float indexDir = mix(-1.0, 1.0, step(segmentIndex, 0.0));
float nextSegmentRatio = getSegmentRatio(segmentIndex + indexDir);
v_distance_ratio = segmentIndex / segmentNumber;
vec3 curr = getPos(source, target, segmentRatio);
vec3 next = getPos(source, target, nextSegmentRatio);
vec2 offset = getExtrusionOffset((next.xy - curr.xy) * indexDir, position.y);

View File

@ -42,14 +42,15 @@ void main() {
#endif
#ifdef DASHLINE
float time = u_time;
float time = 0.;
#ifdef ANIMATE
time =0;
time = u_time / 1000. ;
#endif
gl_FragColor.a *= u_opacity * ceil(mod(v_distance_ratio + u_dash_offset + time / 10., v_dash_array) - (v_dash_array * u_dash_ratio));
gl_FragColor.a *= u_opacity * ceil(mod(v_distance_ratio + u_dash_offset + time, v_dash_array) - (v_dash_array * u_dash_ratio));
#else
gl_FragColor.a *= u_opacity;
#endif
#ifdef ANIMATE
float alpha =1.0 - fract( mod(1.0- v_distance_ratio,u_interval)* (1.0/u_interval) + u_time / u_duration);
alpha = (alpha + u_trailLength -1.0) / u_trailLength;

View File

@ -1,6 +1,3 @@
#define SDF_PX 8.0
#define EDGE_GAMMA 0.105 / float(DEVICE_PIXEL_RATIO)
uniform sampler2D u_sdf_map;
uniform float u_gamma_scale : 0.5;
uniform float u_font_size : 24;
@ -26,6 +23,6 @@ void main() {
highp float alpha = smoothstep(buff - gamma_scaled, buff + gamma_scaled, dist);
gl_FragColor = mix(v_color * u_font_opacity, u_halo_color, smoothstep(0., .5, 1. - dist)) * alpha;
gl_FragColor = mix(v_color * u_font_opacity, u_halo_color, smoothstep(0., 0.5, 1. - dist)) * alpha;
#pragma include "pick"
}

View File

@ -16,7 +16,8 @@ const Global = {
pitch: 0,
hash: false,
zoomControl: true,
scaleControl: true
scaleControl: true,
attributionControl: true
},
animate: true,
height: 0,

View File

@ -4,6 +4,7 @@ import DrawFill from './polygon/drawFill';
import DrawLine from './polygon/drawLine';
import DrawAnimate from './polygon/drawAnimate';
import Draw3DShape from './point/draw_3d_shape';
import DrawText from './text/drawText';
registerRender('polygon', 'fill', DrawFill);
registerRender('polygon', 'extrude', DrawFill);
@ -23,7 +24,6 @@ registerRender('line', 'greatCircle', DrawArcLine);
import DrawPointImage from './point/drawImage';
import DrawPointNormal from './point/drawNormal';
import DrawPointStroke from './point/drawStroke';
import DrawPointText from './point/drawText';
import DrawPointCircle from './point/drawCircle';
import DrawHexagon from './heatmap/hexagon';
@ -31,11 +31,12 @@ import DrawHexagon from './heatmap/hexagon';
registerRender('point', 'image', DrawPointImage);
registerRender('point', 'normal', DrawPointNormal);
registerRender('point', 'stroke', DrawPointStroke);
registerRender('point', 'text', DrawPointText);
registerRender('point', 'text', DrawText);
registerRender('point', 'fill', DrawPointCircle);
registerRender('point', 'shape', Draw3DShape);
registerRender('point', 'extrude', Draw3DShape);
// heatmap
import DrawGrid from './heatmap/gird';
@ -55,8 +56,6 @@ registerRender('image', 'image', DrawImage);
// image
import DrawText from './text/drawText';
registerRender('text', 'text', DrawText);
export { getRender };

View File

@ -54,3 +54,4 @@ export default function DrawText(layerData, layer) {
const mesh = new THREE.Mesh(geometry, material);
return mesh;
}

View File

@ -2,14 +2,52 @@ import * as THREE from '../../../core/three';
import TextMaterial from '../../../geom/material/textMaterial';
import TextBuffer from '../../../geom/buffer/point/text';
import ColorUtil from '../../../attr/color-util';
export default function DrawText(layerData, layer, updateGeometry = false) {
import CollisionIndex from '../../../util/collision-index';
export default function DrawText(layerData, layer) {
const style = layer.get('styleOptions');
const activeOption = layer.get('activedOptions');
const { strokeWidth, strokeColor, opacity,
fontFamily, fontWeight, spacing, textAnchor, textOffset, padding } = style;
const { strokeWidth, strokeColor, opacity } = style;
const { width, height } = layer.scene.getSize();
const { geometry, texture, fontAtlas } = _updateGeometry(layerData, layer);
layer.scene.on('camerachange', () => {
const { geometry } = _updateGeometry(layerData, layer);
layer.layerMesh.geometry = geometry;
layer.layerMesh.geometry.needsUpdate = true;
});
const material = new TextMaterial({
name: layer.layerId,
u_sdf_map: texture,
u_halo_color: ColorUtil.toRGB(strokeColor).map(e => e / 255),
u_halo_width: strokeWidth,
u_halo_blur: 0.5,
u_font_opacity: opacity,
u_sdf_map_size: [ fontAtlas.width, fontAtlas.height ],
u_viewport_size: [ width, height ],
u_activeColor: activeOption.fill
});
const mesh = new THREE.Mesh(geometry, material);
// 更新 viewport
window.addEventListener('resize', () => {
const { width, height } = layer.scene.getSize();
material.uniforms.u_viewport_size.value = [ width, height ];
material.uniforms.needsUpdate = true;
}, false);
// 关闭视锥裁剪
mesh.frustumCulled = false;
return mesh;
}
function _updateGeometry(layerData, layer) {
const style = layer.get('styleOptions');
const {
fontFamily, fontWeight, spacing, textAnchor, textOffset, padding } = style;
const { width, height } = layer.scene.getSize();
const collisionIndex = new CollisionIndex(width, height);
const { _camera: { projectionMatrix, matrixWorldInverse } } = layer.scene._engine;
// 计算 MVP 矩阵
@ -39,7 +77,7 @@ export default function DrawText(layerData, layer, updateGeometry = false) {
padding
},
layer.scene.fontAtlasManager,
layer.collisionIndex,
collisionIndex,
mvpMatrix
);
@ -69,34 +107,5 @@ export default function DrawText(layerData, layer, updateGeometry = false) {
'a_size',
new THREE.Float32BufferAttribute(textSizes, 1)
);
// 只需要更新顶点数据
if (updateGeometry) {
return geometry;
}
const material = new TextMaterial({
name: layer.layerId,
u_sdf_map: texture,
u_halo_color: ColorUtil.toRGB(strokeColor).map(e => e / 255),
u_halo_width: strokeWidth,
u_halo_blur: 0.5,
u_font_opacity: opacity,
u_sdf_map_size: [ fontAtlas.width, fontAtlas.height ],
u_viewport_size: [ width, height ],
u_activeColor: activeOption.fill
});
const mesh = new THREE.Mesh(geometry, material);
// 更新 viewport
window.addEventListener('resize', () => {
const { width, height } = layer.scene.getSize();
material.uniforms.u_viewport_size.value = [ width, height ];
material.uniforms.needsUpdate = true;
}, false);
// 关闭视锥裁剪
mesh.frustumCulled = false;
return mesh;
return { geometry, texture, fontAtlas };
}

View File

@ -1,23 +1,9 @@
import Layer from '../core/layer';
import { getRender } from './render';
import CollisionIndex from '../util/collision-index';
export default class TextLayer extends Layer {
shape(field, values) {
super.shape(field, values);
this.shape = 'text';
// 创建碰撞检测索引
const { width, height } = this.scene.getSize();
this.collisionIndex = new CollisionIndex(width, height);
// 相机变化,需要重新构建索引,由于文本可见性的改变,也需要重新组装顶点数据
this.scene.on('camerachange', () => {
this.collisionIndex = new CollisionIndex(width, height);
this.layerMesh.geometry = getRender(this.type, this.shape)(this.layerData, this, true);
this.layerMesh.geometry.needsUpdate = true;
});
return this;
}
draw() {