gisviewer-vue3-arcgis
Version:
在应用中引入私服的包, 项目根目录下 新建文件 .npmrc 在 .npmrc 中对包源进行配置:
123 lines (122 loc) • 3.68 kB
JavaScript
const d = {
clusterRadius: 120,
minClusterPoints: 2,
maxClusterSymbolSize: 40,
minClusterSymbolSize: 20
};
class m {
constructor(s, e) {
this.clusteredLocations = [], this.map = s, this.options = { ...d, ...e };
}
/**
* 计算聚合结果
* @param locations 原始点位数组
* @returns 聚合结果
*/
calculate(s) {
return this.locationToScreen(s), this.doPixelCluster(this.options.clusterRadius);
}
/**
* 计算聚合符号大小
* @param clusters 聚合结果
* @returns 带有符号大小信息的聚合结果
*/
calculateSymbolSizes(s) {
let e = Number.MIN_VALUE, i = Number.MAX_VALUE;
return s.forEach((t) => {
t.count > 1 && (i = Math.min(i, t.count), e = Math.max(e, t.count));
}), s.map((t) => {
if (t.id !== -1 && t.center) {
let r = i === e ? (this.options.maxClusterSymbolSize + this.options.minClusterSymbolSize) / 2 : this.options.minClusterSymbolSize + (t.count - i) / (e - i) * (this.options.maxClusterSymbolSize - this.options.minClusterSymbolSize);
return r *= 0.75, { ...t, symbolSize: r };
}
return t;
});
}
/**
* 更新配置
*/
updateOptions(s) {
this.options = { ...this.options, ...s };
}
/**
* 获取当前配置
*/
getOptions() {
return { ...this.options };
}
/**
* 将地理坐标转换为屏幕坐标
*/
locationToScreen(s) {
this.clusteredLocations = [], s.forEach((e) => {
const i = this.map.getPixelFromCoordinate([e.x, e.y]), [t, r] = i || [NaN, NaN];
Number.isFinite(t) && Number.isFinite(r) && t > 0 && r > 0 && (e.properties = e.properties || {}, e.properties.screenX = t, e.properties.screenY = r, e.visited = !1, e.clusterId = void 0, this.clusteredLocations.push(e));
});
}
/**
* 基于像素距离的聚合算法
*/
doPixelCluster(s) {
let e = 0;
for (let i = 0; i < this.clusteredLocations.length; i++) {
const t = this.clusteredLocations[i];
if (t.visited)
continue;
t.visited = !0;
const r = this.getNeighbors(t, s);
r.length < this.options.minClusterPoints ? t.clusterId = -1 : (r.forEach((o) => {
o.visited = !0, o.clusterId = e;
}), t.clusterId = e, e++);
}
return this.createClusters();
}
/**
* 获取指定点的邻近点
*/
getNeighbors(s, e) {
return this.clusteredLocations.filter((i) => i.id === s.id || i.visited ? !1 : this.getDistance(s, i) <= e);
}
/**
* 计算两点之间的屏幕距离
*/
getDistance(s, e) {
var i, t, r, o;
return Math.sqrt(
Math.pow(
(((i = s.properties) == null ? void 0 : i.screenX) ?? 0) - (((t = e.properties) == null ? void 0 : t.screenX) ?? 0),
2
) + Math.pow(
(((r = s.properties) == null ? void 0 : r.screenY) ?? 0) - (((o = e.properties) == null ? void 0 : o.screenY) ?? 0),
2
)
);
}
/**
* 根据聚合结果创建聚合对象
*/
createClusters() {
const s = {}, e = [];
for (const t of this.clusteredLocations)
t.clusterId === void 0 || t.clusterId === -1 ? e.push(t) : (s[t.clusterId] || (s[t.clusterId] = []), s[t.clusterId].push(t));
const i = Object.keys(s).map((t) => {
const r = s[Number(t)], o = r.length, c = r.reduce((n, u) => n + u.x, 0), l = r.reduce((n, u) => n + u.y, 0), h = c / o, p = l / o;
return {
id: Number(t),
items: r,
count: o,
center: { x: h, y: p }
};
});
return e.length > 0 && i.push({
id: -1,
items: e,
count: e.length,
center: null
}), i;
}
}
export {
m as PixelClusterCalculator,
m as default
};