gisviewer-vue3-arcgis
Version:
在应用中引入私服的包, 项目根目录下 新建文件 .npmrc 在 .npmrc 中对包源进行配置:
594 lines (593 loc) • 19.2 kB
JavaScript
import { Point as h } from "@arcgis/core/geometry";
import u from "@arcgis/core/Graphic";
import p from "@arcgis/core/layers/GraphicsLayer";
class x {
constructor(e) {
this.crossGraphicSymbol = {
type: "cim",
data: {
type: "CIMSymbolReference",
primitiveOverrides: [
{
type: "CIMPrimitiveOverride",
primitiveName: "textGraphic",
propertyName: "TextString",
valueExpressionInfo: {
type: "CIMExpressionInfo",
title: "Custom",
expression: 'Replace($feature.name, "与", "/") + " " + $feature.signalId',
returnType: "Default"
}
}
],
symbol: {
type: "CIMPointSymbol",
symbolLayers: [
{
type: "CIMVectorMarker",
size: 32,
colorLocked: !0,
anchorPointUnits: "Relative",
frame: { xmin: -16, ymin: -16, xmax: 16, ymax: 16 },
markerGraphics: [
{
type: "CIMMarkerGraphic",
primitiveName: "textGraphic",
geometry: { x: 0, y: 0 },
symbol: {
type: "CIMTextSymbol",
height: 12,
horizontalAlignment: "Center",
offsetX: 0,
offsetY: 18,
haloSize: 1,
haloSymbol: {
type: "CIMPolygonSymbol",
symbolLayers: [
{
type: "CIMSolidFill",
enable: !0,
color: [255, 255, 255, 255]
}
]
},
symbol: {
type: "CIMPolygonSymbol",
symbolLayers: [
{
type: "CIMSolidFill",
enable: !0,
color: [0, 0, 0, 255]
}
]
},
verticalAlignment: "Center"
},
textString: ""
}
],
scaleSymbolsProportionally: !0,
respectFrame: !0
},
{
type: "CIMPictureMarker",
enable: !0,
anchorPoint: {
x: 0,
y: 0
},
anchorPointUnits: "Relative",
size: 20,
rotateClockwise: !0,
textureFilter: "Picture",
url: "/GisViewerAssets/Images/cross/gis_xhj_blue.png"
}
]
}
}
}, this.locations = [], this.clusteredLocations = [], this.filteredLocations = [], this.currentShowMode = "scatter", this.symbolScale = 5e3, this.oldScale = 0, this.clusterRadius = 120, this.minClusterPoints = 2, this.maxClusterSymbolSize = 50, this.minClusterSymbolSize = 25, this.view = e, this.crossLayer = new p(), this.view.map.add(this.crossLayer), this.oldScale = e.scale;
}
async addCrosses(e) {
e.forEach((t) => {
t.signals.forEach((i) => {
i.longitude && i.latitude && !isNaN(i.longitude) && !isNaN(i.latitude) && this.locations.push({
id: i.id,
x: i.longitude,
y: i.latitude,
visited: !1,
filtered: !1,
clusterId: void 0,
properties: {
...i,
districtId: t.id,
districtName: t.name,
subDistrictId: "",
subDistrictName: ""
}
});
}), t.subDistricts.forEach((i) => {
i.signals.forEach((s) => {
s.longitude && s.latitude && !isNaN(s.longitude) && !isNaN(s.latitude) && this.locations.push({
id: s.id,
x: s.longitude,
y: s.latitude,
visited: !1,
filtered: !1,
clusterId: void 0,
properties: {
...s,
districtId: t.id,
districtName: t.name,
subDistrictId: i.id,
subDistrictName: i.name
}
});
});
});
}), this.zoomWatchHandle = this.view.watch("stationary", () => {
if (this.view.stationary !== !1) {
if (this.currentShowMode === "scatter")
(this.oldScale < this.symbolScale && this.view.scale >= this.symbolScale || this.oldScale >= this.symbolScale && this.view.scale < this.symbolScale) && this.updateScatterSymbol(), this.oldScale = this.view.scale;
else if (this.currentShowMode === "cluster") {
this.locationToScreen(), console.time("cluster");
const t = this.doPixelCluster(this.clusterRadius);
console.timeEnd("cluster"), this.showClusterResult(t);
}
}
});
}
/**
* 清除所有路口
*/
clearCrosses() {
var e;
this.crossLayer.removeAll(), this.locations = [], this.clusteredLocations = [], (e = this.zoomWatchHandle) == null || e.remove();
}
/**
* 更新散点符号
*/
updateScatterSymbol() {
this.crossLayer.graphics.forEach((e) => {
e.symbol = this.getCrossSymbol(e.attributes);
});
}
/**
* 将地理位置转换为屏幕坐标
*/
locationToScreen() {
this.clusteredLocations = [], this.locations.forEach((e) => {
const t = this.view.toScreen(
new h({ x: e.x, y: e.y })
);
e.filtered === !1 && t.x > 0 && t.y > 0 && (e.properties.screenX = t.x, e.properties.screenY = t.y, e.visited = !1, e.clusterId = void 0, this.clusteredLocations.push(e));
});
}
/**
* 显示聚合点
*/
showCluster() {
this.crossLayer.removeAll(), this.currentShowMode = "cluster", this.locationToScreen();
const e = this.doPixelCluster(this.clusterRadius);
this.showClusterResult(e);
}
/**
* 显示散点
*/
showScatter() {
this.crossLayer.removeAll(), this.currentShowMode = "scatter";
const e = [];
this.locations.forEach((t) => {
if (!t.filtered) {
const i = new u({
geometry: {
type: "point",
longitude: t.x,
latitude: t.y
},
symbol: this.getCrossSymbol(t.properties),
attributes: t.properties,
popupTemplate: {
title: "{name}信号机",
content: [
{
type: "fields",
fieldInfos: [
{
fieldName: "signalId",
label: "信号机编号"
},
{
fieldName: "nodeId",
label: "路口编号"
},
{
fieldName: "districtName",
label: "区控名称"
},
{
fieldName: "subDistrictName",
label: "子区名称"
}
]
}
]
}
});
e.push(i);
}
}), this.crossLayer.addMany(e);
}
/**
* 隐藏路口
*/
hideCrosses() {
this.crossLayer.removeAll();
}
filter(e) {
this.locations.forEach((t) => {
if (e.type === "district")
t.filtered = t.properties.districtId !== e.id;
else if (e.type === "subDistrict")
t.filtered = t.properties.subDistrictId !== e.id;
else if (e.type === "signal" && (t.filtered = t.id !== e.id, t.filtered))
return t.properties;
});
}
resetFilter() {
this.locations.forEach((e) => {
e.filtered = !1;
}), this.currentShowMode === "scatter" ? this.showScatter() : this.currentShowMode === "cluster" && this.showCluster();
}
/**
* 根据当前比例尺更新路口符号
* @param attributes
* @returns
*/
getCrossSymbol(e) {
if (this.view.scale > this.symbolScale)
return e.isKey ? {
// 关键路口用星号图标
type: "picture-marker",
url: "/GisViewerAssets/Images/icon_star.png",
width: "20px",
height: "20px"
} : {
// 普通路口用圆点
type: "simple-marker",
style: "circle",
color: [5, 116, 255, 0.8],
size: 8,
outline: {
color: "white",
width: 0
}
};
{
const t = e.isKey ? "/GisViewerAssets/Images/cross/gis_gjxklk_orange.png" : "/GisViewerAssets/Images/cross/gis_xhj_blue.png";
return {
type: "cim",
data: {
type: "CIMSymbolReference",
primitiveOverrides: [
{
// 将textGraphic的TextString替换为graphic.attributes.name
type: "CIMPrimitiveOverride",
primitiveName: "textGraphic",
propertyName: "TextString",
valueExpressionInfo: {
type: "CIMExpressionInfo",
title: "Custom",
expression: 'Replace($feature.name, "与", "/") + " " + $feature.signalId',
returnType: "Default"
}
}
],
symbol: {
type: "CIMPointSymbol",
symbolLayers: [
// 路口名称
{
type: "CIMVectorMarker",
size: 32,
colorLocked: !0,
anchorPointUnits: "Relative",
frame: { xmin: -16, ymin: -16, xmax: 16, ymax: 16 },
markerGraphics: [
{
type: "CIMMarkerGraphic",
primitiveName: "textGraphic",
geometry: { x: 0, y: 0 },
symbol: {
type: "CIMTextSymbol",
height: 12,
horizontalAlignment: "Center",
offsetX: 0,
offsetY: 20,
haloSize: 1,
haloSymbol: {
type: "CIMPolygonSymbol",
symbolLayers: [
{
type: "CIMSolidFill",
enable: !0,
color: [255, 255, 255, 255]
}
]
},
symbol: {
type: "CIMPolygonSymbol",
symbolLayers: [
{
type: "CIMSolidFill",
enable: !0,
color: [0, 0, 0, 255]
}
]
},
verticalAlignment: "Center"
},
textString: ""
}
],
scaleSymbolsProportionally: !0,
respectFrame: !0
},
// 路口图标
{
type: "CIMPictureMarker",
enable: !0,
anchorPoint: {
x: 0,
y: 0
},
anchorPointUnits: "Relative",
size: 20,
rotateClockwise: !0,
textureFilter: "Picture",
url: t
}
]
}
}
};
}
}
/**
* 获取邻居点
* @param locations
* @param index
* @param eps
* @returns
*/
getNeighbors(e, t) {
return this.clusteredLocations.filter((i) => i.id === e.id || i.visited ? !1 : this.getDistance(e, i) <= t);
}
/**
* 两点间的像素距离
* @param point1
* @param point2
* @returns
*/
getDistance(e, t) {
return Math.sqrt(
Math.pow(e.properties.screenX - t.properties.screenX, 2) + Math.pow(e.properties.screenY - t.properties.screenY, 2)
);
}
/**
* 从聚类结果中创建聚类对象
* @param locations
* @returns
*/
createClusters() {
const e = {}, t = [];
for (const s of this.clusteredLocations)
s.clusterId === void 0 || s.clusterId === -1 ? t.push(s) : (e[s.clusterId] || (e[s.clusterId] = []), e[s.clusterId].push(s));
const i = Object.keys(e).map((s, r) => {
const o = e[Number(s)], a = o.length, l = o.reduce((n, m) => n + m.x, 0), c = o.reduce((n, m) => n + m.y, 0), y = l / a, d = c / a;
return {
id: Number(s),
items: o,
count: a,
center: {
x: y,
y: d
}
};
});
return t.length > 0 && i.push({
id: -1,
items: t,
count: t.length,
center: null
}), i;
}
/**
* 按照像素距离聚类
* @param locations
* @param eps
* @param minPoints
* @returns
*/
doPixelCluster(e) {
let t = 0;
for (let i = 0; i < this.clusteredLocations.length; i++) {
const s = this.clusteredLocations[i];
if (s.visited)
continue;
s.visited = !0;
const r = this.getNeighbors(s, e);
r.length < this.minClusterPoints ? s.clusterId = -1 : (r.forEach((o) => {
o.visited = !0, o.clusterId = t;
}), s.clusterId = t, t++);
}
return this.createClusters();
}
showClusterResult(e) {
this.crossLayer.removeAll();
let t = Number.MIN_VALUE, i = Number.MAX_VALUE;
e.forEach((s) => {
s.count > 1 && (i = Math.min(i, s.count), t = Math.max(t, s.count));
}), e.forEach((s) => {
if (s.id !== -1) {
let r = i === t ? (this.maxClusterSymbolSize + this.minClusterSymbolSize) / 2 : this.minClusterSymbolSize + (s.count - i) / (t - i) * (this.maxClusterSymbolSize - this.minClusterSymbolSize);
r *= 0.75;
const l = (s.count.toString().length * 8 + 6) / 2, c = new u({
geometry: new h({ x: s.center.x, y: s.center.y }),
attributes: {
count: s.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: r,
colorLocked: !0,
anchorPointUnits: "Relative",
frame: { xmin: -16, ymin: -16, xmax: 16, ymax: 16 },
markerGraphics: [
// 数量文本框
{
type: "CIMMarkerGraphic",
geometry: {
rings: [
[
[-l, 40],
[l, 40],
[l, 20],
[-l, 20],
[-l, 40]
]
]
},
symbol: {
type: "CIMPolygonSymbol",
symbolLayers: [
{
type: "CIMSolidFill",
enable: !0,
color: [2, 72, 200, 255]
},
{
type: "CIMSolidStroke",
enable: !0,
width: 5,
color: [2, 72, 200, 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: [255, 255, 255, 255]
}
]
},
verticalAlignment: "Center"
},
textString: ""
}
],
scaleSymbolsProportionally: !0,
respectFrame: !0
},
// 聚合图标
{
type: "CIMPictureMarker",
enable: !0,
anchorPoint: {
x: 0,
y: 0
},
anchorPointUnits: "Relative",
size: r,
rotateClockwise: !0,
textureFilter: "Picture",
url: "/GisViewerAssets/Images/cross/gis_xhj_blue.png"
}
]
}
}
}
});
this.crossLayer.add(c);
} else
s.items.forEach((r) => {
const o = new u({
geometry: new h({ x: r.x, y: r.y }),
attributes: {
...r,
...r.properties,
type: "clusterPoint",
id: r.id
},
symbol: this.crossGraphicSymbol,
popupTemplate: {
title: "{name}信号机",
content: [
{
type: "fields",
fieldInfos: [
{
fieldName: "signalId",
label: "信号机编号"
},
{
fieldName: "nodeId",
label: "路口编号"
},
{
fieldName: "districtName",
label: "区控名称"
},
{
fieldName: "subDistrictName",
label: "子区名称"
}
]
}
]
}
});
this.crossLayer.add(o);
});
});
}
}
export {
x as default
};