I have GeoJSON vectors on OpenLayers map where I have OlRegularShape 'square' points in my layer as shown below.
I want to add another square point to show different stats as shown below.
Second square does not has any fixed coordinates it should be bounded to the big square whenever map zoomed in and zoomed out small square should move with the big one.
I tried several ways to move the small square but neither works as expected. Can anyone suggest me a solution to overcome this problem?
Is there any way to set offset to features rather than layer?
Is there any easy way to accomplish this feature on client ?
JS code for layer creation
let existsZoomLevel = this.settingsService.getLiveMapZoomLevel()
let mapZoomLevel = existsZoomLevel ? Number(existsZoomLevel) : 16;
this.source = new OlVector({});
// big square layer
this.dockLayer = new OlVectorLayer({
style: (f, r) => this.styleDockFunction(f, r),
source: new OlVector({}),
});
//small square layer
this.countLayer = new OlVectorLayer({
style: (f, r) => this.styleLabelFunction(f, r),
source: new OlVector({})
});
let tileLayer = new OlTileLayer({
source: new OlXYZ({
crossOrigin: null,
url: 'https://cartodb-basemaps-{a-c}.global.ssl.fastly.net/light_all/{z}/{x}/{y}.png'
})
});
let view = new OlView({
center: OlProj.fromLonLat([5.73271, 58.96564]),
zoom: mapZoomLevel,
});
this.map = new OlMap({
layers: [tileLayer, this.dockLayer, this.countLayer],
view: view
});
Style function for layers below
//big square style
static getDockingStationsStyles(highlighted: boolean = false, color: string = '#FF2C00'): OlStyle[] {
let featureColor = highlighted ? '#FF2C00' : '#04A3E3';
if (color) {
featureColor = color;
}
let imageRadius = highlighted ? 5 : 2;
let strokeWidth = highlighted ? 3 : 2;
let styles = [
// polygon
new OlStyle({
stroke: new OlStroke({
color: featureColor,
width: strokeWidth
})
}),
// point
// new OlStyle({
// image: new OlCircle({
// radius: imageRadius,
// fill: new OlFill({
// color: featureColor
// }),
// }),
// text: new OlText({
// font: `14px Roboto, "Helvetica Neue", sans-serif`,
// offsetX: 10,
// offsetY: 0,
// textAlign: 'left',
// placement: 'point',
// fill: new OlFill({
// color: '#000'
// }),
// stroke: new OlStroke({
// color: '#FFF',
// width: 2
// })
// }),
// geometry: function (feature) {
// let data = feature.get('data');
// let coordinates = [data.Position.Longitude, data.Position.Latitude];
// return new OlPoint(OlProj.fromLonLat(coordinates));
// }
// })
new OlStyle({
image: new OlRegularShape({
radius: 20,
fill: new OlFill({
color: featureColor
}),
points: 4,
angle: Math.PI / 4
}),
text: new OlText({
font: `14px Roboto, "Helvetica Neue", sans-serif`,
offsetX: 0,
offsetY: 0,
textAlign: 'center',
placement: 'point',
fill: new OlFill({
color: 'white'
}),
// stroke: new OlStroke({
// color: '#FFF',
// width: 2
// })
}),
// geometry: function (feature) {
// let data = feature.get('data');
// let coordinates = [data.Position.Longitude, data.Position.Latitude];
// return new OlPoint(OlProj.fromLonLat(coordinates));
// }
})
]
return styles;
}
// small square style
static getTickStationsStyles(highlighted: boolean = false, color: string = '#FF2C00'): OlStyle[] {
let featureColor = highlighted ? '#FF2C00' : '#04A3E3';
if (color) {
featureColor = color;
}
let imageRadius = highlighted ? 5 : 2;
let strokeWidth = highlighted ? 3 : 2;
let styles = [
// polygon
new OlStyle({
stroke: new OlStroke({
color: featureColor,
width: strokeWidth
})
}),
// point
new OlStyle({
image: new OlRegularShape({
radius: 10,
fill: new OlFill({
color: featureColor
}),
points: 4,
angle: Math.PI / 4
}),
text: new OlText({
font: `14px Roboto, "Helvetica Neue", sans-serif`,
offsetX: 0,
offsetY: 0,
textAlign: 'center',
placement: 'point',
fill: new OlFill({
color: '#000'
}),
stroke: new OlStroke({
color: '#FFF',
width: 2
})
}),
// geometry: function (feature) {
// let data = feature.get('data');
// let coordinates = [data.Position.Longitude, data.Position.Latitude];
// return new OlPoint(OlProj.fromLonLat(coordinates));
// }
})
]
return styles;
}
feature adding for two squares
getDockingStationAreaFeature(station: DockingStation) {
let point = [station.Position.Longitude, station.Position.Latitude];
let polygon = new OlPoint(point);
polygon.transform('EPSG:4326', 'EPSG:3857');
station.StationStatus = this.getDockedBikeStatus(station.DockingStationId);
let feature = new OlFeature({
name: station.NumberOfAvailableBikes.toString(),
geometry: polygon,
data: station,
type: "dock"
});
feature.setId(station.DockingStationId);
return feature;
}
getTickStationAreaFeature(station: DockingStation) {
let point = [station.Position.Longitude, station.Position.Latitude];
let feature = new OlFeature({
name: station.TotalNumberOfPoints.toString(),
geometry: new OlPoint(OlProj.transform(point, 'EPSG:4326', 'EPSG:3857')),
data: station,
type: "tick"
});
feature.setId(station.DockingStationId);
return feature;
}
getDockedBikeStatus(dockingStationId) {
let filteredBikes = this.filteredBikes.filter(x => x.DockingStationId == dockingStationId);
let status = StationColors.AVAILABLE_BIKES;
for (let bike in filteredBikes) {
if (filteredBikes[bike]["Bike"].Disabled) {
status = StationColors.AVAILABLE_WITH_DISABLED;
break;
}
else if (!filteredBikes[bike]["Bike"].Disabled && filteredBikes[bike]["Bike"].Acknowledged != 0) {
status = StationColors.AVAILABLE_WITH_ERRORS;
break;
}
}
return status;
}
public addDockingStation(station: DockingStation, centerToPoint: boolean = true): void {
let point = [station.Position.Longitude, station.Position.Latitude];
let projectedPoint = OlProj.fromLonLat(point);
station.AddressStr = DockingStationExtension.GetAddress(station.Address);
let areaFeature = this.getDockingStationAreaFeature(station);
let tickFeature = this.getTickStationAreaFeature(station);
let dockSource = this.dockLayer.getSource();
let tickSource = this.countLayer.getSource();
dockSource.addFeature(areaFeature);
//tickFeature.getGeometry().translate(station.Position.Longitude + 1, station.Position.Longitude + 0.0004);
tickSource.addFeature(tickFeature);
if (centerToPoint) {
this.map.getView().setCenter(projectedPoint);
}
}
Best Answer
As I wrote in my comment, I'm not familiar with Angular environment. Since you replied that any hint is welcome, here it is, with standard JS.
The simplest way to create such markers is with
ol.Overlay
layer, using HTML elements for marker design/display.First you create hidden dummy div with two child div elements for marker:
Here
marker-txt
is for main marker text andmarker-txt2
for smaller text in upper right corner.Then you define appropriate CSS classes for marker display (this takes a bit of experimenting):
Then you define a function for creating desired markers, using
ol.Overlay
. Since it will be used for several markers,.cloneNode
method is used to clone dummy marker for each newly created marker:Here is example of creation of three markers:
And that's how they look like when displayed: