feat(src):textLayer

This commit is contained in:
李正学 2018-10-30 11:22:18 +08:00
parent e75f215625
commit 9c517998aa
77 changed files with 527 additions and 1607 deletions

View File

@ -6,3 +6,4 @@ mocks/
node_modules/
demos/assets/
demos/index.html
demos/*

View File

@ -20,13 +20,12 @@
<script src="../build/L7.js"></script>
<script>
const color1 = [ 'rgba(37, 140, 249, 0.8)', 'rgba(14, 241, 242, 0.8)', 'rgba(255, 255, 255, 0.8)' ];
const scene = new L7.Scene({
id: 'map',
mapStyle: 'amap://styles/5a64d4f1af910091f9cc3367dfc4a1dc', // 样式URL
mapStyle: 'light', // 样式URL
center: [ 120.19382669582967, 30.258134 ],
pitch: 0,
zoom: 12.6
zoom: 14.6
});
window.scene = scene;
scene.on('load', () => {
@ -36,11 +35,11 @@ scene.on('load', () => {
})
.source(data)
.shape('2d:circle')
.size('value', [ 8, 80 ]) // default 1
.size('value', [ 8, 500 ]) // default 1
.filter('value', field_8 => {
return field_8 * 1 > 500;
})
.color('type', [ '#002466', '#0D408C', '#105CB3', '#1A76C7', '#2894E0', '#3CB4F0', '#65CEF7', '#98E3FA', '#CFF6FF', '#E8FCFF' ])
.color('type', [ '#ffffd4', '#fed98e', '#fe9929', '#d95f0e', '#993404' ].reverse())
.style({
stroke: 'rgb(255,255,255)',
strokeWidth: 1,

View File

@ -23,7 +23,7 @@
const color1 = [ 'rgba(37, 140, 249, 0.8)', 'rgba(14, 241, 242, 0.8)', 'rgba(255, 255, 255, 0.8)' ];
const scene = new L7.Scene({
id: 'map',
mapStyle: 'amap://styles/5a64d4f1af910091f9cc3367dfc4a1dc', // 样式URL
mapStyle: 'dark', // 样式URL
center: [ 121.51222019389274, 31.23572578718841 ],
pitch: 0,
zoom: 11
@ -39,32 +39,7 @@ scene.on('load', () => {
y: 'lat',
x: 'lng'
})
.shape('2d:circle')
.size(2.0)
/**
.size('name*zoom', function(name, zoom) {
if (zoom < 7) {
return 1;
} else if (zoom < 9) {
return 10;
} else if (zoom < 12) {
return 15;
}
return 50;
})
.color('count', function(count) {
if (count < 3) {
return color1[0];
} else if (count < 15) {
return color1[1];
}
return color1[2];
})
**/
.color('#0198BD')
.style({
stroke: 'rgb(255,255,255)',

59
demos/01_point_image.html Normal file
View File

@ -0,0 +1,59 @@
<!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">
<title>point_distribute</title>
<style>
#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 color1 = [ 'rgba(37, 140, 249, 0.8)', 'rgba(14, 241, 242, 0.8)', 'rgba(255, 255, 255, 0.8)' ];
const scene = new L7.Scene({
id: 'map',
mapStyle: 'light', // 样式URL
center: [ 120.1243238, 30.27331571 ],
pitch: 0,
zoom: 19,
minZoom: 16
});
window.scene = scene;
scene.image.addImage('bike', './image/Bike.png');
scene.on('load', () => {
$.get('./data/bike.json', data => {
scene.PointLayer({
zIndex: 2
})
.source(data.object, {
type: 'array',
y: 'distY',
x: 'distX'
})
.size(128.0)
.shape('image:bike')
.color('#0198BD')
.style({
stroke: 'rgb(255,255,255)',
strokeWidth: 0,
opacity: 1.0
})
.render();
});
});
</script>
</body>
</html>

View File

@ -23,7 +23,7 @@
const color1 = [ 'rgba(37, 140, 249, 0.8)', 'rgba(14, 241, 242, 0.8)', 'rgba(255, 255, 255, 0.8)' ];
const scene = new L7.Scene({
id: 'map',
mapStyle: 'amap://styles/5a64d4f1af910091f9cc3367dfc4a1dc', // 样式URL
mapStyle: 'dark', // 样式URL
center: [ 116.2825, 39.9 ],
pitch: 0,
zoom: 3

View File

@ -23,10 +23,12 @@
const color1 = [ 'rgba(37, 140, 249, 0.8)', 'rgba(14, 241, 242, 0.8)', 'rgba(255, 255, 255, 0.8)' ];
const scene = new L7.Scene({
id: 'map',
mapStyle: 'amap://styles/5a64d4f1af910091f9cc3367dfc4a1dc', // 样式URL
mapStyle: 'dark', // 样式URL
center: [ 116.2825, 39.9 ],
pitch: 0,
zoom: 3
zoom: 5,
minZoom: 5,
maxZoom: 10
});
scene.on('load', () => {
$.get('https://gw.alipayobjects.com/os/rmsportal/lZGtNaYGNHtAIkcjVvfp.json', data => {

View File

@ -27,7 +27,7 @@ customContainer.appendChild(gui.domElement);
const province = { 全国: '00', 新疆维吾尔自治区: '65', 西藏自治区: '54', 内蒙古自治区: '15', 青海省: '63', 四川省: '51', 黑龙江省: '23', 甘肃省: '62', 云南省: '53', 广西壮族自治区: '45', 湖南省: '43', 陕西省: '61', 广东省: '44', 吉林省: '22', 河北省: '13', 湖北省: '42', 贵州省: '52', 山东省: '37', 江西省: '36', 河南省: '41', 辽宁省: '21', 山西省: '14', 安徽省: '34', 福建省: '35', 浙江省: '33', 江苏省: '32', 重庆市: '50', 宁夏回族自治区: '64', 海南省: '46', 台湾省: '71', 北京市: '11', 天津市: '12', 上海市: '31', 香港特别行政区: '81', 澳门特别行政区: '82' };
const scene = new L7.Scene({
id: 'map',
mapStyle: 'amap://styles/5a64d4f1af910091f9cc3367dfc4a1dc', // 样式URL
mapStyle: 'dark', // 样式URL
center: [ 120.4047, 30.0679 ],
pitch: 35,
zoom: 4

View File

@ -27,7 +27,7 @@ customContainer.appendChild(gui.domElement);
const province = { 全国: '00', 新疆维吾尔自治区: '65', 西藏自治区: '54', 内蒙古自治区: '15', 青海省: '63', 四川省: '51', 黑龙江省: '23', 甘肃省: '62', 云南省: '53', 广西壮族自治区: '45', 湖南省: '43', 陕西省: '61', 广东省: '44', 吉林省: '22', 河北省: '13', 湖北省: '42', 贵州省: '52', 山东省: '37', 江西省: '36', 河南省: '41', 辽宁省: '21', 山西省: '14', 安徽省: '34', 福建省: '35', 浙江省: '33', 江苏省: '32', 重庆市: '50', 宁夏回族自治区: '64', 海南省: '46', 台湾省: '71', 北京市: '11', 天津市: '12', 上海市: '31', 香港特别行政区: '81', 澳门特别行政区: '82' };
const scene = new L7.Scene({
id: 'map',
mapStyle: 'amap://styles/5a64d4f1af910091f9cc3367dfc4a1dc', // 样式URL
mapStyle: 'light', // 样式URL
center: [ 120.4047, 30.0679 ],
pitch: 0,
zoom: 4

View File

@ -14,30 +14,42 @@
</head>
<body>
<div id = 'gui' style="position:absolute;top:0px;right:0px;z-index:2;"></div>
<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 gui = new dat.GUI({ autoPlace: false });
const customContainer = document.getElementById('gui');
customContainer.appendChild(gui.domElement);
const scene = new L7.Scene({
id: 'map',
mapStyle: 'amap://styles/ba3e9759545cd618392ef073c0dfda8c?isPublic=true', // 样式URL
center: [ 120.4047, 30.0679 ],
mapStyle: 'dark', // 样式URL
center: [ 110.770672, 34.159869 ],
pitch: 45,
zoom: 4
zoom: 5,
minZoom: 4,
maxZoom: 10
});
scene.on('load', () => {
$.getJSON('https://gw.alipayobjects.com/os/rmsportal/JToMOWvicvJOISZFCkEI.json', city => {
citylayer = scene.PolygonLayer({
zIndex: 10
})
.source(city)
.color('#fff')
.shape('line')
// .active({ fill: 'red' })
.style({
opacity: 1
})
.render();
});
// https://gw.alipayobjects.com/zos/rmsportal/wAQqmdcWOPdomuKUyHDF.png
const imageLayer = scene.ImageLayer().
source({
url: 'https://gw.alipayobjects.com/zos/rmsportal/wAQqmdcWOPdomuKUyHDF.png',
extent: [ 73, 18, 136, 54 ]
})
.render();

74
demos/05_raster_dem.html Normal file
View File

@ -0,0 +1,74 @@
<!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">
<title>dem demo</title>
<style>
#map { position:absolute; top:0; bottom:0; width:100%; }
</style>
</head>
<body>
<div id = 'gui' style="position:absolute;top:0px;right:0px;z-index:2;"></div>
<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/geotiff.browserify.min.js"></script>
<script src="../build/L7.js"></script>
<script>
const scene = new L7.Scene({
id: 'map',
viewMode: '3D',
mapStyle: 'amap://styles/ba3e9759545cd618392ef073c0dfda8c?isPublic=true', // 样式URL
center: [ 110.770672, 34.159869 ],
pitch: 0,
zoom: 4
});
scene.on('load', () => {
const xhr = new XMLHttpRequest();
xhr.open('GET', ' https://gw.alipayobjects.com/os/rmsportal/XKgkjjGaAzRyKupCBiYW.dat', true);
xhr.responseType = 'arraybuffer';
xhr.onload = function(e) {
if (this.status === 200) {
// get binary data as a response
const blob = this.response;
const tiff = GeoTIFF.parse(blob);
const image = tiff.getImage();
const values = image.readRasters()[0];
const m = image.getHeight();
const n = image.getWidth();
const layer = scene.RasterLayer({ zIndex: 2 }).
source(values, {
type: 'raster',
width: n,
height: m,
min: 0,
max: 8000,
extent: [ 73.482190241, 3.82501784112, 135.106618732, 57.6300459963 ]
})
.style({
rampColors: {
colors: [ '#002466', '#0D408C', '#105CB3', '#1A76C7', '#2894E0', '#3CB4F0', '#65CEF7', '#98E3FA', '#CFF6FF', '#E8FCFF' ],
positions: [ 0, 0.02, 0.05, 0.1, 0.2, 0.3, 0.5, 0.6, 0.8, 1.0 ]
}
})
.render();
}
};
xhr.send();
});
</script>
</body>
</html>

53
demos/06_text.html Normal file
View File

@ -0,0 +1,53 @@
<!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">
<title>point_circle</title>
<style>
#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: [ 120.19382669582967, 30.258134 ],
pitch: 0,
zoom: 3
});
window.scene = scene;
scene.on('load', () => {
$.get('./data/provincePoint.geojson', data => {
scene.PointLayer({
zIndex: 2
})
.source(data)
.shape('name', 'text')
.size(10) // default 1
.color('name', [ '#ffffd4', '#fed98e', '#fe9929', '#d95f0e', '#993404' ].reverse())
.style({
stroke: '#999',
strokeWidth: 2,
color: '#fff',
opacity: 0.9
})
.render();
});
});
</script>
</body>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 179 KiB

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 KiB

After

Width:  |  Height:  |  Size: 1016 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 499 KiB

After

Width:  |  Height:  |  Size: 502 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 KiB

After

Width:  |  Height:  |  Size: 187 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 222 KiB

After

Width:  |  Height:  |  Size: 234 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 164 KiB

After

Width:  |  Height:  |  Size: 378 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 303 KiB

After

Width:  |  Height:  |  Size: 612 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 496 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 422 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 892 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 367 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 395 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 738 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 282 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 160 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 161 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 KiB

View File

@ -1,11 +0,0 @@
class Geometry extends BufferGeometry {
constructor() {
super();
}
updateAttribute(name, startIndex, size, value) {
const attribute = this.attributes[name];
for (let i = 0; i < size; i++) {
attribute.array[startIndex + i] = value[i];
}
}
}

View File

@ -11,8 +11,10 @@ export default class Engine extends EventEmitter {
this._renderer = new Renderer(container).renderer;
this._world = world;
this._picking = Picking(this._world, this._renderer, this._camera, this._scene);
this._renderer.context.getExtension('OES_texture_float');
this._renderer.context.getExtension('OES_texture_float_linear');
// this._renderer.context.getExtension('OES_texture_float');
// this._renderer.context.getExtension('OES_texture_float_linear');
this._renderer.context.getExtension('OES_texture_half_float');
this._renderer.context.getExtension('OES_texture_half_float_linear');
}
_initPostProcessing() {

View File

@ -10,7 +10,7 @@ export class RenderPass {
this._init(cfg);
}
_init(cfg) {
_init() {
this.scene = new THREE.Scene();
const parameters = { minFilter: THREE.NearestFilter,
magFilter: THREE.NearestFilter,
@ -19,7 +19,7 @@ export class RenderPass {
depthBuffer: false
};
const size = this.renderer.getSize();
this.pass = new THREE.WebGLRenderTarget(512, 512, parameters);
this.pass = new THREE.WebGLRenderTarget(size.width, size.height, parameters);
this.originClearColor = this.renderer.getClearColor();
this.originClearAlpha = this.renderer.getClearAlpha();
this.texture = this.pass.texture;

View File

@ -1,15 +1,16 @@
import * as THREE from './three';
import EventEmitter from 'wolfy87-eventemitter';
import { getImage } from '../util/ajax';
export default class LoadImage {
export default class LoadImage extends EventEmitter {
constructor() {
super();
this.canvas = document.createElement('canvas');
this.ctx = this.canvas.getContext('2d');
this.imageWidth = 64;
this.canvas.width = this.imageWidth * 8;
this.canvas.height = this.imageWidth * 8;
this.images = [];
this.imagesCount = -1;
this.imagesCount = 0;
this.imagePos = {};
}
addImage(id, opt) {
@ -29,6 +30,9 @@ export default class LoadImage {
texture.needsUpdate = true;
this.texture = texture;
this.imagePos[id] = { x: x / 512, y: y / 512 };
if (this.images.length === this.imagesCount) {
this.emit('imageLoaded');
}
});
} else {
const { width, height, channels } = opt;
@ -40,8 +44,11 @@ export default class LoadImage {
image.id = id;
this.images.push(image);
this.ctx.drawImage(image, x, y, 64, 64);
this.texture = new CanvasTexture(this.canvas);
this.texture = new THREE.CanvasTexture(this.canvas);
this.imagePos[id] = { x: x >> 9, y: y >> 9 };
if (this.images.length === this.imagesCount) {
this.emit('imageLoaded');
}
}
}

View File

@ -60,14 +60,14 @@ export default class Layer extends Base {
this.layerId = layerId;
this._activeIds = null;
// todo 用户参数
this._object3D.position.z = layerId * 1000;
this._object3D.position.z = layerId;
scene._engine._scene.add(this._object3D);
this.layerMesh = null;
}
/**
* 将图层添加加到Object
* @param {*} object
* 将图层添加加到 Object
* @param {*} object three 物体
*/
add(object) {
this.layerMesh = object;
@ -136,7 +136,7 @@ export default class Layer extends Base {
}
style(field, cfg) {
const colorItem = [ 'fill', 'stroke' ];
const colorItem = [ 'fill', 'stroke', 'color' ];
let styleOptions = this.get('styleOptions');
if (!styleOptions) {
styleOptions = {};
@ -153,7 +153,7 @@ export default class Layer extends Base {
styleOptions.fields = fields;
Util.assign(styleOptions, cfg);
for (const item in cfg) {
if (colorItem.indexOf(item) != -1) {
if (colorItem.indexOf(item) !== -1) {
styleOptions[item] = ColorUtil.color2RGBA(styleOptions[item]);
}
styleOptions[item] = styleOptions[item];
@ -474,6 +474,9 @@ export default class Layer extends Base {
filterData.forEach((item,index)=>{
const color = [ ...this.StyleData[index].color ];
if (item.hasOwnProperty('filter') && item.filter === false) {
color[0] = 0;
color[1] = 0;
color[2] = 0;
color[3] = 0;
}
colorAttr.array[index*4+0]=color[0];

View File

@ -5,7 +5,6 @@ import Base from './base';
import LoadImage from './image';
import Utils from '../util';
import { MapProvider } from '../map/provider';
import { MapBox } from '../map/mapbox';
import AMap from '../map/AMap';
import Global from '../global';
export default class Scene extends Base {
@ -28,26 +27,19 @@ export default class Scene extends Base {
this._engine._picking.add(object);
}
_initMap() {
const mapType = this.mapType = this.get('mapType');
this.mapContainer = this.get('id');
this._container = document.getElementById(this.mapContainer);
let Map = null;
if (mapType === 'mapbox') {
Map = new MapBox(this.mapContainer, this.get('map'));
} else {
Map = new MapProvider(this.mapContainer, this._attrs);
}
const Map = new MapProvider(this.mapContainer, this._attrs);
Map.on('mapLoad', () => {
this._initEngine(Map.renderDom);
const sceneMap = new AMap(Map.map);
// eslint-disable-next-line
Utils.assign(this.__proto__, sceneMap.__proto__);
this.map = Map.map;
Map.asyncCamera(this._engine);
// this._addLight();
this.initLayer();
// this.zoomAsync();
this.emit('load');
this.emit('loaded');
});
}

View File

@ -1,101 +0,0 @@
import Engine from './engine';
import * as layers from '../layer';
import Base from './base';
import ImageData from './image';
import ModelData from './model';
import { MapProvider } from '../map/provider';
import { MapBox } from '../map/mapbox';
/**
* const scene = new L7.Scene({
* container:'',
*
* map:{
* }
* })
*/
export default class Scene extends Base {
getDefaultCfg() {
return {
mapType: 'AMAP'
};
}
constructor(cfg) {
super(cfg);
this.mapContainer = this.get('id');
this.layers = [];
this.render = new Render();
this._engine = new Engine(this.mapContainer);
this.initMap();
this.addImage();
this.addModel(this.render);
}
initMap() {
const mapType = this.mapType = this.get('mapType');
let Map = null;
if (mapType === 'mapbox') {
Map = new MapBox(this.mapContainer, this.get('map'));
} else {
Map = new MapProvider(this.mapContainer, this.get('map'));
}
Map.on('mapLoad', () => {
this.renderCanvas = Map.canvas;
this.map = Map.map;
this.render.initScene(this.renderCanvas);
this.addModel();
Map.asyncCamera(this.render.camera, this.render.cameraNode, this.render.layerNode);
this.initLayer();
this.zoomAsync();
this.emit('load');
});
}
initLayer() {
for (const methodName in layers) {
this[methodName] = cfg => {
cfg ? cfg.mapType = this.mapType : cfg = { mapType: this.mapType };
const layer = new layers[methodName](this, cfg);
this.layers.push(layer);
return layer;
};
}
}
removeLayer(layer) {
layer.layerNode.destroy();
this.layers = this.layers.filter(item => {
return item.layerId != layer.layerId;
});
}
getLayers() {
return this.layers;
}
getLayer() {
}
addImage() {
this.image = new ImageData();
}
addModel() {
this.Model = new ModelData(this.render);
}
zoomAsync() {
this.map.on('zoomend', () => {
this.layers.forEach(layer => {
const id = layer.layerId;
const layerNode = this.render.layerNode.findChildByName(id);
const zoom = this.map.getZoom();
const minZoom = layer.get('minZoom');
const maxZoom = layer.get('maxZoom');
if (zoom < minZoom || zoom > maxZoom) {
layerNode.isActive = false;
} else {
layerNode.isActive = true;
}
});
});
}
}

View File

@ -2,12 +2,11 @@
* @Author: ThinkGIS
* @Date: 2018-06-08 11:19:06
* @Last Modified by: mikey.zhaopeng
* @Last Modified time: 2018-10-23 16:20:56
* @Last Modified time: 2018-10-30 11:13:39
*/
const Base = require('./base');
const Controller = require('./controller/index');
import { aProjectFlat } from '../geo/project';
const MAXZOOM = 0;
export default class Source extends Base {
getDefaultCfg() {
return {
@ -83,14 +82,9 @@ export default class Source extends Base {
});
}
_coorConvert(geo) {
const maptype = this.get('mapType');
if (maptype === 'AMAP') {
const ll = aProjectFlat(geo);
return [ ll.x, -ll.y, geo[2] || 0 ];
}
// const ll = projectFlat(geo, Math.pow(2, MAXZOOM));
// return [ ll[0], -ll[1], geo[2] || 0 ];
const ll = aProjectFlat(geo);
return [ ll.x, -ll.y, geo[2] || 0 ];
}

View File

@ -69,24 +69,12 @@ export default class BufferBase extends Base {
const normals = new Float32Array(indexCount * 3);
const colors = new Float32Array(indexCount * 4);
const pickingIds = new Float32Array(indexCount);
// TODO:拾取
// const pickingIds;
// if (polygon.pickingId) {
// // One component per vertex per face (1 x 3 = 3)
// pickingIds = new Float32Array(polygon.facesCount * 3);
// }
const pA = new THREE.Vector3();
const pB = new THREE.Vector3();
const pC = new THREE.Vector3();
const cb = new THREE.Vector3();
const ab = new THREE.Vector3();
let index;
let lastIndex = 0;
indices.forEach((indice, pIndex) => {
for (let i = 0; i < indice.length / 3; i++) {
@ -188,7 +176,6 @@ export default class BufferBase extends Base {
return attributes;
}
_toPolygonLineAttributes(polygonline) {
console.log(polygonline);
const { style, indices, position, indexCount } = polygonline;
const vertices = new Float32Array(indexCount * 3);
const colors = new Float32Array(indexCount * 4);

View File

@ -22,7 +22,7 @@ export default class PointBuffer extends BufferBase {
case 'Model':this._ModelBuffer();
break;
default:
this._3dRegularBuffer();
this._2dRegularBuffer();
}
}

View File

@ -1,107 +0,0 @@
import BufferBase from './bufferBase';
import * as THREE from '../../core/three';
import { colorScales } from '../../attr/colorscales';
export class RainBuffer extends BufferBase {
geometryBuffer() {
const defaultRampColors = {
0.0: '#3288bd',
0.1: '#66c2a5',
0.2: '#abdda4',
0.3: '#e6f598',
0.4: '#fee08b',
0.5: '#fdae61',
0.6: '#f46d43',
1.0: '#d53e4f'
};
const coordinates = this.get('coordinates');
const particleImage1 = this.get('particleImage1');
const particleImage0 = this.get('particleImage0');
const backgroundImage = this.get('backgroundImage');
const extent = this.get('extent');
const imgPos = [ ...extent[0],
extent[1][0], extent[0][1], 0,
...extent[1],
...extent[0],
...extent[1],
extent[0][0], extent[1][1], 0
];
const imgPosUv = [ 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0 ];
const image = this.get('image');
this.bufferStruct.particleStateTexture0 = this._getTexture(particleImage0, THREE.NearestFilter);
this.bufferStruct.particleStateTexture1 = this._getTexture(particleImage1, THREE.NearestFilter);
this.bufferStruct.backgroundTexture = this._getTexture(backgroundImage, THREE.NearestFilter);
const texture = this._getTexture(image, THREE.NearestFilter);
const colorImageData = this.getColorRamp('wind');
const colorTexture = this._getTexture(colorImageData, THREE.LinearFilter);
this.bufferStruct.position = coordinates;
this.bufferStruct.imgPos = imgPos;
this.bufferStruct.imgPosUv = imgPosUv;
this.bufferStruct.u_wind = texture;// 风速 风向
this.bufferStruct.colorTexture = colorTexture; // 颜色表‘=
const attributes = {
vertices: new Float32Array(imgPos),
uvs: new Float32Array(imgPosUv)
};
this.attributes = attributes;
}
// //生成色带纹理
// getColorRamp(colors) {
// const canvas = document.createElement('canvas');
// const ctx = canvas.getContext('2d');
// canvas.width = 256;
// canvas.height = 1;
// const gradient = ctx.createLinearGradient(0, 0, 256, 0);
// for (const stop in colors) {
// gradient.addColorStop(+stop, colors[stop]);
// }
// ctx.fillStyle = gradient;
// ctx.fillRect(0, 0, 256, 1);
// const data = new Uint8ClampedArray(ctx.getImageData(0, 0, 256, 1).data);
// return new ImageData(data, 16, 16);
// }
getColorRamp(name) {
let colorscale = name;
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
canvas.width = 256;
canvas.height = 1;
const gradient = ctx.createLinearGradient(0, 0, 256, 0);
let data = null;
if (typeof (colorscale) === 'string') {
colorscale = colorScales[name];
}
if (Object.prototype.toString.call(colorscale) === '[object Object]') {
const min = colorscale.positions[0];
const max = colorscale.positions[colorscale.positions.length - 1];
for (let i = 0; i < colorscale.colors.length; ++i) {
const value = (colorscale.positions[i] - min) / (max - min);
gradient.addColorStop(value, colorscale.colors[i]);
}
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, 256, 1);
data = new Uint8ClampedArray(ctx.getImageData(0, 0, 256, 1).data);
}
if (Object.prototype.toString.call(colorscale) === '[object Uint8Array]') {
data = ctx.createImageData(256, 1);
}
return new ImageData(data, 16, 16);
}
// 生成纹理
_getTexture(image, filter) {
const texture = new THREE.Texture(image);
texture.magFilter = filter;
texture.minFilter = filter;
texture.needsUpdate = true;
return texture;
}
}

View File

@ -18,9 +18,8 @@ export class RasterBuffer extends BufferBase {
const size = this.get('size');
const texture = new THREE.DataTexture(new Float32Array(raster.data), raster.width, raster.height, THREE.LuminanceFormat, THREE.FloatType);
texture.generateMipmaps = true;
// texture.minFilter = THREE.NearestFilter;
texture.needsUpdate = true;
const colors = this.get('rampColors') || defaultRampColors;
const colors = this.get('rampColors');
const colorImageData = this.getColorRamp(colors);
const colorTexture = this._getTexture(colorImageData);
this.bufferStruct.position = positions;
@ -29,7 +28,7 @@ export class RasterBuffer extends BufferBase {
this.bufferStruct.u_extent = [ coordinates[0][0], coordinates[0][1], coordinates[1][0], coordinates[1][1] ];
this.bufferStruct.u_colorTexture = colorTexture; // 颜色表‘=
const triangles = this._buildTriangles(raster, size);
const triangles = this._buildTriangles(raster, size, this.bufferStruct.u_extent);
const attributes = {
vertices: new Float32Array(triangles.vertices),
uvs: new Float32Array(triangles.uvs),
@ -79,39 +78,35 @@ export class RasterBuffer extends BufferBase {
texture1.needsUpdate = true;
return texture1;
}
_buildTriangles(raster, size = 1) {
_buildTriangles(raster, size = 1, extent) {
// const extent = [ 73.482190241, 3.82501784112, 135.106618732, 57.6300459963 ]
const { width, height } = raster;
const halfSize = size / 2;
const indices = [];
const vertices = [];
const normals = [];
const uvs = [];
const gridX = Math.floor(width / size);
const gridY = Math.floor(height / size);
const gridX1 = gridX + 1;
const gridY1 = gridY + 1;
const stepX = (extent[2] - extent[0]) / gridX1;
const stepY = (extent[3] - extent[1]) / gridY1;
for (let i = 0; i < gridY1; i++) {
const y = i * size - halfSize;
const y = i * size;
for (let j = 0; j < gridX1; j++) {
const x = j * size - halfSize;
vertices.push(x / gridX, -y / gridY, 0);
const x = j * size;
vertices.push(extent[0] + x * stepX, (height - y) * stepY + extent[1], 0);
uvs.push(j / gridX);
uvs.push(i / gridY);
uvs.push(i / gridY);
}
}
for (let iy = 0; iy < gridY; iy++) {
for (let ix = 0; ix < gridX; ix++) {
const a = ix + gridX1 * iy;
const b = ix + gridX1 * (iy + 1);
const c = (ix + 1) + gridX1 * (iy + 1);
const d = (ix + 1) + gridX1 * iy;
indices.push(a, b, d);
indices.push(b, c, d);
}
}

View File

@ -1,7 +1,6 @@
import BufferBase from './bufferBase';
import { Texture2D } from '../../core/three';
import { TextureFilter, TextureWrapMode } from '@ali/r3-base';
import { getJSON, getImage } from '../../util/ajax';
import * as THREE from '../../core/three';
import Global from '../../global';
const Space = 1;
export default class TextBuffer extends BufferBase {
@ -14,13 +13,10 @@ export default class TextBuffer extends BufferBase {
};
const coordinates = this.get('coordinates');
const properties = this.get('properties');
const style = this.get('style');
const { size = 24 } = style;
const chars = [];
const positions = [];
const uvs = [];
properties.forEach(element => {
const text = element.shape;
for (let j = 0; j < text.length; j++) {
const code = text.charCodeAt(j);
if (chars.indexOf(code) === -1) {
@ -29,30 +25,32 @@ export default class TextBuffer extends BufferBase {
}
});
this.on('SourceLoaded', () => {
let indexCount = 0;
const textureElements = [];
const colors = [];
const originPoints = [];
const textSizes = [];
const textOffsets = [];
properties.forEach((element, index) => {
const text = element.shape;
const size = element.size;
const pos = coordinates[index];
const dimensions = this._measureText(text, size);
// const pen = { x: pos[0] - dimensions.advance / 2, y: pos[1] };
const pen = { x: pos[0], y: pos[1] };
const vertexElements = [];
const textureElements = [];
const pen = { x: 0, y: 0 };
for (let i = 0; i < text.length; i++) {
const chr = text.charCodeAt(i);
const offset = dimensions.advance / text.length * i;
this._drawGlyph(chr, pen, size, vertexElements, textureElements, offset);
}
uvs.push(textureElements);
indexCount += vertexElements.length;
positions.push(vertexElements);
const color = element.color;
this._drawGlyph(pos, chr, pen, size, colors, textureElements, originPoints, textSizes, textOffsets, color);
}
});
this.bufferStruct.uv = uvs;
this.bufferStruct.position = positions;
this.bufferStruct.style = properties;
this.bufferStruct.indexCount = indexCount;
this.attributes = {
originPoints,
textSizes,
textOffsets,
colors,
textureElements
};
this.emit('completed');
});
this._loadTextInfo(chars);
@ -75,19 +73,32 @@ export default class TextBuffer extends BufferBase {
this.emit('SourceLoaded');
});
}
_drawGlyph(chr, pen, size, vertexElements, textureElements, offset) {
/**
* 计算每个标注词语的位置
* @param {*} pos 文字三维空间坐标
* @param {*} chr 字符
* @param {*} pen 字符在词语的偏移量
* @param {*} size 字体大小
* @param {*} colors 颜色
* @param {*} textureElements 纹理坐标
* @param {*} originPoints 初始位置数据
* @param {*} textSizes 文字大小数组
* @param {*} textOffsets 字体偏移量数据
* @param {*} color 文字颜色
*/
_drawGlyph(pos, chr, pen, size, colors, textureElements, originPoints, textSizes, textOffsets, color) {
const metrics = this.metrics;
const metric = metrics.chars[chr];
if (!metric) return;
const scale = size / metrics.size;
const factor = 1;
let width = metric[0];
let height = metric[1];
const horiBearingX = metric[2];
const horiBearingY = metric[3];
const horiAdvance = metric[4];
const posX = metric[5];
const posY = metric[6];
@ -98,36 +109,67 @@ export default class TextBuffer extends BufferBase {
width += buffer * 2;
height += buffer * 2;
// Add a quad (= two triangles) per glyph.
const w1 = (horiBearingX - buffer) * scale + offset;
const w2 = (horiBearingX - buffer + width) * scale + offset;
const h1 = -horiBearingY * scale;
const h2 = (height - horiBearingY) * scale;
vertexElements.push(
[ (factor * (pen.x + w1)), (factor * (pen.y + h1)), w1, h1 ],
[ (factor * (pen.x + w2)), (factor * (pen.y + h1)), w2, h1 ],
[ (factor * (pen.x + w1)), (factor * (pen.y + h2)), w1, h2 ],
// Add a quad (= two triangles) per glyph.
const originX = (horiBearingX - buffer + width / 2) * scale;
// const originY = -(height / 2 - horiBearingY) * scale;
const originY = (height / 2 - horiBearingY) * scale;
// const originY = 0;
const offsetWidth = width / 2 * scale / (1.0 - horiBearingX * 1.5 / horiAdvance);
const offsetHeight = (horiAdvance / 2) * scale;
[ (factor * (pen.x + w2)), (factor * (pen.y + h1)), w2, h1 ],
[ (factor * (pen.x + w1)), (factor * (pen.y + h2)), w1, h2 ],
[ (factor * (pen.x + w2)), (factor * (pen.y + h2)), w2, h2 ]
);
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,
);
textSizes.push(
offsetWidth, offsetHeight,
-offsetWidth, offsetHeight,
-offsetWidth, -offsetHeight,
offsetWidth, offsetHeight,
-offsetWidth, -offsetHeight,
offsetWidth, -offsetHeight,
);
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, posY + height ],
[ posX + width, posY + height ],
[ posX, posY ],
[ posX + width, posY + height ],
[ posX, posY ],
[ posX + width, posY ]
);
posX + width, posY,
posX, posY,
posX, posY + height,
posX + width, posY,
posX, posY + height,
posX + width, posY + height
);
}
pen.x = pen.x + (horiAdvance + Space) * scale;
}
_measureText(text, size) {
const dimensions = {
advance: 0
@ -145,13 +187,10 @@ export default class TextBuffer extends BufferBase {
}
_creatTexture(image) {
this.bufferStruct.textSize = [ image.width, image.height ];
const texture = new Texture2D('textTexure', image, {
magFilter: TextureFilter.LINEAR,
minFilter: TextureFilter.LINEAR,
wrapS: TextureWrapMode.CLAMP_TO_EDGE,
wrapT: TextureWrapMode.CLAMP_TO_EDGE
});
const texture = new THREE.Texture(image);
texture.minFilter = THREE.LinearFilter;
texture.magFilter = THREE.LinearFilter;
texture.needsUpdate = true;
return texture;
}
}

View File

@ -1,78 +0,0 @@
import Base from '../../core/base';
import TinySDF from '@mapbox/tiny-sdf';
import { Texture } from '../../core/three';
export default class textBuffer extends Base {
constructor(cfg) {
super(cfg);
this.canvas = document.createElement('canvas');
this.ctx = this.canvas.getContext('2d');
this.fontSize = 24;
this.fontWeight = 400;
this.sdfs = {};
this.bufferStruct = {};
this.chars = this.makeChars();
this.updateSDF();
this.geometryBuffer();
}
geometryBuffer() {
const coordinates = this.get('coordinates');
const properties = this.get('properties');
const uvs = [];
const texture = new Texture2D('charts', this.canvas);
this.bufferStruct.style = properties;
// this.bufferStruct.utexture = this.canvas;
this.bufferStruct.utexture = texture;
const positions = [];
const textIndex = [];
const index = 0;
coordinates.forEach((coor, index) => {
positions.push([[ coor[0], coor[1] ], [ coor[0], coor[1] ]]);
textIndex.push([ 0, 1 ]);
index++;
const posX = this.sdfs[this.chars[index]].x; // pos in sprite x
const posY = this.sdfs[this.chars[index]].y; // pos in sprite y
uvs.push([[ posX / 2048, posY / 2048 ], [ posX / 2048, posY / 2048 ]]);
});
this.bufferStruct.position = positions;
this.bufferStruct.uv = uvs;
this.bufferStruct.textIndex = textIndex;
this.bufferStruct.indexCount = this.bufferStruct.position.length * 2;
}
makeChars() {
const properties = this.get('properties');
const chars = [];
properties.forEach(item => {
const text = item.shape;
text.forEach(char => {
chars.push(char);
});
});
return chars;
}
updateSDF() {
this.canvas.width = 2048;
this.canvas.height = 2048;
const buffer = this.fontSize / 8;
const radius = this.fontSize / 3;
const sdf = new TinySDF(this.fontSize, buffer, radius, null, null, this.fontWeight);
for (let y = 0, i = 0; y + sdf.size <= this.canvas.height && i < this.chars.length; y += sdf.size) {
for (let x = 0; x + sdf.size <= this.canvas.width && i < this.chars.length; x += sdf.size) {
this.ctx.putImageData(this.makeRGBAImageData(sdf.draw(this.chars[i]), sdf.size), x, y);
this.sdfs[this.chars[i]] = { x, y };
i++;
}
}
}
makeRGBAImageData(alphaChannel, size) {
const imageData = this.ctx.createImageData(size, size);
const data = imageData.data;
for (let i = 0; i < alphaChannel.length; i++) {
data[4 * i + 0] = alphaChannel[i];
data[4 * i + 1] = alphaChannel[i];
data[4 * i + 2] = alphaChannel[i];
data[4 * i + 3] = 255;
}
return imageData;
}
}

View File

@ -1,118 +0,0 @@
import { BufferGeometry, Float32BufferAttribute } from '../../core/three';
/**
* 基础几何体
*/
export default class BaseBufferGeometry extends BufferGeometry {
// indices, position, uv, normal
constructor(opts) {
super(opts.name);
// 几何体顶点位置数据
this._opts = opts;
this._position = opts.position;
// 三角形顶点序号数据
this._indices = opts.indices;
// this._colors = opts.colors;
this._style = opts.style;
// 法线数据
this._normals = opts.normals;
this._uv = opts.uv;
this._activeIds = null;
this._textIndex = opts.textIndex;
this._indexCount = opts.indexCount;
if (opts.DrawMode) {
this.mode = DrawMode[opts.DrawMode];
}
if (this._indexCount > 65536) {
this.primitive.indexType = DataType.UNSIGNED_INT;
}
this.initialize();
}
/**
* 更新active操作
* @param {*} featureStyleId 需要更新的要素Id
* @param {*} style 更新的要素样式
*/
updateStyle(featureStyleId, style) {
if (this._activeIds) {
this.resetStyle();
}
this._activeIds = featureStyleId;
let dataIndex = 0;
const id = featureStyleId[0];
if (!this._indices) {
const color = style.color;
this.setVertexValues(id, {
COLOR: color
});
return;
}
for (let i = 0; i < id; i++) {
dataIndex += this._indices[i].length;
}
featureStyleId.forEach(index => {
const indices = this._indices[index];
const color = style.color;
indices.forEach(() => {
this.setVertexValues(dataIndex++, {
COLOR: color
});
});
});
}
/**
* 用于过滤数据
* @param {*} filterData 数据过滤标识符
*/
updateFilter(filterData) {
let dataIndex = 0;
this._indices.forEach((indices, i) => {
const color = [ ...this._style[i].color ];
if (filterData[i].hasOwnProperty('filter') && filterData[i].filter === false) {
color[3] = 0;
}
indices.forEach(() => {
this.setVertexValues(dataIndex++, {
COLOR: color
});
});
});
}
/**
* 重置高亮要素
*/
resetStyle() {
let dataIndex = 0;
const id = this._activeIds[0];
if (!this._indices) {
const color = this._style[id].color;
this.setVertexValues(id, {
COLOR: color
});
return;
}
for (let i = 0; i < id; i++) {
dataIndex += this._indices[i].length;
}
this._activeIds.forEach(index => {
const indices = this._indices[index];
indices.forEach(() => {
this.setVertexValues(dataIndex++, {
COLOR: this._style[index].color
});
});
});
}
}

View File

@ -1,32 +0,0 @@
import { DataType } from '@ali/r3-base';
import BaseBufferGeometry from './baseBufferGeometry';
/**
* 创建Polygon几何体
*/
export default class ImageGeometry extends BaseBufferGeometry {
constructor(opts) {
opts.DrawMode = 'TRIANGLES';
super(opts);
}
/**
* 构造多边形数据
* @private
*/
initialize() {
super.initialize([
{ semantic: 'POSITION', size: 3, type: DataType.FLOAT, normalized: false },
{ semantic: 'TEXCOORD_0', size: 2, type: DataType.FLOAT, normalized: false }
], this._position.length);
this._position.forEach((vert, j) => {
this.setVertexValues(j, {
POSITION: vert,
TEXCOORD_0: this._uv[j]
});
});
}
}

View File

@ -1,5 +0,0 @@
export { default as MeshlineGeometry } from './line';
export { default as PointGeometry } from './point';
export { default as PolygonLine } from './polygon-line';
export { default as PolygonGeometry } from './polygon';

View File

@ -1,66 +0,0 @@
import { DataType, DrawMode } from '@ali/r3-base';
import { BufferGeometry } from '@ali/r3-geometry';
export class meshLineGeometry extends BufferGeometry {
constructor(opts) {
super();
this._verts = opts.verts;
this._style = opts.style;
this._indexs = opts.indexs;
this._initialize();
}
_initialize() {
const self = this;
super.initialize([
{ semantic: 'POSITION', size: 3, type: DataType.FLOAT, normalized: false },
{ semantic: 'COLOR', size: 4, type: DataType.FLOAT, normalized: false }
], self._verts.length);
self.mode = DrawMode.TRIANGLES;
for (let i = 0; i < self._verts.length; i++) {
const index = self._indexs[i];
const color = this._style[index].color;
const values = {
POSITION: self._verts[i],
COLOR: color
};
self.setVertexValues(i, values);
}
}
}
export class arcGeometry extends BufferGeometry {
constructor(opts) {
super();
// 顶点位置数据
this._verts = opts.verts;
this._style = opts.style;
this._indexs = opts.indexs;
this._instances = opts.instances;
this._initialize();
}
_initialize() {
const self = this;
super.initialize([
{ semantic: 'POSITION', size: 3, type: DataType.FLOAT, normalized: false },
{ semantic: 'COLOR', size: 4, type: DataType.FLOAT, normalized: false },
{ semantic: 'INSPOS', size: 4, type: DataType.FLOAT, normalized: false }
], self._verts.length);
self.mode = DrawMode.LINES;
for (let i = 0; i < self._verts.length; i++) {
const index = this._indexs[i];
const color = this._style[index].color;
const values = {
POSITION: self._verts[i],
COLOR: color,
INSPOS: self._instances[i]
};
self.setVertexValues(i, values);
}
}
}

View File

@ -1,55 +0,0 @@
import { DataType, BufferUsage } from '@ali/r3-base';
import BaseBufferGeometry from './baseBufferGeometry';
/**
* 创建点图层几何体
*/
export default class PointGeometry extends BaseBufferGeometry {
constructor(opts) {
opts.DrawMode = 'POINTS';
super(opts);
}
/**
* 构造多边形数据
* @private
*/
initialize() {
const attributesObj = {
size: { semantic: 'SIZE', size: 1, type: DataType.FLOAT, normalized: false },
id: { semantic: 'IDCOLOR', size: 4, type: DataType.FLOAT, normalized: false },
uv: { semantic: 'TEXCOORD_0', size: 2, type: DataType.FLOAT, normalized: false },
color: { semantic: 'COLOR', size: 4, type: DataType.FLOAT, normalized: false },
shape: { semantic: 'SHAPE', size: 1, type: DataType.FLOAT, normalized: false }
};
const keys = Object.keys(this._style[0]);
const attributes = [{ semantic: 'POSITION', size: 3, type: DataType.FLOAT, normalized: false }];
if (this._uv) attributes.push(attributesObj.uv);
keys.forEach(key => { attributes.push(attributesObj[key]); });
super.initialize(attributes, this._position.length, BufferUsage.DYNAMIC_DRAW);
this._position.forEach((vert, i) => {
const color = this._style[i].color;
const attrData = {
POSITION: vert,
COLOR: color,
SIZE: [ this._style[i].size ],
IDCOLOR: this._style[i].id,
SHAPE: [ this._style[i].shape ]
};
if (keys.indexOf('shape') !== -1) attrData.SHAPE = [ this._style[i].shape ];
if (this._uv) attrData.TEXCOORD_0 = this._uv[i];
this.setVertexValues(i, attrData);
});
}
updateSize(data) {
const pointCount = this._position.length;
for (let i = 0; i < pointCount; i++) {
this.setVertexValues(i, {
SIZE: [ data[i] ]
});
}
}
}

View File

@ -1,56 +0,0 @@
import { DataType, DrawMode } from '@ali/r3-base';
import { IndexBufferGeometry } from '@ali/r3-geometry';
// 创建立方体
export default class PolygonLine extends IndexBufferGeometry {
constructor(opts) {
super();
this._positions = opts.verts;
this._positionsIndexs = opts.indexs;
this._vertsCount = opts.vertsCount;
this._style = opts.style;
//
if (this._positionsIndexs.length > 65536) {
this.primitive.indexType = DataType.UNSIGNED_INT;
}
this.initialize();
}
initialize() {
super.initialize([
{ semantic: 'POSITION', size: 3, type: DataType.FLOAT, normalized: false },
{ semantic: 'COLOR', size: 4, type: DataType.FLOAT, normalized: false }
], this._vertsCount, this._positionsIndexs);
this.mode = DrawMode.LINES;
const featureCount = this._positions.length;
let indexCount = 0;
for (let i = 0; i < featureCount; i++) {
const pos = this._positions[i];
for (let j = 0; j < pos.length; j++) {
this.setVertexValues(indexCount, {
POSITION: pos[j],
COLOR: this._style[i].color
});
indexCount++;
}
}
}
updateFilter(filterData) {
this._activeIds = null; // 清空选中元素
const featureCount = this._positions.length;
let indexCount = 0;
for (let i = 0; i < featureCount; i++) {
const pos = this._positions[i];
const color = [ ...this._style[i].color ];
if (filterData[i].hasOwnProperty('filter') && filterData[i].filter === false) {
color[3] = 0;
}
for (let j = 0; j < pos.length; j++) {
this.setVertexValues(indexCount, {
COLOR: color
});
indexCount++;
}
}
}
}

View File

@ -1,128 +0,0 @@
import { DataType, DrawMode } from '@ali/r3-base';
import { BufferGeometry } from '@ali/r3-geometry';
/**
* 创建Polygon几何体
*/
export default class PolygonGeometry extends BufferGeometry {
constructor(opts) {
super(opts.name);
// 几何体顶点位置数据
this._verts = opts.position;
// 三角形顶点序号数据
this._indexs = opts.indices;
this._style = opts.style;
// 法线数据
this._normals = opts.normals;
this._indexCount = opts.indexCount;
this._activeIds = null;
this.initialize();
}
/**
* 构造多边形数据
* @private
*/
initialize() {
super.initialize([
{ semantic: 'POSITION', size: 3, type: DataType.FLOAT, normalized: false },
{ semantic: 'NORMAL', size: 3, type: DataType.FLOAT, normalized: true },
{ semantic: 'COLOR', size: 4, type: DataType.FLOAT, normalized: false },
{ semantic: 'IDCOLOR', size: 4, type: DataType.FLOAT, normalized: false }
], this._indexCount);
this.mode = DrawMode.TRIANGLES;
if (this._indexCount > 65536) {
this.primitive.indexType = DataType.UNSIGNED_INT;
}
// camera.renderHardware
let dataIndex = 0;
this._indexs.forEach((vertIndexs, i) => {
const color = [ ...this._style[i].color ];
if (this._style[i].hasOwnProperty('filter') && !this._style[i].filter) {
color[3] = 0;
}
vertIndexs.forEach((index, j) => {
const vert = this._verts[i][index];
const normalIndex = Math.floor(j / 3);
this.setVertexValues(dataIndex++, {
POSITION: vert,
COLOR: color,
IDCOLOR: this._style[i].id,
NORMAL: this._normals[i][normalIndex]
});
});
});
}
/**
* 更新active操作
* @param {*} featureStyleId 需要更新的要素Id
* @param {*} style 更新的要素样式
*/
updateStyle(featureStyleId, style) {
if (this._activeIds) {
this.resetStyle();
}
this._activeIds = featureStyleId;
let dataIndex = 0;
const id = featureStyleId[0];
for (let i = 0; i < id; i++) {
dataIndex += this._indexs[i].length;
}
featureStyleId.forEach(index => {
const vertindex = this._indexs[index];
const color = style.color;
vertindex.forEach(() => {
this.setVertexValues(dataIndex++, {
COLOR: color
});
});
});
}
/**
* 用于过滤数据
* @param {*} filterData 数据过滤标识符
*/
updateFilter(filterData) {
this._activeIds = null; // 清空选中元素
let dataIndex = 0;
this._indexs.forEach((vertIndexs, i) => {
const color = [ ...this._style[i].color ];
if (filterData[i].hasOwnProperty('filter') && filterData[i].filter === false) {
color[3] = 0;
}
vertIndexs.forEach(() => {
this.setVertexValues(dataIndex++, {
COLOR: color
});
});
});
}
/**
* 重置高亮要素
*/
resetStyle() {
let dataIndex = 0;
const id = this._activeIds[0];
for (let i = 0; i < id; i++) {
dataIndex += this._indexs[i].length;
}
this._activeIds.forEach(index => {
const vertindex = this._indexs[index];
vertindex.forEach(() => {
this.setVertexValues(dataIndex++, {
COLOR: this._style[index].color
});
});
});
}
}

View File

@ -1,32 +0,0 @@
import { DataType } from '@ali/r3-base';
import BaseBufferGeometry from './baseBufferGeometry';
/**
* 创建点图层几何体
*/
export default class RainGeometry extends BaseBufferGeometry {
constructor(opts) {
opts.DrawMode = 'POINTS';
super(opts);
}
/**
* 构造多边形数据
* @private
*/
initialize() {
super.initialize([
{ semantic: 'POSITION', size: 3, type: DataType.FLOAT, normalized: false },
{ semantic: 'TEXCOORD_0', size: 2, type: DataType.FLOAT, normalized: false }
], this._position.length);
this._position.forEach((vert, j) => {
this.setVertexValues(j, {
POSITION: vert,
TEXCOORD_0: this._uv[j]
});
});
}
}

View File

@ -1,41 +0,0 @@
import { DataType, DrawMode } from '@ali/r3-base';
import BaseBufferGeometry from './baseBufferGeometry';
/**
* 创建Polygon几何体
*/
export default class TextGeometry extends BaseBufferGeometry {
constructor(opts) {
opts.DrawMode = opts.drawMode || 'TRIANGLES';
super(opts);
}
/**
* 构造多边形数据
* @private
*/
initialize() {
super.initialize([
{ semantic: 'POSITION', size: 4, type: DataType.FLOAT, normalized: false },
{ semantic: 'COLOR', size: 4, type: DataType.FLOAT, normalized: false },
{ semantic: 'TEXCOORD_0', size: 2, type: DataType.FLOAT, normalized: false },
{ semantic: 'SIZE', size: 1, type: DataType.FLOAT, normalized: false }
], this._indexCount);
let dataIndex = 0;
this._position.forEach((pos, i) => {
const color = this._style[i].color;
const uv = this._uv[i];
pos.forEach((p, j) => {
this.setVertexValues(dataIndex++, {
POSITION: p,
COLOR: color,
SIZE: [ this._style[i].size ],
TEXCOORD_0: uv[j]
});
});
});
}
}

View File

@ -1,9 +1,6 @@
import * as THREE from '../../core/three';
export default class Material extends THREE.ShaderMaterial {
constructor(opts) {
super(opts);
}
setValue(name, value) {
this.uniforms[name].value = value;
this.uniforms.needsUpdate = true;

View File

@ -18,5 +18,8 @@ export default function PointMaterial(options) {
TEXCOORD_0: !!options.u_texture
}
});
if (options.shape === false) {
material.blending = THREE.AdditiveBlending;
}
return material;
}

View File

@ -1,5 +1,4 @@
import Material from './material';
import * as THREE from '../../core/three';
import raster_frag from '../shader/raster_frag.glsl';
import raster_vert from '../shader/raster_vert.glsl';
export default function ImageMaterial(options) {

View File

@ -0,0 +1,24 @@
import Material from './material';
import text_frag from '../shader/text_frag.glsl';
import text_vert from '../shader/text_vert.glsl';
export default function TextMaterial(options) {
const material = new Material({
uniforms: {
u_opacity: { value: options.u_opacity || 1.0 },
u_texture: { value: options.u_texture },
u_strokeWidth: { value: options.u_strokeWidth },
u_stroke: { value: options.u_stroke },
u_textSize: { value: options.u_textSize },
u_scale: { value: options.u_scale },
u_gamma: { value: options.u_gamma },
u_buffer: { value: options.u_buffer },
u_color: { value: options.u_color },
u_glSize: { value: options.u_glSize }
},
vertexShader: text_vert,
fragmentShader: text_frag,
transparent: true
});
return material;
}

View File

@ -1,6 +1,7 @@
precision highp float;
uniform sampler2D u_texture;
uniform sampler2D u_colorTexture;
uniform vec2 u_dimension;
varying vec2 v_texCoord;
varying vec4 v_color;
@ -10,53 +11,55 @@ uniform float u_max;
void main() {
float value = texture2D(u_texture,v_texCoord)[0];
if(value > u_max || u_min > value ) {
discard;
}
vec2 u_latrange = vec2(3.83718,53.5636);
float u_zoom = 7.0;
float u_maxzoom= 10.0;
vec2 epsilon = 1.0 / u_dimension;
vec2 u_light = vec2(0.5000, 5.8469);
vec4 u_accent = vec4(0.,0.,0.,1.);
vec4 u_highlight = vec4(1.0);
vec4 u_shadow = vec4(0.,0.,0.,1.);
float a = texture2D(u_texture,v_texCoord - epsilon)[0];
float b = texture2D(u_texture,v_texCoord+vec2(0,-epsilon.y))[0];
float c = texture2D(u_texture,v_texCoord+ vec2(epsilon.x - epsilon.y))[0];
float d = texture2D(u_texture,v_texCoord+ vec2(-epsilon.x,0))[0];
float e = texture2D(u_texture,v_texCoord)[0];
float f = texture2D(u_texture,v_texCoord+ vec2(epsilon.x,0))[0];
float g = texture2D(u_texture,v_texCoord+ vec2(-epsilon.x,epsilon.y))[0];
float h = texture2D(u_texture,v_texCoord+ vec2(0,epsilon.y))[0];
float i = texture2D(u_texture,v_texCoord+ epsilon)[0];
float exaggeration = u_zoom < 2.0 ? 0.4 : u_zoom < 4.5 ? 0.35 : 0.3;
value = clamp(value,u_min,u_max);
float value1 = (value - u_min) / (u_max -u_min);
vec2 ramp_pos = vec2(
fract(16.0 * (1.0 - value1)),
floor(16.0 * (1.0 - value1)) / 16.0);
vec4 color = texture2D(u_colorTexture,ramp_pos);
// vec2 u_latrange = vec2(3.83718,53.5636);
// float u_zoom = 7.0;
// float u_maxzoom= 10.0;
// vec2 epsilon = 1.0 / u_dimension;
// vec2 u_light = vec2(0.5000, 5.8469);
// vec4 u_accent = vec4(0.,0.,0.,1.);
// vec4 u_highlight = vec4(1.0);
// vec4 u_shadow = vec4(0.,0.,0.,1.);
// float a = texture2D(u_texture,v_texCoord - epsilon)[0];
// float b = texture2D(u_texture,v_texCoord+vec2(0,-epsilon.y))[0];
// float c = texture2D(u_texture,v_texCoord+ vec2(epsilon.x - epsilon.y))[0];
// float d = texture2D(u_texture,v_texCoord+ vec2(-epsilon.x,0))[0];
// float e = texture2D(u_texture,v_texCoord)[0];
// float f = texture2D(u_texture,v_texCoord+ vec2(epsilon.x,0))[0];
// float g = texture2D(u_texture,v_texCoord+ vec2(-epsilon.x,epsilon.y))[0];
// float h = texture2D(u_texture,v_texCoord+ vec2(0,epsilon.y))[0];
// float i = texture2D(u_texture,v_texCoord+ epsilon)[0];
// float exaggeration = u_zoom < 2.0 ? 0.4 : u_zoom < 4.5 ? 0.35 : 0.3;
vec2 deriv = vec2(
(c + f + f + i) - (a + d + d + g),
(g + h + h + i) - (a + b + b + c)
) / pow(2.0, (u_zoom - u_maxzoom) * exaggeration + 19.2562 - u_zoom);
float scaleFactor = cos(radians((u_latrange[0] - u_latrange[1]) * (1.0 - v_texCoord.y) + u_latrange[1]));
float slope = atan(1.25 * length(deriv) / scaleFactor);
float aspect = deriv.x != 0.0 ? atan(deriv.y, -deriv.x) : PI / 2.0 * (deriv.y > 0.0 ? 1.0 : -1.0);
// vec2 deriv = vec2(
// (c + f + f + i) - (a + d + d + g),
// (g + h + h + i) - (a + b + b + c)
// ) / pow(2.0, (u_zoom - u_maxzoom) * exaggeration + 19.2562 - u_zoom);
// float scaleFactor = cos(radians((u_latrange[0] - u_latrange[1]) * (1.0 - v_texCoord.y) + u_latrange[1]));
// float slope = atan(1.25 * length(deriv) / scaleFactor);
// float aspect = deriv.x != 0.0 ? atan(deriv.y, -deriv.x) : PI / 2.0 * (deriv.y > 0.0 ? 1.0 : -1.0);
float intensity = u_light.x;
float azimuth = u_light.y + PI;
// float intensity = u_light.x;
// float azimuth = u_light.y + PI;
float base = 1.875 - intensity * 1.75;
float maxValue = 0.5 * PI;
float scaledSlope = intensity != 0.5 ? ((pow(base, slope) - 1.0) / (pow(base, maxValue) - 1.0)) * maxValue : slope;
// float base = 1.875 - intensity * 1.75;
// float maxValue = 0.5 * PI;
// float scaledSlope = intensity != 0.5 ? ((pow(base, slope) - 1.0) / (pow(base, maxValue) - 1.0)) * maxValue : slope;
float accent = cos(scaledSlope);
// We multiply both the accent and shade color by a clamped intensity value
// so that intensities >= 0.5 do not additionally affect the color values
// while intensity values < 0.5 make the overall color more transparent.
vec4 accent_color = (1.0 - accent) * u_accent * clamp(intensity * 2.0, 0.0, 1.0);
float shade = abs(mod((aspect + azimuth) / PI + 0.5, 2.0) - 1.0);
vec4 shade_color = mix(u_shadow, u_highlight, shade) * sin(scaledSlope) * clamp(intensity * 2.0, 0.0, 1.0);
gl_FragColor = v_color * (1.0 - shade_color.a) + shade_color;
gl_FragColor =v_color;
// float accent = cos(scaledSlope);
// // We multiply both the accent and shade color by a clamped intensity value
// // so that intensities >= 0.5 do not additionally affect the color values
// // while intensity values < 0.5 make the overall color more transparent.
// vec4 accent_color = (1.0 - accent) * u_accent * clamp(intensity * 2.0, 0.0, 1.0);
// float shade = abs(mod((aspect + azimuth) / PI + 0.5, 2.0) - 1.0);
// vec4 shade_color = mix(u_shadow, u_highlight, shade) * sin(scaledSlope) * clamp(intensity * 2.0, 0.0, 1.0);
// gl_FragColor = v_color * (1.0 - shade_color.a) + shade_color;
gl_FragColor = color;
}

View File

@ -10,13 +10,9 @@ varying vec4 v_color;
void main() {
mat4 matModelViewProjection = projectionMatrix * modelViewMatrix;
float value = texture2D(u_texture,uv)[0];
v_texCoord = uv;
float value1 = (value - u_min) / (u_max -u_min);
vec2 ramp_pos = vec2(
fract(16.0 * (1.0 - value1)),
floor(16.0 * (1.0 - value1)) / 16.0);
v_color = texture2D(u_colorTexture,ramp_pos);
value = clamp(value,u_min,u_max);
vec2 range = u_extent.zw - u_extent.xy;
gl_Position = matModelViewProjection * vec4(position.x * range.x + u_extent.x , position.y * range.y - u_extent.y, 0., 1.0);
gl_Position = matModelViewProjection * vec4(position.xy, value*100.0, 1.0);
}

View File

@ -1,6 +1,6 @@
precision mediump float;
uniform sampler2D u_texture;
uniform vec4 u_color;
varying vec4 v_color;
uniform vec4 u_stroke;
uniform float u_strokeWidth;
uniform float u_buffer;
@ -10,11 +10,11 @@ varying vec2 v_texcoord;
void main() {
float dist = texture2D(u_texture, v_texcoord).r;
float dist = texture2D(u_texture, vec2(v_texcoord.x,1.0-v_texcoord.y)).r;
float alpha;
if(u_strokeWidth == 0.0){
alpha = smoothstep(u_buffer - u_gamma, u_buffer, dist);
gl_FragColor = vec4(u_color.rgb, alpha * u_color.a);
gl_FragColor = vec4(v_color.rgb, alpha * v_color.a);
}else{
@ -24,10 +24,10 @@ void main() {
gl_FragColor = vec4(u_stroke.rgb, alpha * u_stroke.a);
}else if(dist < u_buffer){
alpha = smoothstep(u_buffer - u_gamma, u_buffer, dist);
gl_FragColor = vec4(alpha * u_color.rgb + (1.0 - alpha) * u_stroke.rgb, 1.0 * u_color.a * alpha + (1.0 - alpha) * u_stroke.a);
gl_FragColor = vec4(alpha * v_color.rgb + (1.0 - alpha) * u_stroke.rgb, 1.0 * v_color.a * alpha + (1.0 - alpha) * u_stroke.a);
}else{
alpha = 1.0;
gl_FragColor = vec4(u_color.rgb, alpha * u_color.a);
gl_FragColor = vec4(v_color.rgb, alpha * v_color.a);
}
}

View File

@ -1,26 +1,20 @@
precision mediump float;
attribute vec4 a_position;
attribute vec2 a_uv;
uniform mat4 matModelViewProjection;
attribute vec2 a_txtsize;
attribute vec2 a_txtOffsets;
attribute vec4 a_color;
uniform mat4 u_model;
uniform mat4 u_view;
uniform mat4 u_projection;
uniform mat4 u_scale;
uniform vec2 u_textSize;
uniform vec2 u_glSize;
varying vec2 v_texcoord;
varying vec4 v_color;
void main() {
// vec4 mposition = vec4(a_position.zw * 100000.0, 0.0, 0.0) + u_view * u_model * vec4(a_position.xy, 0.0, 1.0);
// vec4 mposition = u_model * u_projection 0* vec4(a_position.xy, 0.0,1.0);
// gl_Position = u_projection * mposition;
// mposition.xy += a_position.zw * u_size;
// gl_Position = u_projection * mposition;
// gl_Position = u_projection * u_model * u_view * vec4(a_position.xy, 0.0,1.0);
vec4 p2 = vec4(a_position.xy, 0.0,1.0) + u_scale * vec4(a_position.zw, 0.0,1.0);
gl_Position = matModelViewProjection * vec4(p2.xy, 0.0,1.0);
v_texcoord = a_uv / u_textSize;
mat4 matModelViewProjection = projectionMatrix * modelViewMatrix;
vec4 cur_position = matModelViewProjection * vec4(position.xy, 0, 1);
gl_Position = cur_position / cur_position.w + vec4((a_txtOffsets + a_txtsize)/ u_glSize * 2.0,0.0, 0.0) +vec4(abs(a_txtsize.x)/u_glSize.x *2.0, -abs(a_txtsize.y)/u_glSize.y* 2.0, 0.0, 0.0);
v_color = a_color;
v_texcoord = uv / u_textSize;
}

View File

@ -85,7 +85,7 @@ export function arc(geo, index) {
* @param {int} index 原始数据index
* @return {object} 顶点坐标,索引坐标
*/
export function defaultLine(geo, index) {
export function defaultLine(geo) {
const indexArray = [];
const positions = [];
geo.slice(0, geo.length - 1).forEach((coor, index) => {

View File

@ -2,7 +2,5 @@ export { default as PolygonLayer } from './polygonLayer';
export { default as PointLayer } from './pointLayer';
export { default as LineLayer } from './lineLayer';
export { default as ImageLayer } from './imageLayer';
// export { default as textPointLayer } from './textPointLayer';
export { default as RainLayer } from './rainLayer';
export { default as RasterLayer } from './rasterLayer';

View File

@ -3,8 +3,9 @@ import * as THREE from '../core/three';
import PointBuffer from '../geom/buffer/point';
import PointMaterial from '../geom/material/pointMaterial';
import PolygonMaterial from '../geom/material/polygonMaterial';
import ColorUtil from '../attr/color-util';
// import TextBuffer from '../geom/buffer/text';
import TextBuffer from '../geom/buffer/text';
import TextMaterial from '../geom/material/textMaterial';
/**
* point shape 2d circle, traingle text,image
* shape 3d cubecolumn, sphere
@ -15,11 +16,6 @@ import ColorUtil from '../attr/color-util';
export default class PointLayer extends Layer {
// shape(type) {
// this.shapeType = type;
// return this;
// }
render() {
this.type = 'point';
this.init();
@ -40,7 +36,7 @@ export default class PointLayer extends Layer {
this._shapePoint();
break;
default:
this._shapePoint();
this._2dPoint();
break;
}
@ -49,33 +45,30 @@ export default class PointLayer extends Layer {
_imagePoint() {
const { opacity, strokeWidth, stroke } = this.get('styleOptions');
const source = this.layerSource;
const geometry = new THREE.BufferGeometry();
const buffer = new PointBuffer({
imagePos: this.scene.image.imagePos,
type: this.shapeType,
coordinates: source.geoData,
properties: this.StyleData
});
const mtl = new PointMaterial({
u_opacity: opacity,
u_strokeWidth: strokeWidth,
u_stroke: stroke,
u_texture: this.scene.image.texture
});
const { attributes } = buffer;
geometry.addAttribute('position', new THREE.Float32BufferAttribute(attributes.vertices, 3));
geometry.addAttribute('a_color', new THREE.Float32BufferAttribute(attributes.colors, 4));
geometry.addAttribute('a_size', new THREE.Float32BufferAttribute(attributes.sizes, 1));
geometry.addAttribute('uv', new THREE.Float32BufferAttribute(attributes.uvs, 2));
geometry.addAttribute('pickingId', new THREE.Float32BufferAttribute(attributes.pickingIds, 1));
const mesh = new THREE.Points(geometry, mtl);
this.add(mesh);
this.scene.image.on('imageLoaded', () => {
const geometry = new THREE.BufferGeometry();
const buffer = new PointBuffer({
imagePos: this.scene.image.imagePos,
type: this.shapeType,
coordinates: source.geoData,
properties: this.StyleData
});
const mtl = new PointMaterial({
u_opacity: opacity,
u_strokeWidth: strokeWidth,
u_stroke: stroke,
u_texture: this.scene.image.texture
});
const { attributes } = buffer;
geometry.addAttribute('position', new THREE.Float32BufferAttribute(attributes.vertices, 3));
geometry.addAttribute('a_color', new THREE.Float32BufferAttribute(attributes.colors, 4));
geometry.addAttribute('a_size', new THREE.Float32BufferAttribute(attributes.sizes, 1));
geometry.addAttribute('uv', new THREE.Float32BufferAttribute(attributes.uvs, 2));
geometry.addAttribute('pickingId', new THREE.Float32BufferAttribute(attributes.pickingIds, 1));
const mesh = new THREE.Points(geometry, mtl);
this.add(mesh);
// TODO update Size
// this.on('sizeUpdated', function(data) {
// geometry.updateSize(data);
// });
});
return this;
}
// sdf 绘制多边形
@ -93,7 +86,8 @@ export default class PointLayer extends Layer {
const mtl = new PointMaterial({
u_opacity: opacity,
u_strokeWidth: strokeWidth,
u_stroke: stroke
u_stroke: stroke,
shape: this.shapeType || false
});
const { attributes } = buffer;
geometry.addAttribute('position', new THREE.Float32BufferAttribute(attributes.vertices, 3));
@ -129,7 +123,6 @@ export default class PointLayer extends Layer {
const mesh = new THREE.Mesh(geometry, material);
this.remove(this.layerMesh);
this.add(mesh);
this.layerMesh = mesh;
}
_textPoint() {
@ -143,41 +136,27 @@ export default class PointLayer extends Layer {
});
buffer.on('completed', () => {
const borderColor = ColorUtil.toRGB(styleOptions.borderColor).map(e => e / 255);
const color = ColorUtil.toRGB(styleOptions.color).map(e => e / 255);
if (borderColor.length === 3) {
borderColor.push(1.0);
}
if (color.length === 3) {
color.push(1.0);
}
// const {width, height} =this.scene.render.camera.renderHardware.canvas;
const geometry = new TextGeometry(buffer.bufferStruct);
const mtl = new TextMaterial({
const { color, stroke } = styleOptions;
const geometry = new THREE.BufferGeometry();
geometry.addAttribute('position', new THREE.Float32BufferAttribute(buffer.attributes.originPoints, 3));
geometry.addAttribute('uv', new THREE.Float32BufferAttribute(buffer.attributes.textureElements, 2));
geometry.addAttribute('a_txtsize', new THREE.Float32BufferAttribute(buffer.attributes.textSizes, 2));
geometry.addAttribute('a_txtOffsets', new THREE.Float32BufferAttribute(buffer.attributes.textOffsets, 2));
geometry.addAttribute('a_color', new THREE.Float32BufferAttribute(buffer.attributes.colors, 4));
const { width, height } = this.scene.getSize();
const material = new TextMaterial({
name: this.layerId,
u_texture: buffer.bufferStruct.textTexture,
// u_opacity: styleOptions.opacity
u_strokeWidth: 1,
u_stroke: borderColor,
u_stroke: stroke,
u_textSize: buffer.bufferStruct.textSize,
u_gamma: 0.08,
u_buffer: 0.75,
u_color: color,
u_scale: this._getPointScale()
u_glSize: [ width, height ]
});
// layer移除需要移除时间
this.scene.map.on('zoomchange', e => {
mtl.setValue('u_scale', this._getPointScale());
});
this.geometry = geometry;
this.renderer.geometry = geometry;
this.renderer.setMaterial(mtl);
const mesh = new THREE.Mesh(geometry, material);
this.add(mesh);
});
@ -185,9 +164,8 @@ export default class PointLayer extends Layer {
_getPointScale() {
const zoom = this.scene.map.getZoom();
const size = this.get('styleOptions').size * Math.pow(2, 18 - zoom);
const out = mat4.create();
mat4.fromScaling(out, [ size, size, size ]);
const out = new THREE.Matrix4();
out.scale([ size, size, size ]);
return out;
}
_customPoint() {

View File

@ -1,296 +0,0 @@
import Layer from '../core/layer';
import * as THREE from '../core/three';
import { RainSource } from '../source/rainSource';
import { RainBuffer } from '../geom/buffer/rain';
import DrawMaterial from '../core/extend/windframebuffer/drawMaterial';
import ImageMaterial from '../geom/material/imageMaterial';
import WindMaterial from '../core/extend/windframebuffer/windMaterial';
import UpdateMaterial from '../core/extend/windframebuffer/updateMaterial';
import { RenderPass } from '../core/engine/renderpass';
export default class RainLayer extends Layer {
source(cfg = {}) {
cfg.mapType = this.get('mapType');
this.layerSource = new RainSource(cfg);
return this;
}
render() {
this.init();
const source = this.layerSource;
const screenPass01 = new RenderPass({
camera: this.scene._engine._camera,
renderer: this.scene._engine._renderer,
clear: {
clearColor: 0xff0000,
clearAlpha: 0.0
}
});
const screenPass02 = new RenderPass({
camera: this.scene._engine._camera,
renderer: this.scene._engine._renderer,
clear: {
clearColor: 0xff0000,
clearAlpha: 0.0
}
});
// 加载 完成事件
source.on('imageLoaded', () => {
const buffer = this.buffer = new RainBuffer({
coordinates: source.geoData,
extent: source.extent,
image: source.image,
uv: source.uv,
particleImage1: source.particleImage1,
particleImage0: source.particleImage0,
backgroundImage: source.backgroundImage
});
const { bufferStruct } = buffer;
const styleOptions = this.get('styleOptions');
// this.screenGeo = new ImageGeometry({
// position: [[ 0, 0, 0 ], [ 1, 0, 0 ], [ 1, 1, 0 ], [ 0, 0, 0 ], [ 1, 1, 0 ], [ 0, 1, 0 ]],
// // position:buffer.bufferStruct.imgPos,
// uv: [[ 0, 1 ], [ 1, 1 ], [ 1, 0 ], [ 0, 1 ], [ 1, 0 ], [ 0, 0 ]]
// });
const u_wind_max = source.get('wind_max');
const u_wind_min = source.get('wind_min');
const u_extent = source.get('extent');
const u_wind_res = source.get('wind_res');
this.initGeometry(source.particleIndices);
this.geometry.addAttribute('position', new THREE.Float32BufferAttribute(buffer.attributes.vertices, 3));
this.geometry.getAttribute('position').count = source.particleIndices.length;
this.geometry.getAttribute('position').needsUpdate = true;
const imageGeo = this.initImageGeometry(buffer.attributes);
const drawMaterial = new DrawMaterial({
u_wind: bufferStruct.u_wind,
u_particles: bufferStruct.particleStateTexture0,
u_bbox: [ source.extent[0][0], source.extent[0][1], source.extent[1][0], source.extent[1][1] ],
u_wind_max,
u_wind_min,
u_opacity: 1.0,
u_particles_res: source.particleRes,
u_color_ramp: bufferStruct.colorTexture
});
const updateMaterial = new UpdateMaterial({
u_wind: buffer.bufferStruct.u_wind, // 风场 uv
u_opacity: styleOptions.fadeOpacity,
u_wind_min,
u_wind_max,
u_wind_res,
u_extent,
u_particles_res: source.particleRes,
u_rand_seed: Math.random(),
u_particles: bufferStruct.particleStateTexture0,
u_speed_factor: styleOptions.speedFactor,
u_drop_rate: styleOptions.dropRate,
u_drop_rate_bump: styleOptions.dropRateBump,
u_bbox: [ source.extent[0][0], source.extent[0][1], source.extent[1][0], source.extent[1][1] ]
});
const updateMesh = new THREE.Mesh(imageGeo, updateMaterial);
const drawMesh = new THREE.Points(this.geometry, drawMaterial);
screenPass01.add(updateMesh);
screenPass02.add(drawMesh);
// screenPass.render();
const imagematerial = new WindMaterial({
u_texture: screenPass02.texture,
u_opacity: 1.0
});
// drawMesh.material.setValue('u_particles',screenPass01.texture)
const imageMesh = new THREE.Mesh(imageGeo, imagematerial);
drawMesh.onBeforeRender = function() {
const temp = bufferStruct.particleStateTexture0;
bufferStruct.particleStateTexture0 = screenPass01.pass.texture;
screenPass01.pass.texture = temp;
updateMesh.material.uniforms.needsUpdate = true;
// screenPass01.render();
};
// updateMesh.onAfterRender = function(){
// drawMesh.material.setValue('u_particles',screenPass01.texture)
// }
// imageMesh.onBeforeRender=function(){
// // imageMesh.material.setValue('u_particles',screenPass02.texture)
// imageMesh.material.uniforms.needsUpdate = true;
// screenPass02.render();
// }
this.add(drawMesh);
return this;
// this.imageGeo = new ImageGeometry({
// // position:[[0, 0, 0], [1, 0, 0], [1, 1,0],[0, 0,0], [1, 1,0],[0, 1,0]],
// position: buffer.bufferStruct.imgPos,
// uv: [[ 0, 1 ], [ 1, 1 ], [ 1, 0 ], [ 0, 1 ], [ 1, 0 ], [ 0, 0 ]]
// });
// this.imageMaterial = new ImageMaterial({
// name: 'TextureMat2',
// u_texture: buffer.bufferStruct.u_wind,
// u_opacity: 1.0
// });
// const camera = this.scene.render.camera;
// const { bufferStruct } = this.buffer;
// const styleOptions = this.get('styleOptions');
// const u_wind_max = source.get('wind_max');
// const u_wind_min = source.get('wind_min');
// const u_wind_res = source.get('wind_res');
// const backgroudNode = this.layerNode.createChild('backgroundNode');
// this.backgroudRenderer = backgroudNode.createAbility(AGeometryRenderer);
// this.backgroudRenderer.id = 'backgroudRenderer';
// this.updateTarget0 = new RenderTarget('updateTarget0', { width: targetSize, height: targetSize, clearColor: [ 0, 0.0, 0.0, 0.0 ] });
// this.updateTarget1 = new RenderTarget('updateTarget1', { width: targetSize, height: targetSize, clearColor: [ 0, 0.0, 0.0, 0.0 ] });
// this.screenTarget = new RenderTarget('screenTarget', { width: targetSize, height: targetSize, clearColor: [ 0, 0.0, 0.0, 0.0 ] });
// this.backgroundTarget = new RenderTarget('backgroundTarget', { width: targetSize, height: targetSize, clearColor: [ 0, 0.0, 0.0, 0.0 ] });
// // 绘制粒子
// this.updateTarget1.texture = bufferStruct.particleStateTexture1;
// this.backgroundTarget.texture = bufferStruct.backgroundTexture;
// const drawMaterial = this.drawMaterial = new DrawMaterial({
// u_wind: bufferStruct.u_wind,
// u_particles: bufferStruct.particleStateTexture0,
// u_bbox: [ source.extent[0][0], source.extent[0][1], source.extent[1][0], source.extent[1][1] ],
// u_wind_max,
// u_wind_min,
// u_opacity: 1.0,
// u_particles_res: source.particleRes,
// u_color_ramp: bufferStruct.colorTexture
// });
// const drawMaterial2 = this.drawMaterial2 = new DrawMaterial({
// u_wind: bufferStruct.u_wind,
// u_particles: bufferStruct.particleStateTexture0,
// u_bbox: [ source.extent[0][0], source.extent[0][1], source.extent[1][0], source.extent[1][1] ],
// u_wind_max,
// u_wind_min,
// u_opacity: 0.9,
// u_particles_res: source.particleRes,
// u_color_ramp: bufferStruct.colorTexture
// });
// // 更新粒子
// const updateMaterial = this.updateMaterial = new UpdateMaterial({
// name: 'updateMaterial',
// u_wind: buffer.bufferStruct.u_wind, // 风场 uv
// u_opacity: styleOptions.fadeOpacity,
// u_wind_min,
// u_wind_max,
// u_wind_res,
// u_extent,
// u_particles_res: source.particleRes,
// u_rand_seed: Math.random(),
// u_particles: bufferStruct.particleStateTexture0,
// u_speed_factor: styleOptions.speedFactor,
// u_drop_rate: styleOptions.dropRate,
// u_drop_rate_bump: styleOptions.dropRateBump,
// u_bbox: [ source.extent[0][0], source.extent[0][1], source.extent[1][0], source.extent[1][1] ]
// });
// this.drawParticles();// 生成geometry;
// this._drawTexture(bufferStruct.u_wind, 0); // render pass geo
// this.updatePass = new GeoRenderPass('updateTarget', -1, this.updateTarget0, 1, updateMaterial, this.layerId, () => {
// this.updateParticles(); // 更新粒子位置
// });
// this.screenPass = new GeoRenderPass('screenTarget', -1, this.screenTarget, 1, drawMaterial, 'wind', () => {
// // this._drawScreen(); // 更新过后的粒子绘制到画布
// });
// const renderer = camera.sceneRenderer;
// renderer.addRenderPass(this.screenPass);
// renderer.addRenderPass(this.updatePass);
// this.updateParticles();
// this._drawScreen();
// return this;
});
}
_drawScreen() {
// 交换背景
this._drawWindTexture(this.screenTarget.texture, 1.0);
//
this._drawBackGround();
const temp = this.backgroundTarget;
this.backgroundTarget = this.screenTarget;
this.screenTarget = temp;
}
_drawBackGround() {
// 将文理
const TextureMat = new WindMaterial({
name: 'TextureMat',
u_texture: this.backgroundTarget.texture,
u_opacity: 0.99
});
this.backgroudRenderer.geometry = this.screenGeo;
this.backgroudRenderer.setMaterial(TextureMat);
}
_drawTexture(texture, opacity) {
// 将文理
const TextureMat = new WindMaterial({
name: 'TextureMat',
u_texture: texture,
u_opacity: opacity
});
this.renderer.geometry = this.screenGeo;
this.renderer.setMaterial(TextureMat);
}
_drawWindTexture(texture) {
// 将文理
const TextureMat = new WindMaterial({
name: 'TextureMat',
u_texture: texture,
u_opacity: 1
});
this.renderer.geometry = this.screenGeo;
this.renderer.setMaterial(TextureMat);
}
drawParticles() {
const windNode = this.layerNode.createChild('windNode');
this.windRenderer = windNode.createAbility(AGeometryRenderer);
this.windRenderer.id = 'wind';
const source = this.layerSource;
const drawGeometry = new DrawGeometry({
index: source.particleIndices
});
this.windRenderer.renderPriority = 1;
this.windRenderer.geometry = drawGeometry;
this.windRenderer.setMaterial(new BlankMaterial('blanktest')); // 直接绘制到屏幕
// this.backgroudRenderer.geometry = drawGeometry;
// this.backgroudRenderer.setMaterial(this.drawMaterial2)
// this.windRenderer.setMaterial(new BlankMaterial('blanktest'));
}
// 更新粒子运动位置
updateParticles() {
this.updatePass.replaceMaterial.setValue('u_particles', this.updateTarget0.texture);
this.drawMaterial.setValue('u_particles', this.updateTarget0.texture);
this.drawMaterial2.setValue('u_particles', this.updateTarget1.texture);
const temp = this.updateTarget0;
this.updateTarget0 = this.updateTarget1;
this.updateTarget1 = temp;
this.updatePass.renderTarget = this.updateTarget0;
}
initGeometry(a_index) {
this.geometry = new THREE.BufferGeometry();
this.geometry.addAttribute('a_index', new THREE.Float32BufferAttribute(a_index, 1));
}
initUpdateGeometry() {
this.geometry = new THREE.BufferGeometry();
}
initImageGeometry(attributes) {
const geometry = new THREE.BufferGeometry();
geometry.addAttribute('position', new THREE.Float32BufferAttribute(new Float32Array([ 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0 ]), 3));
geometry.addAttribute('uv', new THREE.Float32BufferAttribute(attributes.uvs, 2));
return geometry;
}
}

View File

@ -1,47 +0,0 @@
import Layer from '../core/layer';
import PointGeometry from '../geom/bufferGeometry/point';
import { PointMaterial } from '../geom/material/point';
import { TextMaterial } from '../geom/material/text';
import TextGeometry from '../geom/bufferGeometry/text';
import { textBuffer } from '../geom/buffer/index';
import ColorUtil from '../attr/color-util';
export default class textPointLayer extends Layer {
shape(type) {
this.shape = type;
return this;
}
render() {
this.init();
const styleOptions = this.get('styleOptions');
const source = this.layerSource;
const buffer = new textBuffer(
{
coordinates: source.geoData,
properties: this.StyleData
}
);
buffer.bufferStruct.drawMode = 'POINTS';
const geometry = new TextGeometry(buffer.bufferStruct);
const borderColor = ColorUtil.toRGB(styleOptions.borderColor).map(e => e / 255);
if (borderColor.length === 3) {
borderColor.push(1.0);
}
const material = new PointMaterial({
name: 'text',
u_texture: buffer.bufferStruct.utexture,
u_opacity: styleOptions.opacity,
u_strokeWidth: 0,
u_stroke: borderColor,
u_zoom: this.scene.map.getZoom()
});
this.scene.map.on('zoomchange', e => {
const zoom = this.scene.map.getZoom();
material.setValue('u_zoom', zoom);
});
this.renderer.geometry = geometry;
this.renderer.setMaterial(material);
return this;
}
}

View File

@ -1,117 +0,0 @@
import Base from '../core/base';
import { Matrix4 } from '../core/three';// Todo Math
const MAXZOOM = 0;
export class MapBox extends Base {
getDefaultCfg() {
return {
resizeEnable: true,
viewMode: '3D'
};
}
constructor(container, cfg) {
super(cfg);
this.container = container;
this.initMap();
this.map.on('load', () => {
this.addOverLayer();
this.emit('mapLoad');
});
}
initMap() {
mapboxgl.accessToken = 'pk.eyJ1IjoibHp4dWUiLCJhIjoiYnhfTURyRSJ9.Ugm314vAKPHBzcPmY1p4KQ';
this.set('container', this.container);
this.map = new mapboxgl.Map(this._attrs);
}
addOverLayer() {
const canvasContainer = this.map.getCanvasContainer();
this.canvasContainer = canvasContainer;
this.canvas = document.createElement('canvas');
this.canvas.className = 'canvas-layer';
this.canvas.id = 'canvaslayer';
canvasContainer.appendChild(this.canvas);
this._reSizeCanvas();
}
asyncCamera(renderCamera, cameraNode, layerNode) {
this.updateCamera(renderCamera, cameraNode, layerNode);
this.map.on('move', () => { this.updateCamera(renderCamera, cameraNode, layerNode); });
this.map.on('resize', () => { this._reSizeCanvas(); });
}
// updateCamera(renderCamera, cameraNode, layerNode) {
// const camera = this.getCameraOptions();
// const scale = Math.pow(2, (this.map.getZoom() - MAXZOOM));
// const { near, far, width, height, pitch, rotation, cameraToCenterDistance, x, y } = camera;
// // cameraToCenterDistance = cameraToCenterDistance * scale;
// const cameraTarget = [ 0, 0, 0 ];
// // const cameraUp = [ -Math.cos(pitch) * Math.sin(rotation), Math.cos(pitch) * Math.cos(rotation), Math.sin(pitch) * cameraToCenterDistance ];
// // const cameraUp = [ -Math.cos(pitch) * Math.sin(rotation) * cameraToCenterDistance, Math.cos(pitch) * Math.cos(rotation) * cameraToCenterDistance, Math.sin(pitch) ];
// // const scale = Math.pow(2, this.map.getZoom());
// const cameraTranslateZ = mat4.create();
// const cameraRotateX = mat4.create();
// const cameraRotateZ = mat4.create();
// const cameraWorldMatrix = mat4.create();
// mat4.fromTranslation(cameraTranslateZ, [ 0, 0, cameraToCenterDistance ]);
// mat4.fromXRotation(cameraRotateX, pitch);
// mat4.fromZRotation(cameraRotateZ, rotation);
// mat4.mul(cameraWorldMatrix, cameraTranslateZ, cameraWorldMatrix);
// mat4.mul(cameraWorldMatrix, cameraRotateX, cameraWorldMatrix);
// mat4.mul(cameraWorldMatrix, cameraRotateZ, cameraWorldMatrix);
// // modle
// const worldmatrix = mat4.create();
// const scaleMat = mat4.create();
// const translateMap = mat4.create();
// const rotateMap = mat4.create();
// const translateCenter = mat4.create();
// mat4.fromScaling(scaleMat, [ scale, scale, scale ]);
// mat4.fromTranslation(translateMap, [ -x, y, 0 ]);
// mat4.fromTranslation(translateCenter, [ 256, -256, 0 ]);
// mat4.fromZRotation(rotateMap, Math.PI);
// // mat4.mul(worldmatrix,rotateMap,worldmatrix);
// // mat4.mul(worldmatrix,translateCenter,worldmatrix);
// // mat4.mul(worldmatrix,cameraRotateZ,worldmatrix);
// mat4.mul(worldmatrix, scaleMat, worldmatrix);
// mat4.mul(worldmatrix, translateMap, worldmatrix);
// renderCamera.setPerspective(45, width, height, near, far);
// cameraNode.setModelMatrix(cameraWorldMatrix);
// layerNode.setModelMatrix(worldmatrix);
// // console.log(layerNode.children[0]);
// // cameraNode.lookAt(cameraTarget,cameraUp);
// cameraNode.lookAt(cameraTarget, [ 0, 0, 1 ]);
// renderCamera.render();
// }
_resize() {
this._reSizeCanvas();
}
_reSizeCanvas() {
const canvas = this.map.getCanvas();
this.canvas.style.cssText = canvas.style.cssText;
this.canvas.width = canvas.width;
this.canvas.height = canvas.height;
}
getCameraOptions() {
// fov, near, far, height, pitch, rotation, position
const fov = 0.6435011087932844;
// const altitude = 1.5;
const Radian = Math.PI / 180;
const pitch = this.map.getPitch() * Radian;
const rotation = -this.map.getBearing() * Radian;
const cameraToCenterDistance = 0.5 / Math.tan(fov / 2) * this.map.transform.height;
const halfFov = fov / 2;
const groundAngle = Math.PI / 2 + this.map.transform._pitch;
const topHalfSurfaceDistance = Math.sin(halfFov) * cameraToCenterDistance / Math.sin(Math.PI - groundAngle - halfFov);
const furthestDistance = Math.cos(Math.PI / 2 - this.map.transform._pitch) * topHalfSurfaceDistance + cameraToCenterDistance;
const far = furthestDistance * 1.01;
// Calculate z value of the farthest fragment that should be rendered.
const { x, y, width, height } = this.map.transform;
return {
fov, near: 0.01, far, cameraToCenterDistance, x, y, width, height, pitch, rotation
};
}
}

View File

@ -1,11 +1,14 @@
import Base from '../core/base';
import * as Theme from '../theme/index';
import Util from '../util';
import { scene } from '../global';
const DEG2RAD = Math.PI / 180;
export class MapProvider extends Base {
getDefaultCfg() {
return {
return Util.assign(scene, {
resizeEnable: true,
viewMode: '3D'
};
});
}
constructor(container, cfg) {
super(cfg);
@ -17,7 +20,20 @@ export class MapProvider extends Base {
}, 100);
}
initMap() {
const mapStyle = this.get('mapStyle');
switch (mapStyle) {
case 'dark' :
this.set('mapStyle', Theme.DarkTheme.mapStyle);
break;
case 'light':
this.set('mapStyle', Theme.LightTheme.mapStyle);
break;
default:
this.set('mapStyle', Theme.LightTheme.mapStyle);
}
this.set('zooms', [ this.get('minZoom'), this.get('maxZoom') ]);
this.map = new AMap.Map(this.container, this._attrs);
}

View File

@ -1,5 +1,6 @@
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() {
@ -10,7 +11,8 @@ export default class CSVSource extends Source {
const y1 = this.get('y1');
this.propertiesData = [];// 临时使用
this.geoData = [];
const csvdata = csvParse(data);
let csvdata = data;
Util.isArray(csvdata) || (csvdata = csvParse(data));
this.propertiesData = csvdata;
csvdata.forEach((col, featureIndex) => {

View File

@ -1,4 +1,5 @@
export { default as geojson } from './geojsonSource';
export { default as csv } from './csvSource';
export { default as array } from './csvSource';
export { default as basic } from '../core/source';
export { default as imageSource } from './imageSource';

View File

@ -10,7 +10,6 @@ export class RainSource extends imageSource {
this._loadData();
}
_genaratePoints() {
const extent = this.get('extent');
const numParticles = 512 * 512;
const particleRes = this.particleRes = Math.ceil(Math.sqrt(numParticles));

View File

@ -1,6 +1,4 @@
const LightTheme = {
mapStyle: 'amap://styles/a80c558f91b29cf56fa47f895fb1773c?isPublic=true'
};
export default LightTheme;
const DarkTheme = {
mapStyle: 'amap://styles/ba3e9759545cd618392ef073c0dfda8c?isPublic=true'
};
export default DarkTheme;

View File

@ -1,4 +0,0 @@
const DarkTheme = {
mapStyle: 'amap://styles/ba3e9759545cd618392ef073c0dfda8c?isPublic=true'
};
export default DarkTheme;

6
src/theme/index.js Normal file
View File

@ -0,0 +1,6 @@
import DarkTheme from './dark';
import LightTheme from './light';
export {
DarkTheme,
LightTheme
};

6
src/theme/light.js Normal file
View File

@ -0,0 +1,6 @@
const LightTheme = {
mapStyle: 'amap://styles/a80c558f91b29cf56fa47f895fb1773c?isPublic=true'
};
export default LightTheme;

View File

@ -44,6 +44,6 @@ module.exports = {
},
plugins: [
new webpack.NoEmitOnErrorsPlugin(),
new webpack.optimize.AggressiveMergingPlugin(),
new webpack.optimize.AggressiveMergingPlugin()
]
};