mirror of https://gitee.com/antv-l7/antv-l7
commit
27f6f4dfbc
|
@ -66,7 +66,7 @@ scene.on('loaded', () => {
|
||||||
.color('point_count',["#002466","#105CB3","#2894E0","#CFF6FF","#FFF5B8","#FFAB5C","#F27049","#730D1C"])
|
.color('point_count',["#002466","#105CB3","#2894E0","#CFF6FF","#FFF5B8","#FFAB5C","#F27049","#730D1C"])
|
||||||
.style({
|
.style({
|
||||||
stroke: 'rgb(255,255,255)',
|
stroke: 'rgb(255,255,255)',
|
||||||
strokeWidth: 1,
|
strokeWidth: 2,
|
||||||
opacity: 1
|
opacity: 1
|
||||||
})
|
})
|
||||||
.render();
|
.render();
|
||||||
|
@ -76,7 +76,7 @@ scene.on('loaded', () => {
|
||||||
})
|
})
|
||||||
.source(circleLayer.layerSource)
|
.source(circleLayer.layerSource)
|
||||||
.shape('point_count', 'text')
|
.shape('point_count', 'text')
|
||||||
.active(true)
|
.active(false)
|
||||||
.filter('point_count',(p)=>{
|
.filter('point_count',(p)=>{
|
||||||
return p > 50
|
return p > 50
|
||||||
})
|
})
|
||||||
|
@ -84,10 +84,10 @@ scene.on('loaded', () => {
|
||||||
.color('#fff')
|
.color('#fff')
|
||||||
.style({
|
.style({
|
||||||
stroke: '#999',
|
stroke: '#999',
|
||||||
strokeWidth: 0,
|
strokeWidth: 1,
|
||||||
opacity: 1.0
|
opacity: 1.0
|
||||||
})
|
})
|
||||||
.render();
|
.render();
|
||||||
console.log(layerText);
|
console.log(layerText);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -29,8 +29,7 @@ const scene = new L7.Scene({
|
||||||
});
|
});
|
||||||
window.scene = scene;
|
window.scene = scene;
|
||||||
scene.on('loaded', () => {
|
scene.on('loaded', () => {
|
||||||
$.get('./data/provincePoint.geojson', data => {
|
$.get('./data/provincePoint.json', data => {
|
||||||
// data.features = data.features.slice(0,1);
|
|
||||||
scene.PointLayer({
|
scene.PointLayer({
|
||||||
zIndex: 2
|
zIndex: 2
|
||||||
})
|
})
|
||||||
|
|
|
@ -0,0 +1,173 @@
|
||||||
|
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.ColorHash = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
|
||||||
|
/**
|
||||||
|
* BKDR Hash (modified version)
|
||||||
|
*
|
||||||
|
* @param {String} str string to hash
|
||||||
|
* @returns {Number}
|
||||||
|
*/
|
||||||
|
var BKDRHash = function(str) {
|
||||||
|
var seed = 131;
|
||||||
|
var seed2 = 137;
|
||||||
|
var hash = 0;
|
||||||
|
// make hash more sensitive for short string like 'a', 'b', 'c'
|
||||||
|
str += 'x';
|
||||||
|
// Note: Number.MAX_SAFE_INTEGER equals 9007199254740991
|
||||||
|
var MAX_SAFE_INTEGER = parseInt(9007199254740991 / seed2);
|
||||||
|
for(var i = 0; i < str.length; i++) {
|
||||||
|
if(hash > MAX_SAFE_INTEGER) {
|
||||||
|
hash = parseInt(hash / seed2);
|
||||||
|
}
|
||||||
|
hash = hash * seed + str.charCodeAt(i);
|
||||||
|
}
|
||||||
|
return hash;
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = BKDRHash;
|
||||||
|
|
||||||
|
},{}],2:[function(require,module,exports){
|
||||||
|
var BKDRHash = require('./bkdr-hash');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert RGB Array to HEX
|
||||||
|
*
|
||||||
|
* @param {Array} RGBArray - [R, G, B]
|
||||||
|
* @returns {String} 6 digits hex starting with #
|
||||||
|
*/
|
||||||
|
var RGB2HEX = function(RGBArray) {
|
||||||
|
var hex = '#';
|
||||||
|
RGBArray.forEach(function(value) {
|
||||||
|
if (value < 16) {
|
||||||
|
hex += 0;
|
||||||
|
}
|
||||||
|
hex += value.toString(16);
|
||||||
|
});
|
||||||
|
return hex;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert HSL to RGB
|
||||||
|
*
|
||||||
|
* @see {@link http://zh.wikipedia.org/wiki/HSL和HSV色彩空间} for further information.
|
||||||
|
* @param {Number} H Hue ∈ [0, 360)
|
||||||
|
* @param {Number} S Saturation ∈ [0, 1]
|
||||||
|
* @param {Number} L Lightness ∈ [0, 1]
|
||||||
|
* @returns {Array} R, G, B ∈ [0, 255]
|
||||||
|
*/
|
||||||
|
var HSL2RGB = function(H, S, L) {
|
||||||
|
H /= 360;
|
||||||
|
|
||||||
|
var q = L < 0.5 ? L * (1 + S) : L + S - L * S;
|
||||||
|
var p = 2 * L - q;
|
||||||
|
|
||||||
|
return [H + 1/3, H, H - 1/3].map(function(color) {
|
||||||
|
if(color < 0) {
|
||||||
|
color++;
|
||||||
|
}
|
||||||
|
if(color > 1) {
|
||||||
|
color--;
|
||||||
|
}
|
||||||
|
if(color < 1/6) {
|
||||||
|
color = p + (q - p) * 6 * color;
|
||||||
|
} else if(color < 0.5) {
|
||||||
|
color = q;
|
||||||
|
} else if(color < 2/3) {
|
||||||
|
color = p + (q - p) * 6 * (2/3 - color);
|
||||||
|
} else {
|
||||||
|
color = p;
|
||||||
|
}
|
||||||
|
return Math.round(color * 255);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
function isArray(o) {
|
||||||
|
return Object.prototype.toString.call(o) === '[object Array]';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Color Hash Class
|
||||||
|
*
|
||||||
|
* @class
|
||||||
|
*/
|
||||||
|
var ColorHash = function(options) {
|
||||||
|
options = options || {};
|
||||||
|
|
||||||
|
var LS = [options.lightness, options.saturation].map(function(param) {
|
||||||
|
param = param || [0.35, 0.5, 0.65]; // note that 3 is a prime
|
||||||
|
return isArray(param) ? param.concat() : [param];
|
||||||
|
});
|
||||||
|
|
||||||
|
this.L = LS[0];
|
||||||
|
this.S = LS[1];
|
||||||
|
|
||||||
|
if (typeof options.hue === 'number') {
|
||||||
|
options.hue = {min: options.hue, max: options.hue};
|
||||||
|
}
|
||||||
|
if (typeof options.hue === 'object' && !isArray(options.hue)) {
|
||||||
|
options.hue = [options.hue];
|
||||||
|
}
|
||||||
|
if (typeof options.hue === 'undefined') {
|
||||||
|
options.hue = [];
|
||||||
|
}
|
||||||
|
this.hueRanges = options.hue.map(function (range) {
|
||||||
|
return {
|
||||||
|
min: typeof range.min === 'undefined' ? 0 : range.min,
|
||||||
|
max: typeof range.max === 'undefined' ? 360: range.max
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
this.hash = options.hash || BKDRHash;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the hash in [h, s, l].
|
||||||
|
* Note that H ∈ [0, 360); S ∈ [0, 1]; L ∈ [0, 1];
|
||||||
|
*
|
||||||
|
* @param {String} str string to hash
|
||||||
|
* @returns {Array} [h, s, l]
|
||||||
|
*/
|
||||||
|
ColorHash.prototype.hsl = function(str) {
|
||||||
|
var H, S, L;
|
||||||
|
var hash = this.hash(str);
|
||||||
|
|
||||||
|
if (this.hueRanges.length) {
|
||||||
|
var range = this.hueRanges[hash % this.hueRanges.length];
|
||||||
|
var hueResolution = 727; // note that 727 is a prime
|
||||||
|
H = ((hash / this.hueRanges.length) % hueResolution) * (range.max - range.min) / hueResolution + range.min;
|
||||||
|
} else {
|
||||||
|
H = hash % 359; // note that 359 is a prime
|
||||||
|
}
|
||||||
|
hash = parseInt(hash / 360);
|
||||||
|
S = this.S[hash % this.S.length];
|
||||||
|
hash = parseInt(hash / this.S.length);
|
||||||
|
L = this.L[hash % this.L.length];
|
||||||
|
|
||||||
|
return [H, S, L];
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the hash in [r, g, b].
|
||||||
|
* Note that R, G, B ∈ [0, 255]
|
||||||
|
*
|
||||||
|
* @param {String} str string to hash
|
||||||
|
* @returns {Array} [r, g, b]
|
||||||
|
*/
|
||||||
|
ColorHash.prototype.rgb = function(str) {
|
||||||
|
var hsl = this.hsl(str);
|
||||||
|
return HSL2RGB.apply(this, hsl);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the hash in hex
|
||||||
|
*
|
||||||
|
* @param {String} str string to hash
|
||||||
|
* @returns {String} hex with #
|
||||||
|
*/
|
||||||
|
ColorHash.prototype.hex = function(str) {
|
||||||
|
var rgb = this.rgb(str);
|
||||||
|
return RGB2HEX(rgb);
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = ColorHash;
|
||||||
|
|
||||||
|
},{"./bkdr-hash":1}]},{},[2])(2)
|
||||||
|
});
|
|
@ -39,7 +39,7 @@ scene.on('loaded', () => {
|
||||||
//.color('#F08D41')
|
//.color('#F08D41')
|
||||||
.color('#ff893a')
|
.color('#ff893a')
|
||||||
.animate({enable:true})
|
.animate({enable:true})
|
||||||
.render();
|
//.render();
|
||||||
});
|
});
|
||||||
$.get('https://gw.alipayobjects.com/os/rmsportal/vmvAxgsEwbpoSWbSYvix.json', data => {
|
$.get('https://gw.alipayobjects.com/os/rmsportal/vmvAxgsEwbpoSWbSYvix.json', data => {
|
||||||
buildLayer = scene.PolygonLayer({
|
buildLayer = scene.PolygonLayer({
|
||||||
|
|
|
@ -47,6 +47,7 @@ scene.on('loaded', () => {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.source(city)
|
.source(city)
|
||||||
|
.active(false)
|
||||||
.color('pm2_5_24h',["#FFF5B8","#FFDC7D","#FFAB5C","#F27049","#D42F31","#730D1C"])
|
.color('pm2_5_24h',["#FFF5B8","#FFDC7D","#FFAB5C","#F27049","#D42F31","#730D1C"])
|
||||||
.shape('fill')
|
.shape('fill')
|
||||||
.style({
|
.style({
|
||||||
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||||
|
<meta name="geometry" content="diagram">
|
||||||
|
<link rel="stylesheet" href="./assets/common.css">
|
||||||
|
<link rel="stylesheet" href="./assets/info.css">
|
||||||
|
|
||||||
|
<title>hexagon demo</title>
|
||||||
|
<style>
|
||||||
|
body {margin: 0;}
|
||||||
|
#map { position:absolute; top:0; bottom:0; width:100%; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="map"></div>
|
||||||
|
<script src="https://webapi.amap.com/maps?v=1.4.8&key=15cd8a57710d40c9b7c0e3cc120f1200&plugin=Map3D"></script>
|
||||||
|
<script src="./assets/jquery-3.2.1.min.js"></script>
|
||||||
|
<script src="./assets/dat.gui.min.js"></script>
|
||||||
|
<script src="../build/L7.js"></script>
|
||||||
|
<script>
|
||||||
|
|
||||||
|
const scene = new L7.Scene({
|
||||||
|
id: 'map',
|
||||||
|
mapStyle: 'dark', // 样式URL
|
||||||
|
center: [116.5909,39.9225 ],
|
||||||
|
pitch: 0,
|
||||||
|
hash:true,
|
||||||
|
zoom: 14,
|
||||||
|
|
||||||
|
});
|
||||||
|
window.scene = scene;
|
||||||
|
scene.on('loaded', () => {
|
||||||
|
const layer = scene.VectorTileLayer({
|
||||||
|
zIndex:0,
|
||||||
|
layerType:'point'
|
||||||
|
})
|
||||||
|
//.source('https://pre-lbs-show.taobao.com/gettile?x={x}&y={y}&z={z}&pipeId=pipe_vt_test')
|
||||||
|
|
||||||
|
// http://alipay-rmsdeploy-image.cn-hangzhou.alipay.aliyun-inc.com/thinkgis/tile/point/{z}/{x}/{y}.pbf
|
||||||
|
// https://mvt.amap.com/district/CHN2/8/203/105/4096?key=
|
||||||
|
.source('http://alipay-rmsdeploy-image.cn-hangzhou.alipay.aliyun-inc.com/thinkgis/tile/point2/{z}/{x}/{y}.pbf',{
|
||||||
|
parser:{
|
||||||
|
type: 'mvt',
|
||||||
|
sourceLayer:'layer',
|
||||||
|
//idField:'OBJECTID',
|
||||||
|
maxZoom: 17,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.scale({
|
||||||
|
total:{
|
||||||
|
min:0,
|
||||||
|
max:1000000,
|
||||||
|
type:'log'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// cylinder
|
||||||
|
.shape('hexagon')
|
||||||
|
.size(2)
|
||||||
|
.active({fill:'red'})
|
||||||
|
.color('total', ['#d53e4f','#f46d43','#fdae61','#fee08b','#ffffbf','#e6f598','#abdda4','#66c2a5','#3288bd'].reverse())
|
||||||
|
//.color('#0D408C')
|
||||||
|
.style({
|
||||||
|
opacity:1.0
|
||||||
|
})
|
||||||
|
.render(
|
||||||
|
);
|
||||||
|
layer.on('mousemove',(feature)=>{
|
||||||
|
console.log(feature);
|
||||||
|
})
|
||||||
|
console.log(layer);
|
||||||
|
});
|
||||||
|
//OBJECTID',(id)=>{
|
||||||
|
// const index = id % 8;
|
||||||
|
//return ['#9e0142','#d53e4f','#f46d43','#fdae61','#fee08b','#ffffbf','#e6f598','#abdda4','#66c2a5','#3288bd','#5e4fa2'][index];
|
||||||
|
//}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||||
|
<meta name="geometry" content="diagram">
|
||||||
|
<link rel="stylesheet" href="./assets/common.css">
|
||||||
|
<link rel="stylesheet" href="./assets/info.css">
|
||||||
|
|
||||||
|
<title>hexagon demo</title>
|
||||||
|
<style>
|
||||||
|
body {margin: 0;}
|
||||||
|
#map { position:absolute; top:0; bottom:0; width:100%; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="map"></div>
|
||||||
|
<script src="https://webapi.amap.com/maps?v=1.4.8&key=15cd8a57710d40c9b7c0e3cc120f1200&plugin=Map3D"></script>
|
||||||
|
<script src="./assets/color-hash.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 scene = new L7.Scene({
|
||||||
|
id: 'map',
|
||||||
|
mapStyle: 'dark', // 样式URL
|
||||||
|
center: [116.5909,39.9225 ],
|
||||||
|
pitch: 0,
|
||||||
|
hash:true,
|
||||||
|
zoom: 14,
|
||||||
|
|
||||||
|
});
|
||||||
|
window.scene = scene;
|
||||||
|
var colorHash = new ColorHash();
|
||||||
|
scene.on('loaded', () => {
|
||||||
|
const layer = scene.VectorTileLayer({
|
||||||
|
zIndex:0,
|
||||||
|
layerType:'polygon'
|
||||||
|
})
|
||||||
|
//.source('https://pre-lbs-show.taobao.com/gettile?x={x}&y={y}&z={z}&pipeId=pipe_vt_test')
|
||||||
|
|
||||||
|
// http://alipay-rmsdeploy-image.cn-hangzhou.alipay.aliyun-inc.com/thinkgis/tile/point/{z}/{x}/{y}.pbf
|
||||||
|
// https://mvt.amap.com/district/CHN2/8/203/105/4096?key=
|
||||||
|
.source('http://alipay-rmsdeploy-image.cn-hangzhou.alipay.aliyun-inc.com/thinkgis/tile/china/{z}/{x}/{y}.pbf',{
|
||||||
|
parser:{
|
||||||
|
type: 'mvt',
|
||||||
|
sourceLayer:'layer',
|
||||||
|
idField:'adcode',
|
||||||
|
maxZoom: 17,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
//.scale()
|
||||||
|
// cylinder
|
||||||
|
.shape('fill')
|
||||||
|
.size(2)
|
||||||
|
.active({fill:'red'})
|
||||||
|
.color('name',name => {
|
||||||
|
//var colorHash = new ColorHash();
|
||||||
|
return colorHash.hex(name)
|
||||||
|
})
|
||||||
|
.style({
|
||||||
|
opacity:1.0
|
||||||
|
})
|
||||||
|
.render(
|
||||||
|
);
|
||||||
|
layer.on('mousemove',(feature)=>{
|
||||||
|
console.log(feature);
|
||||||
|
})
|
||||||
|
console.log(layer);
|
||||||
|
});
|
||||||
|
//OBJECTID',(id)=>{
|
||||||
|
// const index = id % 8;
|
||||||
|
//return ['#9e0142','#d53e4f','#f46d43','#fdae61','#fee08b','#ffffbf','#e6f598','#abdda4','#66c2a5','#3288bd','#5e4fa2'][index];
|
||||||
|
//}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
|
@ -0,0 +1,80 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||||
|
<meta name="geometry" content="diagram">
|
||||||
|
<link rel="stylesheet" href="./assets/common.css">
|
||||||
|
<link rel="stylesheet" href="./assets/info.css">
|
||||||
|
|
||||||
|
<title>hexagon demo</title>
|
||||||
|
<style>
|
||||||
|
body {margin: 0;}
|
||||||
|
#map { position:absolute; top:0; bottom:0; width:100%; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="map"></div>
|
||||||
|
<script src="https://webapi.amap.com/maps?v=1.4.8&key=15cd8a57710d40c9b7c0e3cc120f1200&plugin=Map3D"></script>
|
||||||
|
<script src="./assets/jquery-3.2.1.min.js"></script>
|
||||||
|
<script src="./assets/dat.gui.min.js"></script>
|
||||||
|
<script src="../build/L7.js"></script>
|
||||||
|
<script>
|
||||||
|
|
||||||
|
const scene = new L7.Scene({
|
||||||
|
id: 'map',
|
||||||
|
mapStyle: 'dark', // 样式URL
|
||||||
|
center: [116.5909,39.9225 ],
|
||||||
|
pitch: 0,
|
||||||
|
hash:true,
|
||||||
|
zoom: 14,
|
||||||
|
|
||||||
|
});
|
||||||
|
window.scene = scene;
|
||||||
|
scene.on('loaded', () => {
|
||||||
|
const layer = scene.VectorTileLayer({
|
||||||
|
zIndex:0,
|
||||||
|
layerType:'heatmap'
|
||||||
|
})
|
||||||
|
.source('http://alipay-rmsdeploy-image.cn-hangzhou.alipay.aliyun-inc.com/thinkgis/tile/point2/{z}/{x}/{y}.pbf',{
|
||||||
|
parser:{
|
||||||
|
type: 'mvt',
|
||||||
|
sourceLayer:'layer',
|
||||||
|
maxZoom: 17,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.scale({
|
||||||
|
total:{
|
||||||
|
min:0,
|
||||||
|
max:1000000,
|
||||||
|
type:'log'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.shape('heatmap')
|
||||||
|
.size('total',[ 0, 1])
|
||||||
|
.style({
|
||||||
|
intensity: 10,
|
||||||
|
radius: 10,
|
||||||
|
opacity:1,
|
||||||
|
rampColors: {
|
||||||
|
colors: [ '#ffda45ff', '#fde725ff', '#ffc934ff', '#ffb824ff', '#ffb824ff', '#fa8100ff' ],
|
||||||
|
positions: [ 0, 0.2, 0.4, 0.6, 0.9, 1.0 ]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.render(
|
||||||
|
);
|
||||||
|
layer.on('mousemove',(feature)=>{
|
||||||
|
console.log(feature);
|
||||||
|
})
|
||||||
|
console.log(layer);
|
||||||
|
});
|
||||||
|
//OBJECTID',(id)=>{
|
||||||
|
// const index = id % 8;
|
||||||
|
//return ['#9e0142','#d53e4f','#f46d43','#fdae61','#fee08b','#ffffbf','#e6f598','#abdda4','#66c2a5','#3288bd','#5e4fa2'][index];
|
||||||
|
//}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@antv/l7",
|
"name": "@antv/l7",
|
||||||
"version": "1.1.10",
|
"version": "1.1.11",
|
||||||
"description": "Large-scale WebGL-powered Geospatial Data Visualization",
|
"description": "Large-scale WebGL-powered Geospatial Data Visualization",
|
||||||
"main": "build/l7.js",
|
"main": "build/l7.js",
|
||||||
"browser": "build/l7.js",
|
"browser": "build/l7.js",
|
||||||
|
|
|
@ -10,11 +10,11 @@ export default class Engine extends EventEmitter {
|
||||||
this._scene = Scene;
|
this._scene = Scene;
|
||||||
this._camera = new Camera(container).camera;
|
this._camera = new Camera(container).camera;
|
||||||
this._renderer = new Renderer(container).renderer;
|
this._renderer = new Renderer(container).renderer;
|
||||||
this._world = world;
|
this._world = world;// 地图场景实例
|
||||||
// for MapBox
|
// for MapBox
|
||||||
this.world = new THREE.Group();
|
this.world = new THREE.Group();
|
||||||
this._scene.add(this.world);
|
this._scene.add(this.world);
|
||||||
this._picking = Picking(this._world, this._renderer, this._camera, this._scene);
|
this._picking = Picking(this._world, this._renderer, this._camera);
|
||||||
this.clock = new THREE.Clock();
|
this.clock = new THREE.Clock();
|
||||||
this.composerLayers = [];
|
this.composerLayers = [];
|
||||||
}
|
}
|
||||||
|
@ -24,11 +24,15 @@ export default class Engine extends EventEmitter {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
update() {
|
update() {
|
||||||
|
this._renderer.clear();
|
||||||
this._renderer.render(this._scene, this._camera);
|
this._renderer.render(this._scene, this._camera);
|
||||||
this._initPostProcessing();
|
this._initPostProcessing();
|
||||||
}
|
}
|
||||||
destroy() {
|
destroy() {
|
||||||
|
}
|
||||||
|
// 渲染第三方Scene对象
|
||||||
|
renderScene(scene) {
|
||||||
|
this._renderer.render(scene, this._camera);
|
||||||
}
|
}
|
||||||
run() {
|
run() {
|
||||||
this.update();
|
this.update();
|
||||||
|
|
|
@ -3,13 +3,10 @@ import * as THREE from '../../three';
|
||||||
let nextId = 1;
|
let nextId = 1;
|
||||||
|
|
||||||
class Picking {
|
class Picking {
|
||||||
constructor(world, renderer, camera, scene) {
|
constructor(world, renderer, camera) {
|
||||||
this._world = world;
|
this._world = world;
|
||||||
this._renderer = renderer;
|
this._renderer = renderer;
|
||||||
this._camera = camera;
|
this._camera = camera;
|
||||||
this._raycaster = new THREE.Raycaster();
|
|
||||||
this.scene = scene;
|
|
||||||
this._raycaster.linePrecision = 10;
|
|
||||||
this._pickingScene = PickingScene;
|
this._pickingScene = PickingScene;
|
||||||
this.world = new THREE.Group();
|
this.world = new THREE.Group();
|
||||||
this._pickingScene.add(this.world);
|
this._pickingScene.add(this.world);
|
||||||
|
@ -49,12 +46,11 @@ class Picking {
|
||||||
this._height = size.height;
|
this._height = size.height;
|
||||||
this._pickingTexture.setSize(this._width, this._height);
|
this._pickingTexture.setSize(this._width, this._height);
|
||||||
this._pixelBuffer = new Uint8Array(4 * this._width * this._height);
|
this._pixelBuffer = new Uint8Array(4 * this._width * this._height);
|
||||||
|
|
||||||
this._needUpdate = true;
|
this._needUpdate = true;
|
||||||
}
|
}
|
||||||
_update(point) {
|
_update(point) {
|
||||||
|
|
||||||
const texture = this._pickingTexture;
|
const texture = this._pickingTexture;
|
||||||
|
// this._pickingTexture
|
||||||
this._renderer.render(this._pickingScene, this._camera, this._pickingTexture);
|
this._renderer.render(this._pickingScene, this._camera, this._pickingTexture);
|
||||||
this.pixelBuffer = new Uint8Array(4);
|
this.pixelBuffer = new Uint8Array(4);
|
||||||
this._renderer.readRenderTargetPixels(texture, point.x, this._height - point.y, 1, 1, this.pixelBuffer);
|
this._renderer.readRenderTargetPixels(texture, point.x, this._height - point.y, 1, 1, this.pixelBuffer);
|
||||||
|
@ -76,9 +72,9 @@ class Picking {
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
_updateRender() {
|
// _updateRender() {
|
||||||
this._renderer.render(this._pickingScene, this._camera, this._pickingTexture);
|
// this._renderer.render(this._pickingScene, this._camera, this._pickingTexture);
|
||||||
}
|
// }
|
||||||
|
|
||||||
_pick(point, normalisedPoint, layerId) {
|
_pick(point, normalisedPoint, layerId) {
|
||||||
this._update(point);
|
this._update(point);
|
||||||
|
@ -125,8 +121,6 @@ class Picking {
|
||||||
this._world._container.removeEventListener(event[0], event[1], false);
|
this._world._container.removeEventListener(event[0], event[1], false);
|
||||||
});
|
});
|
||||||
|
|
||||||
this._world.off('move', this._onWorldMove);
|
|
||||||
|
|
||||||
if (this._pickingScene.children) {
|
if (this._pickingScene.children) {
|
||||||
// Remove everything else in the layer
|
// Remove everything else in the layer
|
||||||
let child;
|
let child;
|
||||||
|
|
|
@ -9,7 +9,8 @@ export default class Renderer {
|
||||||
initRender() {
|
initRender() {
|
||||||
this.renderer = new THREE.WebGLRenderer({
|
this.renderer = new THREE.WebGLRenderer({
|
||||||
antialias: true,
|
antialias: true,
|
||||||
alpha: true
|
alpha: true,
|
||||||
|
autoClear: false
|
||||||
});
|
});
|
||||||
this.renderer.setClearColor(0xff0000, 0.0);
|
this.renderer.setClearColor(0xff0000, 0.0);
|
||||||
this.pixelRatio = window.devicePixelRatio;
|
this.pixelRatio = window.devicePixelRatio;
|
||||||
|
|
|
@ -11,6 +11,7 @@ import pickingFragmentShader from '../core/engine/picking/picking_frag.glsl';
|
||||||
import { getInteraction } from '../interaction/index';
|
import { getInteraction } from '../interaction/index';
|
||||||
import Attr from '../attr/index';
|
import Attr from '../attr/index';
|
||||||
import diff from '../util/diff';
|
import diff from '../util/diff';
|
||||||
|
import { updateObjecteUniform } from '../util/object3d-util';
|
||||||
import Util from '../util';
|
import Util from '../util';
|
||||||
import Global from '../global';
|
import Global from '../global';
|
||||||
let id = 1;
|
let id = 1;
|
||||||
|
@ -97,8 +98,10 @@ export default class Layer extends Base {
|
||||||
this._visibleWithZoom();
|
this._visibleWithZoom();
|
||||||
object.onBeforeRender = () => { // 每次渲染前改变状态
|
object.onBeforeRender = () => { // 每次渲染前改变状态
|
||||||
const zoom = this.scene.getZoom();
|
const zoom = this.scene.getZoom();
|
||||||
object.material.setUniformsValue('u_time', this.scene._engine.clock.getElapsedTime());
|
updateObjecteUniform(this._object3D, {
|
||||||
object.material.setUniformsValue('u_zoom', zoom);
|
u_time: this.scene._engine.clock.getElapsedTime(),
|
||||||
|
u_zoom: zoom
|
||||||
|
});
|
||||||
this.preRender();
|
this.preRender();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -309,7 +312,7 @@ export default class Layer extends Base {
|
||||||
}
|
}
|
||||||
|
|
||||||
createScale(field) {
|
createScale(field) {
|
||||||
const data = this.layerSource.data.dataArray;
|
const data = this.layerSource ? this.layerSource.data.dataArray : null;
|
||||||
const scales = this.get('scales');
|
const scales = this.get('scales');
|
||||||
let scale = scales[field];
|
let scale = scales[field];
|
||||||
const scaleController = this.get('scaleController');
|
const scaleController = this.get('scaleController');
|
||||||
|
@ -370,17 +373,20 @@ export default class Layer extends Base {
|
||||||
|
|
||||||
setActive(id, color) {
|
setActive(id, color) {
|
||||||
this._activeIds = id;
|
this._activeIds = id;
|
||||||
this.layerMesh.material.setUniformsValue('u_activeId', id);
|
|
||||||
if (!Array.isArray(color)) {
|
if (!Array.isArray(color)) {
|
||||||
color = ColorUtil.color2RGBA(color);
|
color = ColorUtil.color2RGBA(color);
|
||||||
}
|
}
|
||||||
this.layerMesh.material.setUniformsValue('u_activeColor', color);
|
updateObjecteUniform(this._object3D, {
|
||||||
|
u_activeColor: color,
|
||||||
|
u_activeId: id
|
||||||
|
});
|
||||||
|
this.scene._engine.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
_addActiveFeature(e) {
|
_addActiveFeature(e) {
|
||||||
const { featureId } = e;
|
const { featureId } = e;
|
||||||
this._activeIds = featureId;
|
this._activeIds = featureId;
|
||||||
this.layerMesh.material.setUniformsValue('u_activeId', featureId);
|
updateObjecteUniform(this._object3D, { u_activeId: featureId });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -404,7 +410,7 @@ export default class Layer extends Base {
|
||||||
const nextAttrs = this.get('attrOptions');
|
const nextAttrs = this.get('attrOptions');
|
||||||
const preStyle = this.get('preStyleOption');
|
const preStyle = this.get('preStyleOption');
|
||||||
const nextStyle = this.get('styleOptions');
|
const nextStyle = this.get('styleOptions');
|
||||||
if (preAttrs === undefined && preStyle === undefined) {
|
if (preAttrs === undefined && preStyle === undefined) { // 首次渲染
|
||||||
this._mapping();
|
this._mapping();
|
||||||
this._setPreOption();
|
this._setPreOption();
|
||||||
this._scaleByZoom();
|
this._scaleByZoom();
|
||||||
|
@ -487,15 +493,15 @@ export default class Layer extends Base {
|
||||||
for (const key in option) {
|
for (const key in option) {
|
||||||
newOption['u_' + key] = option[key];
|
newOption['u_' + key] = option[key];
|
||||||
}
|
}
|
||||||
this.layerMesh.material.updateUninform(newOption);
|
updateObjecteUniform(this._object3D, newOption);
|
||||||
|
|
||||||
}
|
}
|
||||||
_mapping() {
|
_mapping(source) {
|
||||||
const self = this;
|
const self = this;
|
||||||
const attrs = self.get('attrs');
|
const attrs = self.get('attrs');
|
||||||
const mappedData = [];
|
const mappedData = [];
|
||||||
// const data = this.layerSource.propertiesData;
|
// const data = this.layerSource.propertiesData;
|
||||||
const data = this.layerSource.data.dataArray;
|
let data;
|
||||||
|
source ? data = source.data.dataArray : data = this.layerSource.data.dataArray;
|
||||||
for (let i = 0; i < data.length; i++) {
|
for (let i = 0; i < data.length; i++) {
|
||||||
const record = data[i];
|
const record = data[i];
|
||||||
const newRecord = {};
|
const newRecord = {};
|
||||||
|
@ -528,14 +534,16 @@ export default class Layer extends Base {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
this.layerData = mappedData;
|
this.layerData = mappedData;
|
||||||
|
return mappedData;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新地图映射
|
// 更新地图映射
|
||||||
_updateMaping() {
|
_updateMaping(source, layer) {
|
||||||
const self = this;
|
const self = this;
|
||||||
const attrs = self.get('attrs');
|
const attrs = self.get('attrs');
|
||||||
|
|
||||||
const data = this.layerSource.data.dataArray;
|
const data = source ? source.data.dataArray : this.layerSource.data.dataArray;
|
||||||
|
const layerData = layer || this.layerData;
|
||||||
for (let i = 0; i < data.length; i++) {
|
for (let i = 0; i < data.length; i++) {
|
||||||
const record = data[i];
|
const record = data[i];
|
||||||
for (const attrName in attrs) {
|
for (const attrName in attrs) {
|
||||||
|
@ -547,10 +555,10 @@ export default class Layer extends Base {
|
||||||
for (let j = 0; j < values.length; j++) {
|
for (let j = 0; j < values.length; j++) {
|
||||||
const val = values[j];
|
const val = values[j];
|
||||||
const name = names[j];
|
const name = names[j];
|
||||||
this.layerData[i][name] = (Util.isArray(val) && val.length === 1) ? val[0] : val; // 只有一个值时返回第一个属性值
|
layerData[i][name] = (Util.isArray(val) && val.length === 1) ? val[0] : val; // 只有一个值时返回第一个属性值
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.layerData[i][names[0]] = values.length === 1 ? values[0] : values;
|
layerData[i][names[0]] = values.length === 1 ? values[0] : values;
|
||||||
|
|
||||||
}
|
}
|
||||||
attr.neadUpdate = true;
|
attr.neadUpdate = true;
|
||||||
|
@ -603,10 +611,9 @@ export default class Layer extends Base {
|
||||||
pickmaterial.fragmentShader = pickingFragmentShader;
|
pickmaterial.fragmentShader = pickingFragmentShader;
|
||||||
const pickingMesh = new THREE[mesh.type](mesh.geometry, pickmaterial);
|
const pickingMesh = new THREE[mesh.type](mesh.geometry, pickmaterial);
|
||||||
pickingMesh.name = this.layerId;
|
pickingMesh.name = this.layerId;
|
||||||
pickmaterial.setDefinesvalue(this.type, true);
|
|
||||||
pickingMesh.onBeforeRender = () => {
|
pickingMesh.onBeforeRender = () => {
|
||||||
const zoom = this.scene.getZoom();
|
const zoom = this.scene.getZoom();
|
||||||
pickingMesh.material.setUniformsValue('u_zoom', zoom);
|
updateObjecteUniform(pickingMesh, { u_zoom: zoom });
|
||||||
};
|
};
|
||||||
this._pickingMesh.add(pickingMesh);
|
this._pickingMesh.add(pickingMesh);
|
||||||
|
|
||||||
|
@ -618,9 +625,10 @@ export default class Layer extends Base {
|
||||||
type = 'mouseleave';
|
type = 'mouseleave';
|
||||||
}
|
}
|
||||||
this._activeIds = featureId;
|
this._activeIds = featureId;
|
||||||
const feature = this.layerSource.getSelectFeature(featureId);
|
// TODO 瓦片图层获取选中数据信息
|
||||||
const lnglat = this.scene.containerToLngLat(point2d);
|
const lnglat = this.scene.containerToLngLat(point2d);
|
||||||
const style = this.layerData[featureId - 1];
|
const { feature, style } = this.getSelectFeature(featureId, lnglat);
|
||||||
|
// const style = this.layerData[featureId - 1];
|
||||||
const target = {
|
const target = {
|
||||||
featureId,
|
featureId,
|
||||||
feature,
|
feature,
|
||||||
|
@ -629,12 +637,20 @@ export default class Layer extends Base {
|
||||||
type,
|
type,
|
||||||
lnglat: { lng: lnglat.lng, lat: lnglat.lat }
|
lnglat: { lng: lnglat.lng, lat: lnglat.lat }
|
||||||
};
|
};
|
||||||
if (featureId >= 0 || this._activeIds !== null) { // 拾取到元素,或者离开元素
|
if (featureId >= 0 || this._activeIds >= 0) { // 拾取到元素,或者离开元素
|
||||||
this.emit(type, target);
|
this.emit(type, target);
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
getSelectFeature(featureId) {
|
||||||
|
const feature = this.layerSource.getSelectFeature(featureId);
|
||||||
|
const style = this.layerData[featureId - 1];
|
||||||
|
return {
|
||||||
|
feature,
|
||||||
|
style
|
||||||
|
};
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* 用于过滤数据
|
* 用于过滤数据
|
||||||
* @param {*} object 更新颜色和数据过滤
|
* @param {*} object 更新颜色和数据过滤
|
||||||
|
@ -668,6 +684,7 @@ export default class Layer extends Base {
|
||||||
pickAttr.needsUpdate = true;
|
pickAttr.needsUpdate = true;
|
||||||
}
|
}
|
||||||
_visibleWithZoom() {
|
_visibleWithZoom() {
|
||||||
|
if (this._object3D === null) return;
|
||||||
const zoom = this.scene.getZoom();
|
const zoom = this.scene.getZoom();
|
||||||
const minZoom = this.get('minZoom');
|
const minZoom = this.get('minZoom');
|
||||||
const maxZoom = this.get('maxZoom');
|
const maxZoom = this.get('maxZoom');
|
||||||
|
@ -734,13 +751,16 @@ export default class Layer extends Base {
|
||||||
}
|
}
|
||||||
interactions[type] = interaction;
|
interactions[type] = interaction;
|
||||||
}
|
}
|
||||||
|
styleCfg() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 重置高亮要素
|
* 重置高亮要素
|
||||||
*/
|
*/
|
||||||
_resetStyle() {
|
_resetStyle() {
|
||||||
this._activeIds = null;
|
this._activeIds = null;
|
||||||
this.layerMesh.material.setUniformsValue('u_activeId', 0);
|
updateObjecteUniform(this._object3D, { u_activeId: 0 });
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 销毁Layer对象
|
* 销毁Layer对象
|
||||||
|
@ -751,7 +771,6 @@ export default class Layer extends Base {
|
||||||
this.clearMapEvent();
|
this.clearMapEvent();
|
||||||
if (this._object3D.type === 'composer') {
|
if (this._object3D.type === 'composer') {
|
||||||
this.remove(this._object3D);
|
this.remove(this._object3D);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this._object3D && this._object3D.children) {
|
if (this._object3D && this._object3D.children) {
|
||||||
|
@ -778,8 +797,19 @@ export default class Layer extends Base {
|
||||||
child = null;
|
child = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
this.layerMesh.geometry = null;
|
||||||
|
this.layerMesh.material.dispose();
|
||||||
|
this.layerMesh.material = null;
|
||||||
|
if (this._pickingMesh) {
|
||||||
|
this._pickingMesh.children[0].geometry = null;
|
||||||
|
this._pickingMesh.children[0].material.dispose();
|
||||||
|
this._pickingMesh.children[0].material = null;
|
||||||
|
}
|
||||||
|
this._buffer = null;
|
||||||
this._object3D = null;
|
this._object3D = null;
|
||||||
this.scene._engine._scene.remove(this._object3D);
|
this.scene._engine._scene.remove(this._object3D);
|
||||||
|
this.layerData.length = 0;
|
||||||
|
this.layerSource = null;
|
||||||
this.scene._engine._picking.remove(this._pickingMesh);
|
this.scene._engine._picking.remove(this._pickingMesh);
|
||||||
this.destroyed = true;
|
this.destroyed = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@ export default class Scene extends Base {
|
||||||
_initEngine(mapContainer) {
|
_initEngine(mapContainer) {
|
||||||
this._engine = new Engine(mapContainer, this);
|
this._engine = new Engine(mapContainer, this);
|
||||||
this.registerMapEvent();
|
this.registerMapEvent();
|
||||||
|
// this._engine.run();
|
||||||
// this.workerPool = new WorkerPool();
|
// this.workerPool = new WorkerPool();
|
||||||
compileBuiltinModules();
|
compileBuiltinModules();
|
||||||
}
|
}
|
||||||
|
@ -73,7 +74,6 @@ export default class Scene extends Base {
|
||||||
}
|
}
|
||||||
off(type, hander) {
|
off(type, hander) {
|
||||||
if (this.map) { this.map.off(type, hander); }
|
if (this.map) { this.map.off(type, hander); }
|
||||||
|
|
||||||
super.off(type, hander);
|
super.off(type, hander);
|
||||||
}
|
}
|
||||||
addImage() {
|
addImage() {
|
||||||
|
|
|
@ -56,7 +56,9 @@ export default class Source extends Base {
|
||||||
const { type = 'geojson' } = parser;
|
const { type = 'geojson' } = parser;
|
||||||
const data = this.get('data');
|
const data = this.get('data');
|
||||||
this.originData = getParser(type)(data, parser);
|
this.originData = getParser(type)(data, parser);
|
||||||
this.data = clone(this.originData);
|
this.data = {
|
||||||
|
dataArray: clone(this.originData.dataArray)
|
||||||
|
};
|
||||||
this.data.extent = extent(this.data.dataArray);
|
this.data.extent = extent(this.data.dataArray);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
@ -150,4 +152,8 @@ export default class Source extends Base {
|
||||||
}
|
}
|
||||||
return featureIndex;
|
return featureIndex;
|
||||||
}
|
}
|
||||||
|
destroy() {
|
||||||
|
this.data = null;
|
||||||
|
this.originData = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,5 @@ export default function NormalBuffer(layerData) {
|
||||||
attributes.sizes.push(size);
|
attributes.sizes.push(size);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
return attributes;
|
return attributes;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ export default class PointLineMaterial extends Material {
|
||||||
u_stroke: { value: [ 1.0, 1.0, 1.0, 1.0 ] },
|
u_stroke: { value: [ 1.0, 1.0, 1.0, 1.0 ] },
|
||||||
u_strokeWidth: { value: 1.0 },
|
u_strokeWidth: { value: 1.0 },
|
||||||
u_zoom: { value: 10 },
|
u_zoom: { value: 10 },
|
||||||
u_activeId: { value: -1 },
|
u_activeId: { value: 0 },
|
||||||
u_activeColor: { value: [ 1.0, 0, 0, 1.0 ] }
|
u_activeColor: { value: [ 1.0, 0, 0, 1.0 ] }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
import Material from './../material';
|
||||||
|
import { getModule } from '../../../util/shaderModule';
|
||||||
|
export default class MaskMaterial extends Material {
|
||||||
|
getDefaultParameters() {
|
||||||
|
return {
|
||||||
|
uniforms: {
|
||||||
|
},
|
||||||
|
defines: {
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
constructor(_uniforms, _defines, parameters) {
|
||||||
|
super(parameters);
|
||||||
|
const { uniforms, defines } = this.getDefaultParameters();
|
||||||
|
const { vs, fs } = getModule('mask_quard');
|
||||||
|
this.uniforms = Object.assign(uniforms, this.setUniform(_uniforms));
|
||||||
|
this.type = 'MaskMaterial';
|
||||||
|
this.defines = Object.assign(defines, _defines);
|
||||||
|
this.vertexShader = vs;
|
||||||
|
this.fragmentShader = fs;
|
||||||
|
this.transparent = true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -41,6 +41,11 @@ import raster_frag from '../shader/raster_frag.glsl';
|
||||||
import tile_polygon_vert from '../shader/tile/polygon_vert.glsl';
|
import tile_polygon_vert from '../shader/tile/polygon_vert.glsl';
|
||||||
import tile_polygon_frag from '../shader/tile/polygon_frag.glsl';
|
import tile_polygon_frag from '../shader/tile/polygon_frag.glsl';
|
||||||
|
|
||||||
|
// mask
|
||||||
|
import mask_quard_vert from '../shader/tile/mask_quard_vert.glsl';
|
||||||
|
import mask_quard_frag from '../shader/tile/mask_quard_frag.glsl';
|
||||||
|
|
||||||
|
|
||||||
import common from './common.glsl';
|
import common from './common.glsl';
|
||||||
import { registerModule } from '../../util/shaderModule';
|
import { registerModule } from '../../util/shaderModule';
|
||||||
import pick_color from './shaderChunks/pick_color.glsl';
|
import pick_color from './shaderChunks/pick_color.glsl';
|
||||||
|
@ -60,5 +65,6 @@ export function compileBuiltinModules() {
|
||||||
registerModule('image', { vs: image_vert, fs: image_frag });
|
registerModule('image', { vs: image_vert, fs: image_frag });
|
||||||
registerModule('raster', { vs: raster_vert, fs: raster_frag });
|
registerModule('raster', { vs: raster_vert, fs: raster_frag });
|
||||||
registerModule('tilepolygon', { vs: tile_polygon_vert, fs: tile_polygon_frag });
|
registerModule('tilepolygon', { vs: tile_polygon_vert, fs: tile_polygon_frag });
|
||||||
|
registerModule('mask_quard', { vs: mask_quard_vert, fs: mask_quard_frag });
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ attribute float a_dash_array;
|
||||||
|
|
||||||
uniform float u_zoom;
|
uniform float u_zoom;
|
||||||
uniform float u_time : 0;
|
uniform float u_time : 0;
|
||||||
uniform float u_activeId : 1;
|
uniform float u_activeId : 0;
|
||||||
uniform vec4 u_activeColor : [ 1.0, 0, 0, 1.0 ];
|
uniform vec4 u_activeColor : [ 1.0, 0, 0, 1.0 ];
|
||||||
|
|
||||||
varying float v_time;
|
varying float v_time;
|
||||||
|
|
|
@ -20,11 +20,11 @@ const vec3 halo = vec3( 1.0 );
|
||||||
void main() {
|
void main() {
|
||||||
// 纹理坐标
|
// 纹理坐标
|
||||||
#ifdef TEXCOORD_0
|
#ifdef TEXCOORD_0
|
||||||
vec2 pos = v_uv + gl_PointCoord / 512.0 * 64.0;
|
vec2 pos = v_uv + gl_PointCoord / 512.0 * 64.0;
|
||||||
pos.y = 1.0 - pos.y;
|
pos.y = 1.0 - pos.y;
|
||||||
vec4 textureColor = texture2D(u_texture, pos);
|
vec4 textureColor = texture2D(u_texture, pos);
|
||||||
gl_FragColor =textureColor;
|
gl_FragColor =textureColor;
|
||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
if(v_color.a == 0.)
|
if(v_color.a == 0.)
|
||||||
discard;
|
discard;
|
||||||
|
|
|
@ -21,10 +21,12 @@ void main() {
|
||||||
#endif
|
#endif
|
||||||
v_color = u_stroke;
|
v_color = u_stroke;
|
||||||
v_color.a *= u_strokeOpacity;
|
v_color.a *= u_strokeOpacity;
|
||||||
|
|
||||||
|
v_pickingId = pickingId;
|
||||||
if(v_pickingId == u_activeId) {
|
if(v_pickingId == u_activeId) {
|
||||||
v_color = u_activeColor;
|
v_color = u_activeColor;
|
||||||
}
|
}
|
||||||
v_pickingId = pickingId;
|
|
||||||
//vec3 pointPos = newposition.xyz + vec3(normal * u_strokeWidth * pow(2.0,20.0-u_zoom) / 2.0 * a_miter);
|
//vec3 pointPos = newposition.xyz + vec3(normal * u_strokeWidth * pow(2.0,20.0-u_zoom) / 2.0 * a_miter);
|
||||||
vec3 pointPos = newposition.xyz + vec3(normal * u_strokeWidth * scale / 2.0 * a_miter);
|
vec3 pointPos = newposition.xyz + vec3(normal * u_strokeWidth * scale / 2.0 * a_miter);
|
||||||
gl_Position = matModelViewProjection * vec4(pointPos, 1.0);
|
gl_Position = matModelViewProjection * vec4(pointPos, 1.0);
|
||||||
|
|
|
@ -16,7 +16,7 @@ void main() {
|
||||||
mat4 matModelViewProjection = projectionMatrix * modelViewMatrix;
|
mat4 matModelViewProjection = projectionMatrix * modelViewMatrix;
|
||||||
v_color = a_color;
|
v_color = a_color;
|
||||||
v_color.a *= u_opacity;
|
v_color.a *= u_opacity;
|
||||||
if(pickingId == u_activeId) {
|
if(pickingId == u_activeId) {
|
||||||
v_color = u_activeColor;
|
v_color = u_activeColor;
|
||||||
}
|
}
|
||||||
gl_Position = matModelViewProjection * vec4(position, 1.0);
|
gl_Position = matModelViewProjection * vec4(position, 1.0);
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
precision highp float;
|
||||||
|
void main() {
|
||||||
|
gl_FragColor = vec4(1.0);
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
precision highp float;
|
||||||
|
void main(){
|
||||||
|
mat4 matModelViewProjection=projectionMatrix*modelViewMatrix;
|
||||||
|
gl_Position = matModelViewProjection * vec4(position, 1.0);
|
||||||
|
|
||||||
|
}
|
|
@ -65,8 +65,11 @@ export function defaultLine(geo, index) {
|
||||||
return { positions, indexes: indexArray };
|
return { positions, indexes: indexArray };
|
||||||
}
|
}
|
||||||
// mesh line
|
// mesh line
|
||||||
|
|
||||||
export function Line(path, props, positionsIndex, lengthPerDashSegment = 200) {
|
export function Line(path, props, positionsIndex, lengthPerDashSegment = 200) {
|
||||||
if (path.length === 1) path = path[0];// 面坐标转线坐标
|
if (Array.isArray(path[0][0])) {
|
||||||
|
path = path[0]; // 面坐标转线坐标
|
||||||
|
}
|
||||||
const positions = [];
|
const positions = [];
|
||||||
const pickingIds = [];
|
const pickingIds = [];
|
||||||
const normal = [];
|
const normal = [];
|
||||||
|
@ -78,12 +81,13 @@ export function Line(path, props, positionsIndex, lengthPerDashSegment = 200) {
|
||||||
|
|
||||||
let attrDistance = [];
|
let attrDistance = [];
|
||||||
const sizes = [];
|
const sizes = [];
|
||||||
const { size, color, id } = props;
|
let { size, color, id } = props;
|
||||||
|
!Array.isArray(size) && (size = [ size ]);
|
||||||
attrPos.forEach((point, pointIndex) => {
|
attrPos.forEach((point, pointIndex) => {
|
||||||
colors.push(...color);
|
colors.push(...color);
|
||||||
pickingIds.push(id);
|
pickingIds.push(id);
|
||||||
sizes.push(size[0]);
|
sizes.push(size[0]);
|
||||||
point[2] = size[1];
|
point[2] = size[1] || 0;
|
||||||
positions.push(...point);
|
positions.push(...point);
|
||||||
|
|
||||||
if (pointIndex === 0 || pointIndex === 1) {
|
if (pointIndex === 0 || pointIndex === 1) {
|
||||||
|
@ -109,7 +113,6 @@ export function Line(path, props, positionsIndex, lengthPerDashSegment = 200) {
|
||||||
attrDistance = attrDistance.map(d => {
|
attrDistance = attrDistance.map(d => {
|
||||||
return d / totalLength;
|
return d / totalLength;
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
positions,
|
positions,
|
||||||
normal,
|
normal,
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
// const Global = {};
|
// const Global = {};
|
||||||
const FONT_FAMILY = '"-apple-system", BlinkMacSystemFont, "Segoe UI", Roboto,"Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei",SimSun, "sans-serif"';
|
const FONT_FAMILY = '"-apple-system", BlinkMacSystemFont, "Segoe UI", Roboto,"Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei",SimSun, "sans-serif"';
|
||||||
const Global = {
|
const Global = {
|
||||||
version: '1.0.0',
|
version: '1.11.1',
|
||||||
scene: {
|
scene: {
|
||||||
mapType: 'AMAP',
|
mapType: 'AMAP',
|
||||||
zoom: 5,
|
zoom: 5,
|
||||||
|
|
|
@ -13,7 +13,7 @@ export default class Hash extends Interaction {
|
||||||
this._updateHash();
|
this._updateHash();
|
||||||
}
|
}
|
||||||
reset() {
|
reset() {
|
||||||
this.layer._resetStyle();
|
// this.layer._resetStyle();
|
||||||
}
|
}
|
||||||
_getHashString() {
|
_getHashString() {
|
||||||
const center = this.layer.getCenter(),
|
const center = this.layer.getCenter(),
|
||||||
|
|
|
@ -1,9 +1,5 @@
|
||||||
import Layer from '../core/layer';
|
import Layer from '../core/layer';
|
||||||
import gridBuffer from '../geom/buffer/heatmap/grid';
|
import { getRender } from './render/';
|
||||||
import DrawGrid from './render/heatmap/gird';
|
|
||||||
import DrawHexagon from './render/heatmap/hexagon';
|
|
||||||
import { drawHeatmap } from './render/heatmap/heatmap';
|
|
||||||
import hexagonBuffer from '../geom/buffer/heatmap/hexagon';
|
|
||||||
|
|
||||||
export default class HeatMapLayer extends Layer {
|
export default class HeatMapLayer extends Layer {
|
||||||
shape(type) {
|
shape(type) {
|
||||||
|
@ -12,43 +8,6 @@ export default class HeatMapLayer extends Layer {
|
||||||
}
|
}
|
||||||
draw() {
|
draw() {
|
||||||
this.type = 'heatmap';
|
this.type = 'heatmap';
|
||||||
switch (this.shapeType) {
|
this.add(getRender('heatmap', this.shapeType || 'heatmap')(this.layerData, this, this.layerSource));
|
||||||
case 'grid' :
|
|
||||||
this._drawGrid();
|
|
||||||
break;
|
|
||||||
case 'hexagon' :
|
|
||||||
this._drawHexagon();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
drawHeatmap(this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_drawHexagon() {
|
|
||||||
const style = this.get('styleOptions');
|
|
||||||
const activeOption = this.get('activedOptions');
|
|
||||||
const { radius } = this.layerSource.data;
|
|
||||||
this._buffer = new hexagonBuffer(this.layerData);
|
|
||||||
const config = {
|
|
||||||
...style,
|
|
||||||
radius,
|
|
||||||
activeColor: activeOption.fill
|
|
||||||
};
|
|
||||||
const Mesh = new DrawHexagon(this._buffer, config);
|
|
||||||
this.add(Mesh);
|
|
||||||
}
|
|
||||||
_drawGrid() {
|
|
||||||
const style = this.get('styleOptions');
|
|
||||||
const activeOption = this.get('activedOptions');
|
|
||||||
const { xOffset, yOffset } = this.layerSource.data;
|
|
||||||
this._buffer = new gridBuffer(this.layerData);
|
|
||||||
const config = {
|
|
||||||
...style,
|
|
||||||
xOffset,
|
|
||||||
yOffset,
|
|
||||||
activeColor: activeOption.fill
|
|
||||||
};
|
|
||||||
const girdMesh = new DrawGrid(this._buffer, config);
|
|
||||||
this.add(girdMesh);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import RasterLayer from './rasterLayer';
|
||||||
import HeatmapLayer from './heatmapLayer';
|
import HeatmapLayer from './heatmapLayer';
|
||||||
import TileLayer from './tile/tileLayer';
|
import TileLayer from './tile/tileLayer';
|
||||||
import ImageTileLayer from './tile/imageTileLayer';
|
import ImageTileLayer from './tile/imageTileLayer';
|
||||||
|
import VectorTileLayer from './tile/VectorTileLayer';
|
||||||
|
|
||||||
registerLayer('PolygonLayer', PolygonLayer);
|
registerLayer('PolygonLayer', PolygonLayer);
|
||||||
registerLayer('PointLayer', PointLayer);
|
registerLayer('PointLayer', PointLayer);
|
||||||
|
@ -16,7 +17,8 @@ registerLayer('RasterLayer', RasterLayer);
|
||||||
registerLayer('HeatmapLayer', HeatmapLayer);
|
registerLayer('HeatmapLayer', HeatmapLayer);
|
||||||
registerLayer('TileLayer', TileLayer);
|
registerLayer('TileLayer', TileLayer);
|
||||||
registerLayer('ImageTileLayer', ImageTileLayer);
|
registerLayer('ImageTileLayer', ImageTileLayer);
|
||||||
|
registerLayer('VectorTileLayer', VectorTileLayer);
|
||||||
|
|
||||||
export { LAYER_MAP } from './factory';
|
export { LAYER_MAP, getLayer } from './factory';
|
||||||
export { registerLayer };
|
export { registerLayer };
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
import Layer from '../core/layer';
|
import Layer from '../core/layer';
|
||||||
import DrawLine from './render/line/drawMeshLine';
|
import { getRender } from './render/';
|
||||||
import DrawArc from './render/line/drawArc';
|
|
||||||
import { LineBuffer } from '../geom/buffer/index';
|
|
||||||
export default class LineLayer extends Layer {
|
export default class LineLayer extends Layer {
|
||||||
shape(type) {
|
shape(type) {
|
||||||
this.shapeType = type;
|
this.shapeType = type;
|
||||||
|
@ -19,27 +17,7 @@ export default class LineLayer extends Layer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
draw() {
|
draw() {
|
||||||
this.type = 'polyline';
|
this.type = 'line';
|
||||||
const layerData = this.layerData;
|
this.add(getRender('line', this.shapeType || 'line')(this.layerData, this, this.layerSource));
|
||||||
const style = this.get('styleOptions');
|
|
||||||
const animateOptions = this.get('animateOptions');
|
|
||||||
const activeOption = this.get('activedOptions');
|
|
||||||
const layerCfg = {
|
|
||||||
zoom: this.scene.getZoom(),
|
|
||||||
style,
|
|
||||||
animateOptions,
|
|
||||||
activeOption
|
|
||||||
};
|
|
||||||
const buffer = (this._buffer = new LineBuffer({
|
|
||||||
layerData,
|
|
||||||
shapeType: this.shapeType,
|
|
||||||
style
|
|
||||||
}));
|
|
||||||
const { attributes } = buffer;
|
|
||||||
if (this.shapeType === 'arc') {
|
|
||||||
DrawArc(attributes, layerCfg, this);
|
|
||||||
} else {
|
|
||||||
DrawLine(attributes, layerCfg, this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,6 @@
|
||||||
import Layer from '../core/layer';
|
import Layer from '../core/layer';
|
||||||
import * as drawPoint from '../layer/render/point';
|
|
||||||
import TextBuffer from '../geom/buffer/point/text';
|
|
||||||
import DrawText from './render/point/drawText';
|
|
||||||
import Global from '../global';
|
import Global from '../global';
|
||||||
// import PointBuffer from '../geom/buffer/point';
|
import { getRender } from './render/';
|
||||||
import * as PointBuffer from '../geom/buffer/point/index';
|
|
||||||
const { pointShape } = Global;
|
const { pointShape } = Global;
|
||||||
/**
|
/**
|
||||||
* point shape 2d circle, traingle text,image
|
* point shape 2d circle, traingle text,image
|
||||||
|
@ -16,67 +12,9 @@ const { pointShape } = Global;
|
||||||
export default class PointLayer extends Layer {
|
export default class PointLayer extends Layer {
|
||||||
draw() {
|
draw() {
|
||||||
this.type = 'point';
|
this.type = 'point';
|
||||||
const { stroke, fill } = this.get('styleOptions');
|
this.shapeType = this._getShape();
|
||||||
const style = this.get('styleOptions');
|
const mesh = getRender(this.type, this.shapeType)(this.layerData, this, this.layerSource);
|
||||||
const activeOption = this.get('activedOptions');
|
this.add(mesh);
|
||||||
const config = {
|
|
||||||
...style,
|
|
||||||
activeColor: activeOption.fill
|
|
||||||
};
|
|
||||||
const pointShapeType = this._getShape();
|
|
||||||
this.shapeType = pointShapeType;
|
|
||||||
switch (pointShapeType) {
|
|
||||||
case 'fill': { // 填充图形
|
|
||||||
if (fill !== 'none') {
|
|
||||||
// 是否填充
|
|
||||||
const attributes = PointBuffer.FillBuffer(this.layerData, style);
|
|
||||||
const meshfill = drawPoint.DrawFill(attributes, config);
|
|
||||||
this.add(meshfill);
|
|
||||||
}
|
|
||||||
if (stroke !== 'none') {
|
|
||||||
// 是否绘制边界
|
|
||||||
const lineAttribute = PointBuffer.StrokeBuffer(this.layerData, style);
|
|
||||||
const meshStroke = drawPoint.DrawStroke(lineAttribute, config);
|
|
||||||
this.add(meshStroke, 'line');
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'image': { // 绘制图片标注
|
|
||||||
const imageAttribute = PointBuffer.ImageBuffer(this.layerData, {
|
|
||||||
imagePos: this.scene.image.imagePos
|
|
||||||
});
|
|
||||||
const imageMesh = drawPoint.DrawImage(imageAttribute, {
|
|
||||||
...style,
|
|
||||||
texture: this.scene.image.texture
|
|
||||||
});
|
|
||||||
this.add(imageMesh);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'normal': { // 原生点
|
|
||||||
const normalAttribute = PointBuffer.NormalBuffer(this.layerData, style);
|
|
||||||
const normalPointMesh = drawPoint.DrawNormal(normalAttribute, config);
|
|
||||||
this.add(normalPointMesh);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'text': { // 原生点
|
|
||||||
const { width, height } = this.scene.getSize();
|
|
||||||
const textCfg = {
|
|
||||||
...style,
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
activeColor: activeOption.fill
|
|
||||||
};
|
|
||||||
const buffer = new TextBuffer(
|
|
||||||
this.layerData,
|
|
||||||
this.scene.fontAtlasManager
|
|
||||||
);
|
|
||||||
const mesh = new DrawText(buffer, textCfg);
|
|
||||||
this.add(mesh);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_getShape() {
|
_getShape() {
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import Layer from '../core/layer';
|
import Layer from '../core/layer';
|
||||||
import * as drawPolygon from './render/polygon';
|
import { getRender } from './render/';
|
||||||
import PolygonBuffer from '../geom/buffer/polygon';
|
|
||||||
export default class PolygonLayer extends Layer {
|
export default class PolygonLayer extends Layer {
|
||||||
shape(type) {
|
shape(type) {
|
||||||
this.shape = type;
|
this.shape = type;
|
||||||
|
@ -9,33 +8,13 @@ export default class PolygonLayer extends Layer {
|
||||||
draw() {
|
draw() {
|
||||||
this.init();
|
this.init();
|
||||||
this.type = 'polygon';
|
this.type = 'polygon';
|
||||||
this._buffer = new PolygonBuffer({
|
const animateOptions = this.get('animateOptions');
|
||||||
shape: this.shape,
|
if (animateOptions.enable) {
|
||||||
layerData: this.layerData
|
this.shape = 'animate';
|
||||||
});
|
}
|
||||||
this.add(this._getLayerRender());
|
this.add(getRender(this.type, this.shape)(this.layerData, this));
|
||||||
}
|
}
|
||||||
update() {
|
update() {
|
||||||
this.updateFilter(this.layerMesh);
|
this.updateFilter(this.layerMesh);
|
||||||
}
|
}
|
||||||
_getLayerRender() {
|
|
||||||
const animateOptions = this.get('animateOptions');
|
|
||||||
const { attributes } = this._buffer;
|
|
||||||
const style = this.get('styleOptions');
|
|
||||||
const activeOption = this.get('activedOptions');
|
|
||||||
const config = {
|
|
||||||
...style,
|
|
||||||
activeColor: activeOption.fill
|
|
||||||
};
|
|
||||||
if (this.shape === 'line') {
|
|
||||||
return drawPolygon.DrawLine(attributes, style);
|
|
||||||
} else if (animateOptions.enable) {
|
|
||||||
const { near, far } = this.map.getCameraState();
|
|
||||||
this.scene.startAnimate();
|
|
||||||
return drawPolygon.DrawAnimate(attributes, { ...style, near, far });
|
|
||||||
}
|
|
||||||
return drawPolygon.DrawFill(attributes, config);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
export const Render_MAP = {};
|
||||||
|
export const getRender = (layerType, shapeType) => {
|
||||||
|
return Render_MAP[layerType.toLowerCase()] && Render_MAP[layerType.toLowerCase()][shapeType.toLowerCase()];
|
||||||
|
};
|
||||||
|
export const registerRender = (layerType, shapeType, render) => {
|
||||||
|
if (getRender(layerType, shapeType)) {
|
||||||
|
throw new Error(`Render shapeType '${shapeType}' existed.`);
|
||||||
|
}
|
||||||
|
// 存储到 map 中
|
||||||
|
if (!Render_MAP[layerType.toLowerCase()]) Render_MAP[layerType.toLowerCase()] = {};
|
||||||
|
Render_MAP[layerType.toLowerCase()][shapeType.toLowerCase()] = render;
|
||||||
|
};
|
|
@ -1,7 +1,11 @@
|
||||||
import * as THREE from '../../../core/three';
|
import * as THREE from '../../../core/three';
|
||||||
|
import gridBuffer from '../../../geom/buffer/heatmap/grid';
|
||||||
import GridMaterial from '../../../geom/material/grid';
|
import GridMaterial from '../../../geom/material/grid';
|
||||||
export default function DrawGrid(attributes, style) {
|
export default function DrawGrid(layerdata, layer, source) {
|
||||||
const { opacity, xOffset, yOffset, coverage, activeColor } = style;
|
const { opacity, coverage } = layer.get('styleOptions');
|
||||||
|
const activeOption = layer.get('activedOptions');
|
||||||
|
const { xOffset, yOffset } = source.data;
|
||||||
|
const attributes = new gridBuffer(layerdata);
|
||||||
const geometry = new THREE.BufferGeometry();
|
const geometry = new THREE.BufferGeometry();
|
||||||
geometry.addAttribute('position', new THREE.Float32BufferAttribute(attributes.vertices, 3));
|
geometry.addAttribute('position', new THREE.Float32BufferAttribute(attributes.vertices, 3));
|
||||||
geometry.addAttribute('miter', new THREE.Float32BufferAttribute(attributes.miter, 2));
|
geometry.addAttribute('miter', new THREE.Float32BufferAttribute(attributes.miter, 2));
|
||||||
|
@ -12,7 +16,7 @@ export default function DrawGrid(attributes, style) {
|
||||||
u_xOffset: xOffset,
|
u_xOffset: xOffset,
|
||||||
u_yOffset: yOffset,
|
u_yOffset: yOffset,
|
||||||
u_coverage: coverage,
|
u_coverage: coverage,
|
||||||
u_activeColor: activeColor
|
u_activeColor: activeOption.fill
|
||||||
}, {
|
}, {
|
||||||
SHAPE: false
|
SHAPE: false
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,24 +1,23 @@
|
||||||
import HeatmapBuffer from '../../../geom/buffer/heatmap/heatmap';
|
import HeatmapBuffer from '../../../geom/buffer/heatmap/heatmap';
|
||||||
import { createColorRamp } from '../../../geom/buffer/heatmap/heatmap';
|
import { createColorRamp } from '../../../geom/buffer/heatmap/heatmap';
|
||||||
import { HeatmapIntensityMaterial, HeatmapColorizeMaterial } from '../../../geom/material/heatmapMateial';
|
import { HeatmapIntensityMaterial, HeatmapColorizeMaterial } from '../../../geom/material/heatmapMaterial';
|
||||||
// import Renderpass from '../../../core/engine/renderpass.bak';
|
// import Renderpass from '../../../core/engine/renderpass.bak';
|
||||||
import RenderPass from '../../../core/engine/render-pass';
|
import RenderPass from '../../../core/engine/render-pass';
|
||||||
import ShaderPass from '../../../core/engine/shader-pass';
|
import ShaderPass from '../../../core/engine/shader-pass';
|
||||||
import EffectComposer from '../../../core/engine/effect-composer';
|
import EffectComposer from '../../../core/engine/effect-composer';
|
||||||
import * as THREE from '../../../core/three';
|
import * as THREE from '../../../core/three';
|
||||||
|
|
||||||
export function drawHeatmap(layer) {
|
export default function DrawHeatmap(layerdata, layer) {
|
||||||
|
|
||||||
const colors = layer.get('styleOptions').rampColors;
|
const colors = layer.get('styleOptions').rampColors;
|
||||||
|
|
||||||
layer.rampColors = createColorRamp(colors);
|
layer.rampColors = createColorRamp(colors);
|
||||||
const heatmap = new heatmapPass(layer);
|
const heatmap = new heatmapPass(layerdata, layer);
|
||||||
const copy = new copyPass(layer);
|
const copy = new copyPass(layer);
|
||||||
copy.renderToScreen = true;
|
copy.renderToScreen = true;
|
||||||
const composer = new EffectComposer(layer.scene._engine._renderer, layer.scene._container);
|
const composer = new EffectComposer(layer.scene._engine._renderer, layer.scene._container);
|
||||||
composer.addPass(heatmap);
|
composer.addPass(heatmap);
|
||||||
composer.addPass(copy);
|
composer.addPass(copy);
|
||||||
layer.add(composer);
|
|
||||||
layer.scene._engine.update();
|
layer.scene._engine.update();
|
||||||
layer._updateStyle = style => {
|
layer._updateStyle = style => {
|
||||||
if (style.rampColors) {
|
if (style.rampColors) {
|
||||||
|
@ -31,13 +30,14 @@ export function drawHeatmap(layer) {
|
||||||
heatmap.scene.children[0].material.updateUninform(newOption);
|
heatmap.scene.children[0].material.updateUninform(newOption);
|
||||||
copy.scene.children[0].material.updateUninform(newOption);
|
copy.scene.children[0].material.updateUninform(newOption);
|
||||||
};
|
};
|
||||||
|
return composer;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function heatmapPass(layer) {
|
function heatmapPass(layerdata, layer) {
|
||||||
const scene = new THREE.Scene();
|
const scene = new THREE.Scene();
|
||||||
const style = layer.get('styleOptions');
|
const style = layer.get('styleOptions');
|
||||||
const data = layer.layerData;
|
const data = layerdata;
|
||||||
const camera = layer.scene._engine._camera;
|
const camera = layer.scene._engine._camera;
|
||||||
// get attributes data
|
// get attributes data
|
||||||
const buffer = new HeatmapBuffer({
|
const buffer = new HeatmapBuffer({
|
||||||
|
|
|
@ -1,7 +1,12 @@
|
||||||
import * as THREE from '../../../core/three';
|
import * as THREE from '../../../core/three';
|
||||||
|
import hexagonBuffer from '../../../geom/buffer/heatmap/hexagon';
|
||||||
import GridMaterial from '../../../geom/material/hexagon';
|
import GridMaterial from '../../../geom/material/hexagon';
|
||||||
export default function DrawHexagon(attributes, style) {
|
export default function DrawHexagon(layerdata, layer, source) {
|
||||||
const { opacity, radius, angle, coverage, activeColor } = style;
|
const style = layer.get('styleOptions');
|
||||||
|
const { fill } = layer.get('activedOptions');
|
||||||
|
const { radius } = source.data;
|
||||||
|
const attributes = new hexagonBuffer(layerdata);
|
||||||
|
const { opacity, angle, coverage } = style;
|
||||||
const geometry = new THREE.BufferGeometry();
|
const geometry = new THREE.BufferGeometry();
|
||||||
geometry.addAttribute('position', new THREE.Float32BufferAttribute(attributes.vertices, 3));
|
geometry.addAttribute('position', new THREE.Float32BufferAttribute(attributes.vertices, 3));
|
||||||
geometry.addAttribute('miter', new THREE.Float32BufferAttribute(attributes.miter, 2));
|
geometry.addAttribute('miter', new THREE.Float32BufferAttribute(attributes.miter, 2));
|
||||||
|
@ -12,7 +17,7 @@ export default function DrawHexagon(attributes, style) {
|
||||||
u_radius: radius,
|
u_radius: radius,
|
||||||
u_angle: angle / 180 * Math.PI,
|
u_angle: angle / 180 * Math.PI,
|
||||||
u_coverage: coverage,
|
u_coverage: coverage,
|
||||||
u_activeColor: activeColor
|
u_activeColor: fill
|
||||||
}, {
|
}, {
|
||||||
SHAPE: false
|
SHAPE: false
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
import { registerRender, getRender } from './factory';
|
||||||
|
// polygon
|
||||||
|
import DrawFill from './polygon/drawFill';
|
||||||
|
import DrawLine from './polygon/drawLine';
|
||||||
|
import DrawAnimate from './polygon/drawAnimate';
|
||||||
|
|
||||||
|
registerRender('polygon', 'fill', DrawFill);
|
||||||
|
registerRender('polygon', 'extrude', DrawFill);
|
||||||
|
registerRender('polygon', 'line', DrawLine);
|
||||||
|
registerRender('polygon', 'animate', DrawAnimate);
|
||||||
|
|
||||||
|
// line
|
||||||
|
import DrawMeshLine from './line/drawMeshLine';
|
||||||
|
import DrawArcLine from './line/drawArc';
|
||||||
|
|
||||||
|
registerRender('line', 'line', DrawMeshLine);
|
||||||
|
registerRender('line', 'arc', DrawArcLine);
|
||||||
|
|
||||||
|
// point
|
||||||
|
import DrawPointFill from './point/drawFill';
|
||||||
|
import DrawPointImage from './point/drawImage';
|
||||||
|
import DrawPointNormal from './point/drawNormal';
|
||||||
|
import DrawPointStroke from './point/drawStroke';
|
||||||
|
import DrawPointText from './point/drawText';
|
||||||
|
|
||||||
|
registerRender('point', 'fill', DrawPointFill);
|
||||||
|
registerRender('point', 'image', DrawPointImage);
|
||||||
|
registerRender('point', 'normal', DrawPointNormal);
|
||||||
|
registerRender('point', 'stroke', DrawPointStroke);
|
||||||
|
registerRender('point', 'text', DrawPointText);
|
||||||
|
|
||||||
|
// heatmap
|
||||||
|
|
||||||
|
import DrawGrid from './heatmap/gird';
|
||||||
|
import DrawHeatmap from './heatmap/heatmap';
|
||||||
|
import DrawHexagon from './heatmap/hexagon';
|
||||||
|
|
||||||
|
registerRender('heatmap', 'grid', DrawGrid);
|
||||||
|
registerRender('heatmap', 'heatmap', DrawHeatmap);
|
||||||
|
registerRender('heatmap', 'hexagon', DrawHexagon);
|
||||||
|
|
||||||
|
// image
|
||||||
|
|
||||||
|
import DrawImage from './image/drawImage';
|
||||||
|
|
||||||
|
registerRender('image', 'image', DrawImage);
|
||||||
|
|
||||||
|
export { getRender };
|
|
@ -1,8 +1,14 @@
|
||||||
import * as THREE from '../../../core/three';
|
import * as THREE from '../../../core/three';
|
||||||
|
import { LineBuffer } from '../../../geom/buffer/index';
|
||||||
import { ArcLineMaterial } from '../../../geom/material/lineMaterial';
|
import { ArcLineMaterial } from '../../../geom/material/lineMaterial';
|
||||||
export default function DrawArcLine(attributes, cfg, layer) {
|
export default function DrawArcLine(layerdata, layer) {
|
||||||
const { style, activeOption } = cfg;
|
const style = this.get('styleOptions');
|
||||||
const { opacity, zoom } = style;
|
const activeOption = layer.get('activedOptions');
|
||||||
|
const { attributes } = new LineBuffer({
|
||||||
|
layerdata,
|
||||||
|
shapeType: 'arc',
|
||||||
|
style
|
||||||
|
});
|
||||||
const geometry = new THREE.BufferGeometry();
|
const geometry = new THREE.BufferGeometry();
|
||||||
geometry.setIndex(attributes.indexArray);
|
geometry.setIndex(attributes.indexArray);
|
||||||
geometry.addAttribute('position', new THREE.Float32BufferAttribute(attributes.positions, 3));
|
geometry.addAttribute('position', new THREE.Float32BufferAttribute(attributes.positions, 3));
|
||||||
|
@ -10,12 +16,12 @@ export default function DrawArcLine(attributes, cfg, layer) {
|
||||||
geometry.addAttribute('a_instance', new THREE.Float32BufferAttribute(attributes.instances, 4));
|
geometry.addAttribute('a_instance', new THREE.Float32BufferAttribute(attributes.instances, 4));
|
||||||
geometry.addAttribute('a_size', new THREE.Float32BufferAttribute(attributes.sizes, 1));
|
geometry.addAttribute('a_size', new THREE.Float32BufferAttribute(attributes.sizes, 1));
|
||||||
const lineMaterial = new ArcLineMaterial({
|
const lineMaterial = new ArcLineMaterial({
|
||||||
u_opacity: opacity,
|
u_opacity: style.opacity,
|
||||||
u_zoom: zoom,
|
u_zoom: layer.scene.getZoom(),
|
||||||
activeColor: activeOption.fill
|
activeColor: activeOption.fill
|
||||||
}, {
|
}, {
|
||||||
SHAPE: false
|
SHAPE: false
|
||||||
});
|
});
|
||||||
const arcMesh = new THREE.Mesh(geometry, lineMaterial);
|
const arcMesh = new THREE.Mesh(geometry, lineMaterial);
|
||||||
layer.add(arcMesh);
|
return arcMesh;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,16 @@
|
||||||
import * as THREE from '../../../core/three';
|
import * as THREE from '../../../core/three';
|
||||||
|
import { LineBuffer } from '../../../geom/buffer/index';
|
||||||
import { MeshLineMaterial } from '../../../geom/material/lineMaterial';
|
import { MeshLineMaterial } from '../../../geom/material/lineMaterial';
|
||||||
export default function DrawLine(attributes, cfg, layer) {
|
export default function DrawLine(layerData, layer) {
|
||||||
const { style, animateOptions, activeOption, zoom } = cfg;
|
|
||||||
|
const style = layer.get('styleOptions');
|
||||||
|
const animateOptions = layer.get('animateOptions');
|
||||||
|
const activeOption = layer.get('activedOptions');
|
||||||
|
const { attributes } = new LineBuffer({
|
||||||
|
layerData,
|
||||||
|
shapeType: 'line',
|
||||||
|
style
|
||||||
|
});
|
||||||
const geometry = new THREE.BufferGeometry();
|
const geometry = new THREE.BufferGeometry();
|
||||||
geometry.setIndex(attributes.indexArray);
|
geometry.setIndex(attributes.indexArray);
|
||||||
geometry.addAttribute('pickingId', new THREE.Float32BufferAttribute(attributes.pickingIds, 1));
|
geometry.addAttribute('pickingId', new THREE.Float32BufferAttribute(attributes.pickingIds, 1));
|
||||||
|
@ -15,7 +24,7 @@ export default function DrawLine(attributes, cfg, layer) {
|
||||||
|
|
||||||
const lineMaterial = new MeshLineMaterial({
|
const lineMaterial = new MeshLineMaterial({
|
||||||
u_opacity: style.opacity,
|
u_opacity: style.opacity,
|
||||||
u_zoom: zoom,
|
u_zoom: layer.scene.getZoom(),
|
||||||
u_time: 0,
|
u_time: 0,
|
||||||
u_dash_offset: style.dashOffset,
|
u_dash_offset: style.dashOffset,
|
||||||
u_dash_ratio: style.dashRatio,
|
u_dash_ratio: style.dashRatio,
|
||||||
|
@ -44,5 +53,5 @@ export default function DrawLine(attributes, cfg, layer) {
|
||||||
});
|
});
|
||||||
lineMaterial.setDefinesvalue('ANIMATE', true);
|
lineMaterial.setDefinesvalue('ANIMATE', true);
|
||||||
}
|
}
|
||||||
layer.add(lineMesh);
|
return lineMesh;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,9 +6,13 @@
|
||||||
* @desc [description] 绘制点图层的面状填充,圆,三角形,六边形
|
* @desc [description] 绘制点图层的面状填充,圆,三角形,六边形
|
||||||
*/
|
*/
|
||||||
import * as THREE from '../../../core/three';
|
import * as THREE from '../../../core/three';
|
||||||
|
import * as PointBuffer from '../../../geom/buffer/point/index';
|
||||||
|
import DrawStroke from './drawStroke';
|
||||||
import PolygonMaterial from '../../../geom/material/polygonMaterial';
|
import PolygonMaterial from '../../../geom/material/polygonMaterial';
|
||||||
export default function DrawFill(attributes, style) {
|
export default function DrawFill(layerData, layer) {
|
||||||
const { opacity, activeColor } = style;
|
const style = layer.get('styleOptions');
|
||||||
|
const activeOption = layer.get('activedOptions');
|
||||||
|
const attributes = PointBuffer.FillBuffer(layerData, style);
|
||||||
const geometry = new THREE.BufferGeometry();
|
const geometry = new THREE.BufferGeometry();
|
||||||
geometry.addAttribute('position', new THREE.Float32BufferAttribute(attributes.vertices, 3));
|
geometry.addAttribute('position', new THREE.Float32BufferAttribute(attributes.vertices, 3));
|
||||||
geometry.addAttribute('a_color', new THREE.Float32BufferAttribute(attributes.colors, 4));
|
geometry.addAttribute('a_color', new THREE.Float32BufferAttribute(attributes.colors, 4));
|
||||||
|
@ -28,14 +32,20 @@ export default function DrawFill(attributes, style) {
|
||||||
// instancedGeometry.addAttribute('a_size', new THREE.InstancedBufferAttribute(new Float32Array(attributes.a_size), 3));
|
// instancedGeometry.addAttribute('a_size', new THREE.InstancedBufferAttribute(new Float32Array(attributes.a_size), 3));
|
||||||
|
|
||||||
const material = new PolygonMaterial({
|
const material = new PolygonMaterial({
|
||||||
u_opacity: opacity,
|
u_opacity: style.opacity,
|
||||||
u_activeColor: activeColor
|
u_activeColor: activeOption.fill,
|
||||||
|
u_zoom: layer.scene.getZoom()
|
||||||
}, {
|
}, {
|
||||||
SHAPE: true
|
SHAPE: true
|
||||||
});
|
});
|
||||||
material.setDefinesvalue('SHAPE', true);
|
material.setDefinesvalue('SHAPE', true);
|
||||||
material.depthTest = false;
|
material.depthTest = false;
|
||||||
const fillMesh = new THREE.Mesh(geometry, material);
|
const fillMesh = new THREE.Mesh(geometry, material);
|
||||||
|
if (style.stroke !== 'none') {
|
||||||
|
// 是否绘制边界
|
||||||
|
const meshStroke = DrawStroke(layerData, layer);
|
||||||
|
fillMesh.add(meshStroke);
|
||||||
|
}
|
||||||
// const fillMesh = new THREE.Mesh(instancedGeometry, material);
|
// const fillMesh = new THREE.Mesh(instancedGeometry, material);
|
||||||
return fillMesh;
|
return fillMesh;
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,15 @@
|
||||||
|
|
||||||
import * as THREE from '../../../core/three';
|
import * as THREE from '../../../core/three';
|
||||||
|
import * as PointBuffer from '../../../geom/buffer/point/index';
|
||||||
import PointMaterial from '../../../geom/material/pointMaterial';
|
import PointMaterial from '../../../geom/material/pointMaterial';
|
||||||
export default function DrawImage(attributes, style) {
|
export default function DrawImage(layerData, layer) {
|
||||||
const geometry = new THREE.BufferGeometry();
|
const geometry = new THREE.BufferGeometry();
|
||||||
const { strokeWidth, stroke, opacity, texture } = style;
|
const style = layer.get('styleOptions');
|
||||||
|
const { strokeWidth, stroke, opacity } = style;
|
||||||
|
const texture = layer.scene.image.texture;
|
||||||
|
const attributes = PointBuffer.ImageBuffer(layerData, {
|
||||||
|
imagePos: layer.scene.image.imagePos
|
||||||
|
});
|
||||||
geometry.addAttribute('position', new THREE.Float32BufferAttribute(attributes.vertices, 3));
|
geometry.addAttribute('position', new THREE.Float32BufferAttribute(attributes.vertices, 3));
|
||||||
geometry.addAttribute('a_color', new THREE.Float32BufferAttribute(attributes.colors, 4));
|
geometry.addAttribute('a_color', new THREE.Float32BufferAttribute(attributes.colors, 4));
|
||||||
geometry.addAttribute('pickingId', new THREE.Float32BufferAttribute(attributes.pickingIds, 1));
|
geometry.addAttribute('pickingId', new THREE.Float32BufferAttribute(attributes.pickingIds, 1));
|
||||||
|
|
|
@ -2,17 +2,21 @@
|
||||||
* 原生点绘制
|
* 原生点绘制
|
||||||
*/
|
*/
|
||||||
import * as THREE from '../../../core/three';
|
import * as THREE from '../../../core/three';
|
||||||
|
import * as PointBuffer from '../../../geom/buffer/point/index';
|
||||||
import PointMaterial from '../../../geom/material/pointMaterial';
|
import PointMaterial from '../../../geom/material/pointMaterial';
|
||||||
export default function DrawNormal(attributes, style) {
|
export default function DrawNormal(layerData, layer) {
|
||||||
const geometry = new THREE.BufferGeometry();
|
const geometry = new THREE.BufferGeometry();
|
||||||
const { opacity, activeColor } = style;
|
const style = layer.get('styleOptions');
|
||||||
|
const activeOption = layer.get('activedOptions');
|
||||||
|
const { opacity } = style;
|
||||||
|
const attributes = PointBuffer.NormalBuffer(layerData, style);
|
||||||
geometry.addAttribute('position', new THREE.Float32BufferAttribute(attributes.vertices, 3));
|
geometry.addAttribute('position', new THREE.Float32BufferAttribute(attributes.vertices, 3));
|
||||||
geometry.addAttribute('a_color', new THREE.Float32BufferAttribute(attributes.colors, 4));
|
geometry.addAttribute('a_color', new THREE.Float32BufferAttribute(attributes.colors, 4));
|
||||||
geometry.addAttribute('pickingId', new THREE.Float32BufferAttribute(attributes.pickingIds, 1));
|
geometry.addAttribute('pickingId', new THREE.Float32BufferAttribute(attributes.pickingIds, 1));
|
||||||
geometry.addAttribute('a_size', new THREE.Float32BufferAttribute(attributes.sizes, 1));
|
geometry.addAttribute('a_size', new THREE.Float32BufferAttribute(attributes.sizes, 1));
|
||||||
const material = new PointMaterial({
|
const material = new PointMaterial({
|
||||||
u_opacity: opacity,
|
u_opacity: opacity,
|
||||||
u_activeColor: activeColor
|
u_activeColor: activeOption.fill
|
||||||
}, {
|
}, {
|
||||||
SHAPE: false,
|
SHAPE: false,
|
||||||
TEXCOORD_0: false
|
TEXCOORD_0: false
|
||||||
|
|
|
@ -7,9 +7,13 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import PointLineMaterial from '../../../geom/material/pointLineMaterial';
|
import PointLineMaterial from '../../../geom/material/pointLineMaterial';
|
||||||
|
import * as PointBuffer from '../../../geom/buffer/point/index';
|
||||||
import * as THREE from '../../../core/three';
|
import * as THREE from '../../../core/three';
|
||||||
export default function DrawStroke(attributes, style) {
|
export default function DrawStroke(layerData, layer) {
|
||||||
|
const style = layer.get('styleOptions');
|
||||||
|
const activeOption = layer.get('activedOptions');
|
||||||
const { strokeWidth, stroke, strokeOpacity } = style;
|
const { strokeWidth, stroke, strokeOpacity } = style;
|
||||||
|
const attributes = PointBuffer.StrokeBuffer(layerData, style);
|
||||||
const geometry = new THREE.BufferGeometry();
|
const geometry = new THREE.BufferGeometry();
|
||||||
geometry.setIndex(attributes.indexArray);
|
geometry.setIndex(attributes.indexArray);
|
||||||
geometry.addAttribute('position', new THREE.Float32BufferAttribute(attributes.positions, 3));
|
geometry.addAttribute('position', new THREE.Float32BufferAttribute(attributes.positions, 3));
|
||||||
|
@ -22,7 +26,8 @@ export default function DrawStroke(attributes, style) {
|
||||||
const material = new PointLineMaterial({
|
const material = new PointLineMaterial({
|
||||||
u_strokeOpacity: strokeOpacity,
|
u_strokeOpacity: strokeOpacity,
|
||||||
u_stroke: stroke,
|
u_stroke: stroke,
|
||||||
u_strokeWidth: strokeWidth
|
u_strokeWidth: strokeWidth,
|
||||||
|
u_activeColor: activeOption.fill
|
||||||
});
|
});
|
||||||
const strokeMesh = new THREE.Mesh(geometry, material);
|
const strokeMesh = new THREE.Mesh(geometry, material);
|
||||||
return strokeMesh;
|
return strokeMesh;
|
||||||
|
|
|
@ -1,7 +1,15 @@
|
||||||
import * as THREE from '../../../core/three';
|
import * as THREE from '../../../core/three';
|
||||||
import TextMaterial from '../../../geom/material/textMaterial';
|
import TextMaterial from '../../../geom/material/textMaterial';
|
||||||
|
import TextBuffer from '../../../geom/buffer/point/text';
|
||||||
|
|
||||||
export default function DrawText(attributes, style) {
|
export default function DrawText(layerData, layer) {
|
||||||
|
const style = layer.get('styleOptions');
|
||||||
|
const activeOption = layer.get('activedOptions');
|
||||||
|
const { width, height } = layer.scene.getSize();
|
||||||
|
const attributes = new TextBuffer(
|
||||||
|
layerData,
|
||||||
|
layer.scene.fontAtlasManager
|
||||||
|
);
|
||||||
const geometry = new THREE.BufferGeometry();
|
const geometry = new THREE.BufferGeometry();
|
||||||
geometry.addAttribute(
|
geometry.addAttribute(
|
||||||
'position',
|
'position',
|
||||||
|
@ -27,9 +35,9 @@ export default function DrawText(attributes, style) {
|
||||||
'pickingId',
|
'pickingId',
|
||||||
new THREE.Float32BufferAttribute(attributes.pickingIds, 1)
|
new THREE.Float32BufferAttribute(attributes.pickingIds, 1)
|
||||||
);
|
);
|
||||||
const { strokeWidth, width, stroke, height, opacity, activeColor } = style;
|
const { strokeWidth, stroke, opacity } = style;
|
||||||
const material = new TextMaterial({
|
const material = new TextMaterial({
|
||||||
name: this.layerId,
|
name: layer.layerId,
|
||||||
u_texture: attributes.texture,
|
u_texture: attributes.texture,
|
||||||
u_strokeWidth: strokeWidth,
|
u_strokeWidth: strokeWidth,
|
||||||
u_stroke: stroke,
|
u_stroke: stroke,
|
||||||
|
@ -41,7 +49,7 @@ export default function DrawText(attributes, style) {
|
||||||
u_buffer: 0.75,
|
u_buffer: 0.75,
|
||||||
u_opacity: opacity,
|
u_opacity: opacity,
|
||||||
u_glSize: [ width, height ],
|
u_glSize: [ width, height ],
|
||||||
u_activeColor: activeColor
|
u_activeColor: activeOption.fill
|
||||||
});
|
});
|
||||||
const mesh = new THREE.Mesh(geometry, material);
|
const mesh = new THREE.Mesh(geometry, material);
|
||||||
return mesh;
|
return mesh;
|
||||||
|
|
|
@ -1,7 +1,15 @@
|
||||||
import * as THREE from '../../../core/three';
|
import * as THREE from '../../../core/three';
|
||||||
|
import PolygonBuffer from '../../../geom/buffer/polygon';
|
||||||
import PolygonMaterial from '../../../geom/material/polygonMaterial';
|
import PolygonMaterial from '../../../geom/material/polygonMaterial';
|
||||||
export default function DrawAnimate(attributes, style) {
|
export default function DrawAnimate(layerData, layer) {
|
||||||
const { opacity, baseColor, brightColor, windowColor, near, far } = style;
|
const style = layer.get('styleOptions');
|
||||||
|
const { near, far } = layer.map.getCameraState();
|
||||||
|
layer.scene.startAnimate();
|
||||||
|
const { attributes } = new PolygonBuffer({
|
||||||
|
shape: 'extrude',
|
||||||
|
layerData
|
||||||
|
});
|
||||||
|
const { opacity, baseColor, brightColor, windowColor } = style;
|
||||||
const geometry = new THREE.BufferGeometry();
|
const geometry = new THREE.BufferGeometry();
|
||||||
geometry.addAttribute('position', new THREE.Float32BufferAttribute(attributes.vertices, 3));
|
geometry.addAttribute('position', new THREE.Float32BufferAttribute(attributes.vertices, 3));
|
||||||
geometry.addAttribute('a_color', new THREE.Float32BufferAttribute(attributes.colors, 4));
|
geometry.addAttribute('a_color', new THREE.Float32BufferAttribute(attributes.colors, 4));
|
||||||
|
|
|
@ -1,20 +1,24 @@
|
||||||
import * as THREE from '../../../core/three';
|
import * as THREE from '../../../core/three';
|
||||||
|
import PolygonBuffer from '../../../geom/buffer/polygon';
|
||||||
import PolygonMaterial from '../../../geom/material/polygonMaterial';
|
import PolygonMaterial from '../../../geom/material/polygonMaterial';
|
||||||
// import TileMaterial from '../../../geom/material/tile/polygon';
|
|
||||||
|
|
||||||
export default function DrawPolygonFill(attributes, style) {
|
export default function DrawPolygonFill(layerData, layer) {
|
||||||
const { opacity, activeColor } = style;
|
const style = layer.get('styleOptions');
|
||||||
|
const activeOption = layer.get('activedOptions');
|
||||||
|
const config = {
|
||||||
|
...style,
|
||||||
|
activeColor: activeOption.fill
|
||||||
|
};
|
||||||
|
const { opacity, activeColor } = config;
|
||||||
|
const { attributes } = new PolygonBuffer({
|
||||||
|
shape: layer.shape,
|
||||||
|
layerData
|
||||||
|
});
|
||||||
const geometry = new THREE.BufferGeometry();
|
const geometry = new THREE.BufferGeometry();
|
||||||
geometry.addAttribute('position', new THREE.Float32BufferAttribute(attributes.vertices, 3));
|
geometry.addAttribute('position', new THREE.Float32BufferAttribute(attributes.vertices, 3));
|
||||||
geometry.addAttribute('a_color', new THREE.Float32BufferAttribute(attributes.colors, 4));
|
geometry.addAttribute('a_color', new THREE.Float32BufferAttribute(attributes.colors, 4));
|
||||||
geometry.addAttribute('pickingId', new THREE.Float32BufferAttribute(attributes.pickingIds, 1));
|
geometry.addAttribute('pickingId', new THREE.Float32BufferAttribute(attributes.pickingIds, 1));
|
||||||
geometry.addAttribute('normal', new THREE.Float32BufferAttribute(attributes.normals, 3));
|
geometry.addAttribute('normal', new THREE.Float32BufferAttribute(attributes.normals, 3));
|
||||||
// const material = new PolygonMaterial({
|
|
||||||
// u_opacity: opacity,
|
|
||||||
// u_activeColor: activeColor
|
|
||||||
// }, {
|
|
||||||
// SHAPE: false
|
|
||||||
// });
|
|
||||||
const material = new PolygonMaterial({
|
const material = new PolygonMaterial({
|
||||||
u_opacity: opacity,
|
u_opacity: opacity,
|
||||||
u_activeColor: activeColor
|
u_activeColor: activeColor
|
||||||
|
|
|
@ -1,7 +1,18 @@
|
||||||
import * as THREE from '../../../core/three';
|
import * as THREE from '../../../core/three';
|
||||||
|
import PolygonBuffer from '../../../geom/buffer/polygon';
|
||||||
import { LineMaterial } from '../../../geom/material/lineMaterial';
|
import { LineMaterial } from '../../../geom/material/lineMaterial';
|
||||||
export default function DrawPolygonLine(attributes, style) {
|
export default function DrawPolygonLine(layerData, layer) {
|
||||||
const { opacity } = style;
|
const style = layer.get('styleOptions');
|
||||||
|
const activeOption = layer.get('activedOptions');
|
||||||
|
const config = {
|
||||||
|
...style,
|
||||||
|
activeColor: activeOption.fill
|
||||||
|
};
|
||||||
|
const { opacity } = config;
|
||||||
|
const { attributes } = new PolygonBuffer({
|
||||||
|
shape: layer.shape,
|
||||||
|
layerData
|
||||||
|
});
|
||||||
const geometry = new THREE.BufferGeometry();
|
const geometry = new THREE.BufferGeometry();
|
||||||
geometry.addAttribute('position', new THREE.Float32BufferAttribute(attributes.vertices, 3));
|
geometry.addAttribute('position', new THREE.Float32BufferAttribute(attributes.vertices, 3));
|
||||||
geometry.addAttribute('a_color', new THREE.Float32BufferAttribute(attributes.colors, 4));
|
geometry.addAttribute('a_color', new THREE.Float32BufferAttribute(attributes.colors, 4));
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
|
||||||
export { default as DrawAnimate } from './drawAnimate';
|
export { default as DrawAnimate } from './drawAnimate';
|
||||||
export { default as DrawFill } from './drawFill';
|
export { default as DrawFill } from './drawFill';
|
||||||
export { default as DrawLine } from './drawLine';
|
export { default as DrawLine } from './drawLine';
|
||||||
|
|
||||||
|
export function polygonMesh() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
import TileLayer from './tileLayer';
|
||||||
|
import VectorTile from './vectorTile';
|
||||||
|
export default class VectorTileLayer extends TileLayer {
|
||||||
|
_createTile(key, layer) {
|
||||||
|
return new VectorTile(key, this.url, layer);
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,30 +13,34 @@ export default class ImageTile extends Tile {
|
||||||
}, 0);
|
}, 0);
|
||||||
}
|
}
|
||||||
_requestTile() {
|
_requestTile() {
|
||||||
const urlParams = {
|
const image = this._createDebugMesh();
|
||||||
x: this._tile[0],
|
this._createMesh(image);
|
||||||
y: this._tile[1],
|
this.emit('tileLoaded');
|
||||||
z: this._tile[2]
|
// return;
|
||||||
};
|
// const urlParams = {
|
||||||
|
// x: this._tile[0],
|
||||||
|
// y: this._tile[1],
|
||||||
|
// z: this._tile[2]
|
||||||
|
// };
|
||||||
|
|
||||||
const url = this._getTileURL(urlParams);
|
// const url = this._getTileURL(urlParams);
|
||||||
const image = document.createElement('img');
|
// const image = document.createElement('img');
|
||||||
|
|
||||||
image.addEventListener('load', () => {
|
// image.addEventListener('load', () => {
|
||||||
|
// this._isLoaded = true;
|
||||||
|
// this._createMesh(image);
|
||||||
|
// this._ready = true;
|
||||||
|
// }, false);
|
||||||
|
|
||||||
this._createMesh(image);
|
// // image.addEventListener('progress', event => {}, false);
|
||||||
this._ready = true;
|
// // image.addEventListener('error', event => {}, false);
|
||||||
}, false);
|
|
||||||
|
|
||||||
// image.addEventListener('progress', event => {}, false);
|
// image.crossOrigin = '';
|
||||||
// image.addEventListener('error', event => {}, false);
|
|
||||||
|
|
||||||
image.crossOrigin = '';
|
// // Load image
|
||||||
|
// image.src = url;
|
||||||
|
|
||||||
// Load image
|
// this._image = image;
|
||||||
image.src = url;
|
|
||||||
|
|
||||||
this._image = image;
|
|
||||||
}
|
}
|
||||||
_getBufferData(images) {
|
_getBufferData(images) {
|
||||||
const NW = this._tileBounds.getTopLeft();
|
const NW = this._tileBounds.getTopLeft();
|
||||||
|
@ -58,8 +62,20 @@ export default class ImageTile extends Tile {
|
||||||
buffer.attributes.texture = buffer.texture;
|
buffer.attributes.texture = buffer.texture;
|
||||||
const style = this.layer.get('styleOptions');
|
const style = this.layer.get('styleOptions');
|
||||||
const mesh = DrawImage(buffer.attributes, style);
|
const mesh = DrawImage(buffer.attributes, style);
|
||||||
this.Object3D.add(mesh);
|
this._object3D.add(mesh);
|
||||||
return this.Object3D;
|
return this._object3D;
|
||||||
|
}
|
||||||
|
_createDebugMesh() {
|
||||||
|
const canvas = document.createElement('canvas');
|
||||||
|
const context = canvas.getContext('2d');
|
||||||
|
canvas.width = 256;
|
||||||
|
canvas.height = 256;
|
||||||
|
context.font = 'Bold 20px Helvetica Neue, Verdana, Arial';
|
||||||
|
context.fillStyle = '#ff0000';
|
||||||
|
context.fillText(this._tile.join('/'), 20, 20);
|
||||||
|
context.rect(0, 0, 256, 256);
|
||||||
|
context.stroke();
|
||||||
|
return canvas;
|
||||||
}
|
}
|
||||||
_abortRequest() {
|
_abortRequest() {
|
||||||
if (!this._image) {
|
if (!this._image) {
|
||||||
|
@ -68,7 +84,9 @@ export default class ImageTile extends Tile {
|
||||||
|
|
||||||
this._image.src = '';
|
this._image.src = '';
|
||||||
}
|
}
|
||||||
|
getSelectFeature() {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
destroy() {
|
destroy() {
|
||||||
// Cancel any pending requests
|
// Cancel any pending requests
|
||||||
this._abortRequest();
|
this._abortRequest();
|
||||||
|
|
|
@ -1,10 +1,28 @@
|
||||||
import * as THREE from '../../core/three';
|
import * as THREE from '../../core/three';
|
||||||
|
import Base from '../../core/base';
|
||||||
|
import { destoryObject } from '../../util/object3d-util';
|
||||||
|
import Controller from '../../core/controller/index';
|
||||||
|
import Util from '../../util';
|
||||||
|
import Global from '../../global';
|
||||||
|
import Attr from '../../attr/index';
|
||||||
import { toLngLatBounds, toBounds } from '@antv/geo-coord';
|
import { toLngLatBounds, toBounds } from '@antv/geo-coord';
|
||||||
const r2d = 180 / Math.PI;
|
const r2d = 180 / Math.PI;
|
||||||
const tileURLRegex = /\{([zxy])\}/g;
|
const tileURLRegex = /\{([zxy])\}/g;
|
||||||
|
function parseFields(field) {
|
||||||
export default class Tile {
|
if (Util.isArray(field)) {
|
||||||
|
return field;
|
||||||
|
}
|
||||||
|
if (Util.isString(field)) {
|
||||||
|
return field.split('*');
|
||||||
|
}
|
||||||
|
return [ field ];
|
||||||
|
}
|
||||||
|
export default class Tile extends Base {
|
||||||
constructor(key, url, layer) {
|
constructor(key, url, layer) {
|
||||||
|
super({
|
||||||
|
scales: {},
|
||||||
|
attrs: {}
|
||||||
|
});
|
||||||
this.layer = layer;
|
this.layer = layer;
|
||||||
this._tile = key.split('_').map(v => v * 1);
|
this._tile = key.split('_').map(v => v * 1);
|
||||||
this._path = url;
|
this._path = url;
|
||||||
|
@ -15,10 +33,134 @@ export default class Tile {
|
||||||
this._center = this._tileBounds.getCenter();
|
this._center = this._tileBounds.getCenter();
|
||||||
|
|
||||||
this._centerLnglat = this._tileLnglatBounds.getCenter();
|
this._centerLnglat = this._tileLnglatBounds.getCenter();
|
||||||
this.Object3D = new THREE.Object3D();
|
this._object3D = new THREE.Object3D();
|
||||||
this.requestTileAsync();
|
this._object3D.onBeforeRender = () => {
|
||||||
|
};
|
||||||
|
this._isLoaded = false;
|
||||||
|
this.requestTileAsync(data => this._init(data));
|
||||||
|
}
|
||||||
|
_init(data) {
|
||||||
|
this._initControllers();
|
||||||
|
this._creatSource(data);
|
||||||
|
this._initTileAttrs();
|
||||||
|
this._mapping();
|
||||||
|
this._createMesh();
|
||||||
|
}
|
||||||
|
_initControllers() {
|
||||||
|
const scales = this.layer.get('scaleOptions');
|
||||||
|
const scaleController = new Controller.Scale({
|
||||||
|
defs: {
|
||||||
|
...scales
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.set('scaleController', scaleController);
|
||||||
|
}
|
||||||
|
_createScale(field) {
|
||||||
|
// TODO scale更新
|
||||||
|
const scales = this.get('scales');
|
||||||
|
let scale = scales[field];
|
||||||
|
if (!scale) {
|
||||||
|
scale = this.createScale(field);
|
||||||
|
scales[field] = scale;
|
||||||
|
}
|
||||||
|
return scale;
|
||||||
|
}
|
||||||
|
createScale(field) {
|
||||||
|
const data = this.source.data.dataArray;
|
||||||
|
const scales = this.get('scales');
|
||||||
|
let scale = scales[field];
|
||||||
|
const scaleController = this.get('scaleController');
|
||||||
|
if (!scale) {
|
||||||
|
scale = scaleController.createScale(field, data);
|
||||||
|
scales[field] = scale;
|
||||||
|
}
|
||||||
|
return scale;
|
||||||
|
}
|
||||||
|
// 获取属性映射的值
|
||||||
|
_getAttrValues(attr, record) {
|
||||||
|
const scales = attr.scales;
|
||||||
|
const params = [];
|
||||||
|
for (let i = 0; i < scales.length; i++) {
|
||||||
|
const scale = scales[i];
|
||||||
|
const field = scale.field;
|
||||||
|
if (scale.type === 'identity') {
|
||||||
|
params.push(scale.value);
|
||||||
|
} else {
|
||||||
|
params.push(record[field]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const indexZoom = params.indexOf('zoom');
|
||||||
|
indexZoom !== -1 ? params[indexZoom] = attr.zoom : null;
|
||||||
|
const values = attr.mapping(...params);
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
_mapping() {
|
||||||
|
|
||||||
|
const attrs = this.get('attrs');
|
||||||
|
const mappedData = [];
|
||||||
|
// const data = this.layerSource.propertiesData;
|
||||||
|
const data = this.source.data.dataArray;
|
||||||
|
for (let i = 0; i < data.length; i++) {
|
||||||
|
const record = data[i];
|
||||||
|
const newRecord = {};
|
||||||
|
newRecord.id = data[i]._id;
|
||||||
|
for (const k in attrs) {
|
||||||
|
if (attrs.hasOwnProperty(k)) {
|
||||||
|
const attr = attrs[k];
|
||||||
|
const names = attr.names;
|
||||||
|
const values = this._getAttrValues(attr, record);
|
||||||
|
if (names.length > 1) { // position 之类的生成多个字段的属性
|
||||||
|
for (let j = 0; j < values.length; j++) {
|
||||||
|
const val = values[j];
|
||||||
|
const name = names[j];
|
||||||
|
newRecord[name] = (Util.isArray(val) && val.length === 1) ? val[0] : val; // 只有一个值时返回第一个属性值
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
newRecord[names[0]] = values.length === 1 ? values[0] : values;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
newRecord.coordinates = record.coordinates;
|
||||||
|
mappedData.push(newRecord);
|
||||||
|
}
|
||||||
|
// 通过透明度过滤数据
|
||||||
|
if (attrs.hasOwnProperty('filter')) {
|
||||||
|
mappedData.forEach(item => {
|
||||||
|
item.filter === false && (item.color[3] = 0);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.layerData = mappedData;
|
||||||
|
}
|
||||||
|
_initTileAttrs() {
|
||||||
|
const attrOptions = this.layer.get('attrOptions');
|
||||||
|
for (const type in attrOptions) {
|
||||||
|
if (attrOptions.hasOwnProperty(type)) {
|
||||||
|
this._updateTileAttr(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_updateTileAttr(type) {
|
||||||
|
const self = this;
|
||||||
|
const attrs = this.get('attrs');
|
||||||
|
const attrOptions = this.layer.get('attrOptions');
|
||||||
|
const option = attrOptions[type];
|
||||||
|
option.neadUpdate = true;
|
||||||
|
const className = Util.upperFirst(type);
|
||||||
|
const fields = parseFields(option.field);
|
||||||
|
const scales = [];
|
||||||
|
for (let i = 0; i < fields.length; i++) {
|
||||||
|
const field = fields[i];
|
||||||
|
const scale = self._createScale(field);
|
||||||
|
|
||||||
|
if (type === 'color' && Util.isNil(option.values)) { // 设置 color 的默认色值
|
||||||
|
option.values = Global.colors;
|
||||||
|
}
|
||||||
|
scales.push(scale);
|
||||||
|
}
|
||||||
|
option.scales = scales;
|
||||||
|
const attr = new Attr[className](option);
|
||||||
|
attrs[type] = attr;
|
||||||
}
|
}
|
||||||
_createMesh() {}
|
_createMesh() {}
|
||||||
_getTileURL(urlParams) {
|
_getTileURL(urlParams) {
|
||||||
|
@ -34,12 +176,12 @@ export default class Tile {
|
||||||
}
|
}
|
||||||
// 经纬度范围转瓦片范围
|
// 经纬度范围转瓦片范围
|
||||||
_tileBounds(lnglatBound) {
|
_tileBounds(lnglatBound) {
|
||||||
const ne = this.layer.scene.project([ lnglatBound.getNorthWest().lng, lnglatBound.getNorthEast().lat ]);
|
const ne = this.layer.scene.project([ lnglatBound.getNorthEast().lng, lnglatBound.getNorthEast().lat ]);
|
||||||
const sw = this.layer.scene.project([ lnglatBound.getSouthEast().lng, lnglatBound.getSouthWest().lat ]);
|
const sw = this.layer.scene.project([ lnglatBound.getSouthWest().lng, lnglatBound.getSouthWest().lat ]);
|
||||||
return toBounds(sw, ne);
|
return toBounds(sw, ne);
|
||||||
}
|
}
|
||||||
getMesh() {
|
getMesh() {
|
||||||
return this.Object3D;
|
return this._object3D;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -60,31 +202,30 @@ export default class Tile {
|
||||||
const n = Math.PI - 2 * Math.PI * y / Math.pow(2, z);
|
const n = Math.PI - 2 * Math.PI * y / Math.pow(2, z);
|
||||||
return r2d * Math.atan(0.5 * (Math.exp(n) - Math.exp(-n)));
|
return r2d * Math.atan(0.5 * (Math.exp(n) - Math.exp(-n)));
|
||||||
}
|
}
|
||||||
destroy() {
|
_retainParent(x, y, z, minZoom = 5) {
|
||||||
if (this._object3D && this._object3D.children) {
|
const x2 = Math.floor(x / 2),
|
||||||
let child;
|
y2 = Math.floor(y / 2),
|
||||||
for (let i = 0; i < this._object3D.children.length; i++) {
|
z2 = z - 1,
|
||||||
child = this._object3D.children[i];
|
coords2 = [ +x2, +y2, +z2 ];
|
||||||
if (!child) {
|
const tile = this._tiles[coords2]; // 计算保留
|
||||||
continue;
|
if (tile && tile.active) {
|
||||||
}
|
tile.retain = true;
|
||||||
this.remove(child);
|
return true;
|
||||||
if (child.geometry) {
|
|
||||||
// child.geometry.dispose();
|
|
||||||
child.geometry = null;
|
|
||||||
}
|
|
||||||
if (child.material) {
|
|
||||||
if (child.material.map) {
|
|
||||||
child.material.map.dispose();
|
|
||||||
child.material.map = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
child.material.dispose();
|
} else if (tile && tile.loaded) {
|
||||||
child.material = null;
|
tile.retain = true;
|
||||||
}
|
|
||||||
child = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
this._object3D = null;
|
|
||||||
|
if (z2 > minZoom) {
|
||||||
|
return this._retainParent(x2, y2, z2, minZoom);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
_preRender() {
|
||||||
|
}
|
||||||
|
destroy() {
|
||||||
|
super.destroy();
|
||||||
|
destoryObject(this._object3D);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,126 +1,325 @@
|
||||||
import Layer from '../../core/layer';
|
import Layer from '../../core/layer';
|
||||||
|
import source from '../../core/source';
|
||||||
import * as THREE from '../../core/three';
|
import * as THREE from '../../core/three';
|
||||||
|
import Global from '../../global';
|
||||||
|
const { pointShape } = Global;
|
||||||
import TileCache from './tileCache';
|
import TileCache from './tileCache';
|
||||||
import { throttle } from '@antv/util';
|
import pickingFragmentShader from '../../core/engine/picking/picking_frag.glsl';
|
||||||
import { toLngLat } from '@antv/geo-coord';
|
import { throttle, deepMix } from '@antv/util';
|
||||||
|
import { toLngLat, Bounds, Point } from '@antv/geo-coord';
|
||||||
|
import { wrapNum } from '@antv/geo-coord/lib/util/index';
|
||||||
import { epsg3857 } from '@antv/geo-coord/lib/geo/crs/crs-epsg3857';
|
import { epsg3857 } from '@antv/geo-coord/lib/geo/crs/crs-epsg3857';
|
||||||
export default class TileLayer extends Layer {
|
export default class TileLayer extends Layer {
|
||||||
constructor(scene, cfg) {
|
constructor(scene, cfg) {
|
||||||
super(scene, cfg);
|
super(scene, {
|
||||||
this._tileCache = new TileCache(50, this._destroyTile);
|
...cfg,
|
||||||
|
keepBuffer: 2
|
||||||
|
});
|
||||||
|
this._tileCache = new TileCache(100, this._destroyTile);
|
||||||
this._crs = epsg3857;
|
this._crs = epsg3857;
|
||||||
this._tiles = new THREE.Object3D();
|
this._tiles = new THREE.Object3D();
|
||||||
|
this._pickTiles = new THREE.Object3D();
|
||||||
|
this._pickTiles.name = this.layerId;
|
||||||
|
this.scene._engine._picking.add(this._pickTiles);
|
||||||
|
this._tiles.frustumCulled = false;
|
||||||
this._tileKeys = [];
|
this._tileKeys = [];
|
||||||
this.tileList = [];
|
this.tileList = {};
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
source(url) {
|
shape(field, values) {
|
||||||
this.url = url;
|
const layerType = this.get('layerType');
|
||||||
|
if (layerType === 'point') {
|
||||||
|
return super.shape(field, values);
|
||||||
|
}
|
||||||
|
this.shape = field;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
source(url, cfg = {}) {
|
||||||
|
this.url = url;
|
||||||
|
this.sourceCfg = cfg;
|
||||||
|
this.sourceCfg.mapType = this.scene.mapType;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
tileSource(data, cfg) {
|
||||||
|
if (data instanceof source) {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
const tileSourceCfg = {
|
||||||
|
data,
|
||||||
|
zoom: this.scene.getZoom()
|
||||||
|
};
|
||||||
|
deepMix(tileSourceCfg, this.sourceCfg, cfg);
|
||||||
|
return new source(tileSourceCfg);
|
||||||
|
}
|
||||||
render() {
|
render() {
|
||||||
|
// this._initControllers();
|
||||||
this._initMapEvent();
|
this._initMapEvent();
|
||||||
|
// this._initAttrs();
|
||||||
|
this._initInteraction();
|
||||||
this.draw();
|
this.draw();
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
draw() {
|
draw() {
|
||||||
this._object3D.add(this._tiles);
|
this._object3D.add(this._tiles);
|
||||||
this._calculateLOD();
|
this._calculateLOD();
|
||||||
}
|
}
|
||||||
|
|
||||||
drawTile() {
|
drawTile() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
zoomchange(ev) {
|
zoomchange(ev) {
|
||||||
super.zoomchange(ev);
|
super.zoomchange(ev);
|
||||||
throttle(this._calculateLOD, 200);
|
throttle(this._calculateLOD, 200);
|
||||||
this._calculateLOD();
|
this._calculateLOD();
|
||||||
}
|
}
|
||||||
|
|
||||||
dragend(ev) {
|
dragend(ev) {
|
||||||
super.dragend(ev);
|
super.dragend(ev);
|
||||||
this._calculateLOD();
|
this._calculateLOD();
|
||||||
|
|
||||||
}
|
}
|
||||||
_calculateLOD() {
|
_calculateLOD() {
|
||||||
const viewPort = this.scene.getBounds().toBounds();
|
/**
|
||||||
const SE = viewPort.getSouthEast();
|
* 加载完成 active
|
||||||
const NW = viewPort.getNorthWest();
|
* 需要显示 current
|
||||||
|
* 是否保留 retain
|
||||||
|
*/
|
||||||
|
this.updateTileList = [];
|
||||||
const zoom = Math.round(this.scene.getZoom()) - 1;
|
const zoom = Math.round(this.scene.getZoom()) - 1;
|
||||||
const tileCount = Math.pow(2, zoom);
|
|
||||||
const center = this.scene.getCenter();
|
const center = this.scene.getCenter();
|
||||||
const NWPoint = this._crs.lngLatToPoint(toLngLat(NW.lng, NW.lat), zoom);
|
|
||||||
const SEPoint = this._crs.lngLatToPoint(toLngLat(SE.lng, SE.lat), zoom);
|
|
||||||
const centerPoint = this._crs.lngLatToPoint(toLngLat(center.lng, center.lat), zoom);
|
const centerPoint = this._crs.lngLatToPoint(toLngLat(center.lng, center.lat), zoom);
|
||||||
const centerXY = centerPoint.divideBy(256).round();
|
const centerXY = centerPoint.divideBy(256).round();
|
||||||
const minXY = NWPoint.divideBy(256).round();
|
const pixelBounds = this._getPixelBounds();
|
||||||
const maxXY = SEPoint.divideBy(256).round();
|
const tileRange = this._pxBoundsToTileRange(pixelBounds);
|
||||||
// console.log(NW.lng, NW.lat, SE.lng, SE.lat, NWPonint, SEPonint);
|
const margin = this.get('keepBuffer');
|
||||||
let updateTileList = [];
|
this.noPruneRange = new Bounds(tileRange.getBottomLeft().subtract([ margin, -margin ]),
|
||||||
this.tileList = [];
|
tileRange.getTopRight().add([ margin, -margin ]));
|
||||||
const halfx = Math.floor((maxXY.x - minXY.x) / 2) + 1;
|
if (!(isFinite(tileRange.min.x) &&
|
||||||
const halfy = Math.floor((maxXY.y - minXY.y) / 2) + 1;
|
isFinite(tileRange.min.y) &&
|
||||||
if (!(centerPoint.x > NWPoint.x && centerPoint.x < SEPoint.x)) { // 地图循环的问题
|
isFinite(tileRange.max.x) &&
|
||||||
for (let i = 0; i < minXY.x; i++) {
|
isFinite(tileRange.max.y))) { throw new Error('Attempted to load an infinite number of tiles'); }
|
||||||
for (let j = Math.min(0, minXY.y - halfy); j < Math.max(maxXY.y + halfy, tileCount); j++) {
|
for (let j = tileRange.min.y; j <= tileRange.max.y; j++) {
|
||||||
this._updateTileList(updateTileList, i, j, zoom);
|
for (let i = tileRange.min.x; i <= tileRange.max.x; i++) {
|
||||||
}
|
const coords = [ i, j, zoom ];
|
||||||
}
|
const tile = this.tileList[coords.join('_')];
|
||||||
for (let i = maxXY.x; i < tileCount; i++) {
|
if (tile) {
|
||||||
for (let j = Math.min(0, minXY.y - halfy); j < Math.max(maxXY.y + halfy, tileCount); j++) {
|
tile.current = true;
|
||||||
this._updateTileList(updateTileList, i, j, zoom);
|
} else {
|
||||||
|
this.tileList[coords.join('_')] = {
|
||||||
|
current: true,
|
||||||
|
coords
|
||||||
|
};
|
||||||
|
this.updateTileList.push(coords);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (let i = Math.max(0, minXY.x - halfx); i < Math.min(maxXY.x + halfx, tileCount); i++) {
|
this.updateTileList.sort((a, b) => {
|
||||||
for (let j = Math.max(0, minXY.y - halfy); j < Math.min(maxXY.y + halfy, tileCount); j++) {
|
const tile1 = a;
|
||||||
this._updateTileList(updateTileList, i, j, zoom);
|
const tile2 = b;
|
||||||
}
|
|
||||||
}
|
|
||||||
// 过滤掉已经存在的
|
|
||||||
// tileList = tileList.filter(tile => {
|
|
||||||
// })
|
|
||||||
updateTileList = updateTileList.sort((a, b) => {
|
|
||||||
const tile1 = a.split('_');
|
|
||||||
const tile2 = b.split('_');
|
|
||||||
const d1 = Math.pow((tile1[0] * 1 - centerXY.x), 2) + Math.pow((tile1[1] * 1 - centerXY.y), 2);
|
const d1 = Math.pow((tile1[0] * 1 - centerXY.x), 2) + Math.pow((tile1[1] * 1 - centerXY.y), 2);
|
||||||
const d2 = Math.pow((tile2[0] * 1 - centerXY.x), 2) + Math.pow((tile2[1] * 1 - centerXY.y), 2);
|
const d2 = Math.pow((tile2[0] * 1 - centerXY.x), 2) + Math.pow((tile2[1] * 1 - centerXY.y), 2);
|
||||||
return d1 - d2;
|
return d1 - d2;
|
||||||
});
|
});
|
||||||
updateTileList.forEach(key => {
|
this._pruneTiles();
|
||||||
this._requestTile(key, this);
|
// 更新瓦片数据
|
||||||
|
this.updateTileList.forEach(coords => {
|
||||||
|
const key = coords.join('_');
|
||||||
|
if (this.tileList[key].current) {
|
||||||
|
this._requestTile(key, this);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
this._removeOutTiles();
|
|
||||||
}
|
}
|
||||||
_updateTileList(updateTileList, x, y, z) {
|
_getShape(layerData) {
|
||||||
|
let shape = null;
|
||||||
|
if (!layerData[0].hasOwnProperty('shape')) {
|
||||||
|
return 'normal';
|
||||||
|
}
|
||||||
|
for (let i = 0; i < layerData.length; i++) {
|
||||||
|
shape = layerData[i].shape;
|
||||||
|
if (shape !== undefined) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
pointShape['2d'].indexOf(shape) !== -1 ||
|
||||||
|
pointShape['3d'].indexOf(shape) !== -1
|
||||||
|
) {
|
||||||
|
return 'fill';
|
||||||
|
} else if (this.scene.image.imagesIds.indexOf(shape) !== -1) {
|
||||||
|
return 'image';
|
||||||
|
}
|
||||||
|
return 'text';
|
||||||
|
}
|
||||||
|
_updateTileList(x, y, z) {
|
||||||
const key = [ x, y, z ].join('_');
|
const key = [ x, y, z ].join('_');
|
||||||
this.tileList.push(key);
|
const tile = this.tileList[key];
|
||||||
if (this._tileKeys.indexOf(key) === -1) {
|
if (tile) {
|
||||||
updateTileList.push(key);
|
tile.current = true;
|
||||||
|
} else {
|
||||||
|
this.tileList[key] = {
|
||||||
|
current: true,
|
||||||
|
active: false,
|
||||||
|
coords: key.split('_')
|
||||||
|
};
|
||||||
|
this.updateTileList.push(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_requestTile(key, layer) {
|
_requestTile(key, layer) {
|
||||||
|
const t = this.tileList[key];
|
||||||
|
if (!t) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
let tile = this._tileCache.getTile(key);
|
let tile = this._tileCache.getTile(key);
|
||||||
if (!tile) {
|
if (!tile) {
|
||||||
tile = this._createTile(key, layer);
|
tile = this._createTile(key, layer);
|
||||||
const mesh = tile.getMesh();
|
tile.on('tileLoaded', () => {
|
||||||
mesh.name = key;
|
t.active = true;
|
||||||
this._tileCache.setTile(tile, key);
|
const mesh = tile.getMesh();
|
||||||
|
mesh.name = key;
|
||||||
|
this._tileCache.setTile(tile, key);
|
||||||
|
this._tileKeys.push(key);
|
||||||
|
if (mesh.type === 'composer') {
|
||||||
|
this.scene._engine.composerLayers.push(mesh);
|
||||||
|
this.scene._engine.update();
|
||||||
|
this._pruneTiles();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (mesh.children.length !== 0) {
|
||||||
|
this._tiles.add(tile.getMesh());
|
||||||
|
this._addPickTile(tile.getMesh());
|
||||||
|
}
|
||||||
|
this.scene._engine.update();
|
||||||
|
this._pruneTiles();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
if (tile.getMesh().type === 'composer') {
|
||||||
|
this.scene._engine.composerLayers.push(tile.getMesh());
|
||||||
|
this.scene._engine.update();
|
||||||
|
this._pruneTiles();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._tiles.add(tile.getMesh());
|
||||||
|
t.active = true;
|
||||||
|
this._addPickTile(tile.getMesh());
|
||||||
this._tileKeys.push(key);
|
this._tileKeys.push(key);
|
||||||
// this.scene._engine.update();
|
this.scene._engine.update();
|
||||||
|
this._pruneTiles();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_addPickTile(meshobj) {
|
||||||
|
const mesh = meshobj.children[0];
|
||||||
|
const pickmaterial = mesh.material.clone();
|
||||||
|
pickmaterial.fragmentShader = pickingFragmentShader;
|
||||||
|
const pickingMesh = new THREE[mesh.type](mesh.geometry, pickmaterial);
|
||||||
|
pickingMesh.name = this.layerId;
|
||||||
|
pickingMesh.onBeforeRender = () => {
|
||||||
|
const zoom = this.scene.getZoom();
|
||||||
|
pickingMesh.material.setUniformsValue('u_zoom', zoom);
|
||||||
|
};
|
||||||
|
this._pickTiles.add(pickingMesh);
|
||||||
|
|
||||||
|
}
|
||||||
|
// 根据距离优先级查找
|
||||||
|
getSelectFeature(id, lnglat) {
|
||||||
|
const zoom = Math.round(this.scene.getZoom()) - 1;
|
||||||
|
const tilePoint = this._crs.lngLatToPoint(toLngLat(lnglat.lng, lnglat.lat), zoom);
|
||||||
|
const tileXY = tilePoint.divideBy(256).round();
|
||||||
|
const key = [ tileXY.x, tileXY.y, zoom ].join('_');
|
||||||
|
const tile = this._tileCache.getTile(key);
|
||||||
|
const feature = tile ? tile.getSelectFeature(id) : null;
|
||||||
|
return { feature };
|
||||||
|
}
|
||||||
|
_pruneTiles() {
|
||||||
|
let tile;
|
||||||
|
const zoom = Math.round(this.scene.getZoom()) - 1;
|
||||||
|
for (const key in this.tileList) {
|
||||||
|
const c = this.tileList[key].coords;
|
||||||
|
if (c[2] !== zoom || !this.noPruneRange.contains(new Point(c[0], c[1]))) {
|
||||||
|
this.tileList[key].current = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const key in this.tileList) {
|
||||||
|
tile = this.tileList[key];
|
||||||
|
tile.retain = tile.current;
|
||||||
|
}
|
||||||
|
for (const key in this.tileList) {
|
||||||
|
tile = this.tileList[key];
|
||||||
|
if (tile.current && !tile.active) {
|
||||||
|
const [ x, y, z ] = key.split('_').map(v => v * 1);
|
||||||
|
if (!this._retainParent(x, y, z, z - 5)) {
|
||||||
|
this._retainChildren(x, y, z, z + 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
this._removeOutTiles();
|
||||||
|
}
|
||||||
|
_retainParent(x, y, z, minZoom) {
|
||||||
|
const x2 = Math.floor(x / 2);
|
||||||
|
const y2 = Math.floor(y / 2);
|
||||||
|
const z2 = z - 1;
|
||||||
|
const tile = this.tileList[[ x2, y2, z2 ].join('_')];
|
||||||
|
if (tile && tile.active) {
|
||||||
|
tile.retain = true;
|
||||||
|
return true;
|
||||||
|
} else if (tile && tile.loaded) {
|
||||||
|
tile.retain = true;
|
||||||
|
}
|
||||||
|
if (z2 > minZoom) {
|
||||||
|
return this._retainParent(x2, y2, z2, minZoom);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
_retainChildren(x, y, z, maxZoom) {
|
||||||
|
for (let i = 2 * x; i < 2 * x + 2; i++) {
|
||||||
|
for (let j = 2 * y; j < 2 * y + 2; j++) {
|
||||||
|
const key = [ i, j, z + 1 ].join('_');
|
||||||
|
const tile = this.tileList[key];
|
||||||
|
if (tile && tile.active) {
|
||||||
|
tile.retain = true;
|
||||||
|
continue;
|
||||||
|
} else if (tile && tile.loaded) {
|
||||||
|
tile.retain = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (z + 1 < maxZoom) {
|
||||||
|
this._retainChildren(i, j, z + 1, maxZoom);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this._tiles.add(tile.getMesh());
|
|
||||||
this._tileKeys.push(key);
|
|
||||||
}
|
}
|
||||||
// 移除视野外的tile
|
// 移除视野外的tile
|
||||||
_removeOutTiles() {
|
_removeOutTiles() {
|
||||||
for (let i = this._tiles.children.length - 1; i >= 0; i--) {
|
for (const key in this.tileList) {
|
||||||
const tile = this._tiles.children[i];
|
if (!this.tileList[key].retain) {
|
||||||
const key = tile.name;
|
const tileObj = this._tileCache.getTile(key);
|
||||||
if (this.tileList.indexOf(key) === -1) {
|
if (tileObj) {
|
||||||
this._tiles.remove(tile);
|
tileObj._abortRequest();
|
||||||
|
this._tiles.remove(tileObj.getMesh());
|
||||||
|
}
|
||||||
|
if (tileObj && tileObj.getMesh().type === 'composer') {
|
||||||
|
this.scene._engine.composerLayers = this.scene._engine.composerLayers.filter(obj => {
|
||||||
|
return obj.name !== tileObj.getMesh().name;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
delete this.tileList[key];
|
||||||
}
|
}
|
||||||
this._tileKeys = [].concat(this.tileList);
|
|
||||||
}
|
}
|
||||||
|
if (this._tiles.children.length > Object.keys(this.tileList).length) {
|
||||||
|
this._tiles.children.forEach(tile => {
|
||||||
|
const key = tile.name;
|
||||||
|
if (!this.tileList[key]) {
|
||||||
|
this._tiles.remove(tile);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} // 移除 空的geom
|
||||||
|
this.scene._engine.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
_removeTiles() {
|
_removeTiles() {
|
||||||
if (!this._tiles || !this._tiles.children) {
|
if (!this._tiles || !this._tiles.children) {
|
||||||
return;
|
return;
|
||||||
|
@ -130,9 +329,51 @@ export default class TileLayer extends Layer {
|
||||||
this._tiles.remove(this._tiles.children[i]);
|
this._tiles.remove(this._tiles.children[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
_getPixelBounds() {
|
||||||
|
const viewPort = this.scene.getBounds().toBounds();
|
||||||
|
const NE = viewPort.getNorthEast();
|
||||||
|
const SW = viewPort.getSouthWest();
|
||||||
|
const zoom = Math.round(this.scene.getZoom()) - 1;
|
||||||
|
const center = this.scene.getCenter();
|
||||||
|
const NEPoint = this._crs.lngLatToPoint(toLngLat(NE.lng, NE.lat), zoom);
|
||||||
|
const SWPoint = this._crs.lngLatToPoint(toLngLat(SW.lng, SW.lat), zoom);
|
||||||
|
const centerPoint = this._crs.lngLatToPoint(toLngLat(center.lng, center.lat), zoom);
|
||||||
|
const topHeight = centerPoint.y - NEPoint.y;
|
||||||
|
const bottomHeight = SWPoint.y - centerPoint.y;
|
||||||
|
// 跨日界线的情况
|
||||||
|
let leftWidth;
|
||||||
|
let rightWidth;
|
||||||
|
if (center.lng - NE.lng > 0 || center.lng - SW.lng < 0) {
|
||||||
|
const width = Math.pow(2, zoom) * 256 / 360 * (180 - NE.lng) + Math.pow(2, zoom) * 256 / 360 * (SW.lng + 180);
|
||||||
|
if (center.lng - NE.lng > 0) { // 日界线在右侧
|
||||||
|
leftWidth = Math.pow(2, zoom) * 256 / 360 * (center.lng - NE.lng);
|
||||||
|
rightWidth = width - leftWidth;
|
||||||
|
} else {
|
||||||
|
rightWidth = Math.pow(2, zoom) * 256 / 360 * (SW.lng - center.lng);
|
||||||
|
leftWidth = width - rightWidth;
|
||||||
|
}
|
||||||
|
} else { // 不跨日界线
|
||||||
|
leftWidth = Math.pow(2, zoom) * 256 / 360 * (center.lng - SW.lng);
|
||||||
|
rightWidth = Math.pow(2, zoom) * 256 / 360 * (NE.lng - center.lng);
|
||||||
|
}
|
||||||
|
const pixelBounds = new Bounds(centerPoint.subtract(leftWidth, topHeight), centerPoint.add(rightWidth, bottomHeight));
|
||||||
|
return pixelBounds;
|
||||||
|
}
|
||||||
|
_pxBoundsToTileRange(pixelBounds) {
|
||||||
|
return new Bounds(
|
||||||
|
pixelBounds.min.divideBy(256).floor(),
|
||||||
|
pixelBounds.max.divideBy(256).ceil().subtract([ 1, 1 ])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
_wrapCoords(coords) {
|
||||||
|
const wrapX = [ 0, Math.pow(2, coords[2]) ];
|
||||||
|
const newX = wrapNum(coords[0], wrapX);
|
||||||
|
return [ newX, coords[1], coords[2] ];
|
||||||
|
}
|
||||||
_destroyTile(tile) {
|
_destroyTile(tile) {
|
||||||
tile.destroy();
|
tile.destroy();
|
||||||
|
tile = null;
|
||||||
}
|
}
|
||||||
desttroy() {
|
destroy() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,132 @@
|
||||||
|
import Tile from './tile';
|
||||||
|
import { getArrayBuffer } from '../../util/ajax';
|
||||||
|
import { destoryObject, updateObjecteUniform } from '../../util/object3d-util';
|
||||||
|
import * as THREE from '../../core/three';
|
||||||
|
import MaskMaterial from '../../geom/material/tile/maskMaterial';
|
||||||
|
import { getRender } from '../render/index';
|
||||||
|
export default class VectorTile extends Tile {
|
||||||
|
requestTileAsync(done) {
|
||||||
|
// Making this asynchronous really speeds up the LOD framerate
|
||||||
|
setTimeout(() => {
|
||||||
|
if (!this._mesh) {
|
||||||
|
// this._mesh = this._createMesh();
|
||||||
|
this._requestTile(done);
|
||||||
|
}
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
_requestTile(done) {
|
||||||
|
const urlParams = {
|
||||||
|
x: this._tile[0],
|
||||||
|
y: this._tile[1],
|
||||||
|
z: this._tile[2]
|
||||||
|
};
|
||||||
|
|
||||||
|
const url = this._getTileURL(urlParams);
|
||||||
|
this.xhrRequest = getArrayBuffer({ url }, (err, data) => {
|
||||||
|
if (err) {
|
||||||
|
this._noData = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._isLoaded = true;
|
||||||
|
done(data.data);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
_creatSource(data) {
|
||||||
|
this.source = this.layer.tileSource(data, {
|
||||||
|
parser: {
|
||||||
|
tile: this._tile
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
_createMesh() {
|
||||||
|
if (this.layer.get('layerType') === 'point') {
|
||||||
|
this.layer.shape = this.layer._getShape(this.layerData);
|
||||||
|
}
|
||||||
|
this.mesh = getRender(this.layer.get('layerType'), this.layer.shape)(this.layerData, this.layer);
|
||||||
|
if (this.mesh.type !== 'composer') { // 热力图的情况
|
||||||
|
this.mesh.onBeforeRender = renderer => {
|
||||||
|
this._renderMask(renderer);
|
||||||
|
};
|
||||||
|
this.mesh.onAfterRender = renderer => {
|
||||||
|
const context = renderer.context;
|
||||||
|
context.disable(context.STENCIL_TEST);
|
||||||
|
};
|
||||||
|
this._object3D.add(this.mesh);
|
||||||
|
} else {
|
||||||
|
this._object3D = this.mesh;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.emit('tileLoaded');
|
||||||
|
return this._object3D;
|
||||||
|
}
|
||||||
|
_renderMask(renderer) {
|
||||||
|
const zoom = this.layer.scene.getZoom();
|
||||||
|
updateObjecteUniform(this.mesh, {
|
||||||
|
u_time: this.layer.scene._engine.clock.getElapsedTime(),
|
||||||
|
u_zoom: zoom
|
||||||
|
});
|
||||||
|
if (this.layer.get('layerType') === 'point') { // 点图层目前不需要mask
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const maskScene = new THREE.Scene();
|
||||||
|
this.maskScene = maskScene;
|
||||||
|
const tileMesh = this._tileMaskMesh();
|
||||||
|
maskScene.add(tileMesh);
|
||||||
|
const context = renderer.context;
|
||||||
|
renderer.autoClear = false;
|
||||||
|
renderer.clearDepth();
|
||||||
|
context.enable(context.STENCIL_TEST);
|
||||||
|
context.stencilOp(context.REPLACE, context.REPLACE, context.REPLACE);
|
||||||
|
context.stencilFunc(context.ALWAYS, 1, 0xffffffff);
|
||||||
|
context.clearStencil(0);
|
||||||
|
context.clear(context.STENCIL_BUFFER_BIT);
|
||||||
|
context.colorMask(false, false, false, false);
|
||||||
|
|
||||||
|
// config the stencil buffer to collect data for testing
|
||||||
|
this.layer.scene._engine.renderScene(maskScene);
|
||||||
|
context.colorMask(true, true, true, true);
|
||||||
|
context.depthMask(true);
|
||||||
|
renderer.clearDepth();
|
||||||
|
|
||||||
|
// only render where stencil is set to 1
|
||||||
|
|
||||||
|
context.stencilFunc(context.EQUAL, 1, 0xffffffff); // draw if == 1
|
||||||
|
context.stencilOp(context.KEEP, context.KEEP, context.KEEP);
|
||||||
|
}
|
||||||
|
_tileMaskMesh() {
|
||||||
|
const tilebound = this._tileBounds;
|
||||||
|
const bl = [ tilebound.getBottomLeft().x, tilebound.getBottomLeft().y, 0 ];
|
||||||
|
const br = [ tilebound.getBottomRight().x, tilebound.getBottomRight().y, 0 ];
|
||||||
|
const tl = [ tilebound.getTopLeft().x, tilebound.getTopLeft().y, 0 ];
|
||||||
|
const tr = [ tilebound.getTopRight().x, tilebound.getTopRight().y, 0 ];
|
||||||
|
const positions = [ ...bl, ...tr, ...br, ...bl, ...tl, ...tr ];
|
||||||
|
const geometry = new THREE.BufferGeometry();
|
||||||
|
geometry.addAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
|
||||||
|
const maskMaterial = new MaskMaterial();
|
||||||
|
const maskMesh = new THREE.Mesh(geometry, maskMaterial);
|
||||||
|
return maskMesh;
|
||||||
|
}
|
||||||
|
_abortRequest() {
|
||||||
|
if (!this.xhrRequest) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.xhrRequest.abort();
|
||||||
|
}
|
||||||
|
getSelectFeature(id) {
|
||||||
|
const featureIndex = this.source.originData.featureKeys[id];
|
||||||
|
if (featureIndex) {
|
||||||
|
return this.source.originData.dataArray[featureIndex];
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
destroy() {
|
||||||
|
super.destroy();
|
||||||
|
destoryObject(this.maskScene);
|
||||||
|
this._object3D = null;
|
||||||
|
this.maskScene = null;
|
||||||
|
this.layerData = null;
|
||||||
|
this.source.destroy();
|
||||||
|
this.source = null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,6 +5,7 @@ import image from './parser/image';
|
||||||
import csv from './parser/csv';
|
import csv from './parser/csv';
|
||||||
import json from './parser/json';
|
import json from './parser/json';
|
||||||
import raster from './parser/raster';
|
import raster from './parser/raster';
|
||||||
|
import mvt from './parser/mvt';
|
||||||
|
|
||||||
import { registerTransform, registerParser } from './factory';
|
import { registerTransform, registerParser } from './factory';
|
||||||
import { aggregatorToGrid } from './transform/grid';
|
import { aggregatorToGrid } from './transform/grid';
|
||||||
|
@ -16,6 +17,7 @@ registerParser('image', image);
|
||||||
registerParser('csv', csv);
|
registerParser('csv', csv);
|
||||||
registerParser('json', json);
|
registerParser('json', json);
|
||||||
registerParser('raster', raster);
|
registerParser('raster', raster);
|
||||||
|
registerParser('mvt', mvt);
|
||||||
// 注册transform
|
// 注册transform
|
||||||
|
|
||||||
registerTransform('grid', aggregatorToGrid);
|
registerTransform('grid', aggregatorToGrid);
|
||||||
|
|
|
@ -1,23 +1,35 @@
|
||||||
import * as turfMeta from '@turf/meta';
|
import * as turfMeta from '@turf/meta';
|
||||||
import { getCoords } from '@turf/invariant';
|
import { getCoords } from '@turf/invariant';
|
||||||
|
import { BKDRHash } from '../../util/bkdr-hash';
|
||||||
export default function geoJSON(data) {
|
export default function geoJSON(data, cfg) {
|
||||||
const resultData = [];
|
const resultData = [];
|
||||||
|
const featureKeys = {};
|
||||||
data.features = data.features.filter(item => {
|
data.features = data.features.filter(item => {
|
||||||
return item != null && item.geometry && item.geometry.type && item.geometry.coordinates && item.geometry.coordinates.length > 0;
|
return item != null && item.geometry && item.geometry.type && item.geometry.coordinates && item.geometry.coordinates.length > 0;
|
||||||
});
|
});
|
||||||
|
|
||||||
// 数据为空时处理
|
// 数据为空时处理
|
||||||
turfMeta.flattenEach(data, (currentFeature, featureIndex) => { // 多个polygon 拆成一个
|
turfMeta.flattenEach(data, (currentFeature, featureIndex) => { // 多个polygon 拆成一个
|
||||||
const coord = getCoords(currentFeature);
|
const coord = getCoords(currentFeature);
|
||||||
|
let id = featureIndex + 1;
|
||||||
|
if (cfg.idField && currentFeature.properties[cfg.idField]) {
|
||||||
|
const value = currentFeature.properties[cfg.idField];
|
||||||
|
// id = value;
|
||||||
|
id = BKDRHash(value) % 1000019;
|
||||||
|
// if (featureKeys[id] && featureIndex !== featureKeys[id]) {
|
||||||
|
// // TODO 哈希冲突解决方法
|
||||||
|
// console.log('哈希冲突', value);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
featureKeys[id] = featureIndex;
|
||||||
const dataItem = {
|
const dataItem = {
|
||||||
...currentFeature.properties,
|
...currentFeature.properties,
|
||||||
coordinates: coord,
|
coordinates: coord,
|
||||||
_id: featureIndex + 1
|
_id: id
|
||||||
};
|
};
|
||||||
resultData.push(dataItem);
|
resultData.push(dataItem);
|
||||||
});
|
});
|
||||||
return {
|
return {
|
||||||
dataArray: resultData
|
dataArray: resultData,
|
||||||
|
featureKeys
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
import PBF from 'pbf';
|
||||||
|
import * as VectorParser from '@mapbox/vector-tile';
|
||||||
|
import geojson from './geojson';
|
||||||
|
export default function mvt(data, cfg) {
|
||||||
|
const tile = new VectorParser.VectorTile(new PBF(data));
|
||||||
|
// CHN_Cities_L CHN_Cities CHN_L
|
||||||
|
const layerName = cfg.sourceLayer;
|
||||||
|
const features = [];
|
||||||
|
const vectorLayer = tile.layers[layerName];
|
||||||
|
for (let i = 0; i < vectorLayer.length; i++) {
|
||||||
|
const feature = vectorLayer.feature(i);
|
||||||
|
features.push(feature.toGeoJSON(cfg.tile[0], cfg.tile[1], cfg.tile[2]));
|
||||||
|
}
|
||||||
|
const geodata = {
|
||||||
|
type: 'FeatureCollection',
|
||||||
|
features
|
||||||
|
};
|
||||||
|
return geojson(geodata, cfg);
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
export function BKDRHash(str) {
|
||||||
|
const seed = 131;
|
||||||
|
const seed2 = 137;
|
||||||
|
let hash = 0;
|
||||||
|
// make hash more sensitive for short string like 'a', 'b', 'c'
|
||||||
|
str += 'x';
|
||||||
|
// Note: Number.MAX_SAFE_INTEGER equals 9007199254740991
|
||||||
|
const MAX_SAFE_INTEGER = parseInt(9007199254740991 / seed2);
|
||||||
|
for (let i = 0; i < str.length; i++) {
|
||||||
|
if (hash > MAX_SAFE_INTEGER) {
|
||||||
|
hash = parseInt(hash / seed2);
|
||||||
|
}
|
||||||
|
hash = hash * seed + str.charCodeAt(i);
|
||||||
|
}
|
||||||
|
return hash;
|
||||||
|
}
|
|
@ -48,10 +48,10 @@ export default class LRUCache {
|
||||||
|
|
||||||
delete(key) {
|
delete(key) {
|
||||||
const value = this._cache[key];
|
const value = this._cache[key];
|
||||||
this.destroy(value);
|
|
||||||
if (value) {
|
if (value) {
|
||||||
this._deleteCache(key);
|
this._deleteCache(key);
|
||||||
this._deleteOrder(key);
|
this._deleteOrder(key);
|
||||||
|
this.destroy(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
import pickingFragmentShader from '../core/engine/picking/picking_frag.glsl';
|
||||||
|
import * as THREE from '../core/three';
|
||||||
|
export function destoryObject(obj) {
|
||||||
|
if (!obj) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (obj.children) {
|
||||||
|
for (let i = 0; i < obj.children.length; i++) {
|
||||||
|
const child = obj.children[i];
|
||||||
|
destoryObject(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (obj.geometry) {
|
||||||
|
obj.geometry.dispose();
|
||||||
|
obj.geometry = null;
|
||||||
|
}
|
||||||
|
if (obj.material) {
|
||||||
|
if (obj.material.map) {
|
||||||
|
obj.material.map.dispose();
|
||||||
|
obj.material.map = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj.material.dispose();
|
||||||
|
obj.material = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export function updateObjecteUniform(obj, newOption) {
|
||||||
|
if (!obj) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (obj.children) {
|
||||||
|
for (let i = 0; i < obj.children.length; i++) {
|
||||||
|
const child = obj.children[i];
|
||||||
|
updateObjecteUniform(child, newOption);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (obj.material) {
|
||||||
|
obj.material.updateUninform(newOption);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export function getPickObject(obj, newbj) {
|
||||||
|
if (!obj) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (obj.isMesh) {
|
||||||
|
const pickmaterial = obj.material.clone();
|
||||||
|
pickmaterial.fragmentShader = pickingFragmentShader;
|
||||||
|
const pickMesh = new THREE[obj.type](obj.geometry, pickmaterial);
|
||||||
|
newbj.add(pickMesh);
|
||||||
|
}
|
||||||
|
if (obj.children) {
|
||||||
|
const newObj = new THREE.Object3D();
|
||||||
|
for (let i = 0; i < obj.children.length; i++) {
|
||||||
|
const child = obj.children[i];
|
||||||
|
newObj.add(getPickObject(child, newbj));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue