Merge branch 'dev' into 'master'

Dev



See merge request !1
This commit is contained in:
象数 2018-11-20 15:06:04 +08:00
commit b88ea86164
149 changed files with 2941 additions and 2572 deletions

View File

@ -3,12 +3,6 @@
"transform-remove-strict-mode"
],
"presets": [
[
"env",
{
"loose": true,
"modules": false
}
]
"@babel/preset-env"
]
}

View File

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

View File

@ -1,16 +1,18 @@
const path = require('path');
module.exports = {
babelrc: {
presets: [
'es2015',
'stage-0'
],
sourceMaps: 'inline'
"@babel/preset-env"
]
},
extensions: ['.js'],
include: [
'node_modules/**/src/gl-matrix/**/*.js '
'src/**/*.js',
'test/**/*.js',
'node_modules/three/**/*.js'
],
exclude: [
'bower_components/**/*.js',
'node_modules/@babel/**/*.js'
]
}

View File

@ -6,6 +6,7 @@
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<meta name="geometry" content="diagram">
<link rel="stylesheet" href="./assets/common.css">
<link rel="stylesheet" href="./assets/info.css">
<title>point_circle</title>
<style>
#map { position:absolute; top:0; bottom:0; width:100%; }
@ -14,40 +15,95 @@
<body>
<div id="map"></div>
<div class='info-panel top-right'>
<h4>杭州市微博签到数据</h4>
<p>
<label>min</label><input name="minaqi" type="range" step="1" min="0" max="30000" value=500> <label>500</label>
</p>
<p>
<label>max</label><input name="maxaqi" type="range" step="1" min="0" max="30000" value=30000><label>30000</label>
</p>
<p><label>color</label><select>
<option value ="blue">blue</option>
<option value ="red">red</option>
<option value="orange">orange</option>
<option value="green">green</option>
<option value="yellow">yellow</option>
<option value="purple">purple</option>
</select> </p>
<p><label>shape</label><select>
<option value ="circle">circle</option>
<option value ="triangle">triangle</option>
<option value="hexagon">hexagon</option>
<option value="square">square</option>
</select> </p>
<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 colorObj ={
blue: ["#E8FCFF", "#CFF6FF", "#A1E9ff", "#65CEF7", "#3CB1F0", "#2894E0", "#1772c2", "#105CB3", "#0D408C", "#002466"].reverse(),
red: ["#FFF4F2", "#FFDFDB", "#FAADAA", "#F77472", "#F04850", "#D63147", "#BD223E", "#A81642", "#820C37", "#5C0023"].reverse(),
orange:["#FFF7EB", "#FFECD4", "#FAD09D", "#F7B16A", "#F08D41", "#DB6C2C", "#C2491D", "#AD2B11", "#871D0C", "#610800"].reverse(),
green:["#FAFFF0", "#EBF7D2", "#C8E695", "#A5D660", "#7DC238", "#59A616", "#3F8C0B", "#237804", "#125200", "#082B00"].reverse(),
yellow:["#FFFFE8", "#FFFECC", "#FAF896", "#F7E463", "#F0CE3A", "#DBB125", "#C29117", "#AD7410", "#87500C", "#613000"].reverse(),
purple:["#FCF2FF", "#F5DEFF", "#DDB3F2", "#BE7BE3", "#9B4ECF", "#7737B3", "#5B2899", "#411C85", "#270F5E", "#100338"].reverse()
}
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: 11.6
});
window.scene = scene;
scene.on('load', () => {
scene.on('loaded', () => {
$.get('https://gw.alipayobjects.com/os/rmsportal/epnZEheZeDgsiSjSPcCv.json', data => {
scene.PointLayer({
const circleLayer = scene.PointLayer({
zIndex: 2
})
.source(data)
.shape('2d:circle')
.size('value', [ 8, 80 ]) // default 1
.filter('value', field_8 => {
return field_8 * 1 > 500;
.source(data,{
scale:{
min:0,
max:1000,
type:'linear'
}
})
.color('type', [ '#002466', '#0D408C', '#105CB3', '#1A76C7', '#2894E0', '#3CB4F0', '#65CEF7', '#98E3FA', '#CFF6FF', '#E8FCFF' ])
.shape('2d:circle')
.size('value', [ 0, 60]) // default 1
//.size('value', [ 10, 300]) // default 1
.active(true)
.filter('value', field_8 => {
return field_8 * 1 > 500;
})
.color('type', colorObj.red)
.style({
stroke: 'rgb(255,255,255)',
strokeWidth: 1,
opacity: 0.9
})
.render();
$('.info-panel input').change(function(){
$(this).next().text($(this).val());
const min = $('.info-panel input').val();
const max = $($('.info-panel input')[1]).val();
circleLayer.filter('value',(value)=>{
return (value>=min && value<=max)
}).render();
})
$('.info-panel select').change(function(){
const color = $(this).val();
console.time('color');
circleLayer.color('type',colorObj[color]).render();
console.timeEnd('color')
})
});
});
</script>

View File

@ -0,0 +1,54 @@
<!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.037828998113099, 30.086317611850635 ],
pitch: 36.002858,
zoom: 5.44
});
window.scene = scene;
scene.on('loaded', () => {
$.get('./data/rainfall.json', data => {
scene.PointLayer({
zIndex: 2
})
.source(data.list, {
type: 'array',
x: 'j',
y: 'w',
})
.shape('3d:circle')
.size('t',(level)=> {
return [4,4,(level+40)];
})
.active(true)
.color('t', ["#002466","#105CB3","#2894E0","#CFF6FF","#FFF5B8","#FFAB5C","#F27049","#730D1C"])
.render();
});
});
</script>
</body>
</html>

View File

@ -19,18 +19,17 @@
<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: 'amap://styles/5a64d4f1af910091f9cc3367dfc4a1dc', // 样式URL
mapStyle: 'dark', // 样式URL
center: [ 121.51222019389274, 31.23572578718841 ],
pitch: 0,
zoom: 11
});
window.scene = scene;
scene.on('load', () => {
$.get('https://gw.alipayobjects.com/os/rmsportal/mUQPWCYaxOfiSznuANvG.txt', data => {
scene.on('loaded', () => {
// ./data/mUQPWCYaxOfiSznuANvG.txt
$.get('./data/00.csv', data => {
scene.PointLayer({
zIndex: 2
})
@ -39,33 +38,8 @@ 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')
.size(1.0)
.color('#0D408C')
.style({
stroke: 'rgb(255,255,255)',
strokeWidth: 0,

137
demos/01_point_image.html Normal file
View File

@ -0,0 +1,137 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<meta name="geometry" content="diagram">
<link rel="stylesheet" href="./assets/common.css">
<link rel="stylesheet" href="./assets/info.css">
<title>point_distribute</title>
<style>
body {
margin:0px;
}
#map { position:absolute; top:0; bottom:0; width:100%; }
</style>
</head>
<body>
<div id="map"></div>
<div class ='info'>
<div class="input-card" style='width: 12rem;'>
<div class="input-item">
<input type="radio" name='func' checked=true value=0><span class="input-text">全部</span>
<input type="radio" name='func' value=0><span class="input-text">可用车</span>
<input type="radio" name='func' value=1><span class="input-text">不可用</span>
</div>
</div>
</div>
<script src="https://webapi.amap.com/maps?v=1.4.8&key=15cd8a57710d40c9b7c0e3cc120f1200&plugin=Map3D"></script>
<script src="https://unpkg.com/supercluster@4.1.1/dist/supercluster.min.js"></script>
<script src="./assets/jquery-3.2.1.min.js"></script>
<script src="../build/L7.js"></script>
<script>
const scene = new L7.Scene({
id: 'map',
mapStyle: 'light', // 样式URL
center: [ 120.1243238, 30.27331571 ],
pitch: 0,
zoom: 14,
minZoom: 9
});
window.scene = scene;
scene.on('loaded', () => {
$.get('./data/pointbike.json', data => {
var extent = [ 110,29.2378,122.189,33.3173]
var dataindex = supercluster({radius:80});
dataindex.load(data.features);
var clusterData = dataindex.getClusters(extent,13);
scene.PointLayer({
zIndex: 4,
maxZoom:15.5
})
.source({
"type": "FeatureCollection",
"features":clusterData
})
.color('#6492E9')
.size('point_count',[1,30])
.shape('2d:circle')
.style({
opacity:0.8
})
.render();
// 自行车数据
scene.PointLayer({
zIndex: 4,
minZoom:15.5,
})
.source(data)
.color('power',(v)=>{
return v > 5 ? '#4F93EA' :'#F5684A'
})
.active({fill:'#91C25B'})
.size(8)
.shape('2d:circle')
.style({
opacity:1.0
})
.render();
});
$.get('./data/fence.json', data => {
scene.LineLayer({
zIndex: 5
})
.source(data)
.shape('line')
.size([2,0])
.color('#2F54EB')
.style({
opacity:1.0,
})
.render();
scene.PolygonLayer({
zIndex: 0
})
.source(data)
.shape('fill')
.size([2,0])
.color('#2F54EB')
.style({
opacity:0.05,
})
.render();
});
$.getJSON('./data/pointZone.json', data => {
const fenceLayer = scene.LineLayer({
zIndex: 1,
minZoom:16,
})
.source(data)
.size([1.5,0])
.shape('line')
.color("#2F54EB")
.style({
opacity:1.0,
})
.render();
});
});
</script>
</body>
</html>

View File

@ -17,34 +17,34 @@
<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="./assets/geotiff.browserify.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: 'amap://styles/5a64d4f1af910091f9cc3367dfc4a1dc', // 样式URL
center: [ 116.2825, 39.9 ],
pitch: 0,
zoom: 3
mapStyle: 'dark', // 样式URL
center: [ 102.615023, 23.107799],
pitch: 15,
zoom: 14,
});
scene.on('load', () => {
$.get('https://gw.alipayobjects.com/os/rmsportal/UEXQMifxtkQlYfChpPwT.txt', data => {
scene.on('loaded', () => {
$.get('./data/contour.geojson', data => {
// data.features = data.features.slice(0,1);
scene.LineLayer({
zIndex: 2
})
.source(data, { // lng1,lat1,lng2,lat2
type: 'csv',
x: 'lng1',
y: 'lat1',
x1: 'lng2',
y1: 'lat2'
})
.shape('arc')
.size(2.0)
.color('value', [ '#002466', '#0D408C', '#105CB3', '#1A76C7', '#2894E0', '#3CB4F0', '#65CEF7', '#98E3FA', '#CFF6FF', '#E8FCFF' ])
.source(data)
.size('ELEV',(value)=>{
return [1,(value-1000)*7];
})
.active(true)
.shape('line')
.color('ELEV',["#E8FCFF", "#CFF6FF", "#A1E9ff", "#65CEF7", "#3CB1F0", "#2894E0", "#1772c2", "#105CB3", "#0D408C", "#002466"].reverse())
.render();
});
});
</script>

View File

@ -0,0 +1,107 @@
<!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>one belt one road </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: 'light', // 样式URL
center: [ 120.3672, 36.0968 ],
pitch: 0,
zoom: 3
});
scene.on('loaded', () => {
scene.image.addImage('marker', './data/onebelt/marker.png');
scene.image.addImage('local', './image/local.png');
$.getJSON('./data/onebelt/regions.json', region => {
const color = [ 'rgb(22,32,101)', 'rgb(28,43,127)', 'rgb(36,68,142)', 'rgb(45,94,158)', 'rgb(53,119,174)', 'rgb(61,145,190)', 'rgb(70,170,206)', 'rgb(98,190,210)', 'rgb(138,205,206)', 'rgb(179,221,204)', 'rgb(220,236,201)' ];
var points = region.features.map((feature)=>{
return feature.properties;
})
const layer = scene.PolygonLayer({
zIndex:1,
})
.source(region)
.color('cname',(value)=>{
return (value =='中国' ? 'rgba(46,149,169,0.45)': 'rgba(227,244,244,0.1)');
})
.shape('fill')
.render();
});
$.getJSON('./data/onebelt/seaway.geojson', contourData => {
const layer = scene.LineLayer({
zIndex:2}
)
.source(contourData)
.color('rgb(79,147,234)')
.size([ 1.5, 0 ])
.shape('line')
.style({
'lineType':'solid'
})
.render();
});
$.getJSON('./data/onebelt/landway.json', contourData => {
const landlayer = scene.LineLayer(
{zIndex:2}
)
.source(contourData)
.color('rgb(11,94,69)')
.size([ 1.5, 0 ])
.shape('line')
.style({
// 'lineType':'solid'
})
.render();
});
$.getJSON('./data/onebelt/city.geojson', city => {
var makerLayer = scene.PointLayer({
zIndex: 4
})
.source(city)
.size(20.0)
.shape('image:local')
.color('#0D408C')
.render();
var makerText = scene.PointLayer({
zIndex: 8,
minZoom:5,
})
.source(city)
.size(14.0)
.shape('name', 'text')
.color('rgba(0,0,0,0.85)')
.style({
textOffset:[-20,22],
stroke: '#fff',
strokeWidth: 4,
})
.render();
})
})
</script>
</body>
</html>

View File

@ -21,34 +21,41 @@
<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 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
});
window.scene = scene;
scene.on('load', () => {
$.getJSON('https://gw.alipayobjects.com/os/rmsportal/oOzMjBOaxFROWLBYeqTB.json', city => {
scene.on('loaded', () => {
$.getJSON('./data/chinandvohexagon.geojson', city => {
citylayer = scene.PolygonLayer()
.source(city)
.color('gdp', [ '#002466', '#0D408C', '#105CB3', '#1A76C7', '#2894E0', '#3CB4F0', '#65CEF7', '#98E3FA', '#CFF6FF', '#E8FCFF' ])
.color('sum', ["#FAFFF0", "#EBF7D2", "#C8E695", "#A5D660", "#7DC238", "#59A616", "#3F8C0B", "#237804", "#125200", "#082B00"])
.shape('extrude')
.filter('gdp', gdp => {
return gdp > 0;
.size('max',(value)=>{
return value * 1000;
})
.size('gdp', [ 1000, 5000000 ])
// .active({ fill: 'red' })
.active(true)
.style({
opacity: 1
opacity: 1.0
})
.render();
const citylayer2 = scene.PolygonLayer()
.source(city)
.shape('line')
.color('#fff')
.style({
opacity: 1
})
.render();
});
});

View File

@ -6,46 +6,82 @@
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<meta name="geometry" content="diagram">
<link rel="stylesheet" href="./assets/common.css">
<link rel="stylesheet" href="./assets/info.css">
<title>hexagon demo</title>
<style>
body {margin: 0;}
#map { position:absolute; top:0; bottom:0; width:100%; }
</style>
</head>
<body>
<div id = 'gui' style="position:absolute;top:0px;right:0px;z-index:2;"></div>
<div id="map"></div>
<div id ="info" class ="tooltip" style="display:none">
</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 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 colorObj ={
blue: ["#E8FCFF", "#CFF6FF", "#98E3FA", "#65CEF7", "#3CB4F0", "#2894E0", "#1A76C7", "#105CB3", "#0D408C", "#002466"],
red: ["#FFF4F2", "#FFDFDB", "#FAADAA", "#F77472", "#F04850", "#D63147", "#BD223E", "#A81642", "#820C37", "#5C0023"],
orange:["#FFF7EB", "#FFECD4", "#FAD09D", "#F7B16A", "#F08D41", "#DB6C2C", "#C2491D", "#AD2B11", "#871D0C", "#610800"],
green:["#FAFFF0", "#EBF7D2", "#C8E695", "#A5D660", "#7DC238", "#59A616", "#3F8C0B", "#237804", "#125200", "#082B00"],
yellow:["#FFFFE8", "#FFFECC", "#FAF896", "#F7E463", "#F0CE3A", "#DBB125", "#C29117", "#AD7410", "#87500C", "#613000"],
purple:["#FCF2FF", "#F5DEFF", "#DDB3F2", "#BE7BE3", "#9B4ECF", "#7737B3", "#5B2899", "#411C85", "#270F5E", "#100338"],
}
const scene = new L7.Scene({
id: 'map',
mapStyle: 'amap://styles/5a64d4f1af910091f9cc3367dfc4a1dc', // 样式URL
mapStyle: 'light', // 样式URL
center: [ 120.4047, 30.0679 ],
pitch: 0,
zoom: 4
});
window.scene = scene;
scene.on('load', () => {
scene.on('loaded', () => {
var colors = ["#FFF5B8","#FFDC7D","#FFAB5C","#F27049","#D42F31","#730D1C"];
$.getJSON('https://gw.alipayobjects.com/os/rmsportal/JToMOWvicvJOISZFCkEI.json', city => {
citylayer = scene.PolygonLayer()
const citylayer = scene.PolygonLayer()
.source(city)
.color('pm2_5_24h', [ '#002466', '#0D408C', '#105CB3', '#1A76C7', '#2894E0', '#3CB4F0', '#65CEF7', '#98E3FA', '#CFF6FF', '#E8FCFF' ])
//.color('pm2_5_24h',["#FFF5B8","#FFDC7D","#FFAB5C","#F27049","#D42F31","#730D1C"])
.color('pm2_5_24h',(p)=>{
if(p>120){
return colors[5];
} else if(p>65){
return colors[4];
} else if(p>30) {
return colors[3];
} else if(p>15){
return colors[2];
} else if(p>8){
return colors[1];
}else {
return colors[0];
}
})
.shape('fill')
// .active({ fill: 'red' })
.active(true)
.style({
opacity: 1
})
.render();
const citylayer2 = scene.PolygonLayer()
.source(city)
.shape('line')
.color('#fff')
.style({
opacity: 0.1
})
.render();
citylayer.on('click',(e)=>{
$("#info").css({'left': e.pixel.x,'top':e.pixel.y, display:'block'});
$("#info").html(`<p>${e.feature.properties.area || e.feature.properties.name }<span">${e.feature.properties.pm2_5_24h || 0}</span></p>`);
})
});
});

View File

@ -14,30 +14,32 @@
</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 ],
pitch: 45,
zoom: 4
mapStyle: 'dark', // 样式URL
center: [ 121.2680, 30.3628 ],
pitch: 0,
zoom: 15,
minZoom: 4,
maxZoom: 18
});
scene.on('load', () => {
scene.on('loaded', () => {
// 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 ]
source('./image/hangzhoubay.jpg',{
extent: [ 121.1680, 30.2828, 121.3840, 30.4219 ]
})
.style({
opacity:1.0,
})
.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('loaded', () => {
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>

View File

@ -6,7 +6,7 @@
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<meta name="geometry" content="diagram">
<link rel="stylesheet" href="./assets/common.css">
<title>hexagon demo</title>
<title>point_circle</title>
<style>
#map { position:absolute; top:0; bottom:0; width:100%; }
</style>
@ -20,22 +20,29 @@
<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
center: [ 116.2825, 39.9 ],
mapStyle: 'dark', // 样式URL
center: [ 120.19382669582967, 30.258134 ],
pitch: 0,
zoom: 3
});
scene.on('load', () => {
$.get('https://gw.alipayobjects.com/os/rmsportal/lZGtNaYGNHtAIkcjVvfp.json', data => {
scene.LineLayer({
window.scene = scene;
scene.on('loaded', () => {
$.get('./data/provincePoint.geojson', data => {
scene.PointLayer({
zIndex: 2
})
.source(data)
.color('#3CB4F0')
.render();
.source(data)
.shape('name', 'text')
.size(10) // default 1
.color('#fff')
.style({
stroke: '#999',
strokeWidth: 2,
opacity: 0.85
})
.render();
});
});

84
demos/07_city.html Normal file
View File

@ -0,0 +1,84 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<meta name="geometry" content="diagram">
<link rel="stylesheet" href="./assets/common.css">
<link rel="stylesheet" href="./assets/info.css">
<title>city</title>
<style>
#map { position:absolute; top:0; bottom:0; width:100%; }
</style>
</head>
<body>
<div id="map">
<div id ="info" class ="tooltip" style="display:none">
</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="../build/L7.js"></script>
<script>
const scene = new L7.Scene({
id: 'map',
mapStyle: 'light', // 样式URL
center: [120.173104, 30.244072],
pitch: 66.50572,
zoom: 15.79,
minZoom:10
});
window.scene = scene;
scene.on('loaded', () => {
$.get('./data/water.geojson', data => {
scene.PolygonLayer({
zIndex: 0
})
.source(data)
.shape('fill')
.color('rgb(79,174,234)')
.render();
});
$.get('./data/land.geojson', data => {
scene.PolygonLayer({
zIndex: 0
})
.source(data)
.shape('fill')
.color('rgb(156,194,116)')
.render();
});
$.get('./data/river.geojson', data => {
scene.LineLayer({
zIndex: 2
})
.source(data)
.shape('line')
.size([3,0])
.color('rgb(79,174,234)')
.render();
});
$.get('./data/build.geojson', data => {
citylayer = scene.PolygonLayer({
zIndex: 2
})
.source(data)
.shape('extrude')
.active({fill:'red'})
.size('floor',[10,2000])
.color('rgba(242,246,250,0.96)')
.render();
citylayer.on('click',(e)=>{
$("#info").css({'left': e.pixel.x,'top':e.pixel.y, display:'block'});
$("#info").html(`<p>楼高<span">${e.feature.properties.floor || 0}</span></p>`);
})
});
});
</script>
</body>
</html>

79
demos/08_arc_line.html Normal file
View File

@ -0,0 +1,79 @@
<!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>hexagon demo</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='https://npmcdn.com/@turf/turf/turf.min.js'></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: 'dark', // 样式URL
center: [ 116.2825, 39.9 ],
pitch: 0,
zoom: 3
});
scene.on('loaded', () => {
$.get('https://gw.alipayobjects.com/os/rmsportal/UEXQMifxtkQlYfChpPwT.txt', data => {
const rows = data.split('\n');
var features =[];
for(var i =1;i<rows.length-1;i++){
var row = rows[i].split(',');
var start = turf.point([row[4], row[5]]);
var end = turf.point([row[6], row[7]]);
var greatCircle = turf.greatCircle(start, end, {'npoints': 50});
features.push(greatCircle);
}
var fc = turf.featureCollection(features);
scene.LineLayer({
zIndex: 2
})
.source(fc)
.color('rgb(13,64,140)')
.style({
opacity:0.6,
})
//.animate({enable:true})
.render();
/**
scene.LineLayer({
zIndex: 2
})
.source(data, { // lng1,lat1,lng2,lat2
type: 'csv',
x: 'lng1',
y: 'lat1',
x1: 'lng2',
y1: 'lat2'
})
.shape('arc')
.size(0.8)
.color('rgb(13,64,140)')
.style({
opacity:0.6,
})
//.animate({enable:true})
.render();
**/
});
});
</script>
</body>
</html>

63
demos/08_point_shape.html Normal file
View File

@ -0,0 +1,63 @@
<!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.037828998113099, 30.086317611850635 ],
pitch: 0,
zoom: 5.44
});
window.scene = scene;
var colorObj={
'黄色':'yellow',
'蓝色':'blue',
'橙色':'orange'
}
scene.on('loaded', () => {
$.get('./data/waringData.json', data => {
scene.PointLayer({
zIndex: 2
})
.source(data, {
type: 'array',
x: 'lon',
y: 'lat',
})
.shape('2d:radar')
.size(80 )
.active(false)
.color('signallevel',(v)=>{
return colorObj[v];
})
.style({
shape:'radar'
})
.render();
});
});
</script>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 198 KiB

159
demos/assets/info.css Normal file
View File

@ -0,0 +1,159 @@
.top-right{
right: 10px;
position:absolute;
}
.bottom-right{
right: 0;
bottom: 10px;
position:absolute;
}
.info-panel {
width: 250px;
background: #fff;
box-shadow: 0 0 4px rgba(0,0,0,.15);
margin: 24px;
padding: 12px 24px;
outline: none;
z-index: 10;
}
.info-panel p {
margin: 0px;
}
.info-panel h4 {
font-size: 1em;
font-weight: 500;
margin: 8px 0;
}
.info-panel label {
display: inline-block;
width: 30px;
margin-right: 10%;
color: #5a666d;
margin-bottom: 4px;
}
.tooltip {
position:absolute;
pointer-events: none;
transition: opacity .2s;
padding: 4px;
background: rgba(0,0,0,.8);
color: #fff;
max-width: 300px;
font-size: 10px;
z-index: 9;
}
.tooltip p {
padding: 0;
margin: 0;
}
.input-item {
position: relative;
display: -ms-flexbox;
display: flex;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
-ms-flex-align: center;
align-items: center;
width: 100%;
height: 3rem;
}
.input-item:last-child {
margin-bottom: 0;
}
.input-item>select, .input-item>input[type=text], .input-item>input[type=date] {
position: relative;
-ms-flex: 1 1 auto;
flex: 1 1 auto;
width: 1%;
margin-bottom: 0;
}
.input-item>select:not(:last-child), .input-item>input[type=text]:not(:last-child), .input-item>input[type=date]:not(:last-child) {
border-top-right-radius: 0;
border-bottom-right-radius: 0
}
.input-item>select:not(:first-child), .input-item>input[type=text]:not(:first-child), .input-item>input[type=date]:not(:first-child) {
border-top-left-radius: 0;
border-bottom-left-radius: 0
}
.input-item-prepend {
margin-right: -1px;
}
.input-item-text, input[type=text],input[type=date], select {
height: calc(2.2rem + 2px);
}
.input-item-text {
width: 6rem;
text-align: justify;
padding: 0.4rem 0.7rem;
display: inline-block;
text-justify: distribute-all-lines;
/*ie6-8*/
text-align-last: justify;
/* ie9*/
-moz-text-align-last: justify;
/*ff*/
-webkit-text-align-last: justify;
/*chrome 20+*/
-ms-flex-align: center;
align-items: center;
margin-bottom: 0;
font-size: 1rem;
font-weight: 400;
line-height: 1.5;
color: #495057;
text-align: center;
white-space: nowrap;
background-color: #e9ecef;
border: 1px solid #ced4da;
border-radius: .25rem;
border-bottom-right-radius: 0;
border-top-right-radius: 0;
}
.input-item-text input[type=checkbox], .input-item-text input[type=radio] {
margin-top: 0
}
.input-card {
display: flex;
flex-direction: column;
min-width: 0;
word-wrap: break-word;
background-color: #fff;
background-clip: border-box;
width: 10rem;
border-width: 0;
position: fixed;
top: 1rem;
right: 1rem;
-ms-flex: 1 1 auto;
flex: 1 1 auto;
padding: 0.1rem 0.6rem;
}
.info hr {
margin-right: 0;
margin-left: 0;
border-top-color: grey;
}
.info {
padding: .75rem 1.25rem;
margin-bottom: 1rem;
position: fixed;
top: 1rem;
background-color: white;
width: auto;
border-width: 0;
right: 1rem;
z-index: 10;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 179 KiB

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 332 KiB

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: 385 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 499 KiB

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 647 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 KiB

After

Width:  |  Height:  |  Size: 187 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 195 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 222 KiB

After

Width:  |  Height:  |  Size: 438 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 164 KiB

After

Width:  |  Height:  |  Size: 205 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 303 KiB

After

Width:  |  Height:  |  Size: 2.7 MiB

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.

After

Width:  |  Height:  |  Size: 2.1 MiB

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

43
demos/meshline.html Normal file
View File

@ -0,0 +1,43 @@
<!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>line demo</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.3672, 36.0968 ],
pitch: 0,
zoom: 13
});
scene.on('loaded', () => {
$.getJSON('./data/contour.json', contourData => {
const color = [ 'rgb(22,32,101)', 'rgb(28,43,127)', 'rgb(36,68,142)', 'rgb(45,94,158)', 'rgb(53,119,174)', 'rgb(61,145,190)', 'rgb(70,170,206)', 'rgb(98,190,210)', 'rgb(138,205,206)', 'rgb(179,221,204)', 'rgb(220,236,201)' ];
//contourData.features = contourData.features.slice(0,1);
const layer = scene.LineLayer()
.source(contourData)
.color('ELEV', color)
.size([ 1, 0 ])
.shape('meshLine')
.render();
});
})
</script>
</body>
</html>

107
demos/taxi.html Normal file
View File

@ -0,0 +1,107 @@
<!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>city 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/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);
var palette = {
baseColor: '#3CB4F0', // CSS string
windowColor: '#65CEF7', // RGB array
brightColor: '#98E3FA', // RGB with alpha
};
gui.addColor(palette, 'baseColor').onChange(()=>{
changeStyle();
});
gui.addColor(palette, 'windowColor').onChange(()=>{
changeStyle();
});
gui.addColor(palette, 'brightColor').onChange(()=>{
changeStyle();
});
var buildLayer =null;
const scene = new L7.Scene({
id: 'map',
mapStyle: 'dark', // 样式URL
center: [ 121.507674, 31.223043 ],
pitch: 65.59312320916906,
zoom: 16.4,
minZoom: 15,
maxZoom: 18
});
scene.on('loaded', () => {
$.get('./data/cityPoint.json', data => {
scene.PointLayer({
zIndex: 10
})
.source(data)
.shape('2d:warn')
.size(90)
.color('#F00')
.style({
shape:'warn'
})
.render();
});
$.get('./data/road.json', data => {
scene.LineLayer({
zIndex: 2
})
.source(data)
.color('#F08D41')
.animate({enable:true})
.render();
});
$.get('./data/2.geojson', data => {
buildLayer = scene.PolygonLayer({
zIndex: 2
})
.source(data)
.shape('extrude')
.size('floor',[0,2000])
.color('rgba(242,246,250,1.0)')
.animate({enable:true})
.style({
opacity:1.0,
baseColor:'rgb(25,25,165)',
windowColor:'rgb(30,60,89)',
brightColor:'rgb(155,217,255)',
})
.render();
});
});
function changeStyle(e){
buildLayer.style({
opacity:0.8,
baseColor:palette.baseColor,
windowColor:palette.windowColor,
brightColor:palette.brightColor,
}
).render();
}
</script>
</body>
</html>

View File

@ -1,7 +1,7 @@
{
"name": "@ali/l7",
"version": "0.1.1",
"description": "the Grammar of Graphics in Javascript",
"name": "@antv/l7",
"version": "1.0.0",
"description": "Large-scale WebGL-powered Geospatial Data Visualization",
"main": "build/l7.js",
"browser": "build/l7.js",
"module": "lib/index.js",
@ -15,16 +15,17 @@
},
"keywords": [
"l7",
"chart"
"gis",
"geometry"
],
"author": "https://github.com/orgs/antvis/people",
"license": "MIT",
"devDependencies": {
"@antv/util": "~1.2.5",
"babel-cli": "~6.26.0",
"babel-core": "~6.26.0",
"@babel/cli": "~7.0.0",
"@babel/core": "~7.0.0",
"@babel/preset-env": "~7.1.0",
"babel-eslint": "~8.0.3",
"babel-loader": "^7.1.4",
"babel-loader": "~8.0.0",
"babel-plugin-transform-remove-strict-mode": "~0.0.2",
"babel-preset-env": "~1.6.1",
"body-parser": "^1.18.2",
@ -33,7 +34,7 @@
"connect": "^3.6.6",
"d3-queue": "~3.0.7",
"debug": "~3.1.0",
"electron": "^1.8.4",
"electron": "~2.0.2",
"eslint": "~3.19.0",
"eslint-config-airbnb": "~15.0.1",
"eslint-config-egg": "~4.2.0",
@ -50,7 +51,7 @@
"serve-static": "^1.13.2",
"shelljs": "~0.7.8",
"string-replace-loader": "~1.3.0",
"torchjs": "~1.0.4",
"torchjs": "~2.1.0",
"uglify-js": "~3.1.10",
"webpack": "~3.10.0"
},
@ -76,11 +77,11 @@
"prepublishOnly": "npm run build-lib && npm run dist",
"screenshot": "node ./bin/screenshot.js",
"start": "npm run dev",
"test": "torch --compile --renderer --recursive ./test/unit",
"test": "torch --compile --renderer --recursive test/unit",
"test-all": "npm run test && npm run test-bugs",
"test-bugs": "torch --compile --renderer --recursive ./test/bugs",
"test-bugs-live": "torch --compile --interactive --watch --recursive ./test/bugs",
"test-live": "torch --compile --interactive --watch --recursive ./test/unit",
"test-bugs": "torch --compile --renderer --recursive test/bugs",
"test-bugs-live": "torch --compile --interactive --watch --recursive test/bugs",
"test-live": "torch --compile --interactive --watch --recursive test/unit",
"watch": "webpack --config webpack-dev.config.js",
"win-dev": "node ./bin/win-dev.js"
},
@ -96,6 +97,7 @@
},
"dependencies": {
"@antv/g": "^3.1.3",
"@antv/util": "~1.2.5",
"@mapbox/tiny-sdf": "^1.1.0",
"@turf/bbox": "^6.0.1",
"@turf/clean-coords": "^6.0.1",
@ -106,6 +108,7 @@
"fecha": "^2.3.3",
"gl-matrix": "^2.4.1",
"lodash": "^4.17.5",
"polyline-normals": "^2.0.2",
"rbush": "^2.0.2",
"three": "^0.96.0",
"venn.js": "^0.2.20",

View File

@ -97,3 +97,4 @@ export const colorScales = {
magma: new Uint8Array([ 0, 0, 4, 255, 1, 0, 5, 255, 1, 1, 6, 255, 1, 1, 8, 255, 2, 1, 9, 255, 2, 2, 11, 255, 2, 2, 13, 255, 3, 3, 15, 255, 3, 3, 18, 255, 4, 4, 20, 255, 5, 4, 22, 255, 6, 5, 24, 255, 6, 5, 26, 255, 7, 6, 28, 255, 8, 7, 30, 255, 9, 7, 32, 255, 10, 8, 34, 255, 11, 9, 36, 255, 12, 9, 38, 255, 13, 10, 41, 255, 14, 11, 43, 255, 16, 11, 45, 255, 17, 12, 47, 255, 18, 13, 49, 255, 19, 13, 52, 255, 20, 14, 54, 255, 21, 14, 56, 255, 22, 15, 59, 255, 24, 15, 61, 255, 25, 16, 63, 255, 26, 16, 66, 255, 28, 16, 68, 255, 29, 17, 71, 255, 30, 17, 73, 255, 32, 17, 75, 255, 33, 17, 78, 255, 34, 17, 80, 255, 36, 18, 83, 255, 37, 18, 85, 255, 39, 18, 88, 255, 41, 17, 90, 255, 42, 17, 92, 255, 44, 17, 95, 255, 45, 17, 97, 255, 47, 17, 99, 255, 49, 17, 101, 255, 51, 16, 103, 255, 52, 16, 105, 255, 54, 16, 107, 255, 56, 16, 108, 255, 57, 15, 110, 255, 59, 15, 112, 255, 61, 15, 113, 255, 63, 15, 114, 255, 64, 15, 116, 255, 66, 15, 117, 255, 68, 15, 118, 255, 69, 16, 119, 255, 71, 16, 120, 255, 73, 16, 120, 255, 74, 16, 121, 255, 76, 17, 122, 255, 78, 17, 123, 255, 79, 18, 123, 255, 81, 18, 124, 255, 82, 19, 124, 255, 84, 19, 125, 255, 86, 20, 125, 255, 87, 21, 126, 255, 89, 21, 126, 255, 90, 22, 126, 255, 92, 22, 127, 255, 93, 23, 127, 255, 95, 24, 127, 255, 96, 24, 128, 255, 98, 25, 128, 255, 100, 26, 128, 255, 101, 26, 128, 255, 103, 27, 128, 255, 104, 28, 129, 255, 106, 28, 129, 255, 107, 29, 129, 255, 109, 29, 129, 255, 110, 30, 129, 255, 112, 31, 129, 255, 114, 31, 129, 255, 115, 32, 129, 255, 117, 33, 129, 255, 118, 33, 129, 255, 120, 34, 129, 255, 121, 34, 130, 255, 123, 35, 130, 255, 124, 35, 130, 255, 126, 36, 130, 255, 128, 37, 130, 255, 129, 37, 129, 255, 131, 38, 129, 255, 132, 38, 129, 255, 134, 39, 129, 255, 136, 39, 129, 255, 137, 40, 129, 255, 139, 41, 129, 255, 140, 41, 129, 255, 142, 42, 129, 255, 144, 42, 129, 255, 145, 43, 129, 255, 147, 43, 128, 255, 148, 44, 128, 255, 150, 44, 128, 255, 152, 45, 128, 255, 153, 45, 128, 255, 155, 46, 127, 255, 156, 46, 127, 255, 158, 47, 127, 255, 160, 47, 127, 255, 161, 48, 126, 255, 163, 48, 126, 255, 165, 49, 126, 255, 166, 49, 125, 255, 168, 50, 125, 255, 170, 51, 125, 255, 171, 51, 124, 255, 173, 52, 124, 255, 174, 52, 123, 255, 176, 53, 123, 255, 178, 53, 123, 255, 179, 54, 122, 255, 181, 54, 122, 255, 183, 55, 121, 255, 184, 55, 121, 255, 186, 56, 120, 255, 188, 57, 120, 255, 189, 57, 119, 255, 191, 58, 119, 255, 192, 58, 118, 255, 194, 59, 117, 255, 196, 60, 117, 255, 197, 60, 116, 255, 199, 61, 115, 255, 200, 62, 115, 255, 202, 62, 114, 255, 204, 63, 113, 255, 205, 64, 113, 255, 207, 64, 112, 255, 208, 65, 111, 255, 210, 66, 111, 255, 211, 67, 110, 255, 213, 68, 109, 255, 214, 69, 108, 255, 216, 69, 108, 255, 217, 70, 107, 255, 219, 71, 106, 255, 220, 72, 105, 255, 222, 73, 104, 255, 223, 74, 104, 255, 224, 76, 103, 255, 226, 77, 102, 255, 227, 78, 101, 255, 228, 79, 100, 255, 229, 80, 100, 255, 231, 82, 99, 255, 232, 83, 98, 255, 233, 84, 98, 255, 234, 86, 97, 255, 235, 87, 96, 255, 236, 88, 96, 255, 237, 90, 95, 255, 238, 91, 94, 255, 239, 93, 94, 255, 240, 95, 94, 255, 241, 96, 93, 255, 242, 98, 93, 255, 242, 100, 92, 255, 243, 101, 92, 255, 244, 103, 92, 255, 244, 105, 92, 255, 245, 107, 92, 255, 246, 108, 92, 255, 246, 110, 92, 255, 247, 112, 92, 255, 247, 114, 92, 255, 248, 116, 92, 255, 248, 118, 92, 255, 249, 120, 93, 255, 249, 121, 93, 255, 249, 123, 93, 255, 250, 125, 94, 255, 250, 127, 94, 255, 250, 129, 95, 255, 251, 131, 95, 255, 251, 133, 96, 255, 251, 135, 97, 255, 252, 137, 97, 255, 252, 138, 98, 255, 252, 140, 99, 255, 252, 142, 100, 255, 252, 144, 101, 255, 253, 146, 102, 255, 253, 148, 103, 255, 253, 150, 104, 255, 253, 152, 105, 255, 253, 154, 106, 255, 253, 155, 107, 255, 254, 157, 108, 255, 254, 159, 109, 255, 254, 161, 110, 255, 254, 163, 111, 255, 254, 165, 113, 255, 254, 167, 114, 255, 254, 169, 115, 255, 254, 170, 116, 255, 254, 172, 118, 255, 254, 174, 119, 255, 254, 176, 120, 255, 254, 178, 122, 255, 254, 180, 123, 255, 254, 182, 124, 255, 254, 183, 126, 255, 254, 185, 127, 255, 254, 187, 129, 255, 254, 189, 130, 255, 254, 191, 132, 255, 254, 193, 133, 255, 254, 194, 135, 255, 254, 196, 136, 255, 254, 198, 138, 255, 254, 200, 140, 255, 254, 202, 141, 255, 254, 204, 143, 255, 254, 205, 144, 255, 254, 207, 146, 255, 254, 209, 148, 255, 254, 211, 149, 255, 254, 213, 151, 255, 254, 215, 153, 255, 254, 216, 154, 255, 253, 218, 156, 255, 253, 220, 158, 255, 253, 222, 160, 255, 253, 224, 161, 255, 253, 226, 163, 255, 253, 227, 165, 255, 253, 229, 167, 255, 253, 231, 169, 255, 253, 233, 170, 255, 253, 235, 172, 255, 252, 236, 174, 255, 252, 238, 176, 255, 252, 240, 178, 255, 252, 242, 180, 255, 252, 244, 182, 255, 252, 246, 184, 255, 252, 247, 185, 255, 252, 249, 187, 255, 252, 251, 189, 255, 252, 253, 191, 255 ]),
plasma: new Uint8Array([ 13, 8, 135, 255, 16, 7, 136, 255, 19, 7, 137, 255, 22, 7, 138, 255, 25, 6, 140, 255, 27, 6, 141, 255, 29, 6, 142, 255, 32, 6, 143, 255, 34, 6, 144, 255, 36, 6, 145, 255, 38, 5, 145, 255, 40, 5, 146, 255, 42, 5, 147, 255, 44, 5, 148, 255, 46, 5, 149, 255, 47, 5, 150, 255, 49, 5, 151, 255, 51, 5, 151, 255, 53, 4, 152, 255, 55, 4, 153, 255, 56, 4, 154, 255, 58, 4, 154, 255, 60, 4, 155, 255, 62, 4, 156, 255, 63, 4, 156, 255, 65, 4, 157, 255, 67, 3, 158, 255, 68, 3, 158, 255, 70, 3, 159, 255, 72, 3, 159, 255, 73, 3, 160, 255, 75, 3, 161, 255, 76, 2, 161, 255, 78, 2, 162, 255, 80, 2, 162, 255, 81, 2, 163, 255, 83, 2, 163, 255, 85, 2, 164, 255, 86, 1, 164, 255, 88, 1, 164, 255, 89, 1, 165, 255, 91, 1, 165, 255, 92, 1, 166, 255, 94, 1, 166, 255, 96, 1, 166, 255, 97, 0, 167, 255, 99, 0, 167, 255, 100, 0, 167, 255, 102, 0, 167, 255, 103, 0, 168, 255, 105, 0, 168, 255, 106, 0, 168, 255, 108, 0, 168, 255, 110, 0, 168, 255, 111, 0, 168, 255, 113, 0, 168, 255, 114, 1, 168, 255, 116, 1, 168, 255, 117, 1, 168, 255, 119, 1, 168, 255, 120, 1, 168, 255, 122, 2, 168, 255, 123, 2, 168, 255, 125, 3, 168, 255, 126, 3, 168, 255, 128, 4, 168, 255, 129, 4, 167, 255, 131, 5, 167, 255, 132, 5, 167, 255, 134, 6, 166, 255, 135, 7, 166, 255, 136, 8, 166, 255, 138, 9, 165, 255, 139, 10, 165, 255, 141, 11, 165, 255, 142, 12, 164, 255, 143, 13, 164, 255, 145, 14, 163, 255, 146, 15, 163, 255, 148, 16, 162, 255, 149, 17, 161, 255, 150, 19, 161, 255, 152, 20, 160, 255, 153, 21, 159, 255, 154, 22, 159, 255, 156, 23, 158, 255, 157, 24, 157, 255, 158, 25, 157, 255, 160, 26, 156, 255, 161, 27, 155, 255, 162, 29, 154, 255, 163, 30, 154, 255, 165, 31, 153, 255, 166, 32, 152, 255, 167, 33, 151, 255, 168, 34, 150, 255, 170, 35, 149, 255, 171, 36, 148, 255, 172, 38, 148, 255, 173, 39, 147, 255, 174, 40, 146, 255, 176, 41, 145, 255, 177, 42, 144, 255, 178, 43, 143, 255, 179, 44, 142, 255, 180, 46, 141, 255, 181, 47, 140, 255, 182, 48, 139, 255, 183, 49, 138, 255, 184, 50, 137, 255, 186, 51, 136, 255, 187, 52, 136, 255, 188, 53, 135, 255, 189, 55, 134, 255, 190, 56, 133, 255, 191, 57, 132, 255, 192, 58, 131, 255, 193, 59, 130, 255, 194, 60, 129, 255, 195, 61, 128, 255, 196, 62, 127, 255, 197, 64, 126, 255, 198, 65, 125, 255, 199, 66, 124, 255, 200, 67, 123, 255, 201, 68, 122, 255, 202, 69, 122, 255, 203, 70, 121, 255, 204, 71, 120, 255, 204, 73, 119, 255, 205, 74, 118, 255, 206, 75, 117, 255, 207, 76, 116, 255, 208, 77, 115, 255, 209, 78, 114, 255, 210, 79, 113, 255, 211, 81, 113, 255, 212, 82, 112, 255, 213, 83, 111, 255, 213, 84, 110, 255, 214, 85, 109, 255, 215, 86, 108, 255, 216, 87, 107, 255, 217, 88, 106, 255, 218, 90, 106, 255, 218, 91, 105, 255, 219, 92, 104, 255, 220, 93, 103, 255, 221, 94, 102, 255, 222, 95, 101, 255, 222, 97, 100, 255, 223, 98, 99, 255, 224, 99, 99, 255, 225, 100, 98, 255, 226, 101, 97, 255, 226, 102, 96, 255, 227, 104, 95, 255, 228, 105, 94, 255, 229, 106, 93, 255, 229, 107, 93, 255, 230, 108, 92, 255, 231, 110, 91, 255, 231, 111, 90, 255, 232, 112, 89, 255, 233, 113, 88, 255, 233, 114, 87, 255, 234, 116, 87, 255, 235, 117, 86, 255, 235, 118, 85, 255, 236, 119, 84, 255, 237, 121, 83, 255, 237, 122, 82, 255, 238, 123, 81, 255, 239, 124, 81, 255, 239, 126, 80, 255, 240, 127, 79, 255, 240, 128, 78, 255, 241, 129, 77, 255, 241, 131, 76, 255, 242, 132, 75, 255, 243, 133, 75, 255, 243, 135, 74, 255, 244, 136, 73, 255, 244, 137, 72, 255, 245, 139, 71, 255, 245, 140, 70, 255, 246, 141, 69, 255, 246, 143, 68, 255, 247, 144, 68, 255, 247, 145, 67, 255, 247, 147, 66, 255, 248, 148, 65, 255, 248, 149, 64, 255, 249, 151, 63, 255, 249, 152, 62, 255, 249, 154, 62, 255, 250, 155, 61, 255, 250, 156, 60, 255, 250, 158, 59, 255, 251, 159, 58, 255, 251, 161, 57, 255, 251, 162, 56, 255, 252, 163, 56, 255, 252, 165, 55, 255, 252, 166, 54, 255, 252, 168, 53, 255, 252, 169, 52, 255, 253, 171, 51, 255, 253, 172, 51, 255, 253, 174, 50, 255, 253, 175, 49, 255, 253, 177, 48, 255, 253, 178, 47, 255, 253, 180, 47, 255, 253, 181, 46, 255, 254, 183, 45, 255, 254, 184, 44, 255, 254, 186, 44, 255, 254, 187, 43, 255, 254, 189, 42, 255, 254, 190, 42, 255, 254, 192, 41, 255, 253, 194, 41, 255, 253, 195, 40, 255, 253, 197, 39, 255, 253, 198, 39, 255, 253, 200, 39, 255, 253, 202, 38, 255, 253, 203, 38, 255, 252, 205, 37, 255, 252, 206, 37, 255, 252, 208, 37, 255, 252, 210, 37, 255, 251, 211, 36, 255, 251, 213, 36, 255, 251, 215, 36, 255, 250, 216, 36, 255, 250, 218, 36, 255, 249, 220, 36, 255, 249, 221, 37, 255, 248, 223, 37, 255, 248, 225, 37, 255, 247, 226, 37, 255, 247, 228, 37, 255, 246, 230, 38, 255, 246, 232, 38, 255, 245, 233, 38, 255, 245, 235, 39, 255, 244, 237, 39, 255, 243, 238, 39, 255, 243, 240, 39, 255, 242, 242, 39, 255, 241, 244, 38, 255, 241, 245, 37, 255, 240, 247, 36, 255, 240, 249, 33, 255 ])
};
// module.exports = colorScales;

View File

@ -3,8 +3,8 @@
* @author dxq613@gmail.com
*/
const EventEmitter = require('wolfy87-eventemitter');
const Util = require('../util');
import EventEmitter from 'wolfy87-eventemitter';
import Util from '../util';
class Base extends EventEmitter {
@ -29,16 +29,6 @@ class Base extends EventEmitter {
set(name, value) {
this._attrs[name] = value;
}
/**
* @protected
* @param {Boolean} visible 是否可见
* 显示隐藏
*/
changeVisible(/* visible */) {
}
destroy() {
this._attrs = {};
this.removeAllListeners();
@ -46,4 +36,4 @@ class Base extends EventEmitter {
}
}
module.exports = Base;
export default Base;

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

@ -1,4 +1,5 @@
import EventEmitter from 'wolfy87-eventemitter';
import * as THREE from '../three';
import Scene from './scene';
import Camera from './camera';
import Renderer from './renderer';
@ -11,8 +12,7 @@ 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.clock = new THREE.Clock();
}
_initPostProcessing() {
@ -26,10 +26,9 @@ export default class Engine extends EventEmitter {
}
run() {
this.engineID = requestAnimationFrame(() => {
this.update();
this.engineID = requestAnimationFrame(this.run.bind(this));
});
this.update();
this.engineID = requestAnimationFrame(this.run.bind(this));
}
stop() {
cancelAnimationFrame(this.engineID);

View File

@ -1,20 +1,5 @@
import PickingScene from './pickingScene';
import * as THREE from '../../three';
// TODO: Look into a way of setting this up without passing in a renderer and
// camera from the engine
// TODO: Add a basic indicator on or around the mouse pointer when it is over
// something pickable / clickable
//
// A simple transparent disc or ring at the mouse point should work to start, or
// even just changing the cursor to the CSS 'pointer' style
//
// Probably want this on mousemove with a throttled update as not to spam the
// picking method
//
// Relies upon the picking method not redrawing the scene every call due to
// the way TileLayer invalidates the picking scene
let nextId = 1;
class Picking {
@ -24,6 +9,7 @@ class Picking {
this._camera = camera;
this._raycaster = new THREE.Raycaster();
this.scene = scene;
this._envents = [];
// TODO: Match this with the line width used in the picking layers
this._raycaster.linePrecision = 3;
@ -52,15 +38,15 @@ class Picking {
this._mouseUpHandler = this._onMouseUp.bind(this);
this._world._container.addEventListener('mouseup', this._mouseUpHandler, false);
// this._world.on('move', this._onWorldMove, this);
this._world._container.addEventListener('mousemove', this._mouseUpHandler, false);
this._world._container.addEventListener('mousemove', this._onWorldMove.bind(this), false);
}
_onMouseUp(event) {
// Only react to main button click
if (event.button !== 0) {
return;
}
// if (event.button !== 0) {
// return;
// }
const point = { x: event.clientX, y: event.clientY };
const normalisedPoint = { x: 0, y: 0 };
@ -71,6 +57,7 @@ class Picking {
}
_onWorldMove() {
this._needUpdate = true;
}
@ -86,26 +73,31 @@ class Picking {
this._needUpdate = true;
}
// TODO: Make this only re-draw the scene if both an update is needed and the
// camera has moved since the last update
//
// Otherwise it re-draws the scene on every click due to the way LOD updates
// work in TileLayer spamming this.add() and this.remove()
//
// TODO: Pause updates during map move / orbit / zoom as this is unlikely to
// be a point in time where the user cares for picking functionality
_update(point) {
// if (this._needUpdate) {
const texture = this._pickingTexture;
this._renderer.render(this._pickingScene, this._camera, this._pickingTexture);// this._pickingTexture this._pickingScene
// Read the rendering texture
const texture = this._pickingTexture;
if (this._needUpdate) {
this._renderer.render(this._pickingScene, this._camera, this._pickingTexture);
this._needUpdate = false;
}
this.pixelBuffer = new Uint8Array(4);
this._renderer.readRenderTargetPixels(texture, point.x, this._height - point.y, 1, 1, this.pixelBuffer);
// this._needUpdate = false;
// }
}
// 添加dom事件 支持 mousedown ,mouseenter mouseleave mousemove mouseover mouseout mouse up
on(type) {
this._mouseUpHandler = this._onMouseUp.bind(this);
this._world._container.addEventListener(type, this._mouseUpHandler, false);
this._envents.push([ type, this._mouseUpHandler ]);
}
off(type, hander) {
this._world._container.removeEventListener(type, this._mouseUpHandler, false);
this._envents = this._envents.filter(item => {
return item[0] === 'type' && hander === item[1];
});
}
_updateRender() {
this._renderer.render(this._pickingScene, this._camera, this._pickingTexture);
@ -116,7 +108,7 @@ class Picking {
// Interpret the pixel as an ID
const id = (this.pixelBuffer[2] * 255 * 255) + (this.pixelBuffer[1] * 255) + (this.pixelBuffer[0]);
// Skip if ID is 16646655 (white) as the background returns this
if (id === 16646655) {
if (id === 16646655 || this.pixelBuffer[3] === 0) {
return;
}
@ -139,7 +131,7 @@ class Picking {
//
// TODO: Look into the leak potential for passing so much by reference here
const item = {
featureId: id,
featureId: id - 1,
point2d: _point2d,
point3d: _point3d,
intersects
@ -171,7 +163,9 @@ class Picking {
// TODO: Find a way to properly remove these listeners as they stay
// active at the moment
window.removeEventListener('resize', this._resizeHandler, false);
this._world._container.removeEventListener('mouseup', this._mouseUpHandler, false);
this._envents.forEach(event => {
this._world._container.removeEventListener(event[0], event[1], false);
});
this._world.off('move', this._onWorldMove);

View File

@ -1,37 +1,15 @@
import * as THREE from '../../three';
import Material from '../../../geom/material/material';
import picking_frag from './picking_frag.glsl';
import picking_vert from './picking_vert.glsl';
// FROM: https://github.com/brianxu/GPUPicker/blob/master/GPUPicker.js
const PickingMaterial = function() {
THREE.ShaderMaterial.call(this, {
export default function PickingMaterial(options) {
const material = new Material({
uniforms: {
size: {
type: 'f',
value: 0.01
},
scale: {
type: 'f',
value: 400
}
u_zoom: { value: options.u_zoom || 1 }
},
vertexShader: picking_vert,
fragmentShader: picking_frag
fragmentShader: picking_frag,
transparent: false
});
this.linePadding = 2;
};
PickingMaterial.prototype = Object.create(THREE.ShaderMaterial.prototype);
PickingMaterial.prototype.constructor = PickingMaterial;
PickingMaterial.prototype.setPointSize = function(size) {
this.uniforms.size.value = size;
};
PickingMaterial.prototype.setPointScale = function(scale) {
this.uniforms.scale.value = scale;
};
export default PickingMaterial;
return material;
}

View File

@ -1,7 +1,10 @@
#ifdef GL_ES
precision highp float;
#endif
varying vec4 worldId;
void main() {
if(worldId.x == 0. &&worldId.y == 0. && worldId.z==0.){
discard;
return;
}
gl_FragColor = worldId;
}

View File

@ -1,11 +1,28 @@
attribute float pickingId;
attribute float a_size;
#ifdef polyline
attribute float a_size;
attribute float a_miter;
#endif
#ifdef point
attribute vec3 a_size;
attribute vec3 a_shape;
#endif
uniform float u_zoom;
varying vec4 worldId;
void main() {
mat4 matModelViewProjection = projectionMatrix * modelViewMatrix;
vec3 a = fract(vec3(1.0/255.0, 1.0/(255.0*255.0), 1.0/(255.0*255.0*255.0)) * pickingId);
float scale = pow(2.0,(20.0 - u_zoom));
vec3 newposition = position;
#ifdef point
newposition =position + a_size * scale * a_shape;
#endif
#ifdef polyline
newposition = position.xyz + vec3(normal * a_size * pow(2.0,20.0-u_zoom) / 2.0 * a_miter);
#endif
float id = step(0.,pickingId) * pickingId;
vec3 a = fract(vec3(1.0/255.0, 1.0/(255.0*255.0), 1.0/(255.0*255.0*255.0)) * id);
a -= a.xxy * vec3(0.0, 1.0/255.0, 1.0/255.0);
worldId = vec4(a,1);
gl_PointSize = a_size;
gl_Position = matModelViewProjection * vec4( position, 1.0 );
//gl_PointSize = a_size;
gl_Position = matModelViewProjection * vec4( newposition, 1.0 );
}

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,23 +0,0 @@
import Material from '../../../geom/material/material';
import draw_vert from './draw_vert.glsl';
import draw_frag from './draw_frag.glsl';
export default function DrawMaterial(options) {
const material = new Material({
uniforms: {
u_color_ramp: { value: options.u_color_ramp },
u_wind_max: { value: options.u_wind_max },
u_particles_res: { value: options.u_particles_res },
u_wind_min: { value: options.u_wind_min },
u_opacity: { value: options.u_opacity },
u_wind: { value: options.u_wind },
u_particles: { value: options.u_particles },
u_bbox: { value: options.u_bbox }
},
vertexShader: draw_vert,
fragmentShader: draw_frag,
transparent: true
});
// material.blending = THREE.AdditiveBlending
return material;
}

View File

@ -1,19 +0,0 @@
precision mediump float;
uniform sampler2D u_wind;
uniform vec2 u_wind_min;
uniform vec2 u_wind_max;
uniform sampler2D u_color_ramp;
uniform float u_opacity;
varying vec2 v_particle_pos;
void main() {
vec2 velocity = mix(u_wind_min, u_wind_max, texture2D(u_wind, v_particle_pos).rg);
float speed_t = length(velocity) / length(u_wind_max);
// color ramp is encoded in a 16x16 texture
vec2 ramp_pos = vec2(
fract(16.0 * speed_t),
floor(16.0 * speed_t) / 16.0);
gl_FragColor = texture2D(u_color_ramp, ramp_pos);
}

View File

@ -1,34 +0,0 @@
import { DataType, DrawMode } from '@ali/r3-base';
import { BufferGeometry } from '@ali/r3-geometry';
/**
* 创建点图层几何体
*/
export default class DrawGeometry extends BufferGeometry {
constructor(opts) {
super(opts.name);
this._index = opts.index;
this.mode = DrawMode.POINTS;
this.primitive.indexType = DataType.UNSIGNED_INT;
this.initialize();
}
/**
* 构造多边形数据
* @private
*/
initialize() {
super.initialize([
{ semantic: 'INDEX', size: 1, type: DataType.FLOAT, normalized: false }
], this._index.length);
this._index.forEach((vert, j) => {
this.setVertexValues(j, {
INDEX: [ vert ]
});
});
}
}

View File

@ -1,26 +0,0 @@
precision mediump float;
attribute float a_index;
uniform sampler2D u_particles;
uniform vec4 u_bbox;
uniform float u_particles_res;
varying vec2 v_particle_pos;
void main() {
mat4 matModelViewProjection = projectionMatrix * modelViewMatrix;
vec4 color = texture2D(u_particles, vec2(
fract(a_index / u_particles_res),
1.0 - floor(a_index / u_particles_res) / u_particles_res));
// decode current particle position from the pixel's RGBA value
v_particle_pos = vec2(
color.r / 255.0 + color.b,
1.0 - (color.g / 255.0 + color.a));
vec2 xyrange = u_bbox.zw - u_bbox.xy;
float x = u_bbox.x + v_particle_pos.x * xyrange.x;
float y = u_bbox.w - v_particle_pos.y * xyrange.y;
gl_PointSize = 1.0;
//gl_Position = matModelViewProjection * vec4(v_particle_pos, 0.0, 1.0);
gl_Position = vec4(2.0 * v_particle_pos.x - 1.0, 1.0 - 2.0 * v_particle_pos.y, 0, 1);
}

View File

@ -1,39 +0,0 @@
import { RenderPass } from '@ali/r3-renderer-basic';
import { TextureFilter } from '@ali/r3-base';
export class GeoRenderPass extends RenderPass {
constructor(name, priority, renderTarget, mask, Material, id, done) {
renderTarget.texture.setFilter(TextureFilter.NEAREST, TextureFilter.NEAREST);
super(name, priority, renderTarget, Material, mask);
typeof (id) === 'string' || typeof (id) === 'number' && (id = [ id ]);
this.id = id;
this.renderPassFlags = [];
this.done = done;
}
/* eslint-disable */
preRender(camera, opaquaQueue, transparentQueue) {
/* eslint-disable */
opaquaQueue.items.forEach(item => {
const nodeAbility = item.nodeAbility;
this.renderPassFlags.push(nodeAbility.renderPassFlag);
this.id.indexOf(nodeAbility.id) > -1 ? nodeAbility.renderPassFlag = 0 : nodeAbility.renderPassFlag = 1;
});
}
postRender(camera, opaquaQueue, transparentQueue) {
opaquaQueue.items.forEach((item, index) => {
const nodeAbility = item.nodeAbility;
nodeAbility.renderPassFlag = this.renderPassFlags[index];
});
this.renderPassFlags.length = 0;
if(this.done) {
this.done();
}
}
}
export { ColorRenderPass };

View File

@ -1,7 +0,0 @@
precision highp float;
varying vec2 v_texCoord;
void main() {
v_texCoord = uv;
gl_Position = vec4(1.0 - 2.0 * vec2(position), 0., 1.0);
}

View File

@ -1,12 +0,0 @@
precision mediump float;
uniform sampler2D u_texture;
uniform float u_opacity;
varying vec2 v_texCoord;
void main() {
if(u_opacity == 0.0)
discard;
gl_FragColor = texture2D(u_texture,1.0 - v_texCoord) * u_opacity;
// gl_FragColor.w =u_opacity;
}

View File

@ -1,26 +0,0 @@
import Material from '../../../geom/material/material';
import quad_vert from './quad.vert.glsl';
import update_frag from './update_frag.glsl';
export default function UpdateMaterial(options) {
const material = new Material({
uniforms: {
u_wind_max: { value: options.u_wind_max },
u_particles_res: { value: options.u_particles_res },
u_wind_min: { value: options.u_wind_min },
u_opacity: { value: options.u_opacity },
u_wind: { value: options.u_wind },
u_particles: { value: options.u_particles },
u_drop_rate_bump: { value: options.u_drop_rate_bump },
u_drop_rate: { value: options.u_drop_rate },
u_speed_factor: { value: options.u_speed_factor },
u_rand_seed: { value: options.u_rand_seed },
u_extent: { value: options.u_extent },
u_wind_res: { value: options.u_wind_res }
},
vertexShader: quad_vert,
fragmentShader: update_frag,
transparent: true
});
// material.blending = THREE.AdditiveBlending
return material;
}

View File

@ -1,76 +0,0 @@
precision highp float;
uniform sampler2D u_particles;
uniform sampler2D u_wind;
uniform vec2 u_wind_res;
uniform vec2 u_wind_min;
uniform vec2 u_wind_max;
uniform float u_rand_seed;
uniform float u_speed_factor;
uniform float u_drop_rate;
uniform float u_drop_rate_bump;
uniform vec4 u_extent;
uniform float u_particles_res;
varying vec2 v_texCoord;
// pseudo-random generator
const vec3 rand_constants = vec3(12.9898, 78.233, 4375.85453);
float rand(const vec2 co) {
float t = dot(rand_constants.xy, co);
return fract(sin(t) * (rand_constants.z + t));
}
// wind speed lookup; use manual bilinear filtering based on 4 adjacent pixels for smooth interpolation
vec2 lookup_wind(const vec2 uv) {
// return texture2D(u_wind, uv).rg; // lower-res hardware filtering
vec2 px = 1.0 / u_wind_res;
vec2 vc = (floor(uv * u_wind_res)) * px;
vec2 f = fract(uv * u_wind_res);
vec2 tl = texture2D(u_wind, vc).rg;
vec2 tr = texture2D(u_wind, vc + vec2(px.x, 0)).rg;
vec2 bl = texture2D(u_wind, vc + vec2(0, px.y)).rg;
vec2 br = texture2D(u_wind, vc + px).rg;
return mix(mix(tl, tr, f.x), mix(bl, br, f.x), f.y);
}
void main() {
vec4 color = texture2D(u_particles, v_texCoord);
vec2 pos = vec2(
color.r / 255.0 + color.b,
color.g / 255.0 + color.a); // decode particle position from pixel RGBA
vec2 velocity = mix(u_wind_min, u_wind_max, lookup_wind(pos));
float speed_t = length(velocity) / length(u_wind_max);
// pos = pos + vec2(0.001,0.001);
// take EPSG:4236 distortion into account for calculating where the particle moved
// float y = u_extent.w - pos.y * (u_extent.w - u_extent.y);
// float distortion = cos(radians(y));
// vec2 offset = vec2(velocity.x / distortion, -velocity.y) * 0.0001 * u_speed_factor;
// take EPSG:4236 distortion into account for calculating where the particle moved
float distortion = cos(radians(pos.y * 180.0 - 90.0));
vec2 offset = vec2(velocity.x / distortion, -velocity.y) * 0.0001 * u_speed_factor;
// vec2 offset = vec2(velocity.x / distortion, -velocity.y) * 0.0001 * u_speed_factor;
// update particle position, wrapping around the date line
pos = fract(1.0 + pos + offset);
// // a random seed to use for the particle drop
vec2 seed = (pos + v_texCoord) * u_rand_seed;
// drop rate is a chance a particle will restart at random position, to avoid degeneration
float drop_rate = u_drop_rate + speed_t * u_drop_rate_bump;
float drop = step(1.0 - drop_rate, rand(seed));
vec2 random_pos = vec2(
rand(seed + 1.3),
rand(seed + 2.1));
pos = mix(pos, random_pos, drop);
// encode the new particle position back into RGBA
gl_FragColor = vec4(
fract(pos * 255.0),
floor(pos * 255.0) / 255.0);
}

View File

@ -1,17 +0,0 @@
import image_vert from './wind_vert.glsl';
import image_frag from './wind_frag.glsl';
import Material from '../../../geom/material/material';
export default function WindMaterial(options) {
const material = new Material({
uniforms: {
u_texture: { value: options.u_texture },
u_opacity: { value: options.u_opacity }
},
vertexShader: image_vert,
fragmentShader: image_frag,
transparent: true
});
// material.blending = THREE.AdditiveBlending
return material;
}

View File

@ -1,11 +0,0 @@
precision mediump float;
uniform sampler2D u_texture;
uniform float u_opacity;
varying vec2 v_texCoord;
void main() {
if(u_opacity == 0.0)
discard;
gl_FragColor = texture2D(u_texture,1.0 - v_texCoord) * u_opacity;
}

View File

@ -1,6 +0,0 @@
precision highp float;
varying vec2 v_texCoord;
void main() {
v_texCoord = uv;
gl_Position = vec4(1.0 - 2.0 * vec2(position), 0., 1.0);
}

View File

@ -1,15 +1,20 @@
import * as THREE from './three';
import EventEmitter from 'wolfy87-eventemitter';
import { getImage } from '../util/ajax';
export default class LoadImage {
// 将图片标注绘制在512*512的画布上每个大小 64*64 支持 64种图片
export default class LoadImage extends EventEmitter {
constructor() {
this.canvas = document.createElement('canvas');
this.ctx = this.canvas.getContext('2d');
super();
this.imageWidth = 64;
this.canvas = document.createElement('canvas');
this.canvas.style.cssText += 'height: 512px;width: 512px;';
this.canvas.width = this.imageWidth * 8;
this.canvas.height = this.imageWidth * 8;
this.ctx = this.canvas.getContext('2d');
this.images = [];
this.imagesCount = -1;
this.imagesCount = 0;
this.imagePos = {};
}
addImage(id, opt) {
@ -17,18 +22,21 @@ export default class LoadImage {
const imageCount = this.imagesCount;
const x = imageCount % 8 * 64;
const y = parseInt(imageCount / 8) * 64;
this.imagePos[id] = { x: x / 512, y: y / 512 };
this.texture = new THREE.Texture(this.canvas);
if (typeof opt === 'string') {
getImage({ url: opt }, (err, img) => {
img.id = id;
this.images.push(img);
this.ctx.drawImage(img, x, y, 64, 64);
const texture = new THREE.Texture(this.canvas);
texture.magFilter = THREE.LinearFilter;
texture.minFilter = THREE.LinearFilter;
texture.needsUpdate = true;
this.texture = texture;
this.imagePos[id] = { x: x / 512, y: y / 512 };
this.texture.magFilter = THREE.LinearFilter;
this.texture.minFilter = THREE.LinearFilter;
this.texture.needsUpdate = true;
if (this.images.length === this.imagesCount) {
this.emit('imageLoaded');
}
});
} else {
const { width, height, channels } = opt;
@ -40,8 +48,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

@ -6,7 +6,6 @@ import Base from './base';
import * as THREE from './three';
import ColorUtil from '../attr/color-util';
import * as source from '../source/index';
import * as turfMeta from '@turf/meta';
import PickingMaterial from '../core/engine/picking/pickingMaterial';
import Attr from '../attr/index';
import Util from '../util';
@ -37,15 +36,18 @@ export default class Layer extends Base {
attrs: {},
// 样式配置项
styleOptions: {
stroke: 'rgb(255,255,255)',
stroke: [ 1.0, 1.0, 1.0, 1.0 ],
strokeWidth: 1.0,
opacity: 1.0
opacity: 1.0,
texture: false
},
// 选中时的配置项
selectedOptions: null,
// active 时的配置项
activedOptions: null,
animateOptions: null
animateOptions: {
enable: false
}
};
}
constructor(scene, cfg) {
@ -59,23 +61,37 @@ export default class Layer extends Base {
const layerId = this._getUniqueId();
this.layerId = layerId;
this._activeIds = null;
// todo 用户参数
this._object3D.position.z = layerId * 1000;
scene._engine._scene.add(this._object3D);
this.layerMesh = null;
}
/**
* 将图层添加加到Object
* @param {*} object
* 将图层添加加到 Object
* @param {*} object three 物体
*/
add(object) {
this.layerMesh = object;
this._visibleWithZoom();
this.scene.on('zoomchange', () => {
this._visibleWithZoom();
});
this.layerMesh.onBeforeRender = () => {
const zoom = this.scene.getZoom();
this.layerMesh.material.setUniformsValue('u_time', this.scene._engine.clock.getElapsedTime());
this.layerMesh.material.setUniformsValue('u_zoom', zoom);
};
// 更新
if (this._needUpdateFilter) {
this._updateFilter();
}
this._object3D.add(object);
this._addPickMesh(object);
}
remove(object) {
this._object3D.remove(object);
}
_getUniqueId() {
return id++;
@ -89,11 +105,13 @@ export default class Layer extends Base {
const { type = dataType } = cfg;
cfg.data = data;
cfg.mapType = this.get('mapType');
this.layerSource = new source[type](cfg);
return this;
}
color(field, values) {
this._needUpdateColor = true;// 标识颜色是否需要更新
this._createAttrOption('color', field, values, Global.colors);
return this;
}
@ -136,7 +154,7 @@ export default class Layer extends Base {
}
style(field, cfg) {
const colorItem = [ 'fill', 'stroke' ];
const colorItem = [ 'fill', 'stroke', 'color', 'baseColor', 'brightColor', 'windowColor' ];
let styleOptions = this.get('styleOptions');
if (!styleOptions) {
styleOptions = {};
@ -153,7 +171,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];
@ -162,11 +180,27 @@ export default class Layer extends Base {
return this;
}
filter(field, values) {
this._needUpdateFilter = true;
this._createAttrOption('filter', field, values, true);
return this;
}
animate(callback) {
this.set('animateOptions', callback);
animate(field, cfg) {
let animateOptions = this.get('animateOptions');
if (!animateOptions) {
animateOptions = {};
this.set('animateOptions', animateOptions);
}
if (Util.isObject(field)) {
cfg = field;
field = null;
}
let fields;
if (field) {
fields = parseFields(field);
}
animateOptions.fields = fields;
Util.assign(animateOptions, cfg);
this.set('animateOptions', animateOptions);
return this;
}
texture() {
@ -211,10 +245,12 @@ export default class Layer extends Base {
}
this._setAttrOptions(attrName, attrCfg);
}
// 初始化图层
init() {
this._initAttrs();
this._scaleByZoom();
this._mapping();
const activeHander = this._addActiveFeature.bind(this);
if (this.get('allowActive')) {
@ -227,53 +263,46 @@ export default class Layer extends Base {
_addActiveFeature(e) {
const { featureId } = e;
const activeStyle = this.get('activedOptions');
const data = this.layerSource.get('data');
const selectFeatureIds = [];
let featureStyleId = 0;
/* eslint-disable */
turfMeta.flattenEach(data, (currentFeature, featureIndex, multiFeatureIndex) => {
/* eslint-disable */
if (featureIndex === featureId) {
selectFeatureIds.push(featureStyleId);
}
featureStyleId++;
if (featureIndex > featureId) {
return;
}
});
const selectFeatureIds = this.layerSource.getSelectFeatureId(featureId);
if (this.StyleData[selectFeatureIds[0]].hasOwnProperty('filter') && this.StyleData[selectFeatureIds[0]].filter === false) { return; }
const style = Util.assign({}, this.StyleData[featureId]);
style.color = ColorUtil.toRGB(activeStyle.fill).map(e => e / 255);
this.updateStyle(selectFeatureIds, style);
this.updateStyle([ featureId ], style);
}
_initAttrs() {
const self = this;
const attrs = this.get('attrs');
const attrOptions = this.get('attrOptions');
for (const type in attrOptions) {
if (attrOptions.hasOwnProperty(type)) {
const option = attrOptions[type];
const className = Util.upperFirst(type);
const fields = parseFields(option.field);
const scales = [];
for (let i = 0; i < fields.length; i++) {
const field = fields[i];
const scale = self._createScale(field);
if (type === 'color' && Util.isNil(option.values)) { // 设置 color 的默认色值
option.values = Global.colors;
}
scales.push(scale);
}
option.scales = scales;
const attr = new Attr[className](option);
attrs[type] = attr;
this._updateAttr(type);
}
}
}
_updateAttr(type) {
const self = this;
const attrs = this.get('attrs');
const attrOptions = this.get('attrOptions');
const option = attrOptions[type];
option.neadUpdate = true;
const className = Util.upperFirst(type);
const fields = parseFields(option.field);
const scales = [];
for (let i = 0; i < fields.length; i++) {
const field = fields[i];
const scale = self._createScale(field);
if (type === 'color' && Util.isNil(option.values)) { // 设置 color 的默认色值
option.values = Global.colors;
}
scales.push(scale);
}
option.scales = scales;
const attr = new Attr[className](option);
attrs[type] = attr;
}
_updateSize(zoom) {
const sizeOption = this.get('attrOptions').size;
const fields = parseFields(sizeOption.field);
@ -303,6 +332,7 @@ export default class Layer extends Base {
for (const k in attrs) {
if (attrs.hasOwnProperty(k)) {
const attr = attrs[k];
attr.needUpdate = false;
const names = attr.names;
const values = self._getAttrValues(attr, record);
if (names.length > 1) { // position 之类的生成多个字段的属性
@ -323,26 +353,30 @@ export default class Layer extends Base {
this.StyleData = mappedData;
return mappedData;
}
_updateMap(attrName) {
// 更新地图映射
_updateMaping() {
const self = this;
const attrs = self.get('attrs');
const data = this.layerSource.propertiesData;
for (let i = 0; i < data.length; i++) {
const record = data[i];
if (attrs.hasOwnProperty(attrName)) {
const attr = attrs[attrName];
const names = attr.names;
const values = self._getAttrValues(attr, record);
if (names.length > 1) { // position 之类的生成多个字段的属性
for (let j = 0; j < values.length; j++) {
const val = values[j];
const name = names[j];
this.StyleData[i][name] = (Util.isArray(val) && val.length === 1) ? val[0] : val; // 只有一个值时返回第一个属性值
}
} else {
this.StyleData[i][names[0]] = values.length === 1 ? values[0] : values;
for (const attrName in attrs) {
if (attrs.hasOwnProperty(attrName) && attrs[attrName].neadUpdate) {
const attr = attrs[attrName];
const names = attr.names;
const values = self._getAttrValues(attr, record);
if (names.length > 1) { // position 之类的生成多个字段的属性
for (let j = 0; j < values.length; j++) {
const val = values[j];
const name = names[j];
this.StyleData[i][name] = (Util.isArray(val) && val.length === 1) ? val[0] : val; // 只有一个值时返回第一个属性值
}
} else {
this.StyleData[i][names[0]] = values.length === 1 ? values[0] : values;
}
attr.neadUpdate = true;
}
}
}
@ -385,17 +419,17 @@ export default class Layer extends Base {
}
}
/**
*
* @param {*} overwrite
* @param {*} callback
*
* @param {*} overwrite
* @param {*} callback
*/
on(type,callback) {
on(type, callback) {
this._addPickingEvents();
super.on(type, callback);
}
getPickingId() {
return this.scene._engine._picking.getNextId();
return this.scene._engine._picking.getNextId();
}
addToPicking(object) {
this.scene._engine._picking.add(object);
@ -403,11 +437,24 @@ export default class Layer extends Base {
removeFromPicking(object) {
this.scene._engine._picking.remove(object);
}
_addPickMesh(mesh){
_addPickMesh(mesh) {
this._pickingMesh = new THREE.Object3D();
this._visibleWithZoom();
this.scene.on('zoomchange', () => {
this._visibleWithZoom();
});
this.addToPicking(this._pickingMesh);
const pickmaterial = new PickingMaterial();
const pickmaterial = new PickingMaterial({
u_zoom: this.scene.getZoom()
});
const pickingMesh = new THREE[mesh.type](mesh.geometry, pickmaterial);
pickmaterial.setDefinesvalue(this.type, true);
pickingMesh.onBeforeRender = () => {
const zoom = this.scene.getZoom();
pickingMesh.material.setUniformsValue('u_zoom', zoom);
};
this._pickingMesh.add(pickingMesh);
}
_setPickingId() {
@ -415,9 +462,20 @@ export default class Layer extends Base {
}
_addPickingEvents() {
// TODO: Find a way to properly remove this listener on destroy
this.scene.on('pick', (point2d, point3d, intersects) => {
this.scene.on('pick', e => {
// Re-emit click event from the layer
this.emit('click', this, point2d, point3d, intersects);
const { featureId, point2d, point3d, intersects } = e;
if (intersects.length === 0) { return; }
const source = this.layerSource.get('data');
const feature = source.features[featureId];
const lnglat = this.scene.containerToLngLat(point2d);
const target = {
feature,
pixel: point2d,
lnglat: { lng: lnglat.lng, lat: lnglat.lat }
};
this.emit('click', target);
// this.emit('move', target);
});
}
/**
@ -426,126 +484,123 @@ export default class Layer extends Base {
* @param {*} style 更新的要素样式
*/
updateStyle(featureStyleId, style) {
const {indices} = this.buffer.bufferStruct;
if (this._activeIds) {
this.resetStyle();
}
this._activeIds = featureStyleId;
const id = featureStyleId[0];
let dataIndex = 0;
if(indices){
// 面图层和
for (let i = 0; i < id; i++) {
dataIndex += indices[i].length;
}
} else {
dataIndex = id;
}
featureStyleId.forEach((index,value) => {
let vertindex =[value]
if(indices)
vertindex = indices[index];
const color = style.color;
const colorAttr =this.layerMesh.geometry.attributes.a_color;
colorAttr.dynamic =true;
vertindex.forEach(() => {
colorAttr.array[dataIndex*4+0]=color[0];
colorAttr.array[dataIndex*4+1]=color[1];
colorAttr.array[dataIndex*4+2]=color[2];
colorAttr.array[dataIndex*4+3]=color[3];
dataIndex++;
});
colorAttr.needsUpdate =true
});
const pickingId = this.layerMesh.geometry.attributes.pickingId.array;
const color = style.color;
const colorAttr = this.layerMesh.geometry.attributes.a_color;
const firstId = pickingId.indexOf(featureStyleId[0] + 1);
for (let i = firstId; i < pickingId.length; i++) {
if (pickingId[i] == featureStyleId[0] + 1) {
colorAttr.array[i * 4 + 0] = color[0];
colorAttr.array[i * 4 + 1] = color[1];
colorAttr.array[i * 4 + 2] = color[2];
colorAttr.array[i * 4 + 3] = color[3];
} else {
break;
}
}
colorAttr.needsUpdate = true;
return;
}
_updateColor() {
this._updateMaping();
}
/**
* 用于过滤数据
* @param {*} filterData 数据过滤标识符
*/
updateFilter(filterData) {
_updateFilter() {
this._updateMaping();
const filterData = this.StyleData;
this._activeIds = null; // 清空选中元素
let dataIndex = 0;
const colorAttr = this.layerMesh.geometry.attributes.a_color;
if(this.layerMesh.type =='Points'){ //点图层更新
filterData.forEach((item,index)=>{
const color = [ ...this.StyleData[index].color ];
if (item.hasOwnProperty('filter') && item.filter === false) {
color[3] = 0;
}
colorAttr.array[index*4+0]=color[0];
colorAttr.array[index*4+1]=color[1];
colorAttr.array[index*4+2]=color[2];
colorAttr.array[index*4+3]=color[3];
})
colorAttr.needsUpdate =true;
return;
}
const {indices} = this.buffer.bufferStruct;
indices.forEach((vertIndexs, i) => {
const color = [ ...this.StyleData[i].color ];
if (filterData[i].hasOwnProperty('filter') && filterData[i].filter === false) {
color[3] = 0;
const colorAttr = this.layerMesh.geometry.attributes.a_color;
const pickAttr = this.layerMesh.geometry.attributes.pickingId;
pickAttr.array.forEach((id, index) => {
id = Math.abs(id);
const color = [ ...this.StyleData[id - 1].color ];
id = Math.abs(id);
const item = filterData[id - 1];
if (item.hasOwnProperty('filter') && item.filter === false) {
colorAttr.array[index * 4 + 0] = 0;
colorAttr.array[index * 4 + 1] = 0;
colorAttr.array[index * 4 + 2] = 0;
colorAttr.array[index * 4 + 3] = 0;
pickAttr.array[index] = -id;
} else {
colorAttr.array[index * 4 + 0] = color[0];
colorAttr.array[index * 4 + 1] = color[1];
colorAttr.array[index * 4 + 2] = color[2];
colorAttr.array[index * 4 + 3] = color[3];
pickAttr.array[index] = id;
}
vertIndexs.forEach(() => {
colorAttr.array[dataIndex*4+0]=color[0];
colorAttr.array[dataIndex*4+1]=color[1];
colorAttr.array[dataIndex*4+2]=color[2];
colorAttr.array[dataIndex*4+3]=color[3];
dataIndex++;
});
colorAttr.needsUpdate =true;
});
colorAttr.needsUpdate = true;
pickAttr.needsUpdate = true;
this._needUpdateFilter = false;
this._needUpdateColor = false;
}
_visibleWithZoom() {
const zoom = this.scene.getZoom();
const minZoom = this.get('minZoom');
const maxZoom = this.get('maxZoom');
// z-fighting
let offset = 0;
if (this.type === 'point') {
offset = 5;
} else if (this.type === 'polyline') {
offset = 2;
}
this._object3D.position.z = offset * Math.pow(2, 20 - zoom);
if (zoom < minZoom || zoom > maxZoom) {
this._object3D.visible = false;
} else if (this.get('visible')) {
this._object3D.visible = true;
}
}
/**
* 重置高亮要素
*/
resetStyle() {
const {indices} = this.buffer.bufferStruct;
const colorAttr = this.layerMesh.geometry.attributes.a_color;
let dataIndex = 0;
const id = this._activeIds[0];
if(indices){
for (let i = 0; i < id; i++) {
dataIndex += indices[i].length;
}
} else {
dataIndex = id;
}
this._activeIds.forEach((index,value) => {
const pickingId = this.layerMesh.geometry.attributes.pickingId.array;
const colorAttr = this.layerMesh.geometry.attributes.a_color;
this._activeIds.forEach((index, value) => {
const color = this.StyleData[index].color;
let vertindex = [value];
if(indices){
vertindex = indices[index];
const firstId = pickingId.indexOf(index + 1);
for (let i = firstId; i < pickingId.length; i++) {
if (pickingId[i] == index + 1) {
colorAttr.array[i * 4 + 0] = color[0];
colorAttr.array[i * 4 + 1] = color[1];
colorAttr.array[i * 4 + 2] = color[2];
colorAttr.array[i * 4 + 3] = color[3];
}
}
vertindex.forEach(() => {
colorAttr.array[dataIndex*4+0]=color[0];
colorAttr.array[dataIndex*4+1]=color[1];
colorAttr.array[dataIndex*4+2]=color[2];
colorAttr.array[dataIndex*4+3]=color[3];
dataIndex++;
});
colorAttr.needsUpdate =true
});
colorAttr.needsUpdate = true;
}
destroy() {
if(this._object3D && this._object3D.children){
/**
* 销毁Layer对象
*/
despose() {
this.destroy();
if (this._object3D && this._object3D.children) {
let child;
for(let i =0;i<this._object3D.children.length;i++){
child = this._object3D.children[i];
if(!child){
continue;
}
this.remove(child);
if(child.geometry){
child.geometry.dispose();
child.geometry = null;
}
if (child.material) {
for (let i = 0; i < this._object3D.children.length; i++) {
child = this._object3D.children[i];
if (!child) {
continue;
}
this.remove(child);
if (child.geometry) {
child.geometry.dispose();
child.geometry = null;
}
if (child.material) {
if (child.material.map) {
child.material.map.dispose();
child.material.map = null;
@ -556,7 +611,7 @@ export default class Layer extends Base {
}
}
}
this._object3D =null;
this._object3D = null;
this.scene = null;
}
}

View File

@ -3,10 +3,8 @@ import * as THREE from './three';
import * as layers from '../layer';
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 GaodeMap from '../map/gaodeMap';
import Global from '../global';
export default class Scene extends Base {
getDefaultCfg() {
@ -15,6 +13,7 @@ export default class Scene extends Base {
constructor(cfg) {
super(cfg);
this._initMap();
this._initAttribution();
this.addImage();
this._layers = [];
}
@ -28,26 +27,20 @@ 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);
Utils.assign(this.__proto__, sceneMap.__proto__);
const sceneMap = new GaodeMap(Map.map);
// eslint-disable-next-line
Object.getOwnPropertyNames(sceneMap.__proto__).forEach((key)=>{
if ('key' !== 'constructor') { this.__proto__[key] = sceneMap.__proto__[key]; }
});
this.map = Map.map;
Map.asyncCamera(this._engine);
// this._addLight();
this.initLayer();
// this.zoomAsync();
this.emit('load');
this.emit('loaded');
});
}
@ -61,11 +54,26 @@ export default class Scene extends Base {
};
}
}
on(type, hander) {
if (this.map) { this.map.on(type, hander); }
super.on(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');
element.innerHTML = message;
element.style.cssText += 'position: absolute; pointer-events:none;background: rgba(255, 255, 255, 0.7);font-size: 11px;z-index:100; padding:4px;bottom: 0;right:0px;';
this._container.appendChild(element);
}
addImage() {
this.image = new LoadImage();
}
_initEvent() {
}
getLayers() {
return this._layers;
}
_addLight() {
const scene = this._engine._scene;

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-11-01 11:50:43
*/
const Base = require('./base');
import Base from './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

@ -4,6 +4,7 @@ export { Scene } from 'three/src/scenes/Scene.js';
export { WebGLRenderer } from 'three/src/renderers/WebGLRenderer.js';
export { CanvasTexture } from 'three/src/textures/CanvasTexture.js';
export { Object3D } from 'three/src/core/Object3D.js';
export { Clock } from 'three/src/core/Clock';
export { Points } from 'three/src/objects/Points.js';
export { LineSegments } from 'three/src/objects/LineSegments.js';
export { Mesh } from 'three/src/objects/Mesh.js';
@ -39,3 +40,5 @@ export {
Int8BufferAttribute,
BufferAttribute
} from 'three/src/core/BufferAttribute.js';
// export * from '../../build/Three.js';

View File

@ -15,4 +15,3 @@ export function aProjectFlat(lnglat) {
y = scale * (c * y + d) - 106744817;
return { x, y };
}

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++) {
@ -96,24 +84,15 @@ export default class BufferBase extends Base {
const ax = position[pIndex][index][0];
const ay = position[pIndex][index][1];
const az = position[pIndex][index][2];
index = indice[i * 3 + 1];
const bx = position[pIndex][index][0];
const by = position[pIndex][index][1];
const bz = position[pIndex][index][2];
index = indice[i * 3 + 2];
const cx = position[pIndex][index][0];
const cy = position[pIndex][index][1];
const cz = position[pIndex][index][2];
// Flat face normals
// From: http://threejs.org/examples/webgl_buffergeometry.html
pA.set(ax, ay, az);
pB.set(bx, by, bz);
pC.set(cx, cy, cz);
@ -181,6 +160,142 @@ export default class BufferBase extends Base {
normals,
colors,
pickingIds,
faceUv: new Float32Array(polygon.faceUv),
sizes: new Float32Array(polygon.sizes)
};
return attributes;
}
_toPointShapeAttributes(polygon) {
// Three components per vertex per face (3 x 3 = 9)
const { style, indices, position, indexCount, shapes, sizes } = polygon;
const vertices = new Float32Array(indexCount * 3);
const shapePositions = new Float32Array(indexCount * 3);
const a_size = new Float32Array(indexCount * 3);
const normals = new Float32Array(indexCount * 3);
const colors = new Float32Array(indexCount * 4);
const pickingIds = new Float32Array(indexCount);
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 lastIndex = 0;
indices.forEach((indice, pIndex) => {
for (let i = 0; i < indice.length / 3; i++) {
let index = indice[i * 3];
const color = style[pIndex].color;
const coor1 = position[pIndex];
const size = sizes[pIndex];
const _pickingId = style[pIndex].id;
const ax = shapes[pIndex][index][0];
const ay = shapes[pIndex][index][1];
const az = shapes[pIndex][index][2];
index = indice[i * 3 + 1];
const bx = shapes[pIndex][index][0];
const by = shapes[pIndex][index][1];
const bz = shapes[pIndex][index][2];
index = indice[i * 3 + 2];
const cx = shapes[pIndex][index][0];
const cy = shapes[pIndex][index][1];
const cz = shapes[pIndex][index][2];
pA.set(ax, ay, az);
pB.set(bx, by, bz);
pC.set(cx, cy, cz);
cb.subVectors(pC, pB);
ab.subVectors(pA, pB);
cb.cross(ab);
cb.normalize();
const nx = cb.x;
const ny = cb.y;
const nz = cb.z;
vertices[lastIndex * 9 + 0] = coor1[0];
vertices[lastIndex * 9 + 1] = coor1[1];
vertices[lastIndex * 9 + 2] = coor1[2];
shapePositions[lastIndex * 9 + 0] = ax;
shapePositions[lastIndex * 9 + 1] = ay;
shapePositions[lastIndex * 9 + 2] = az;
a_size[lastIndex * 9 + 0] = size[0];
a_size[lastIndex * 9 + 1] = size[1];
a_size[lastIndex * 9 + 2] = size[2];
normals[lastIndex * 9 + 0] = nx;
normals[lastIndex * 9 + 1] = ny;
normals[lastIndex * 9 + 2] = nz;
colors[lastIndex * 12 + 0] = color[0];
colors[lastIndex * 12 + 1] = color[1];
colors[lastIndex * 12 + 2] = color[2];
colors[lastIndex * 12 + 3] = color[3];
vertices[lastIndex * 9 + 3] = coor1[0];
vertices[lastIndex * 9 + 4] = coor1[1];
vertices[lastIndex * 9 + 5] = coor1[2];
shapePositions[lastIndex * 9 + 3] = bx;
shapePositions[lastIndex * 9 + 4] = by;
shapePositions[lastIndex * 9 + 5] = bz;
a_size[lastIndex * 9 + 3] = size[0];
a_size[lastIndex * 9 + 4] = size[1];
a_size[lastIndex * 9 + 5] = size[2];
normals[lastIndex * 9 + 3] = nx;
normals[lastIndex * 9 + 4] = ny;
normals[lastIndex * 9 + 5] = nz;
colors[lastIndex * 12 + 4] = color[0];
colors[lastIndex * 12 + 5] = color[1];
colors[lastIndex * 12 + 6] = color[2];
colors[lastIndex * 12 + 7] = color[3];
vertices[lastIndex * 9 + 6] = coor1[0];
vertices[lastIndex * 9 + 7] = coor1[1];
vertices[lastIndex * 9 + 8] = coor1[2];
a_size[lastIndex * 9 + 6] = size[0];
a_size[lastIndex * 9 + 7] = size[1];
a_size[lastIndex * 9 + 8] = size[2];
shapePositions[lastIndex * 9 + 6] = cx;
shapePositions[lastIndex * 9 + 7] = cy;
shapePositions[lastIndex * 9 + 8] = cz;
normals[lastIndex * 9 + 6] = nx;
normals[lastIndex * 9 + 7] = ny;
normals[lastIndex * 9 + 8] = nz;
colors[lastIndex * 12 + 8] = color[0];
colors[lastIndex * 12 + 9] = color[1];
colors[lastIndex * 12 + 10] = color[2];
colors[lastIndex * 12 + 11] = color[3];
pickingIds[lastIndex * 3 + 0] = _pickingId;
pickingIds[lastIndex * 3 + 1] = _pickingId;
pickingIds[lastIndex * 3 + 2] = _pickingId;
lastIndex++;
}
});
const attributes = {
vertices,
normals,
colors,
pickingIds,
shapePositions,
a_size,
faceUv: new Float32Array(polygon.faceUv)
};
@ -188,7 +303,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);
@ -236,7 +350,7 @@ export default class BufferBase extends Base {
colors[index * 4 + 2] = style[index].color[2];
colors[index * 4 + 3] = style[index].color[3];
pickingIds[index] = style[index].id;
sizes[index] = style[index].size;
sizes[index] = style[index].size * window.devicePixelRatio;
if (style[index].shape) { shapes[index] = style[index].shape; }
});
const attributes = {
@ -266,7 +380,8 @@ export default class BufferBase extends Base {
context.fillRect(x, y, 2, 4);
}
}
context.fillStyle = '#105CB3';
context.fillRect(0, 60, 32, 64);
// build a bigger canvas and copy the small one in it
// This is a trick to upscale the texture without filtering
const canvas2 = document.createElement('canvas');

View File

@ -32,7 +32,7 @@ export default class ImageBuffer extends BufferBase {
this.texture = texture;
}
_getTexture(name, image) {
_getTexture(image) {
const texture = new THREE.Texture(image);
texture.magFilter = THREE.LinearFilter;
texture.minFilter = THREE.LinearFilter;

View File

@ -3,51 +3,120 @@ import { lineShape } from '../shape';
export default class LineBuffer extends BufferBase {
geometryBuffer() {
const self = this;
const coordinates = self.get('coordinates');
const properties = self.get('properties');
const propertiesData = self.get('propertiesData');
const coordinates = this.get('coordinates');
const properties = this.get('properties');
const shapeType = this.shapeType = this.get('shapeType');
const positions = [];
const positionsIndex = [];
const instances = [];
if (shapeType === 'line') {
this.attributes = this._getMeshLineAttributes();
return;
} else if (shapeType === 'arc') {
this.attributes = this._getArcLineAttributes();
return;
}
coordinates.forEach((geo, index) => {
const props = properties[index];
const attrData = self._getShape(geo, props, index);
const attrData = this._getShape(geo, props, index);
positions.push(...attrData.positions);
positionsIndex.push(...attrData.indexes);
if (attrData.hasOwnProperty('instances')) {
instances.push(...attrData.instances);
}
});
self.bufferStruct.style = properties;
self.bufferStruct.verts = positions;
self.bufferStruct.indexs = positionsIndex;
self.shape = properties[0].shape || 'default';
this.bufferStruct.style = properties;
this.bufferStruct.verts = positions;
this.bufferStruct.indexs = positionsIndex;
if (instances.length > 0) {
self.bufferStruct.instances = instances;
this.bufferStruct.instances = instances;
}
self.attributes = this._toAttributes(self.bufferStruct, propertiesData);
this.attributes = this._toAttributes(this.bufferStruct);
}
_getShape(geo, props, index) {
if (!props.hasOwnProperty('shape')) {
if (!this.shapeType) {
return lineShape.defaultLine(geo, index);
}
const shape = props.shape;
const shape = this.shapeType;
if (shape === 'meshLine') {
return lineShape[shape](geo, props, index);
} else if (shape === 'tubeLine') {
return lineShape[shape](geo, props, index);
} else if (shape === 'arc') {
return lineShape[shape](geo, index);
return lineShape[shape](geo, props, index);
}
return lineShape.Line(geo, props, index);
}
_toAttributes(bufferStruct, propertiesData) {
_getArcLineAttributes() {
const coordinates = this.get('coordinates');
const properties = this.get('properties');
const positions = [];
const colors = [];
const indexArray = [];
const sizes = [];
const instances = [];
coordinates.forEach((geo, index) => {
const props = properties[index];
const positionCount = positions.length / 3;
const attrData = this._getShape(geo, props, positionCount);
positions.push(...attrData.positions);
colors.push(...attrData.colors);
indexArray.push(...attrData.indexArray);
instances.push(...attrData.instances);
sizes.push(...attrData.sizes);
});
return {
positions,
colors,
indexArray,
sizes,
instances
};
}
_getMeshLineAttributes() {
const coordinates = this.get('coordinates');
const properties = this.get('properties');
const { lineType } = this.get('style');
const positions = [];
const pickingIds = [];
const normal = [];
const miter = [];
const colors = [];
const indexArray = [];
const sizes = [];
const attrDistance = [];
coordinates.forEach((geo, index) => {
const props = properties[index];
const positionCount = positions.length / 3;
const attr = lineShape.Line(geo, props, positionCount, (lineType !== 'soild'));
positions.push(...attr.positions);
normal.push(...attr.normal);
miter.push(...attr.miter);
colors.push(...attr.colors);
indexArray.push(...attr.indexArray);
sizes.push(...attr.sizes);
attrDistance.push(...attr.attrDistance);
pickingIds.push(...attr.pickingIds);
});
return {
positions,
normal,
miter,
colors,
indexArray,
pickingIds,
sizes,
attrDistance
};
}
_toAttributes(bufferStruct) {
const vertCount = bufferStruct.verts.length;
const vertices = new Float32Array(vertCount * 3);
const inposs = new Float32Array(vertCount * 4);
const colors = new Float32Array(vertCount * 4);
const times = new Float32Array(vertCount);
for (let i = 0; i < vertCount; i++) {
const index = bufferStruct.indexs[i];
const color = bufferStruct.style[index].color;
@ -58,22 +127,18 @@ export default class LineBuffer extends BufferBase {
colors[i * 4 + 1] = color[1];
colors[i * 4 + 2] = color[2];
colors[i * 4 + 3] = color[3];
if (bufferStruct.instances) {
if (bufferStruct.instances) { // 弧线
inposs[i * 4] = bufferStruct.instances[i][0];
inposs[i * 4 + 1] = bufferStruct.instances[i][1];
inposs[i * 4 + 2] = bufferStruct.instances[i][2];
inposs[i * 4 + 3] = bufferStruct.instances[i][3];
}
if (propertiesData) {
const time = propertiesData[index].time;
times[i] = time;
}
}
return {
vertices,
colors,
inposs,
times
inposs
};
}
}

View File

@ -1,28 +1,21 @@
import BufferBase from './bufferBase';
import { regularShape } from '../shape/index';
import Util from '../../util';
import * as THREE from '../../core/three';
const shapeObj = {
circle: 30,
square: 4,
triangle: 3,
hexagon: 6
};
export default class PointBuffer extends BufferBase {
geometryBuffer() {
const type = this.get('type');
switch (type) {
case 'image' : this._imageBuffer();
break;
case '2d': this._2dRegularBuffer();
case '2d': this._3dRegularBuffer();
break;
case '3d': this._3dRegularBuffer();
break;
case 'Model':this._ModelBuffer();
break;
default:
this._3dRegularBuffer();
this._sdfRegularBuffer();
}
}
@ -31,7 +24,6 @@ export default class PointBuffer extends BufferBase {
const properties = this.get('properties');
const imagePos = this.get('imagePos');
const uv = new Float32Array(properties.length * 2);
for (let i = 0; i < properties.length; i++) {
const { x, y } = imagePos[properties[i].shape];
uv[i * 2] = x;
@ -44,56 +36,52 @@ export default class PointBuffer extends BufferBase {
this.attributes = this._toPointsAttributes(this.bufferStruct);
this.attributes.uvs = uv;
}
_2dRegularBuffer() {
_sdfRegularBuffer() {
const coordinates = this.get('coordinates');
const properties = this.get('properties');
const shapes = [];
for (let i = 0; i < properties.length; i++) {
const shape = shapeObj[properties[i].shape];
properties[i].shape = shape;
}
this.bufferStruct.position = coordinates;
properties.shapes = shapes;
this.bufferStruct.style = properties;
this.attributes = this._toPointsAttributes(this.bufferStruct);
}
_3dRegularBuffer() {
const coordinates = this.get('coordinates');
const properties = this.get('properties');
const type = this.get('type');
const positions = [];
const shapes = [];
const sizes = [];
const uvs = [];
const positionsIndex = [];
let indexCount = 0;
this.bufferStruct.style = properties;
coordinates.forEach((geo, index) => {
const m1 = new THREE.Matrix4();
const { size, shape } = properties[index];
const vert = regularShape[shape]('extrude');
m1.setPosition(new THREE.Vector3(...geo));
size[2] += Math.random() * 1000;
m1.scale(new THREE.Vector3(...size));
vert.positions = vert.positions.map(coor => {
const vector = new THREE.Vector4(...coor, 1);
vector.applyMatrix4(m1);
return vector.toArray();
});// 旋转矩阵
positions.push(vert.positions);
let { size, shape } = properties[index];
let shapeType = 'extrude';
if (type === '2d' || (type === '3d' && size[2] === 0)) {
shapeType = 'fill';
Util.isArray(size) || (size = [ size, size, 0 ]);
} else {
Util.isArray(size) || (size = [ size, size, size ]);
}
if (regularShape[shape] == null) {
uvs.push(0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0);
shape = 'square';
}
const vert = regularShape[shape](shapeType);
shapes.push(vert.positions);
positions.push(geo);
sizes.push(size);
positionsIndex.push(vert.positionsIndex);
indexCount += vert.positionsIndex.length;
});
this.bufferStruct.indices = positionsIndex;
this.bufferStruct.position = positions;
this.bufferStruct.indexCount = indexCount;
this.attributes = this._toPolygonAttributes(this.bufferStruct);
this.bufferStruct.shapes = shapes;
this.bufferStruct.sizes = sizes;
this.bufferStruct.faceUv = uvs;
this.attributes = this._toPointShapeAttributes(this.bufferStruct);
}
_ModelBuffer() {
}
_textBuffer() {
}
}

View File

@ -8,6 +8,7 @@ export default class PolygonBuffer extends BufferBase {
const shape = this.get('shape');
const positions = [];
const faceUv = [];
const sizes = [];
const positionsIndex = [];
let indexCount = 0;
this.bufferStruct.style = properties;
@ -24,7 +25,23 @@ export default class PolygonBuffer extends BufferBase {
});
}
positions.push(extrudeData.positions);
faceUv.push(...extrudeData.faceUv);
if (shape !== 'line') {
// faceUv.push(...extrudeData.faceUv);
const count = extrudeData.faceUv.length / 2;
for (let i = 0; i < count; i++) {
// uv 系数生成等大小的窗户
let x = extrudeData.faceUv[i * 2];
let y = extrudeData.faceUv[i * 2 + 1];
if (x !== -1) {
x = x * 0.1;
y = y * heightValue / 2000;
}
faceUv.push(x, y);
sizes.push((1.0 - extrudeData.faceUv[i * 2 + 1]) * heightValue);
}
}
indexCount += extrudeData.positionsIndex.length;
positionsIndex.push(extrudeData.positionsIndex);
});
@ -33,6 +50,7 @@ export default class PolygonBuffer extends BufferBase {
this.bufferStruct.indexCount = indexCount;
this.bufferStruct.style = properties;
this.bufferStruct.faceUv = faceUv;
this.bufferStruct.sizes = sizes;
if (shape !== 'line') {
this.attributes = this._toPolygonAttributes(this.bufferStruct);
this.faceTexture = this._generateTexture();

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,11 @@ 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 { textOffset = [ 0, 0 ] } = this.get('style');
const chars = [];
const positions = [];
const uvs = [];
properties.forEach(element => {
const text = element.shape;
let text = element.shape || '';
text = text.toString();
for (let j = 0; j < text.length; j++) {
const code = text.charCodeAt(j);
if (chars.indexOf(code) === -1) {
@ -28,38 +25,41 @@ export default class TextBuffer extends BufferBase {
}
}
});
this._loadTextInfo(chars);
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: textOffset[0], y: textOffset[1] };
let text = element.shape || '';
text = text.toString();
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);
}
_loadTextInfo(chars) {
getJSON({
url: `${Global.sdfHomeUrl}/getsdfdata?chars=${chars.join('|')}`
}, (e, info) => {
@ -75,19 +75,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 +111,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 +189,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

@ -22,9 +22,7 @@ export default function extrudePolygon(points, extrude) {
const triangles = earcut(flattengeo.vertices, flattengeo.holes, flattengeo.dimensions);
cells = triangles;
triangles.forEach(() => {
faceUv.push(-1, -1);
});
const pointCount = flattengeo.vertices.length / 3;
const { vertices } = flattengeo;
extrude ? full() : flat();
@ -32,11 +30,16 @@ export default function extrudePolygon(points, extrude) {
function flat() {
for (let i = 0; i < pointCount; i++) {
positions.push([ vertices[ i * 3 ], vertices[i * 3 + 1 ], 0 ]);
}
}
function full() {
// 顶部纹理
triangles.forEach(() => {
faceUv.push(-1, -1);
});
// 顶部坐标
for (let i = 0; i < pointCount; i++) {
positions.push([ vertices[ i * 3 ], vertices[i * 3 + 1 ], 1 ]);
}

View File

@ -1,8 +1,8 @@
import * as THREE from '../../core/three';
import image_frag from '../shader/image_frag.glsl';
import image_vert from '../shader/image_vert.glsl';
import Material from './material';
export default function ImageMaterial(options) {
const material = new THREE.ShaderMaterial({
const material = new Material({
uniforms: {
u_opacity: { value: options.u_opacity },
u_texture: { value: options.u_texture }
@ -11,8 +11,5 @@ export default function ImageMaterial(options) {
fragmentShader: image_frag,
transparent: true
});
// material.roughness = 1;
// material.metalness = 0.1;
// material.envMapIntensity = 3;
return material;
}

View File

@ -1,13 +1,21 @@
import * as THREE from '../../core/three';
import Material from './material';
import line_frag from '../shader/line_frag.glsl';
import line_vert from '../shader/line_vert.glsl';
import arcline_frag from '../shader/arcline_frag.glsl';
import arcline_vert from '../shader/arcline_vert.glsl';
import meshline_vert from '../shader/meshline_vert.glsl';
import meshline_frag from '../shader/meshline_frag.glsl';
import dashline_frag from '../shader/dashline_frag.glsl';
import dashline_vert from '../shader/dashline_vert.glsl';
export function LineMaterial(options) {
const material = new THREE.ShaderMaterial({
const material = new Material({
uniforms: {
u_opacity: { value: options.u_opacity || 1.0 },
currentTime: { value: options.u_time || 2500 }
u_time: { value: options.u_time || 0 },
u_zoom: { value: options.u_zoom || 10 }
},
vertexShader: line_vert,
fragmentShader: line_frag,
@ -17,13 +25,46 @@ export function LineMaterial(options) {
return material;
}
export function ArcLineMaterial(options) {
const material = new THREE.ShaderMaterial({
const material = new Material({
uniforms: {
u_opacity: { value: options.u_opacity || 1.0 },
segmentNumber: { value: 50 }
segmentNumber: { value: 49 },
u_time: { value: 0 },
u_zoom: { value: options.u_zoom || 10 }
},
vertexShader: arcline_vert,
fragmentShader: arcline_frag,
transparent: true,
blending: THREE.AdditiveBlending
});
return material;
}
export function MeshLineMaterial(options) {
const material = new Material({
uniforms: {
u_opacity: { value: options.u_opacity || 1.0 },
u_time: { value: options.u_time || 0 },
u_zoom: { value: options.u_zoom }
},
vertexShader: meshline_vert,
fragmentShader: meshline_frag,
transparent: true
});
return material;
}
export function DashLineMaterial(options) {
const material = new Material({
uniforms: {
u_opacity: { value: options.u_opacity || 1.0 },
u_time: { value: options.u_time || 0 },
u_zoom: { value: options.u_zoom },
u_dashSteps: { value: options.u_dashSteps || 12 },
u_dashSmooth: { value: options.u_dashSmooth || 0.01 },
u_dashDistance: { value: options.u_dashDistance || 0.2 }
},
vertexShader: dashline_vert,
fragmentShader: dashline_frag,
transparent: true
});
return material;

View File

@ -1,11 +1,29 @@
import * as THREE from '../../core/three';
export default class Material extends THREE.ShaderMaterial {
constructor(opts) {
super(opts);
}
setValue(name, value) {
setUniformsValue(name, value) {
if (!this.uniforms[name]) { return; }
this.uniforms[name].value = value;
this.uniforms.needsUpdate = true;
}
setDefinesvalue(name, value) {
this.defines[name] = value;
this.needsUpdate = true;
}
setUniform(option) {
const uniforms = {};
for (const key in option) {
if (key.substr(0, 2) === 'u_') {
uniforms[key] = { value: option[key] };
}
}
return uniforms;
}
upDateUninform(option) {
for (const key in option) {
if (key.substr(0, 2) === 'u_') {
this.setUniformsValue(key, option[key]);
}
}
}
}

View File

@ -1,22 +1,37 @@
import * as THREE from '../../core/three';
import Material from './material';
import point_frag from '../shader/point_frag.glsl';
import point_vert from '../shader/point_vert.glsl';
export default function PointMaterial(options) {
const material = new THREE.ShaderMaterial({
uniforms: {
u_opacity: { value: options.u_opacity },
u_stroke: { value: options.u_stroke },
u_strokeWidth: { value: options.u_strokeWidth },
u_texture: { value: options.u_texture }
},
vertexShader: point_vert,
fragmentShader: point_frag,
blending: THREE.NormalBlending,
transparent: true,
defines: {
SHAPE: true,
TEXCOORD_0: !!options.u_texture
export default class PointMaterial extends Material {
getDefaultParameters() {
return {
uniforms: {
u_opacity: { value: 1 },
u_stroke: { value: [ 1.0, 1.0, 1.0, 1.0 ] },
u_strokeWidth: { value: 1 }
},
defines: {
SHAPE: false,
TEXCOORD_0: false
}
};
}
constructor(_uniforms, _defines, parameters) {
super(parameters);
const { uniforms, defines } = this.getDefaultParameters();
this.uniforms = Object.assign(uniforms, this.setUniform(_uniforms));
this.defines = Object.assign(defines, _defines);
this.type = 'PointMaterial';
this.vertexShader = point_vert;
this.fragmentShader = point_frag;
this.transparent = true;
if (!_uniforms.shape) { this.blending = THREE.AdditiveBlending; }
if (_uniforms.u_texture) {
this.defines.TEXCOORD_0 = true;
}
});
return material;
}
}

View File

@ -1,11 +1,16 @@
import * as THREE from '../../core/three';
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 THREE.ShaderMaterial({
const material = new Material({
uniforms: {
u_opacity: { value: options.u_opacity },
u_texture: { value: options.u_texture }
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 ] }
},
vertexShader: polygon_vert,
fragmentShader: polygon_frag,
@ -14,8 +19,5 @@ export default function PolygonMaterial(options) {
TEXCOORD_0: !!options.u_texture
}
});
material.roughness = 1;
material.metalness = 0.1;
material.envMapIntensity = 3;
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) {

Some files were not shown because too many files have changed in this diff Show More