gisviewer-vue3-arcgis
Version:
在应用中引入私服的包, 项目根目录下 新建文件 .npmrc 在 .npmrc 中对包源进行配置:
293 lines (292 loc) • 10.3 kB
JavaScript
import { Point as c } from "@arcgis/core/geometry";
import y from "@arcgis/core/Graphic";
import C from "@arcgis/core/layers/GraphicsLayer";
class S {
constructor(e) {
this.maxClusterSymbolSize = 50, this.minClusterSymbolSize = 25, this.clusterRadius = 120, this.minClusterPoints = 2, this.zoomWatchHandle = null, this.countBackgroundColor = [2, 72, 200], this.countFontColor = [255, 255, 255], this.locations = [], this.clusteredLocations = [], this.clusterMarkUrl = "", this.currentStyle = "cluster", this.view = e, this.clusterLayer = new C(), this.view.map.add(this.clusterLayer);
}
/**
* 将地理位置转换为屏幕坐标
*/
locationToScreen() {
this.clusteredLocations = [], this.locations.forEach((e) => {
const s = this.view.toScreen(
new c({ x: e.x, y: e.y })
);
s.x > 0 && s.y > 0 && (e.properties.screenX = s.x, e.properties.screenY = s.y, e.visited = !1, e.clusterId = void 0, this.clusteredLocations.push(e));
});
}
/**
* 添加聚类点到视图
* @param params
*/
addClusterPoints(e) {
var r;
this.locations = e.points, e.countBackgroundColor && (this.countBackgroundColor = e.countBackgroundColor), e.countFontColor && (this.countFontColor = e.countFontColor), this.scaleThreshold = e.scaleThreshold, this.clusterMarkUrl = ((r = e.clusterSymbol) == null ? void 0 : r.url) || "/GisViewerAssets/Images/cross/gis_xhj_blue.png", this.locations = this.locations.filter((t) => t.x !== null && t.y !== null && !isNaN(t.x) && !isNaN(t.y)), this.locations.forEach((t) => {
t.x = Number(t.x), t.y = Number(t.y), t.symbol || (t.symbol = e.pointSymbol || {
type: "simple-marker",
style: "circle",
color: "#3388ff",
size: 8,
outline: {
color: "#ffffff",
width: 1
}
});
}), this.zoomWatchHandle || (this.zoomWatchHandle = this.view.watch("stationary", () => {
if (this.view.stationary)
if (this.scaleThreshold) {
if (this.view.scale < this.scaleThreshold && this.currentStyle === "cluster")
this.currentStyle = "normal", this.clusterLayer.removeAll(), this.locations.forEach((t) => {
const i = new y({
geometry: new c({ x: t.x, y: t.y }),
attributes: {
...t,
...t.properties,
type: "clusterPoint",
id: t.id
},
symbol: t.symbol
});
this.clusterLayer.add(i);
});
else if (this.view.scale > this.scaleThreshold) {
this.currentStyle = "cluster", this.locationToScreen();
const t = this.doPixelCluster(
this.clusterRadius,
this.minClusterPoints
);
this.showClusters(t);
}
} else {
this.locationToScreen();
const t = this.doPixelCluster(
this.clusterRadius,
this.minClusterPoints
);
this.showClusters(t);
}
})), this.locationToScreen();
const s = this.doPixelCluster(
this.clusterRadius,
this.minClusterPoints
);
this.showClusters(s);
}
removeAllClusterPoints() {
var e;
(e = this.zoomWatchHandle) == null || e.remove(), this.zoomWatchHandle = null, this.clusterLayer.removeAll();
}
showClusters(e) {
this.clusterLayer.removeAll();
let s = Number.MIN_VALUE, r = Number.MAX_VALUE;
e.forEach((t) => {
t.count > 1 && (r = Math.min(r, t.count), s = Math.max(s, t.count));
}), e.forEach((t) => {
if (t.id !== -1) {
let i = r === s ? (this.maxClusterSymbolSize + this.minClusterSymbolSize) / 2 : this.minClusterSymbolSize + (t.count - r) / (s - r) * (this.maxClusterSymbolSize - this.minClusterSymbolSize);
i *= 0.75;
const n = (t.count.toString().length * 8 + 6) / 2, u = new y({
geometry: new c({ x: t.center.x, y: t.center.y }),
attributes: {
count: t.count
},
symbol: {
type: "cim",
data: {
type: "CIMSymbolReference",
primitiveOverrides: [
{
// 将textGraphic的TextString替换为graphic.attributes.name
type: "CIMPrimitiveOverride",
primitiveName: "textGraphic",
propertyName: "TextString",
valueExpressionInfo: {
type: "CIMExpressionInfo",
title: "Custom",
expression: "$feature.count",
returnType: "Default"
}
}
],
symbol: {
type: "CIMPointSymbol",
symbolLayers: [
// 聚合数量
{
type: "CIMVectorMarker",
size: i,
colorLocked: !0,
anchorPointUnits: "Relative",
frame: { xmin: -16, ymin: -16, xmax: 16, ymax: 16 },
markerGraphics: [
// 数量文本框
{
type: "CIMMarkerGraphic",
geometry: {
rings: [
[
[-n, 40],
[n, 40],
[n, 20],
[-n, 20],
[-n, 40]
]
]
},
symbol: {
type: "CIMPolygonSymbol",
symbolLayers: [
{
type: "CIMSolidFill",
enable: !0,
color: [...this.countBackgroundColor, 255]
},
{
type: "CIMSolidStroke",
enable: !0,
width: 5,
color: [...this.countBackgroundColor, 128]
}
]
}
},
// 数量文字
{
type: "CIMMarkerGraphic",
primitiveName: "textGraphic",
geometry: { x: 0, y: 0 },
symbol: {
type: "CIMTextSymbol",
height: 16,
horizontalAlignment: "Center",
offsetX: 0,
offsetY: 30,
symbol: {
type: "CIMPolygonSymbol",
symbolLayers: [
{
type: "CIMSolidFill",
enable: !0,
color: [...this.countFontColor, 255]
}
]
},
verticalAlignment: "Center"
},
textString: ""
}
],
scaleSymbolsProportionally: !0,
respectFrame: !0
},
// 聚合图标
{
type: "CIMPictureMarker",
enable: !0,
anchorPoint: {
x: 0,
y: 0
},
anchorPointUnits: "Relative",
size: i,
rotateClockwise: !0,
textureFilter: "Picture",
url: this.clusterMarkUrl
}
]
}
}
}
});
this.clusterLayer.add(u);
} else
t.items.forEach((i) => {
const o = new y({
geometry: new c({ x: i.x, y: i.y }),
attributes: {
...i,
...i.properties,
type: "clusterPoint",
id: i.id
},
symbol: i.symbol
});
this.clusterLayer.add(o);
});
});
}
/**
* 获取邻居点
* @param locations
* @param index
* @param eps
* @returns
*/
getNeighbors(e, s) {
return this.clusteredLocations.filter((r) => r.id === e.id || r.visited ? !1 : this.getDistance(e, r) <= s);
}
/**
* 两点间的像素距离
* @param point1
* @param point2
* @returns
*/
getDistance(e, s) {
return Math.sqrt(
Math.pow(e.properties.screenX - s.properties.screenX, 2) + Math.pow(e.properties.screenY - s.properties.screenY, 2)
);
}
/**
* 从聚类结果中创建聚类对象
* @param locations
* @returns
*/
createClusters() {
const e = {}, s = [];
for (const t of this.clusteredLocations)
t.clusterId === void 0 || t.clusterId === -1 ? s.push(t) : (e[t.clusterId] || (e[t.clusterId] = []), e[t.clusterId].push(t));
const r = Object.keys(e).map((t, i) => {
const o = e[Number(t)], l = o.length, n = o.reduce((h, a) => h + a.x, 0), u = o.reduce((h, a) => h + a.y, 0), m = n / l, d = u / l;
return {
id: Number(t),
items: o,
count: l,
center: {
x: m,
y: d
}
};
});
return s.length > 0 && r.push({
id: -1,
items: s,
count: s.length,
center: null
}), r;
}
/**
* 按照像素距离聚类
* @param locations
* @param eps
* @param minPoints
* @returns
*/
doPixelCluster(e, s) {
let r = 0;
for (let t = 0; t < this.clusteredLocations.length; t++) {
const i = this.clusteredLocations[t];
if (i.visited)
continue;
i.visited = !0;
const o = this.getNeighbors(i, e);
o.length < s ? i.clusterId = -1 : (o.forEach((l) => {
l.visited = !0, l.clusterId = r;
}), i.clusterId = r, r++);
}
return this.createClusters();
}
}
export {
S as default
};