I want to paint several clusters red, but when zoom the red flags disappear. I code on vue3 optionAPI.
script.js
import View from 'ol/View'
import Map from 'ol/Map'
import TileLayer from 'ol/layer/Tile'
import OSM from 'ol/source/OSM'
import VectorLayer from 'ol/layer/Vector'
import Point from 'ol/geom/Point';
import LineString from 'ol/geom/LineString';
import VectorSource from 'ol/source/Vector';
import Feature from 'ol/Feature'
import {
Circle as CircleStyle,
Fill,
Stroke,
Style,
Text,
} from 'ol/style';
import Overlay from 'ol/Overlay';
import Cluster from "ol/source/Cluster"
import { useGeographic } from 'ol/proj';
import 'ol/ol.css'
import './style.css'
import axios from 'axios'
export default {
name: 'MapContainer',
components: {},`your text`
props: {},
data() {
return {
place: [43.984506, 56.305298],
data: [],
featuresPoints: [],
featuresLines: [],
}
},
methods: {
async getData() {
axios("https://someRestApiLink.com").then(res => {
this.data = res.data;
this.createFeachers();
this.renderMap();
});
},
setCircleStyle(feature) {
const size = feature.get('features').length;
let style = styleCache[size];
if (!style) {
style = new Style({
image: new CircleStyle({
radius: 10,
stroke: new Stroke({
color: '#fff',
}),
fill: new Fill({
color: '#3399CC',
}),
}),
text: new Text({
text: size.toString(),
fill: new Fill({
color: '#fff',
}),
}),
});
styleCache[size] = style;
}
return style;
},
createFeachers() {
for (let item of this.data) {
let coords = JSON.parse(item.coords);
if (coords.length === 1) {
let feature = new Feature(new Point(coords[0].reverse()));
feature.mydata = item;
this.featuresPoints.push(feature);
} else {
let rightCoords = coords.map(el => el.reverse());
let isValidFeacture = true;
for (let i = 0; i < rightCoords.length - 1; i++) {
if (Math.abs(rightCoords[i][0] - rightCoords[i + 1][0]) > .01) {
isValidFeacture = false;
break
}
}
if (!isValidFeacture) continue;
let feature = new Feature({
geometry: new LineString(rightCoords)
});
feature.setStyle(new Style({
stroke: new Stroke({
color: '#0000ff',
width: 3
})
}))
feature.mydata = item
this.featuresLines.push(feature);
}
}
},
createMap() {
return new Map({
target: this.$refs['map-root'],
view: new View({
zoom: 12,
center: this.place
}),
layers: [
new TileLayer({
source: new OSM()
}),
this.createLineLayer(),
this.createPointLayer(),
],
});
},
createPointLayer() {
const styleCache = {};
let cluster = new Cluster({
distance: 15,
minDistance: 6,
source: new VectorSource({
features: this.featuresPoints,
})
});
const mainCluster = new VectorLayer({
source: cluster,
style: function (feature) {
function calculateFired(cluster, length) {
let pointList = cluster.values_.features;
let countFired = 0;
for (let point of pointList) {
if (point.mydata.status === "Просрочен") {
countFired++;
}
}
return countFired === length ? "full" : countFired > 0 ? "several" : "none";
}
const size = feature.get('features').length;
let style = styleCache[size];
if (!style) {
let hasFired = calculateFired(feature, size);
style = new Style({
image: new CircleStyle({
radius: 10,
stroke: new Stroke({
color: hasFired === "none" ? '#fff' : "#f00",
// color: '#fff',
}),
fill: new Fill({
color: hasFired === "full" ? "#f00" : '#3399CC',
// color: '#3399CC',
}),
}),
text: new Text({
text: size.toString(),
fill: new Fill({
color: '#fff',
}),
}),
});
styleCache[size] = style;
// console.log(style);
}
return style;
},
});
mainCluster.mydata = this.featuresPoints.map(el => el.mydata);
return mainCluster
},
createLineLayer() {
return new VectorLayer({
source: new VectorSource({
features: this.featuresLines,
}),
})
},
renderMap() {
useGeographic();
const createPopUp = this.createPopUp;
var container = document.getElementById("popup");
var content = document.getElementById("popup-content");
const map = this.createMap();
const overlay = new Overlay({
element: container,
autoPan: true
});
map.on('click', function (e) {
let pixel = map.getEventPixel(e.originalEvent);
if (document.getElementsByClassName('popup-content').length != 0) {
document.getElementsByClassName('popup-content')[0].style.display = 'none'
}
map.forEachFeatureAtPixel(pixel, function (feature) {
let data = feature.mydata ?? feature.values_.features.map(el => el.mydata);
let coodinate = e.coordinate;
content.innerHTML = createPopUp(data);
overlay.setPosition(coodinate);
map.addOverlay(overlay);
});
});
},
createPopUp(data) {
let content = "";
if (data.length) {
let sortedData = data.sort((a, b)=> {
if (a.time.split(".").reverse().join("-") > b.time.split(".").reverse().join("-")) return 1;
if (a.time.split(".").reverse().join("-") < b.time.split(".").reverse().join("-")) return -1;
return 0;
});
for (let el of sortedData) {
content += `
<div class="popup-content__valueBlock">
<div class="popup-content__valueBlock__organization">
${el.organization}:
</div>
<div class="popup-content__valueBlock__aimOfWorks">
Тип: ${el.aim_of_works}
</div>
<div class="popup-content__valueBlock__stripSurface">
Работы ведутся над: ${el.strip_surface}
</div>
<div class="popup-content__valueBlock__status">
${el.status} - ${el.finish_date}
</div>
</div>
`;
}
} else {
content = `
<div class="popup-content__valueBlock">
<div class="popup-content__valueBlock__organization">
${data.organization}:
</div>
<div class="popup-content__valueBlock__aimOfWorks">
Тип: ${data.aim_of_works}
</div>
<div class="popup-content__valueBlock__stripSurface">
Работы ведутся над: ${data.strip_surface}
</div>
<div class="popup-content__valueBlock__status">
${data.status} - ${data.time}
</div>
</div>
`;
}
return `
<div class="popup-content">
<span class="close" onclick="closePopup()">x</span>
<span class="count">Количество выбранных ордеров: ${data.length ?? 1}</span>
${content}
</div>
`;
},
},
mounted() {
this.getData();
},
}
I checked ol_uid
of cluster when I rezoomed, and I was so surprised by changed this property at the same cluster. Also I tried to rerender map at every time when I changed zoom, but this not work too.
I think that I mb do something wrong on creating or rendering map or clusters.