gisviewer-vue3-arcgis
Version:
在应用中引入私服的包, 项目根目录下 新建文件 .npmrc 在 .npmrc 中对包源进行配置:
270 lines (269 loc) • 9.85 kB
JavaScript
import F from "ol/Feature";
import v from "ol/geom/Point";
import U from "ol/layer/Vector";
import { unByKey as K } from "ol/Observable";
import X from "ol/source/Vector";
import V from "ol/style/Circle";
import y from "ol/style/Fill";
import Z from "ol/style/Icon";
import C from "ol/style/Stroke";
import g from "ol/style/Style";
import z from "ol/style/Text";
import { PixelClusterCalculator as G } from "../cluster/pixel-cluster-calculator.mjs";
class re {
// 大于17级时样式是否从圆点变为图标,默认为true
constructor(e) {
this.showName = "detail", this.showStyle = "scatter", this.viewChangeKey = null, this.mapMoveKey = null, this.resolutionChangeTimeout = null, this.locations = [], this.allLocations = [], this.changeStyle = !0, this.map = e, this.view = e.getView(), this.clusterCalculator = new G(e), this.source = new X(), this.crossLayer = new U({
source: this.source
}), this.crossLayer.set("id", "signal-control-cross-layer"), this.map.addLayer(this.crossLayer), this.configureVectorLayerStyle();
}
showSignalCross(e) {
if (this.changeStyle = e.changeStyle ?? !0, this.crossLayer.setVisible(!0), this.source.clear(), this.showName = e.showName || "detail", this.showStyle = e.style || "scatter", this.viewChangeKey || (this.viewChangeKey = this.view.on("change:resolution", () => {
this.showStyle === "cluster" && (this.resolutionChangeTimeout && clearTimeout(this.resolutionChangeTimeout), this.resolutionChangeTimeout = setTimeout(() => {
this.calculateCluster(), this.resolutionChangeTimeout = null;
}, 150));
})), this.mapMoveKey || (this.mapMoveKey = this.map.on("moveend", () => {
this.showStyle === "cluster" && this.calculateCluster();
})), this.showStyle === "scatter") {
const t = [], i = [];
e.points.forEach((a) => {
const r = this.createCrossFeature(a);
a.isMalfunction === !0 || a.isOnline === !1 ? i.push(r) : t.push(r);
}), this.source.addFeatures(t), this.source.addFeatures(i), this.crossLayer.changed();
} else
this.locations = e.points.map((t) => ({
id: t.crossId,
x: t.x,
y: t.y,
visited: !1,
clusterId: void 0,
properties: t
})), this.allLocations = [...this.locations], this.calculateCluster();
return {
status: 0,
message: "success"
};
}
calculateCluster() {
const e = this.clusterCalculator.calculate(this.locations), t = this.clusterCalculator.calculateSymbolSizes(e);
this.showClusterResult(t);
}
clearSignalCross() {
this.source.clear(), this.viewChangeKey && (K(this.viewChangeKey), this.viewChangeKey = null), this.mapMoveKey && (K(this.mapMoveKey), this.mapMoveKey = null), this.resolutionChangeTimeout && (clearTimeout(this.resolutionChangeTimeout), this.resolutionChangeTimeout = null);
}
changeShowName(e) {
this.showName = e, this.showStyle === "scatter" && this.updateScatterSymbol();
}
setVisible(e) {
this.crossLayer.setVisible(e);
}
updateScatterSymbol() {
this.crossLayer.changed();
}
/**
* 配置矢量图层样式:复用 Icon,并为不同 feature 渲染不同 Text。
* - 使用 resolution 判断是否显示文字(在指定缩放级别后才显示)
* - 使用缓存避免每次渲染都创建新的 Style/Icon/数组对象
*/
configureVectorLayerStyle() {
const s = this.map.getView(), h = s.getResolutionForZoom(14), u = s.getResolutionForZoom(17), m = s.getResolutionForZoom(17), k = (o, n, l) => o === void 0 && n === void 0 && l === void 0 ? "/GisViewerAssets/Images/cross/gis_xhj_blue.png" : `/GisViewerAssets/Images/cross/ic_${(o ?? "gc").toLowerCase() === "scats" ? "scats" : "gc"}_${n === !1 ? "offline" : "online"}_${l ? "malfunction" : "normal"}.png`, p = /* @__PURE__ */ new Map(), M = /* @__PURE__ */ new Map(), O = /* @__PURE__ */ new WeakMap(), x = {
online: "#22c55e",
// 绿色 - 在线
offline: "#9ca3af"
// 灰色 - 离线
}, I = new C({ color: "#ffffff", width: 1.5 }), L = /* @__PURE__ */ new Map(), A = (o) => {
const n = o === !1 ? "offline" : "online", l = L.get(n);
if (l)
return l;
const c = [
new g({
image: new V({
radius: 3,
fill: new y({ color: x[n] }),
stroke: I
}),
zIndex: 1
})
];
return L.set(n, c), c;
}, b = /* @__PURE__ */ new Map(), S = (o) => {
const n = o === !1 ? "offline" : "online", l = b.get(n);
if (l)
return l;
const c = [
new g({
image: new V({
radius: 5,
fill: new y({ color: x[n] }),
stroke: I
}),
zIndex: 1
})
];
return b.set(n, c), c;
}, B = new y({ color: "#1f2937" }), R = new C({ color: "#ffffff", width: 3 }), _ = (o) => {
const n = p.get(o);
if (n)
return n;
const l = new g({
image: new Z({
src: o,
scale: 0.5,
anchor: [0.5, 1],
anchorXUnits: "fraction",
anchorYUnits: "fraction"
}),
zIndex: 1
});
return p.set(o, l), l;
}, D = (o) => {
const n = M.get(o);
if (n)
return n;
const l = [_(o)];
return M.set(o, l), l;
};
this.crossLayer.setStyle((o, n) => {
if ((o.get("type") ?? "") === "signal-cluster")
return this.getClusterStyle(o.getProperties());
const c = this.showName === "crossName" ? o.get("name") : this.showName === "signalId" ? o.get("signalId") : `${o.get("name")}(${o.get("signalId")})`, T = o.get("brand"), f = o.get("isOnline"), N = o.get("isMalfunction"), d = k(T, f, N);
if (n > h)
return A(f);
if (n > u)
return S(f);
if (n > m)
return this.changeStyle ? D(d) : S(f);
const w = O.get(o);
if (w && w.label === c && w.iconKey === d)
return w.styles;
const P = this.changeStyle ? _(d) : S(f)[0], Y = new g({
text: new z({
text: c,
font: '12px "Microsoft YaHei"',
textAlign: "center",
textBaseline: "bottom",
offsetY: this.changeStyle ? -28 : -8,
fill: B,
stroke: R
}),
zIndex: 2
}), E = [P, Y];
return O.set(o, {
label: c,
iconKey: d,
styles: E
}), E;
});
}
createCrossFeature(e) {
var i;
return e.brand = (i = e.brand) == null ? void 0 : i.toLowerCase(), new F({
geometry: new v([e.x, e.y]),
type: "signal-cross",
id: e.crossId,
brandLabel: this.getBrandLabel(e.brand),
isOnlineLabel: this.getOnlineLabel(e.isOnline),
isMalfunctionLabel: this.getMalfunctionLabel(e.isMalfunction),
...e
});
}
getClusterStyle(e) {
const t = e.clusterSymbolSize, i = new Z({
src: "/GisViewerAssets/Images/cross/gis_xhj_blue.png",
scale: t / 32
// 近似缩放
}), a = -(t + 10), r = new z({
text: String(e.count ?? 0),
font: "16px Arial Unicode MS",
fill: new y({ color: [255, 255, 255, 255] }),
backgroundFill: new y({ color: [2, 72, 200, 1] }),
backgroundStroke: new C({ color: [2, 72, 200, 0.5], width: 2 }),
padding: [1, 2, 1, 2],
offsetY: a,
textAlign: "center",
justify: "center",
textBaseline: "middle"
});
return [new g({ image: i }), new g({ text: r })];
}
// private formatCrossName(name?: string) {
// return (name || '').replace(/与/g, '/');
// }
getBrandLabel(e) {
const t = (e ?? "").toLowerCase();
return t === "scats" ? "SCATS" : t === "gc" ? "国产" : e ?? "";
}
getOnlineLabel(e) {
return e ? "在线" : "离线";
}
getMalfunctionLabel(e) {
return e ? "故障" : "正常";
}
showClusterResult(e) {
this.source.clear(), e.forEach((t) => {
if (t.id !== -1 && t.center && t.symbolSize) {
const i = new F({
geometry: new v([t.center.x, t.center.y]),
type: "signal-cluster",
count: t.count,
clusterSymbolSize: t.symbolSize
});
this.source.addFeature(i);
} else
t.items.forEach((i) => {
const a = this.createCrossFeature({
...i.properties,
x: i.x,
y: i.y
});
this.source.addFeature(a);
});
}), this.crossLayer.changed();
}
highlight(e, t) {
var a;
if (this.showStyle === "cluster") {
const r = this.allLocations.filter((s) => s.properties[e] === t);
if (r.length > 0) {
this.locations = r, this.calculateCluster();
const s = [
1 / 0,
1 / 0,
-1 / 0,
-1 / 0
];
return r.forEach((h) => {
s[0] = Math.min(s[0], h.x), s[1] = Math.min(s[1], h.y), s[2] = Math.max(s[2], h.x), s[3] = Math.max(s[3], h.y);
}), s;
}
return null;
}
const i = [];
if (this.source.getFeatures().forEach((r) => {
r.get(e) === t ? (r.setStyle(void 0), i.push(r)) : r.setStyle(new g({}));
}), i.length > 0) {
const r = (a = i[0].getGeometry()) == null ? void 0 : a.getExtent();
if (r) {
const s = [...r];
return i.slice(1).forEach((h) => {
var m;
const u = (m = h.getGeometry()) == null ? void 0 : m.getExtent();
u && (s[0] = Math.min(s[0], u[0]), s[1] = Math.min(s[1], u[1]), s[2] = Math.max(s[2], u[2]), s[3] = Math.max(s[3], u[3]));
}), s;
}
}
return null;
}
clearHighlight() {
if (this.showStyle === "cluster") {
this.locations = [...this.allLocations], this.calculateCluster();
return;
}
this.source.getFeatures().forEach((e) => {
e.setStyle(void 0);
});
}
}
export {
re as default
};