772 lines
20 KiB
JavaScript
772 lines
20 KiB
JavaScript
/**
|
||
* Openlayers Map
|
||
* author: khy
|
||
* date: 23.09.07
|
||
* */
|
||
|
||
const proj = {
|
||
viewProjection: "EPSG:3857",
|
||
WGS84Projection: "EPSG:4326",
|
||
};
|
||
Object.freeze(proj);
|
||
Array.prototype.toWGS84 = function () {
|
||
if (this.length === 2) {
|
||
//coordinate
|
||
return ol.proj.transform(this, proj.viewProjection, proj.WGS84Projection);
|
||
} else if (this.length === 4) {
|
||
//extent
|
||
return ol.proj.transformExtent(this, proj.viewProjection, proj.WGS84Projection);
|
||
} else {
|
||
return this;
|
||
}
|
||
};
|
||
Array.prototype.toEPSG3857 = function () {
|
||
if (this.length === 2) {
|
||
//coordinate
|
||
return ol.proj.transform(this, proj.WGS84Projection, proj.viewProjection);
|
||
} else if (this.length === 4) {
|
||
//extent
|
||
return ol.proj.transformExtent(this, proj.WGS84Projection, proj.viewProjection);
|
||
} else {
|
||
return this;
|
||
}
|
||
};
|
||
|
||
ol.Map.prototype.getProxyURL = function (url) {
|
||
return `${document.location.protocol}//${document.location.host}/proxy/?${url ? url : ""}`;
|
||
};
|
||
|
||
ol.Map.prototype.addBaseTileLayer = function (options) {
|
||
let host = 'gis.korail.com';
|
||
function createBaseTileLayer(map) {
|
||
const proxy = map.getProxyURL();
|
||
const base = new ol.layer.Tile({
|
||
name: "base",
|
||
source: new ol.source.XYZ({
|
||
tileUrlFunction: (zxy) => {
|
||
const [z, x, y] = zxy;
|
||
if (z < 5 || z > 15) {
|
||
return;
|
||
}
|
||
return `https://${host}/tilemap/background/${z}/${x}/${y}.png`;
|
||
},
|
||
minZoom: 5,
|
||
maxZoom: 15,
|
||
}),
|
||
zIndex: 0,
|
||
});
|
||
|
||
if (options === "korean") {
|
||
const label = new ol.layer.Tile({
|
||
name: "base-label",
|
||
source: new ol.source.XYZ({
|
||
tileUrlFunction: (zxy) => {
|
||
const [z, x, y] = zxy;
|
||
if (z < 5 || z > 15) {
|
||
return;
|
||
}
|
||
return `https://${host}/tilemap/korean/${z}/${x}/${y}.png`;
|
||
},
|
||
minZoom: 5,
|
||
maxZoom: 15,
|
||
}),
|
||
zIndex: 0,
|
||
});
|
||
|
||
const layergroup = new ol.layer.Group({
|
||
layers: [base, label],
|
||
});
|
||
return layergroup;
|
||
} else {
|
||
return base;
|
||
}
|
||
}
|
||
|
||
const layer = createBaseTileLayer(this);
|
||
this.addLayer(layer);
|
||
|
||
return layer;
|
||
};
|
||
ol.Map.prototype.createBaseLayerButton = function () {
|
||
const mapElement = this.getTargetElement();
|
||
|
||
if (!mapElement.querySelector("button[usage=base]")) {
|
||
const toggleButton = document.createElement("button");
|
||
toggleButton.setAttribute("usage", "base");
|
||
toggleButton.textContent = "";
|
||
toggleButton.style.position = "absolute";
|
||
toggleButton.style.top = "0px";
|
||
toggleButton.style.left = "0px";
|
||
toggleButton.style.margin = "10px";
|
||
toggleButton.style.marginLeft = "42px";
|
||
toggleButton.style.width = "30px";
|
||
toggleButton.style.height = "30px";
|
||
toggleButton.style.borderRadius = "50%";
|
||
toggleButton.style.border = "1px solid gray";
|
||
toggleButton.style.background = "white";
|
||
toggleButton.style.color = "black";
|
||
toggleButton.style.textAlign = "center";
|
||
|
||
let status = false;
|
||
|
||
const toggleLayer = () => {
|
||
this.getAllLayers()
|
||
.filter((l) => l.get("name") !== "base" && l.get("name") !== "base-label" && l.get("name") !== "grid-tile")
|
||
.forEach((l) => {
|
||
l.setVisible(status);
|
||
});
|
||
|
||
status = !status;
|
||
|
||
toggleButton.style.background = status ? "dodgerblue" : "white";
|
||
toggleButton.style.color = status ? "white" : "black";
|
||
|
||
if (status) {
|
||
viewChange(null, null);
|
||
map.getView().setConstrainResolution(true);
|
||
} else {
|
||
map.getView().setConstrainResolution(false);
|
||
viewChange(0, document.querySelector("ul.notice > li"));
|
||
}
|
||
};
|
||
toggleButton.onclick = toggleLayer;
|
||
|
||
let zoomLevel = undefined;
|
||
this.on("moveend", (view) => {
|
||
const nowZoomLevel = Number(this.getView().getZoom().toFixed());
|
||
if (zoomLevel !== nowZoomLevel) {
|
||
zoomLevel = nowZoomLevel;
|
||
toggleButton.textContent = zoomLevel;
|
||
}
|
||
});
|
||
|
||
mapElement.appendChild(toggleButton);
|
||
}
|
||
};
|
||
|
||
ol.Map.prototype.createGridTiles = function () {
|
||
const mapElement = this.getTargetElement();
|
||
|
||
if (!mapElement.querySelector("button[usage=grid-tile]")) {
|
||
const toggleButton = document.createElement("button");
|
||
toggleButton.setAttribute("usage", "grid-tile");
|
||
toggleButton.textContent = "#";
|
||
toggleButton.style.position = "absolute";
|
||
toggleButton.style.top = "0px";
|
||
toggleButton.style.left = "0px";
|
||
toggleButton.style.margin = "10px";
|
||
toggleButton.style.width = "30px";
|
||
toggleButton.style.height = "30px";
|
||
toggleButton.style.borderRadius = "50%";
|
||
toggleButton.style.border = "1px solid gray";
|
||
toggleButton.style.background = "white";
|
||
toggleButton.style.color = "black";
|
||
toggleButton.style.textAlign = "center";
|
||
|
||
const toggleLayer = () => {
|
||
const layer = this.getLayer("grid-tile");
|
||
|
||
if (layer) {
|
||
const currentVisible = layer.getVisible();
|
||
const postVisible = !currentVisible;
|
||
|
||
this.getAllLayers()
|
||
.filter((l) => l.get("name") !== "base" && l.get("name") !== "base-label" && l.get("name") !== "grid-tile")
|
||
.forEach((l) => {
|
||
l.setVisible(currentVisible);
|
||
});
|
||
|
||
layer.setVisible(postVisible);
|
||
|
||
toggleButton.style.background = postVisible ? "dodgerblue" : "white";
|
||
toggleButton.style.color = postVisible ? "white" : "black";
|
||
|
||
if (postVisible) {
|
||
viewChange(null, null);
|
||
} else {
|
||
viewChange(0, document.querySelector("ul.notice > li"));
|
||
}
|
||
}
|
||
};
|
||
toggleButton.onclick = toggleLayer;
|
||
|
||
mapElement.appendChild(toggleButton);
|
||
}
|
||
|
||
if (!this.getLayer("grid-tile")) {
|
||
const tileSize = 256;
|
||
|
||
const canvas = document.createElement("canvas");
|
||
canvas.width = tileSize;
|
||
canvas.height = tileSize;
|
||
|
||
const context = canvas.getContext("2d");
|
||
context.strokeStyle = "gray";
|
||
context.textAlign = "center";
|
||
const lineHeight = 30;
|
||
context.font = `${lineHeight - 6}px sans-serif`;
|
||
|
||
const layer = new ol.layer.WebGLTile({
|
||
name: "grid-tile",
|
||
source: new ol.source.DataTile({
|
||
loader: (z, x, y) => {
|
||
const half = tileSize / 2;
|
||
|
||
context.clearRect(0, 0, tileSize, tileSize);
|
||
// context.fillStyle = 'rgba(255, 255, 255, 0.7)';
|
||
// context.fillRect(0, 0, tileSize, tileSize);
|
||
|
||
context.fillStyle = "black";
|
||
context.fillText(`z: ${z}`, half, half - lineHeight);
|
||
context.fillText(`x: ${x}`, half, half);
|
||
context.fillText(`y: ${y}`, half, half + lineHeight);
|
||
|
||
context.strokeRect(0, 0, tileSize, tileSize);
|
||
|
||
const data = context.getImageData(0, 0, tileSize, tileSize).data;
|
||
|
||
return new Uint8Array(data.buffer);
|
||
},
|
||
}),
|
||
zIndex: 999,
|
||
});
|
||
|
||
layer.setVisible(false);
|
||
|
||
this.addLayer(layer);
|
||
}
|
||
};
|
||
|
||
ol.source.Vector.fromGeoJSON = function (geojson) {
|
||
return new ol.source.Vector({
|
||
features: new ol.format.GeoJSON().readFeatures(geojson, { featureProjection: proj.viewProjection }),
|
||
format: new ol.format.GeoJSON(),
|
||
strategy: ol.loadingstrategy.bbox,
|
||
});
|
||
};
|
||
|
||
ol.Map.prototype.addRegionalLayer = async function () {
|
||
const regional_lines = new Array(8);
|
||
|
||
async function createRegionalLine(url, index) {
|
||
return new Promise(async (resolve, reject) => {
|
||
try {
|
||
const response = await fetch(url);
|
||
const json = await response.json();
|
||
insertLine(json, index);
|
||
resolve();
|
||
} catch {
|
||
reject();
|
||
}
|
||
});
|
||
}
|
||
|
||
// 권역 라인이 포인트 형식으로 되어있어서 라인형식으로 바꾸고 데이터 교체하는 함수
|
||
function insertLine(json, i) {
|
||
const coordinates = json.features.map((point) => {
|
||
const converted = point.geometry.coordinates.toEPSG3857();
|
||
return converted;
|
||
});
|
||
const geomLineString = new ol.geom.LineString(coordinates);
|
||
const featureLineString = new ol.Feature({ geometry: geomLineString });
|
||
regional_lines[i] = featureLineString;
|
||
}
|
||
|
||
// $.getJOSN 으로 json 데이터 읽어 드리고 insertLine 은 현재 json 파일이 line 형식이 아닌 포인트
|
||
// 형식으로
|
||
// 만들었음
|
||
// 포인트 형식을 만든 이유는 수정시 포인트 형식이 필요해서 우선 포인트 형식으로 저장
|
||
|
||
await Promise.all([
|
||
createRegionalLine("resource/Regional_point_chungbuk.json", 0),
|
||
createRegionalLine("resource/Regional_point_gang.json", 1),
|
||
createRegionalLine("resource/Regional_point_seoul_east.json", 2),
|
||
createRegionalLine("resource/Regional_point_seoul_west.json", 3),
|
||
createRegionalLine("resource/Regional_point_daejeon_chungnam.json", 4),
|
||
createRegionalLine("resource/Regional_point_jeonbuk.json", 5),
|
||
createRegionalLine("resource/Regional_point_jeonnam.json", 6),
|
||
createRegionalLine("resource/Regional_point_daegu.json", 7),
|
||
]);
|
||
|
||
const regionalSource = new ol.source.Vector({
|
||
features: regional_lines,
|
||
});
|
||
|
||
this.addVectorLayer({
|
||
name: "Regional_Line",
|
||
source: regionalSource,
|
||
style: layerStyles.regional,
|
||
zIndex: 0,
|
||
});
|
||
};
|
||
|
||
/**
|
||
* WebGL Layer
|
||
* author: khy
|
||
*/
|
||
const canvas = document.createElement("canvas");
|
||
const gl = canvas?.getContext("webgl") || canvas?.getContext("experimental-webgl");
|
||
const webglAvailable = gl instanceof WebGLRenderingContext;
|
||
|
||
class WebGLVectorLayer extends ol.layer.Layer {
|
||
constructor(params) {
|
||
super(params);
|
||
this.style = params.style;
|
||
}
|
||
createRenderer() {
|
||
const style = this.style;
|
||
|
||
return new ol.renderer.webgl.VectorLayer(this, {
|
||
style,
|
||
});
|
||
}
|
||
}
|
||
|
||
function VectorLayer(params) {
|
||
return new ol.layer.Vector(params);
|
||
//return (webglAvailable) ? new WebGLVectorLayer(params) : new ol.layer.Vector(params);
|
||
}
|
||
|
||
function PointsLayer(params) {
|
||
const hasStyleFunction = typeof params?.style === "function";
|
||
|
||
return (webglAvailable && !hasStyleFunction) ? new ol.layer.WebGLPoints(params) : new ol.layer.Vector(params);
|
||
}
|
||
|
||
/**
|
||
* ol.Map prototype 확장
|
||
* @param ...args
|
||
* @returns
|
||
*/
|
||
ol.Map.prototype.addLayerWithType = async function (...args) {
|
||
const LayerType = args[0];
|
||
args = args[1];
|
||
|
||
return new Promise(async (resolve, reject) => {
|
||
try {
|
||
let url, fetchOption, layerOption;
|
||
let response, geojson;
|
||
|
||
switch (args.length) {
|
||
case 3:
|
||
if (
|
||
typeof args[0] === "string" && //fetch url
|
||
typeof args[1] === "object" && //fetch option
|
||
typeof args[2] === "object"
|
||
) {
|
||
//layer option
|
||
(url = args[0]), (fetchOption = args[1]), (layerOption = args[2]);
|
||
response = await fetch(url, fetchOption);
|
||
geojson = await response.json();
|
||
layerOption.source = await ol.source.Vector.fromGeoJSON(geojson);
|
||
} else {
|
||
reject();
|
||
}
|
||
break;
|
||
case 2:
|
||
if (
|
||
typeof args[0] === "string" && //fetch url
|
||
typeof args[1] === "object"
|
||
) {
|
||
//layer option
|
||
(url = args[0]), (layerOption = args[1]);
|
||
|
||
console.log(`addLayerWithType(${url})`, fetch);
|
||
response = await fetch(url);
|
||
geojson = await response.json();
|
||
console.log(geojson);
|
||
layerOption.source = await ol.source.Vector.fromGeoJSON(geojson);
|
||
} else if (
|
||
typeof args[0] === "object" && //layer option
|
||
typeof args[1] === "object"
|
||
) {
|
||
//map object
|
||
layerOption = args[0];
|
||
} else {
|
||
reject();
|
||
}
|
||
break;
|
||
case 1: //layer option
|
||
default:
|
||
layerOption = args[0];
|
||
}
|
||
|
||
if (layerOption.labelStyleFunction) {
|
||
const layergroup = new ol.layer.Group({
|
||
layers: [
|
||
new LayerType({
|
||
...layerOption,
|
||
source: layerOption.source || new ol.source.Vector(),
|
||
style: layerOption.style || ol.style.flat.createDefaultStyle(),
|
||
}),
|
||
new ol.layer.Vector({
|
||
name: layerOption.name ? `${layerOption.name}_label` : "label",
|
||
source: layerOption.source || new ol.source.Vector(),
|
||
style: layerOption.labelStyleFunction,
|
||
declutter: true,
|
||
zIndex: layerOption.zIndex + 1,
|
||
}),
|
||
],
|
||
});
|
||
this.addLayer(layergroup);
|
||
|
||
resolve(layergroup);
|
||
} else {
|
||
const layer = new LayerType({
|
||
...layerOption,
|
||
source: layerOption.source || new ol.source.Vector(),
|
||
style: layerOption.style || ol.style.flat.createDefaultStyle(),
|
||
});
|
||
|
||
this.addLayer(layer);
|
||
|
||
resolve(layer);
|
||
}
|
||
} catch {
|
||
reject();
|
||
}
|
||
});
|
||
};
|
||
|
||
/**
|
||
* @author khy
|
||
* @description WebGL벡터레이어나 일반벡터레이어를 생성하여 map객체에 addLayer()함
|
||
* 전달인자를 1개, 2개, 3개를 줄 수 있음.
|
||
* 전달인자 1개: layer option
|
||
* 전달인자 2개: fetch url, layer option
|
||
* 전달인자 3개: fetch url, fetch option, layer option
|
||
* @param ...args
|
||
* case (args0) Layer option
|
||
* case (args0, args1) fetch url, layer option || layer option, map target
|
||
* case (args0, args1, args2) fetch url, fetch option, layer option
|
||
*/
|
||
|
||
/**
|
||
* @returns
|
||
* ol.layer.vector || WebGLVectorLayer
|
||
*/
|
||
ol.Map.prototype.addVectorLayer = async function (...args) {
|
||
return new Promise(async (resolve) => {
|
||
resolve(this.addLayerWithType(VectorLayer, args));
|
||
});
|
||
};
|
||
ol.Map.prototype.addRailLayer = async function (...args) {
|
||
return new Promise(async (resolve) => {
|
||
resolve(this.addLayerWithType(ol.layer.Vector, args));
|
||
});
|
||
};
|
||
|
||
/**
|
||
* @returns
|
||
* ol.layer.vector || ol.layer.WebGLPoints
|
||
*/
|
||
ol.Map.prototype.addPointsLayer = async function (...args) {
|
||
return new Promise(async (resolve) => {
|
||
resolve(this.addLayerWithType(PointsLayer, args));
|
||
});
|
||
};
|
||
ol.Map.prototype.addNormalRailLayer = function (options) {
|
||
return this.addVectorLayer(
|
||
"resource/NormalLine.json",
|
||
Object.assign(
|
||
{
|
||
name: "NormalLine",
|
||
style: {
|
||
"stroke-width": 2,
|
||
},
|
||
zIndex: 2,
|
||
},
|
||
options
|
||
)
|
||
);
|
||
};
|
||
ol.Map.prototype.addNormalStationLayer = function (options) {
|
||
return this.addPointsLayer(
|
||
"resource/NormalStation.json",
|
||
Object.assign(
|
||
{
|
||
name: "NormalStation",
|
||
style: {
|
||
"circle-radius": 5,
|
||
"circle-stroke-width": 3,
|
||
"circle-fill-color": "gainsboro",
|
||
},
|
||
zIndex: 3,
|
||
},
|
||
options
|
||
)
|
||
);
|
||
};
|
||
ol.Map.prototype.addKTXRailLayer = function (options) {
|
||
return this.addVectorLayer(
|
||
"resource/KTXLine.json",
|
||
Object.assign(
|
||
{
|
||
name: "KTXLine",
|
||
style: {
|
||
"stroke-color": "#005BAC",
|
||
"stroke-width": 5,
|
||
},
|
||
zIndex: 1,
|
||
},
|
||
options
|
||
)
|
||
);
|
||
};
|
||
ol.Map.prototype.addKTXStationLayer = function (options) {
|
||
return this.addPointsLayer(
|
||
"resource/KTXStation.json",
|
||
Object.assign(
|
||
{
|
||
name: "KTXStation",
|
||
style: {
|
||
"circle-radius": 7,
|
||
"circle-stroke-color": "#005BAC",
|
||
"circle-stroke-width": 3,
|
||
"circle-fill-color": "gainsboro",
|
||
},
|
||
zIndex: 4,
|
||
},
|
||
options
|
||
)
|
||
);
|
||
};
|
||
ol.Map.prototype.addBaseRailLayer = function () {
|
||
this.addNormalRailLayer();
|
||
this.addKTXRailLayer();
|
||
};
|
||
ol.Map.prototype.addBaseStationLayer = function () {
|
||
this.addNormalStationLayer();
|
||
this.addKTXStationLayer();
|
||
};
|
||
|
||
/*
|
||
function removeLayer(layername) {
|
||
getLayers(layername).forEach((layer) => {
|
||
layer.dispose();
|
||
map.removeLayer(layer);
|
||
})
|
||
}
|
||
*/
|
||
|
||
ol.Map.prototype.getLayer = function (layername) {
|
||
return this.getLayers(layername)[0];
|
||
};
|
||
ol.Map.prototype.getLayers = function (layername) {
|
||
return layername ? this.getAllLayers().filter((layer) => layer.get("name") === layername) : this.getLayerGroup().getLayers();
|
||
};
|
||
ol.Map.prototype.flyTo = function (params) {
|
||
this.once("postrender", () => {
|
||
this.flyToNow(params);
|
||
});
|
||
};
|
||
ol.Map.prototype.flyToNow = function (params) {
|
||
const convertedCenter = params.center.toEPSG3857();
|
||
|
||
const option = Object.assign(params, {
|
||
center: convertedCenter,
|
||
duration: 700,
|
||
easing: ol.easing.easeOut,
|
||
});
|
||
this.getView().animate(option);
|
||
};
|
||
ol.Map.prototype.setVisibleLayer = function (layername, visible) {
|
||
this.getLayers(layername).forEach((layer) => {
|
||
layer.setVisible(visible);
|
||
});
|
||
};
|
||
|
||
/**
|
||
* Overlay
|
||
* author: khy
|
||
* date: 23.09.07
|
||
* */
|
||
ol.Map.prototype.createOverlay = function () {
|
||
if (!document.getElementById("popup")) {
|
||
const popupElement = document.createElement("div");
|
||
popupElement.id = "popup";
|
||
this.getTargetElement().appendChild(popupElement);
|
||
}
|
||
|
||
const popup = new ol.Overlay({
|
||
id: "popup",
|
||
element: document.getElementById("popup"),
|
||
autoPan: true
|
||
});
|
||
|
||
this.addOverlay(popup);
|
||
|
||
return popup;
|
||
};
|
||
ol.Map.prototype.getOverlay = function () {
|
||
const popup = this.getOverlayById("popup") || this.createOverlay();
|
||
|
||
return popup;
|
||
};
|
||
ol.Map.prototype.showOverlay = function () {
|
||
this.getOverlay().element.style.display = null;
|
||
};
|
||
ol.Map.prototype.hideOverlay = function () {
|
||
this.getOverlay().element.style.display = "none";
|
||
};
|
||
ol.Map.prototype.isShowingOverlay = function () {
|
||
return (map.getOverlay().element.style.display !== "none")
|
||
}
|
||
|
||
/**
|
||
* Drag Interaction
|
||
* author: khy
|
||
* param
|
||
* options : {
|
||
* layerFilter: function(default=undefined),
|
||
* hitTolerance: number(default=0),
|
||
* checkWrapped: boolean(default=true),
|
||
* }
|
||
* usage
|
||
* map.addInteraction(new Drag( options | null ));
|
||
*
|
||
*/
|
||
class Drag extends ol.interaction.Pointer {
|
||
constructor(options) {
|
||
super({
|
||
handleDownEvent: handleDownEvent,
|
||
handleDragEvent: handleDragEvent,
|
||
handleMoveEvent: handleMoveEvent,
|
||
handleUpEvent: handleUpEvent,
|
||
});
|
||
|
||
this.options_ = options;
|
||
|
||
this.coordinate_ = null;
|
||
this.cursor_ = "grabbing";
|
||
this.feature_ = null;
|
||
this.previousCursor_ = undefined;
|
||
}
|
||
}
|
||
|
||
function handleDownEvent(evt) {
|
||
const map = evt.map;
|
||
const feature = map.forEachFeatureAtPixel(evt.pixel, (feature) => feature, this.options_);
|
||
|
||
if (feature) {
|
||
this.coordinate_ = evt.coordinate;
|
||
this.feature_ = feature;
|
||
}
|
||
|
||
return !!feature;
|
||
}
|
||
function handleDragEvent(evt) {
|
||
const deltaX = evt.coordinate[0] - this.coordinate_[0];
|
||
const deltaY = evt.coordinate[1] - this.coordinate_[1];
|
||
|
||
const geometry = this.feature_.getGeometry();
|
||
geometry.translate(deltaX, deltaY);
|
||
|
||
this.coordinate_[0] = evt.coordinate[0];
|
||
this.coordinate_[1] = evt.coordinate[1];
|
||
}
|
||
function handleMoveEvent(evt) {
|
||
if (this.cursor_) {
|
||
const map = evt.map;
|
||
const feature = map.forEachFeatureAtPixel(evt.pixel, (feature) => feature, this.options_);
|
||
|
||
const element = evt.map.getTargetElement();
|
||
|
||
if (feature) {
|
||
if (element.style.cursor != this.cursor_) {
|
||
this.previousCursor_ = element.style.cursor;
|
||
element.style.cursor = this.cursor_;
|
||
}
|
||
} else if (this.previousCursor_ !== undefined) {
|
||
element.style.cursor = this.previousCursor_;
|
||
this.previousCursor_ = undefined;
|
||
}
|
||
}
|
||
}
|
||
function handleUpEvent() {
|
||
this.coordinate_ = null;
|
||
this.feature_ = null;
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* loading spinner
|
||
* author: khy
|
||
* start
|
||
* mapLoadStart();
|
||
* end
|
||
* mapLoadEnd();
|
||
*/
|
||
ol.Map.prototype.addLoadingEffect = function (option) {
|
||
const css = `
|
||
@keyframes spinner {
|
||
to {
|
||
transform: rotate(360deg);
|
||
}
|
||
}
|
||
#map {
|
||
background: linear-gradient(to top left, #005bac, #3a3a3f);
|
||
}
|
||
${option?.transparent ? "/*" : ""}
|
||
#map > .ol-viewport {
|
||
display: none;
|
||
}
|
||
${option?.transparent ? "*/" : ""}
|
||
${option?.background ? "" : "/*"}
|
||
#map.spinner::before {
|
||
content: "";
|
||
position: absolute;
|
||
width: 100%;
|
||
height: 100%;
|
||
background: ${option?.background};
|
||
z-index:8;
|
||
}
|
||
${option?.background ? "" : "*/"}
|
||
#map.spinner::after {
|
||
content: "";
|
||
box-sizing: border-box;
|
||
position: absolute;
|
||
top: 50%;
|
||
left: 50%;
|
||
width: 40px;
|
||
height: 40px;
|
||
margin-top: -20px;
|
||
margin-left: -20px;
|
||
border-radius: 50%;
|
||
border: 4px solid ${option?.color ? option.color : "white"};
|
||
border-top-color: transparent;
|
||
animation: spinner 0.6s linear infinite;
|
||
z-index:9;
|
||
}
|
||
`;
|
||
|
||
const head = document.head || document.getElementsByTagName("head")[0];
|
||
|
||
if (head.querySelector("style[usage=spinner]")) {
|
||
return;
|
||
}
|
||
|
||
const style = document.createElement("style");
|
||
style.setAttribute("usage", "spinner");
|
||
style.type = "text/css";
|
||
|
||
if (style.styleSheet) {
|
||
style.styleSheet.cssText = css;
|
||
} else {
|
||
style.appendChild(document.createTextNode(css));
|
||
}
|
||
|
||
head.appendChild(style);
|
||
};
|
||
ol.Map.prototype.removeLoadingEffect = function () {
|
||
const head = document.head || document.getElementsByTagName("head")[0];
|
||
head.querySelector("style[usage=spinner]")?.remove();
|
||
};
|
||
ol.Map.prototype.startLoadingEffect = function (option) {
|
||
this.addLoadingEffect(option);
|
||
this.getTargetElement().classList.add("spinner");
|
||
};
|
||
ol.Map.prototype.finishLoadingEffect = function () {
|
||
this.removeLoadingEffect();
|
||
this.getTargetElement().classList.remove("spinner");
|
||
}; |