refator(polygonLayer): update polygon Layer
|
@ -86,16 +86,16 @@ scene.on('loaded', () => {
|
|||
opacity: 1
|
||||
})
|
||||
.render();
|
||||
/**
|
||||
|
||||
const citylayer2 = scene.PolygonLayer()
|
||||
.source(city)
|
||||
.shape('line')
|
||||
.color('#fff')
|
||||
.style({
|
||||
opacity: 0.1
|
||||
opacity: 1.0
|
||||
})
|
||||
// .render();
|
||||
**/
|
||||
.render();
|
||||
|
||||
|
||||
citylayer.on('click',(e)=>{
|
||||
$("#info").css({'left': e.pixel.x,'top':e.pixel.y, display:'block'});
|
||||
|
|
Before Width: | Height: | Size: 1.6 MiB After Width: | Height: | Size: 7.2 KiB |
Before Width: | Height: | Size: 332 KiB After Width: | Height: | Size: 564 KiB |
Before Width: | Height: | Size: 1016 KiB After Width: | Height: | Size: 8.9 KiB |
Before Width: | Height: | Size: 385 KiB After Width: | Height: | Size: 214 KiB |
Before Width: | Height: | Size: 647 KiB After Width: | Height: | Size: 528 KiB |
Before Width: | Height: | Size: 195 KiB After Width: | Height: | Size: 8.9 KiB |
Before Width: | Height: | Size: 438 KiB After Width: | Height: | Size: 7.2 KiB |
Before Width: | Height: | Size: 205 KiB After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 2.7 MiB After Width: | Height: | Size: 7.2 KiB |
Before Width: | Height: | Size: 3.6 MiB After Width: | Height: | Size: 7.2 KiB |
Before Width: | Height: | Size: 496 KiB After Width: | Height: | Size: 7.2 KiB |
Before Width: | Height: | Size: 2.1 MiB After Width: | Height: | Size: 7.2 KiB |
After Width: | Height: | Size: 8.9 KiB |
After Width: | Height: | Size: 8.9 KiB |
After Width: | Height: | Size: 7.2 KiB |
After Width: | Height: | Size: 5.3 KiB |
After Width: | Height: | Size: 7.2 KiB |
After Width: | Height: | Size: 7.2 KiB |
|
@ -46,38 +46,16 @@ scene.on('loaded', () => {
|
|||
interval:1,
|
||||
duration:2,
|
||||
trailLength:0.1,
|
||||
repeat:10,
|
||||
repeat:1,
|
||||
})
|
||||
.render();
|
||||
|
||||
|
||||
linelayer.on('animateEnd',()=>{
|
||||
console.log('动画结束');
|
||||
scene.removeLayer(linelayer);
|
||||
//linelayer.hide();
|
||||
})
|
||||
$.get('./data/yunqi.geojson', data => {
|
||||
citylayer = scene.PolygonLayer({
|
||||
zIndex: 2
|
||||
})
|
||||
.source(data)
|
||||
.shape('fill')
|
||||
.active({fill:'red'})
|
||||
.size('floor',[10,2000])
|
||||
.color('rgba(242,246,250,0.96)')
|
||||
.render();
|
||||
})
|
||||
|
||||
$.get('./data/test.json', data => {
|
||||
citylayer2 = scene.PolygonLayer({
|
||||
zIndex: 2
|
||||
})
|
||||
.source(data)
|
||||
.shape('fill')
|
||||
.active({fill:'red'})
|
||||
// .size('floor',[10,2000])
|
||||
.color('red')
|
||||
.render();
|
||||
})
|
||||
|
||||
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
|
|
|
@ -53,7 +53,8 @@
|
|||
"string-replace-loader": "~1.3.0",
|
||||
"torchjs": "~2.1.0",
|
||||
"uglify-js": "~3.1.10",
|
||||
"webpack": "~3.10.0"
|
||||
"webpack": "~3.10.0",
|
||||
"worker-loader": "^2.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "webpack",
|
||||
|
@ -92,9 +93,6 @@
|
|||
],
|
||||
"silent": false
|
||||
},
|
||||
"publishConfig": {
|
||||
"registry": "http://registry.npm.alibaba-inc.com"
|
||||
},
|
||||
"dependencies": {
|
||||
"@antv/g": "^3.1.3",
|
||||
"@antv/util": "~1.2.5",
|
||||
|
@ -113,6 +111,7 @@
|
|||
"three": "^0.96.0",
|
||||
"venn.js": "^0.2.20",
|
||||
"viewport-mercator-project": "^5.2.0",
|
||||
"webworkify-webpack": "^2.1.3",
|
||||
"wolfy87-eventemitter": "~5.2.4"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
*/
|
||||
|
||||
import EventEmitter from 'wolfy87-eventemitter';
|
||||
import Util from '../util';
|
||||
import { assign } from '../util';
|
||||
|
||||
class Base extends EventEmitter {
|
||||
|
||||
|
@ -19,7 +19,7 @@ class Base extends EventEmitter {
|
|||
};
|
||||
const defaultCfg = this.getDefaultCfg();
|
||||
this._attrs = attrs;
|
||||
Util.assign(attrs, defaultCfg, cfg);
|
||||
assign(attrs, defaultCfg, cfg);
|
||||
}
|
||||
|
||||
get(name) {
|
||||
|
|
|
@ -61,8 +61,6 @@ class Picking {
|
|||
this._pickAllObject(point, normalisedPoint);
|
||||
// this._pick(point, normalisedPoint);
|
||||
}
|
||||
|
||||
|
||||
_onWorldMove() {
|
||||
|
||||
this._needUpdate = true;
|
||||
|
@ -74,7 +72,6 @@ class Picking {
|
|||
|
||||
this._width = size.width;
|
||||
this._height = size.height;
|
||||
|
||||
this._pickingTexture.setSize(this._width, this._height);
|
||||
this._pixelBuffer = new Uint8Array(4 * this._width * this._height);
|
||||
|
||||
|
@ -203,15 +200,6 @@ class Picking {
|
|||
}
|
||||
|
||||
this._pickingScene.remove(child);
|
||||
|
||||
// Probably not a good idea to dispose of geometry due to it being
|
||||
// shared with the non-picking scene
|
||||
// if (child.geometry) {
|
||||
// // Dispose of mesh and materials
|
||||
// child.geometry.dispose();
|
||||
// child.geometry = null;
|
||||
// }
|
||||
|
||||
if (child.material) {
|
||||
if (child.material.map) {
|
||||
child.material.map.dispose();
|
||||
|
|
|
@ -42,6 +42,7 @@ export default class Layer extends Base {
|
|||
strokeOpacity: 1.0,
|
||||
texture: false
|
||||
},
|
||||
destroyed: false,
|
||||
// 选中时的配置项
|
||||
selectedOptions: null,
|
||||
// active 时的配置项
|
||||
|
@ -65,7 +66,7 @@ export default class Layer extends Base {
|
|||
scene._engine._scene.add(this._object3D);
|
||||
this.layerMesh = null;
|
||||
this.layerLineMesh = null;
|
||||
this._addPickingEvents();
|
||||
this._initEvents();
|
||||
|
||||
}
|
||||
/**
|
||||
|
@ -77,9 +78,8 @@ export default class Layer extends Base {
|
|||
type === 'fill' ? this.layerMesh = object : this.layerLineMesh = object;
|
||||
|
||||
this._visibleWithZoom();
|
||||
this.scene.on('zoomchange', () => {
|
||||
this._visibleWithZoom();
|
||||
});
|
||||
this._zoomchangeHander = this._visibleWithZoom.bind(this);
|
||||
this.scene.on('zoomchange', this._zoomchangeHander);
|
||||
|
||||
object.onBeforeRender = () => {
|
||||
const zoom = this.scene.getZoom();
|
||||
|
@ -97,7 +97,6 @@ export default class Layer extends Base {
|
|||
}
|
||||
remove(object) {
|
||||
this._object3D.remove(object);
|
||||
|
||||
}
|
||||
_getUniqueId() {
|
||||
return id++;
|
||||
|
@ -113,6 +112,12 @@ export default class Layer extends Base {
|
|||
cfg.mapType = this.get('mapType');
|
||||
|
||||
this.layerSource = new source[type](cfg);
|
||||
// this.scene.workerPool.runTask({
|
||||
// command: 'geojson',
|
||||
// data: cfg
|
||||
// }).then(data => {
|
||||
// console.log(data);
|
||||
// });
|
||||
|
||||
return this;
|
||||
}
|
||||
|
@ -445,10 +450,10 @@ export default class Layer extends Base {
|
|||
_addPickMesh(mesh) {
|
||||
this._pickingMesh = new THREE.Object3D();
|
||||
this._pickingMesh.name = this.layerId;
|
||||
this._visibleWithZoom();
|
||||
this.scene.on('zoomchange', () => {
|
||||
this._visibleWithZoom();
|
||||
});
|
||||
// this._visibleWithZoom();
|
||||
// this.scene.on('zoomchange', () => {
|
||||
// this._visibleWithZoom();
|
||||
// });
|
||||
|
||||
this.addToPicking(this._pickingMesh);
|
||||
const pickmaterial = new PickingMaterial({
|
||||
|
@ -467,16 +472,13 @@ export default class Layer extends Base {
|
|||
_setPickingId() {
|
||||
this._pickingId = this.getPickingId();
|
||||
}
|
||||
_addPickingEvents() {
|
||||
// TODO: Find a way to properly remove this listener on destroy
|
||||
_initEvents() {
|
||||
this.scene.on('pick-' + this.layerId, e => {
|
||||
const { featureId, point2d, type } = e;
|
||||
|
||||
if (featureId < -100 && this._activeIds !== null) {
|
||||
this.emit('mouseleave');
|
||||
return;
|
||||
}
|
||||
// if (intersects.length === 0) { return; }
|
||||
const feature = this.layerSource.getSelectFeature(featureId);
|
||||
const lnglat = this.scene.containerToLngLat(point2d);
|
||||
const target = {
|
||||
|
@ -555,8 +557,6 @@ export default class Layer extends Base {
|
|||
});
|
||||
colorAttr.needsUpdate = true;
|
||||
pickAttr.needsUpdate = true;
|
||||
// this._needUpdateFilter = false;
|
||||
// this._needUpdateColor = false;
|
||||
}
|
||||
_visibleWithZoom() {
|
||||
const zoom = this.scene.getZoom();
|
||||
|
@ -601,8 +601,8 @@ export default class Layer extends Base {
|
|||
/**
|
||||
* 销毁Layer对象
|
||||
*/
|
||||
despose() {
|
||||
this.destroy();
|
||||
destroy() {
|
||||
this.removeAllListeners();
|
||||
if (this._object3D && this._object3D.children) {
|
||||
let child;
|
||||
for (let i = 0; i < this._object3D.children.length; i++) {
|
||||
|
@ -612,7 +612,7 @@ export default class Layer extends Base {
|
|||
}
|
||||
this.remove(child);
|
||||
if (child.geometry) {
|
||||
child.geometry.dispose();
|
||||
// child.geometry.dispose();
|
||||
child.geometry = null;
|
||||
}
|
||||
if (child.material) {
|
||||
|
@ -624,10 +624,14 @@ export default class Layer extends Base {
|
|||
child.material.dispose();
|
||||
child.material = null;
|
||||
}
|
||||
child = null;
|
||||
}
|
||||
}
|
||||
this._object3D = null;
|
||||
this.scene = null;
|
||||
this.scene._engine._scene.remove(this._object3D);
|
||||
this.scene._engine._picking.remove(this._pickingMesh);
|
||||
this.scene.off('zoomchange', this._zoomchangeHander);
|
||||
this.destroyed = true;
|
||||
}
|
||||
_preRender() {
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ import Engine from './engine';
|
|||
import * as layers from '../layer';
|
||||
import Base from './base';
|
||||
import LoadImage from './image';
|
||||
import WorkerPool from './worker';
|
||||
import { MapProvider } from '../map/provider';
|
||||
import GaodeMap from '../map/gaodeMap';
|
||||
import Global from '../global';
|
||||
|
@ -20,6 +21,7 @@ export default class Scene extends Base {
|
|||
_initEngine(mapContainer) {
|
||||
this._engine = new Engine(mapContainer, this);
|
||||
this._engine.run();
|
||||
this.workerPool = new WorkerPool();
|
||||
}
|
||||
// 为pickup场景添加 object 对象
|
||||
addPickMesh(object) {
|
||||
|
@ -59,6 +61,11 @@ export default class Scene extends Base {
|
|||
if (this.map) { this.map.on(type, hander); }
|
||||
super.on(type, hander);
|
||||
}
|
||||
off(type, hander) {
|
||||
if (this.map) { this.map.off(type, hander); }
|
||||
|
||||
super.off(type, hander);
|
||||
}
|
||||
_initAttribution() {
|
||||
const message = '<a href="http://antv.alipay.com/zh-cn/index.html title="Large-scale WebGL-powered Geospatial Data Visualization">AntV | L7 </a>';
|
||||
const element = document.createElement('div');
|
||||
|
@ -105,13 +112,13 @@ export default class Scene extends Base {
|
|||
}, false);
|
||||
});
|
||||
}
|
||||
// 代理map事件
|
||||
removeLayer(layer) {
|
||||
const layerIndex = this._layers.indexOf(layer);
|
||||
if (layerIndex > -1) {
|
||||
this._layers.splice(layerIndex, 1);
|
||||
}
|
||||
layer.destroy();
|
||||
layer = null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import Worker from './main.worker.js';
|
||||
import Worker from '../worker/main.worker.js';
|
||||
class WorkerPool {
|
||||
constructor(workerCount) {
|
||||
this.workerCount = workerCount || Math.max(Math.floor(window.navigator.hardwareConcurrency / 2), 1);
|
||||
|
|
|
@ -68,10 +68,10 @@ export default class PointBuffer extends BufferBase {
|
|||
this.bufferStruct.style = properties;
|
||||
coordinates.forEach((geo, index) => {
|
||||
let { size, shape } = properties[index];
|
||||
let shapeType = '';
|
||||
// let shapeType = '';
|
||||
|
||||
if (type === '2d' || (type === '3d' && size[2] === 0)) {
|
||||
shapeType = 'fill';
|
||||
// let shapeType = 'fill';
|
||||
Util.isArray(size) || (size = [ size, size, 0 ]);
|
||||
} else {
|
||||
Util.isArray(size) || (size = [ size, size, size ]);
|
||||
|
@ -80,7 +80,6 @@ export default class PointBuffer extends BufferBase {
|
|||
uvs.push(0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0);
|
||||
shape = 'square';
|
||||
}
|
||||
// const vert = regularShape[shape](shapeType);
|
||||
properties[index].size = size;
|
||||
|
||||
const [ vert, polygonLine ] = this._getShape(properties[index], style, lineAttribute.miter.length);
|
||||
|
|
|
@ -2,8 +2,181 @@
|
|||
|
||||
import { getJSON } from '../../../util/ajax';
|
||||
import * as THREE from '../../../core/three';
|
||||
import EventEmitter from 'wolfy87-eventemitter';
|
||||
import Global from '../../../global';
|
||||
const Space = 1;
|
||||
const metrics = {
|
||||
buffer: 3,
|
||||
family: 'ios9',
|
||||
size: 24
|
||||
};
|
||||
export default function TextBuffer(coordinates, properties, style) {
|
||||
EventEmitter.call(this);
|
||||
const attributes = {
|
||||
originPoints: [],
|
||||
textSizes: [],
|
||||
textOffsets: [],
|
||||
colors: [],
|
||||
textureElements: []
|
||||
};
|
||||
const { textOffset = [ 0, 0 ] } = style;
|
||||
const chars = [];
|
||||
const textChars = {};
|
||||
properties.forEach(element => {
|
||||
let text = element.shape || '';
|
||||
text = text.toString();
|
||||
for (let j = 0; j < text.length; j++) {
|
||||
const code = text.charCodeAt(j);
|
||||
textChars[text] = 0;
|
||||
if (chars.indexOf(code) === -1) {
|
||||
chars.push(text.charCodeAt(j));
|
||||
}
|
||||
}
|
||||
});
|
||||
loadTextInfo(chars, (chars, texture) => {
|
||||
properties.forEach((element, index) => {
|
||||
const size = element.size;
|
||||
const pos = coordinates[index];
|
||||
const pen = { x: textOffset[0], y: textOffset[1] };
|
||||
let text = element.shape || '';
|
||||
text = text.toString();
|
||||
for (let i = 0; i < text.length; i++) {
|
||||
const color = element.color;
|
||||
drawGlyph(chars, pos, text[i], pen, size, attributes.colors, attributes.textureElements, attributes.originPoints, attributes.textSizes, attributes.textOffsets, color);
|
||||
}
|
||||
this.emit('completed', { attributes, texture });
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function loadTextInfo(chars, done) {
|
||||
getJSON({
|
||||
url: `${Global.sdfHomeUrl}/getsdfdata?chars=${chars.join('|')}`
|
||||
}, (e, info) => {
|
||||
loadTextTexture(info.url, texture => {
|
||||
done(info.info, texture);
|
||||
});
|
||||
});
|
||||
}
|
||||
function loadTextTexture(url, cb) {
|
||||
|
||||
|
||||
const img = new Image();
|
||||
img.crossOrigin = 'anonymous';
|
||||
|
||||
img.onload = () => {
|
||||
const textTexture = this._creatTexture(img);
|
||||
cb(textTexture);
|
||||
};
|
||||
img.src = url;
|
||||
|
||||
}
|
||||
/**
|
||||
* 计算每个标注词语的位置
|
||||
* @param {*} chars 文本信息
|
||||
* @param {*} pos 文字三维空间坐标
|
||||
* @param {*} chr 字符
|
||||
* @param {*} pen 字符在词语的偏移量
|
||||
* @param {*} size 字体大小
|
||||
* @param {*} colors 颜色
|
||||
* @param {*} textureElements 纹理坐标
|
||||
* @param {*} originPoints 初始位置数据
|
||||
* @param {*} textSizes 文字大小数组
|
||||
* @param {*} textOffsets 字体偏移量数据
|
||||
* @param {*} color 文字颜色
|
||||
*/
|
||||
function drawGlyph(chars, pos, text, pen, size, colors, textureElements, originPoints, textSizes, textOffsets, color) {
|
||||
const chr = text.charCodeAt(0);
|
||||
const metric = chars[chr];
|
||||
if (!metric) return;
|
||||
const scale = size / metrics.size;
|
||||
|
||||
let width = metric[0];
|
||||
let height = metric[1];
|
||||
const posX = metric[5];
|
||||
const posY = metric[6];
|
||||
const buffer = metrics.buffer;
|
||||
if (width > 0 && height > 0) {
|
||||
width += buffer * 2;
|
||||
height += buffer * 2;
|
||||
const originX = 0;
|
||||
const originY = 0;
|
||||
const offsetX = pen.x;
|
||||
const offsetY = pen.y;
|
||||
originPoints.push(
|
||||
pos[0] + originX, pos[1] + originY, 0,
|
||||
pos[0] + originX, pos[1] + originY, 0,
|
||||
pos[0] + originX, pos[1] + originY, 0,
|
||||
pos[0] + originX, pos[1] + originY, 0,
|
||||
pos[0] + originX, pos[1] + originY, 0,
|
||||
pos[0] + originX, pos[1] + originY, 0,
|
||||
);
|
||||
const bx = 0;
|
||||
const by = metrics.size / 2 + buffer;
|
||||
textSizes.push(
|
||||
((bx - buffer + width) * scale), (height - by) * scale,
|
||||
((bx - buffer) * scale), (height - by) * scale,
|
||||
((bx - buffer) * scale), -by * scale,
|
||||
|
||||
((bx - buffer + width) * scale), (height - by) * scale,
|
||||
((bx - buffer) * scale), -by * scale,
|
||||
((bx - buffer + width) * scale), -by * scale,
|
||||
);
|
||||
|
||||
|
||||
textOffsets.push(
|
||||
offsetX, offsetY,
|
||||
offsetX, offsetY,
|
||||
offsetX, offsetY,
|
||||
offsetX, offsetY,
|
||||
offsetX, offsetY,
|
||||
offsetX, offsetY,
|
||||
);
|
||||
|
||||
colors.push(
|
||||
...color,
|
||||
...color,
|
||||
...color,
|
||||
...color,
|
||||
...color,
|
||||
...color,
|
||||
);
|
||||
textureElements.push(
|
||||
|
||||
posX + width, posY,
|
||||
posX, posY,
|
||||
posX, posY + height,
|
||||
|
||||
posX + width, posY,
|
||||
posX, posY + height,
|
||||
posX + width, posY + height
|
||||
);
|
||||
}
|
||||
pen.x = pen.x + size * 1.8;
|
||||
|
||||
}
|
||||
|
||||
|
||||
function measureText(text, size) {
|
||||
const dimensions = {
|
||||
advance: 0
|
||||
};
|
||||
const metrics = this.metrics;
|
||||
const scale = size / metrics.size;
|
||||
for (let i = 0; i < text.length; i++) {
|
||||
const code = text.charCodeAt(i);
|
||||
const horiAdvance = metrics.chars[code][4];
|
||||
|
||||
dimensions.advance += (horiAdvance + Space) * scale;
|
||||
}
|
||||
|
||||
return dimensions;
|
||||
}
|
||||
function creatTexture(image) {
|
||||
this.bufferStruct.textSize = [ image.width, image.height ];
|
||||
const texture = new THREE.Texture(image);
|
||||
texture.minFilter = THREE.LinearFilter;
|
||||
texture.magFilter = THREE.ClampToEdgeWrapping;
|
||||
texture.needsUpdate = true;
|
||||
return texture;
|
||||
}
|
||||
|
|
|
@ -1,25 +1,55 @@
|
|||
import polygon_frag from '../shader/polygon_frag.glsl';
|
||||
import polygon_vert from '../shader/polygon_vert.glsl';
|
||||
import Material from './material';
|
||||
export default function PolygonMaterial(options) {
|
||||
const material = new Material({
|
||||
uniforms: {
|
||||
u_opacity: { value: options.u_opacity || 1.0 },
|
||||
u_texture: { value: options.u_texture },
|
||||
u_time: { value: options.u_time || 0 },
|
||||
u_zoom: { value: options.u_zoom || 0 },
|
||||
u_baseColor: { value: options.u_baseColor || [ 1.0, 0, 0, 1.0 ] },
|
||||
u_brightColor: { value: options.u_brightColor || [ 1.0, 0, 0, 1.0 ] },
|
||||
u_windowColor: { value: options.u_windowColor || [ 1.0, 0, 0, 1.0 ] },
|
||||
u_near: { value: options.u_near || 0.0 },
|
||||
u_far: { value: options.u_far || 1.0 }
|
||||
},
|
||||
vertexShader: polygon_vert,
|
||||
fragmentShader: polygon_frag,
|
||||
transparent: true,
|
||||
defines: {
|
||||
TEXCOORD_0: !!options.u_texture
|
||||
}
|
||||
});
|
||||
return material;
|
||||
// export default function PolygonMaterial(options) {
|
||||
// const material = new Material({
|
||||
// uniforms: {
|
||||
// u_opacity: { value: options.u_opacity || 1.0 },
|
||||
// u_texture: { value: options.u_texture },
|
||||
// u_time: { value: options.u_time || 0 },
|
||||
// u_zoom: { value: options.u_zoom || 0 },
|
||||
// u_baseColor: { value: options.u_baseColor || [ 1.0, 0, 0, 1.0 ] },
|
||||
// u_brightColor: { value: options.u_brightColor || [ 1.0, 0, 0, 1.0 ] },
|
||||
// u_windowColor: { value: options.u_windowColor || [ 1.0, 0, 0, 1.0 ] },
|
||||
// u_near: { value: options.u_near || 0.0 },
|
||||
// u_far: { value: options.u_far || 1.0 }
|
||||
// },
|
||||
// vertexShader: polygon_vert,
|
||||
// fragmentShader: polygon_frag,
|
||||
// transparent: true,
|
||||
// defines: {
|
||||
// TEXCOORD_0: !!options.u_texture
|
||||
// }
|
||||
// });
|
||||
// return material;
|
||||
// }
|
||||
|
||||
export default class PolygonMaterial extends Material {
|
||||
getDefaultParameters() {
|
||||
return {
|
||||
uniforms: {
|
||||
u_opacity: { value: 1.0 },
|
||||
u_time: { value: 0 },
|
||||
u_zoom: { value: 0 },
|
||||
u_baseColor: { value: [ 1.0, 0, 0, 1.0 ] },
|
||||
u_brightColor: { value: [ 1.0, 0, 0, 1.0 ] },
|
||||
u_windowColor: { value: [ 1.0, 0, 0, 1.0 ] },
|
||||
u_near: { value: 0.0 },
|
||||
u_far: { value: 1.0 }
|
||||
},
|
||||
defines: {
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
constructor(_uniforms, _defines, parameters) {
|
||||
super(parameters);
|
||||
const { uniforms, defines } = this.getDefaultParameters();
|
||||
this.uniforms = Object.assign(uniforms, this.setUniform(_uniforms));
|
||||
this.type = 'PolygonMaterial';
|
||||
this.defines = Object.assign(defines, _defines);
|
||||
this.vertexShader = polygon_vert;
|
||||
this.fragmentShader = polygon_frag;
|
||||
this.transparent = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ uniform float u_dashSmooth;
|
|||
uniform float u_dashDistance;
|
||||
varying vec4 v_color;
|
||||
void main() {
|
||||
float lineUMod = mod(v_lineU, 1.0/u_dashSteps) * u_dashSteps;
|
||||
float lineUMod = mod(v_lineU, 1.0/ u_dashSteps) * u_dashSteps;
|
||||
float dash = smoothstep(u_dashDistance, u_dashDistance+u_dashSmooth, length(lineUMod-0.5));
|
||||
gl_FragColor = vec4(v_color.xyz * vec3(dash), v_color.a*u_opacity * dash);
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
precision highp float;
|
||||
#define ambientRatio 0.5
|
||||
#define diffuseRatio 0.4
|
||||
#define specularRatio 0.1
|
||||
attribute vec4 a_color;
|
||||
attribute vec4 a_idColor;
|
||||
attribute vec2 faceUv;
|
||||
attribute vec3 a_shape;
|
||||
attribute vec3 a_size;
|
||||
uniform float u_zoom;
|
||||
varying vec2 v_texCoord;
|
||||
varying vec4 v_color;
|
||||
varying float v_lightWeight;
|
||||
varying float v_size;
|
||||
|
||||
void main() {
|
||||
float scale = pow(2.0,(20.0 - u_zoom));
|
||||
mat4 matModelViewProjection = projectionMatrix * modelViewMatrix;
|
||||
vec3 newposition = position;
|
||||
#ifdef SHAPE
|
||||
newposition =position + a_size * scale* a_shape;
|
||||
#endif
|
||||
v_texCoord = faceUv;
|
||||
if(normal == vec3(0.,0.,1.)){
|
||||
v_color = a_color;
|
||||
gl_Position = matModelViewProjection * vec4(newposition, 1.0);
|
||||
return;
|
||||
}
|
||||
|
||||
vec3 worldPos = vec3(vec4(newposition,1.0) * modelMatrix);
|
||||
vec3 worldNormal = vec3(vec4(normal,1.0) * modelMatrix);
|
||||
// //cal light weight
|
||||
vec3 viewDir = normalize(cameraPosition - worldPos);
|
||||
//vec3 lightDir = normalize(vec3(1, -10.5, 12));
|
||||
vec3 lightDir = normalize(vec3(0.,-10.,1.));
|
||||
vec3 halfDir = normalize(viewDir+lightDir);
|
||||
// //lambert
|
||||
float lambert = dot(worldNormal, lightDir);
|
||||
//specular
|
||||
float specular = pow( max(0.0, dot(worldNormal, halfDir)), 32.0);
|
||||
//sum to light weight
|
||||
float lightWeight = ambientRatio + diffuseRatio * lambert + specularRatio * specular;
|
||||
v_texCoord = faceUv;
|
||||
v_lightWeight = lightWeight;
|
||||
// v_size = a_size;
|
||||
v_color =vec4(a_color.rgb*lightWeight, a_color.w);
|
||||
gl_Position = matModelViewProjection * vec4(newposition, 1.0);
|
||||
}
|
|
@ -55,8 +55,8 @@ export default class PointLayer extends Layer {
|
|||
const meshStroke = drawPoint.DrawStroke(lineAttribute, this.get('styleOptions'));
|
||||
this.add(meshStroke, 'line');
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'image':// 绘制图片标注
|
||||
{
|
||||
const imageAttribute = PointBuffer.ImageBuffer(source.geoData, this.StyleData, { imagePos: this.scene.image.imagePos });
|
||||
|
@ -69,9 +69,13 @@ export default class PointLayer extends Layer {
|
|||
const normalAttribute = PointBuffer.NormalBuffer(source.geoData, this.StyleData, style);
|
||||
const normalPointMesh = drawPoint.DrawNormal(normalAttribute, style);
|
||||
this.add(normalPointMesh);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
_getShape() {
|
||||
let shape = null;
|
||||
if (!this.StyleData[0].hasOwnProperty('shape')) {
|
||||
|
@ -83,7 +87,6 @@ export default class PointLayer extends Layer {
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (pointShape['2d'].indexOf(shape) !== -1 || pointShape['3d'].indexOf(shape) !== -1) {
|
||||
return 'fill';
|
||||
} else if (shape === 'text') {
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
import * as THREE from '../core/three';
|
||||
import Layer from '../core/layer';
|
||||
import * as drawPolygon from './render/polygon';
|
||||
import PolygonBuffer from '../geom/buffer/polygon';
|
||||
import PolygonMaterial from '../geom/material/polygonMaterial';
|
||||
import { LineMaterial } from '../geom/material/lineMaterial';
|
||||
export default class PolygonLayer extends Layer {
|
||||
shape(type) {
|
||||
this.shape = type;
|
||||
|
@ -15,80 +13,38 @@ export default class PolygonLayer extends Layer {
|
|||
} else {
|
||||
|
||||
this._initAttrs();
|
||||
(this._needUpdateFilter || this._needUpdateColor) ? this._updateFilter() : null;
|
||||
const { opacity, baseColor, brightColor, windowColor } = this.get('styleOptions');
|
||||
this.layerMesh.material.upDateUninform({
|
||||
u_opacity: opacity,
|
||||
u_baseColor: baseColor,
|
||||
u_brightColor: brightColor,
|
||||
u_windowColor: windowColor
|
||||
});
|
||||
|
||||
(this._needUpdateFilter || this._needUpdateColor) ? this._updateFilter(this.layerMesh) : null;
|
||||
// TODO update Style;
|
||||
}
|
||||
|
||||
|
||||
return this;
|
||||
}
|
||||
_prepareRender() {
|
||||
this.init();
|
||||
this.type = 'polygon';
|
||||
|
||||
const source = this.layerSource;
|
||||
this._buffer = new PolygonBuffer({
|
||||
shape: this.shape,
|
||||
coordinates: source.geoData,
|
||||
properties: this.StyleData
|
||||
});
|
||||
const { attributes } = this._buffer;
|
||||
this.geometry = new THREE.BufferGeometry();
|
||||
this.geometry.addAttribute('position', new THREE.Float32BufferAttribute(attributes.vertices, 3));
|
||||
this.geometry.addAttribute('a_color', new THREE.Float32BufferAttribute(attributes.colors, 4));
|
||||
this.geometry.addAttribute('pickingId', new THREE.Float32BufferAttribute(attributes.pickingIds, 1));
|
||||
if (this.shape === 'line') {
|
||||
this._renderLine();
|
||||
} else {
|
||||
this._renderPolygon();
|
||||
}
|
||||
this.add(this._getLayerRender());
|
||||
}
|
||||
_renderLine() {
|
||||
const { opacity } = this.get('styleOptions');
|
||||
const lineMaterial = new LineMaterial({
|
||||
u_opacity: opacity
|
||||
});
|
||||
const polygonLine = new THREE.LineSegments(this.geometry, lineMaterial);
|
||||
this.add(polygonLine);
|
||||
|
||||
}
|
||||
_renderPolygon() {
|
||||
const animateOptions = this.get('animateOptions');
|
||||
const { opacity, baseColor, brightColor, windowColor } = this.get('styleOptions');
|
||||
const camera = this.map.getCameraState();
|
||||
const material = new PolygonMaterial({
|
||||
u_opacity: opacity,
|
||||
u_baseColor: baseColor,
|
||||
u_brightColor: brightColor,
|
||||
u_windowColor: windowColor,
|
||||
u_near: camera.near,
|
||||
u_far: camera.far
|
||||
});
|
||||
|
||||
const { attributes } = this._buffer;
|
||||
this.geometry.addAttribute('normal', new THREE.Float32BufferAttribute(attributes.normals, 3));
|
||||
if (animateOptions.enable) {
|
||||
material.setDefinesvalue('ANIMATE', true);
|
||||
|
||||
this.geometry.addAttribute('faceUv', new THREE.Float32BufferAttribute(attributes.faceUv, 2));
|
||||
this.geometry.addAttribute('a_size', new THREE.Float32BufferAttribute(attributes.sizes, 1));
|
||||
}
|
||||
|
||||
// const pickmaterial = new PickingMaterial();
|
||||
const polygonMesh = new THREE.Mesh(this.geometry, material);
|
||||
this.add(polygonMesh);
|
||||
}
|
||||
|
||||
update() {
|
||||
this.updateFilter(this.StyleData);
|
||||
this.updateFilter(this.layerMesh);
|
||||
// 动态更新相关属性
|
||||
}
|
||||
_getLayerRender() {
|
||||
const animateOptions = this.get('animateOptions');
|
||||
const { attributes } = this._buffer;
|
||||
const style = this.get('styleOptions');
|
||||
if (this.shape === 'line') {
|
||||
return drawPolygon.DrawLine(attributes, style);
|
||||
} else if (animateOptions.enable) {
|
||||
const { near, far } = this.map.getCameraState();
|
||||
return drawPolygon.DrawAnimate(attributes, { ...style, near, far });
|
||||
}
|
||||
return drawPolygon.DrawFill(attributes, style);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
import * as THREE from '../../../core/three';
|
||||
import { ArcLineMaterial } from '../../../geom/material/lineMaterial';
|
||||
export default function DrawArcLine(attributes, style) {
|
||||
const { opacity, zoom } = style;
|
||||
const geometry = new THREE.BufferGeometry();
|
||||
geometry.setIndex(attributes.indexArray);
|
||||
geometry.addAttribute('position', new THREE.Float32BufferAttribute(attributes.positions, 3));
|
||||
geometry.addAttribute('a_color', new THREE.Float32BufferAttribute(attributes.colors, 4));
|
||||
geometry.addAttribute('a_instance', new THREE.Float32BufferAttribute(attributes.instances, 4));
|
||||
geometry.addAttribute('a_size', new THREE.Float32BufferAttribute(attributes.sizes, 1));
|
||||
const lineMaterial = new ArcLineMaterial({
|
||||
u_opacity: opacity,
|
||||
u_zoom: zoom
|
||||
}, {
|
||||
SHAPE: false
|
||||
});
|
||||
const arcMesh = new THREE.Mesh(geometry, lineMaterial);
|
||||
return arcMesh;
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
import * as THREE from '../../../core/three';
|
||||
import { MeshLineMaterial } from '../../../geom/material/lineMaterial';
|
||||
export default function DrawLine(attributes, style) {
|
||||
const { opacity, zoom, animate, duration, interval, trailLength } = style;
|
||||
const geometry = new THREE.BufferGeometry();
|
||||
geometry.setIndex(attributes.indexArray);
|
||||
geometry.addAttribute('pickingId', new THREE.Float32BufferAttribute(attributes.pickingIds, 1));
|
||||
geometry.addAttribute('position', new THREE.Float32BufferAttribute(attributes.positions, 3));
|
||||
geometry.addAttribute('a_color', new THREE.Float32BufferAttribute(attributes.colors, 4));
|
||||
geometry.addAttribute('a_size', new THREE.Float32BufferAttribute(attributes.sizes, 1));
|
||||
geometry.addAttribute('normal', new THREE.Float32BufferAttribute(attributes.normal, 3));
|
||||
geometry.addAttribute('a_miter', new THREE.Float32BufferAttribute(attributes.miter, 1));
|
||||
geometry.addAttribute('a_distance', new THREE.Float32BufferAttribute(attributes.attrDistance, 1));
|
||||
const lineMaterial = new MeshLineMaterial({
|
||||
u_opacity: opacity,
|
||||
u_zoom: zoom,
|
||||
u_duration: duration,
|
||||
u_interval: interval,
|
||||
u_trailLength: trailLength,
|
||||
u_time: 0
|
||||
}, {
|
||||
SHAPE: false,
|
||||
ANIMATE: animate
|
||||
});
|
||||
const arcMesh = new THREE.Mesh(geometry, lineMaterial);
|
||||
return arcMesh;
|
||||
}
|
|
@ -22,6 +22,7 @@ export default function DrawFill(attributes, style) {
|
|||
SHAPE: true
|
||||
});
|
||||
material.setDefinesvalue('SHAPE', true);
|
||||
material.depthTest = false;
|
||||
const fillMesh = new THREE.Mesh(geometry, material);
|
||||
return fillMesh;
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ export default function DrawImage(attributes, style) {
|
|||
SHAPE: false,
|
||||
TEXCOORD_0: true
|
||||
});
|
||||
material.depthTest = false;
|
||||
const strokeMesh = new THREE.Points(geometry, material);
|
||||
return strokeMesh;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
|
||||
/**
|
||||
* 原生点绘制
|
||||
*/
|
||||
import * as THREE from '../../../core/three';
|
||||
import PointMaterial from '../../../geom/material/pointMaterial';
|
||||
export default function DrawNormal(attributes, style) {
|
||||
|
|
|
@ -1,23 +1,23 @@
|
|||
import * as THREE from '../../../core/three';
|
||||
import TextMaterial from '../../../geom/material/textMaterial';
|
||||
export default function DawText(attributes, style) {
|
||||
const geometry = new THREE.BufferGeometry();
|
||||
const { strokeWidth, stroke, opacity } = style;
|
||||
geometry.addAttribute('position', new THREE.Float32BufferAttribute(attributes.originPoints, 3));
|
||||
geometry.addAttribute('uv', new THREE.Float32BufferAttribute(attributes.textureElements, 2));
|
||||
geometry.addAttribute('a_txtsize', new THREE.Float32BufferAttribute(attributes.textSizes, 2));
|
||||
geometry.addAttribute('a_txtOffsets', new THREE.Float32BufferAttribute(attributes.textOffsets, 2));
|
||||
geometry.addAttribute('a_color', new THREE.Float32BufferAttribute(attributes.colors, 4));
|
||||
const material = new TextMaterial({
|
||||
name: this.layerId,
|
||||
u_texture: buffer.bufferStruct.textTexture,
|
||||
u_strokeWidth: 1,
|
||||
u_stroke: stroke,
|
||||
u_textSize: buffer.bufferStruct.textSize,
|
||||
u_gamma: 0.11,
|
||||
u_buffer: 0.8,
|
||||
u_color: color,
|
||||
u_glSize: [ width, height ]
|
||||
});
|
||||
const mesh = new THREE.Mesh(geometry, material);
|
||||
}
|
||||
// import * as THREE from '../../../core/three';
|
||||
// import TextMaterial from '../../../geom/material/textMaterial';
|
||||
// export default function DawText(attributes, texture, style) {
|
||||
// const geometry = new THREE.BufferGeometry();
|
||||
// const { strokeWidth, stroke, opacity } = style;
|
||||
// geometry.addAttribute('position', new THREE.Float32BufferAttribute(attributes.originPoints, 3));
|
||||
// geometry.addAttribute('uv', new THREE.Float32BufferAttribute(attributes.textureElements, 2));
|
||||
// geometry.addAttribute('a_txtsize', new THREE.Float32BufferAttribute(attributes.textSizes, 2));
|
||||
// geometry.addAttribute('a_txtOffsets', new THREE.Float32BufferAttribute(attributes.textOffsets, 2));
|
||||
// geometry.addAttribute('a_color', new THREE.Float32BufferAttribute(attributes.colors, 4));
|
||||
// const material = new TextMaterial({
|
||||
// name: this.layerId,
|
||||
// u_texture: texture,
|
||||
// u_strokeWidth: 1,
|
||||
// u_stroke: stroke,
|
||||
// u_textSize: buffer.bufferStruct.textSize,
|
||||
// u_gamma: 0.11,
|
||||
// u_buffer: 0.8,
|
||||
// u_color: color,
|
||||
// u_glSize: [ width, height ]
|
||||
// });
|
||||
// const mesh = new THREE.Mesh(geometry, material);
|
||||
// }
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
import * as THREE from '../../../core/three';
|
||||
import PolygonMaterial from '../../../geom/material/polygonMaterial';
|
||||
export default function DrawAnimate(attributes, style) {
|
||||
const { opacity, baseColor, brightColor, windowColor, near, far } = style;
|
||||
const geometry = new THREE.BufferGeometry();
|
||||
geometry.addAttribute('position', new THREE.Float32BufferAttribute(attributes.vertices, 3));
|
||||
geometry.addAttribute('a_color', new THREE.Float32BufferAttribute(attributes.colors, 4));
|
||||
geometry.addAttribute('pickingId', new THREE.Float32BufferAttribute(attributes.pickingIds, 1));
|
||||
geometry.addAttribute('normal', new THREE.Float32BufferAttribute(attributes.normals, 3));
|
||||
geometry.addAttribute('faceUv', new THREE.Float32BufferAttribute(attributes.faceUv, 2));
|
||||
geometry.addAttribute('a_size', new THREE.Float32BufferAttribute(attributes.sizes, 1));
|
||||
const material = new PolygonMaterial({
|
||||
u_opacity: opacity,
|
||||
u_baseColor: baseColor,
|
||||
u_brightColor: brightColor,
|
||||
u_windowColor: windowColor,
|
||||
u_near: near,
|
||||
u_far: far
|
||||
}, {
|
||||
SHAPE: false,
|
||||
ANIMATE: true
|
||||
});
|
||||
const fillPolygonMesh = new THREE.Mesh(geometry, material);
|
||||
this.fillPolygonMesh = fillPolygonMesh;
|
||||
return fillPolygonMesh;
|
||||
}
|
||||
|
||||
DrawAnimate.prototype.updateStyle = function(style) {
|
||||
this.fillPolygonMesh.material.upDateUninform({
|
||||
u_opacity: style.opacity,
|
||||
u_baseColor: style.baseColor,
|
||||
u_brightColor: style.brightColor,
|
||||
u_windowColor: style.windowColor
|
||||
});
|
||||
};
|
|
@ -0,0 +1,18 @@
|
|||
import * as THREE from '../../../core/three';
|
||||
import PolygonMaterial from '../../../geom/material/polygonMaterial';
|
||||
export default function DrawPolygonFill(attributes, style) {
|
||||
const { opacity } = style;
|
||||
const geometry = new THREE.BufferGeometry();
|
||||
geometry.addAttribute('position', new THREE.Float32BufferAttribute(attributes.vertices, 3));
|
||||
geometry.addAttribute('a_color', new THREE.Float32BufferAttribute(attributes.colors, 4));
|
||||
geometry.addAttribute('pickingId', new THREE.Float32BufferAttribute(attributes.pickingIds, 1));
|
||||
geometry.addAttribute('normal', new THREE.Float32BufferAttribute(attributes.normals, 3));
|
||||
const material = new PolygonMaterial({
|
||||
u_opacity: opacity
|
||||
}, {
|
||||
SHAPE: false
|
||||
});
|
||||
const fillPolygonMesh = new THREE.Mesh(geometry, material);
|
||||
return fillPolygonMesh;
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
import * as THREE from '../../../core/three';
|
||||
import { LineMaterial } from '../../../geom/material/lineMaterial';
|
||||
export default function DrawPolygonLine(attributes, style) {
|
||||
const { opacity } = style;
|
||||
const geometry = new THREE.BufferGeometry();
|
||||
geometry.addAttribute('position', new THREE.Float32BufferAttribute(attributes.vertices, 3));
|
||||
geometry.addAttribute('a_color', new THREE.Float32BufferAttribute(attributes.colors, 4));
|
||||
geometry.addAttribute('pickingId', new THREE.Float32BufferAttribute(attributes.pickingIds, 1));
|
||||
const lineMaterial = new LineMaterial({
|
||||
u_opacity: opacity
|
||||
}, {
|
||||
SHAPE: false
|
||||
});
|
||||
const polygonLineMesh = new THREE.LineSegments(geometry, lineMaterial);
|
||||
return polygonLineMesh;
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
export { default as DrawAnimate } from './drawAnimate';
|
||||
export { default as DrawFill } from './drawFill';
|
||||
export { default as DrawLine } from './drawLine';
|
|
@ -1,6 +1,5 @@
|
|||
import Source from '../core/source';
|
||||
import FeatureIndex from '../geo/featureIndex';
|
||||
import Util from '../util';
|
||||
import { csvParse } from 'd3-dsv';
|
||||
export default class CSVSource extends Source {
|
||||
prepareData() {
|
||||
|
@ -14,7 +13,7 @@ export default class CSVSource extends Source {
|
|||
this.propertiesData = [];// 临时使用
|
||||
this.geoData = [];
|
||||
let csvdata = data;
|
||||
Util.isArray(csvdata) || (csvdata = csvParse(data));
|
||||
Array.isArray(csvdata) || (csvdata = csvParse(data));
|
||||
this.propertiesData = csvdata;
|
||||
csvdata.forEach((col, featureIndex) => {
|
||||
let coordinates = [];
|
||||
|
|
|
@ -1,22 +1,2 @@
|
|||
import { getJSON } from '../util/ajax';
|
||||
import { GeojsonSource } from '../source/geojsonSource';
|
||||
const EventEmitter = require('wolfy87-eventemitter');
|
||||
export class geoJsonSourceWorker extends EventEmitter {
|
||||
constructor(cfg) {
|
||||
super();
|
||||
this.source = new GeojsonSource(cfg);
|
||||
}
|
||||
_loadData(url) {
|
||||
const data = this.source.get('data');
|
||||
if (typeof (data) === 'string') {
|
||||
this.emit('dataLoading');
|
||||
getJSON(url, data => {
|
||||
this.emit('dataLoaded', { data });
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1,13 +1,4 @@
|
|||
const extrude = require('geometry-extrude');
|
||||
// import { geoJsonSourceWorker } from './geojsonSourceWorker';
|
||||
/**
|
||||
* workerOption
|
||||
* {
|
||||
* type:
|
||||
* data:
|
||||
*
|
||||
* }
|
||||
*/
|
||||
|
||||
self.addEventListener('message', e => {
|
||||
const res = e.data;
|
||||
// res = {
|
||||
|
@ -17,12 +8,8 @@ self.addEventListener('message', e => {
|
|||
let result;
|
||||
switch (res.command) {
|
||||
case 'geojson':
|
||||
result = extrude.extrudeGeoJSON(res.data.data, res.data.options).polygon;
|
||||
self.postMessage(result, [ result.indices.buffer, result.normal.buffer, result.position.buffer, result.uv.buffer ]);
|
||||
break;
|
||||
case 'POLYLINE-EXTRUDE':
|
||||
result = extrude.extrudeGeoJSON(res.data.data, res.data.options).polyline;
|
||||
self.postMessage(result, [ result.indices.buffer, result.normal.buffer, result.position.buffer, result.uv.buffer ]);
|
||||
result = res;
|
||||
self.postMessage(result);
|
||||
break;
|
||||
default:
|
||||
self.postMessage(result);
|
||||
|
|
|
@ -30,6 +30,16 @@ module.exports = {
|
|||
loader: 'glsl-shaders-loader'
|
||||
}
|
||||
},
|
||||
{
|
||||
test: /\.worker\.js$/,
|
||||
use: {
|
||||
loader: 'worker-loader',
|
||||
options: {
|
||||
inline: true,
|
||||
fallback: false
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
test: /global\.js$/,
|
||||
use: {
|
||||
|
|