gisviewer-vue3-arcgis
Version:
在应用中引入私服的包, 项目根目录下 新建文件 .npmrc 在 .npmrc 中对包源进行配置:
424 lines (423 loc) • 14.7 kB
JavaScript
import { Point as u } from "@arcgis/core/geometry";
import y from "@arcgis/core/Graphic";
import p from "@arcgis/core/layers/GraphicsLayer";
class C {
constructor(t) {
this.iconSymbolScale = 1e4, this.largeMarkerScale = 4e4, this.oldScale = 0, this.showName = "detail", this.showStyle = "scatter", this.clusterRadius = 120, this.minClusterPoints = 2, this.maxClusterSymbolSize = 50, this.minClusterSymbolSize = 25, this.clusteredLocations = [], this.locations = [], this.view = t, this.crossLayer = new p({
id: "signal-control-cross-layer",
title: "信控路口图层"
}), this.view.map.add(this.crossLayer);
}
didCrossScaleThreshold(t, s, i) {
return t < i && s >= i || t >= i && s < i;
}
locationToScreen() {
this.clusteredLocations = [], this.locations.forEach((t) => {
const s = this.view.toScreen(
new u({ x: t.x, y: t.y })
);
s.x > 0 && s.y > 0 && (t.properties.screenX = s.x, t.properties.screenY = s.y, t.visited = !1, t.clusterId = void 0, this.clusteredLocations.push(t));
});
}
/**
* 显示信控路口
* @param params
* @returns
*/
showSignalCross(t) {
if (this.crossLayer.removeAll(), this.showName = t.showName || "detail", this.showStyle = t.style || "scatter", this.oldScale = this.view.scale, this.scaleWatchHandle || (this.scaleWatchHandle = this.view.watch("stationary", () => {
if (this.showStyle === "scatter") {
const s = this.view.scale, i = this.didCrossScaleThreshold(
this.oldScale,
s,
this.iconSymbolScale
), e = this.didCrossScaleThreshold(
this.oldScale,
s,
this.largeMarkerScale
);
(i || e) && this.updateScatterSymbol(), this.oldScale = s;
} else {
this.locationToScreen();
const s = this.doPixelCluster(this.clusterRadius);
this.showClusterResult(s);
}
})), this.showStyle === "scatter") {
const s = [], i = [];
t.points.forEach((e) => {
const r = this.getCrossSymbol(e), o = this.getBrandLabel(e.brand), a = this.getOnlineLabel(e.isOnline), l = this.getMalfunctionLabel(
e.isMalfunction
), n = new y({
geometry: {
type: "point",
longitude: e.x,
latitude: e.y
},
symbol: r,
attributes: {
type: "signal-cross",
id: e.crossId,
brandLabel: o,
isOnlineLabel: a,
isMalfunctionLabel: l,
...e
}
});
e.isMalfunction === !0 || e.isOnline === !1 ? i.push(n) : s.push(n);
}), this.crossLayer.addMany(s), this.crossLayer.addMany(i);
} else {
this.locations = t.points.map((i) => ({
id: i.crossId,
x: i.x,
y: i.y,
visited: !1,
clusterId: void 0,
properties: i
})), this.locationToScreen();
const s = this.doPixelCluster(this.clusterRadius);
this.showClusterResult(s);
}
return { status: 0, message: "ok" };
}
clearSignalCross() {
var t;
this.crossLayer.removeAll(), (t = this.scaleWatchHandle) == null || t.remove(), this.scaleWatchHandle = null;
}
/**
* 更改路口显示名称内容
* @param showName
*/
changeShowName(t) {
this.showName = t, this.showStyle === "scatter" && this.updateScatterSymbol();
}
/**
* 更新散点符号
*/
updateScatterSymbol() {
this.crossLayer.graphics.forEach((t) => {
t.symbol = this.getCrossSymbol(t.attributes);
});
}
/**
* 按照像素距离聚类
* @param locations
* @param eps
* @param minPoints
* @returns
*/
doPixelCluster(t) {
let s = 0;
for (let i = 0; i < this.clusteredLocations.length; i++) {
const e = this.clusteredLocations[i];
if (e.visited)
continue;
e.visited = !0;
const r = this.getNeighbors(e, t);
r.length < this.minClusterPoints ? e.clusterId = -1 : (r.forEach((o) => {
o.visited = !0, o.clusterId = s;
}), e.clusterId = s, s++);
}
return this.createClusters();
}
/**
* 获取邻居点
* @param locations
* @param index
* @param eps
* @returns
*/
getNeighbors(t, s) {
return this.clusteredLocations.filter((i) => i.id === t.id || i.visited ? !1 : this.getDistance(t, i) <= s);
}
/**
* 两点间的像素距离
* @param point1
* @param point2
* @returns
*/
getDistance(t, s) {
return Math.sqrt(
Math.pow(t.properties.screenX - s.properties.screenX, 2) + Math.pow(t.properties.screenY - s.properties.screenY, 2)
);
}
/**
* 从聚类结果中创建聚类对象
* @param locations
* @returns
*/
createClusters() {
const t = {}, s = [];
for (const e of this.clusteredLocations)
e.clusterId === void 0 || e.clusterId === -1 ? s.push(e) : (t[e.clusterId] || (t[e.clusterId] = []), t[e.clusterId].push(e));
const i = Object.keys(t).map((e, r) => {
const o = t[Number(e)], a = o.length, l = o.reduce((c, h) => c + h.x, 0), n = o.reduce((c, h) => c + h.y, 0), m = l / a, d = n / a;
return {
id: Number(e),
items: o,
count: a,
center: {
x: m,
y: d
}
};
});
return s.length > 0 && i.push({
id: -1,
items: s,
count: s.length,
center: null
}), i;
}
showClusterResult(t) {
this.crossLayer.removeAll();
let s = Number.MIN_VALUE, i = Number.MAX_VALUE;
t.forEach((e) => {
e.count > 1 && (i = Math.min(i, e.count), s = Math.max(s, e.count));
}), t.forEach((e) => {
if (e.id !== -1) {
let r = i === s ? (this.maxClusterSymbolSize + this.minClusterSymbolSize) / 2 : this.minClusterSymbolSize + (e.count - i) / (s - i) * (this.maxClusterSymbolSize - this.minClusterSymbolSize);
r *= 0.75;
const l = (e.count.toString().length * 8 + 6) / 2, n = new y({
geometry: new u({ x: e.center.x, y: e.center.y }),
attributes: {
count: e.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(n);
} else
e.items.forEach((r) => {
const o = new y({
geometry: new u({ x: r.x, y: r.y }),
attributes: {
...r,
...r.properties,
type: "signal-cross",
id: r.id
},
symbol: this.getCrossSymbol(r.properties)
});
this.crossLayer.add(o);
});
});
}
getBrandLabel(t) {
const s = (t ?? "").toLowerCase();
return s === "scats" ? "SCATS" : s === "gc" ? "国产" : t ?? "";
}
getOnlineLabel(t) {
return t ? "在线" : "离线";
}
getMalfunctionLabel(t) {
return t ? "故障" : "正常";
}
getCrossSymbol(t) {
var s, i;
if (this.view.scale <= this.iconSymbolScale) {
let e = "/GisViewerAssets/Images/cross/ic_";
return e += ((s = t.brand) == null ? void 0 : s.toLowerCase()) === "scats" ? "scats_" : "gc_", e += t.isOnline ? "online_" : "offline_", e += t.isMalfunction ? "malfunction.png" : "normal.png", {
type: "cim",
data: {
type: "CIMSymbolReference",
primitiveOverrides: [
{
// 将textGraphic的TextString替换为graphic.attributes.name
type: "CIMPrimitiveOverride",
primitiveName: "textGraphic",
propertyName: "TextString",
valueExpressionInfo: {
type: "CIMExpressionInfo",
title: "Custom",
expression: this.showName === "crossName" ? 'Replace($feature.name, "与", "/")' : this.showName === "signalId" ? "$feature.signalId" : 'Replace($feature.name, "与", "/") + " " + $feature.signalId',
returnType: "Default"
}
}
],
symbol: {
type: "CIMPointSymbol",
symbolLayers: [
// 路口名称
{
type: "CIMVectorMarker",
size: 25,
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: e
}
]
}
}
};
} else {
const e = {
type: "simple-marker",
style: "circle",
size: this.view.scale > this.largeMarkerScale ? 3 : 6,
outline: { width: 1 }
};
return ((i = t.brand) == null ? void 0 : i.toLowerCase()) === "scats" ? t.isOnline ? (e.color = [68, 203, 188], e.outline.color = [59, 176, 163]) : (e.color = [100, 100, 100], e.outline.color = [150, 150, 150]) : t.isOnline ? (e.color = [129, 226, 73], e.outline.color = [108, 189, 61]) : (e.color = [100, 100, 100], e.outline.color = [150, 150, 150]), e;
}
}
}
export {
C as default
};