Object data
This commit is contained in:
199
client/src/components/map/Measure/MeasureStyles.ts
Normal file
199
client/src/components/map/Measure/MeasureStyles.ts
Normal file
@ -0,0 +1,199 @@
|
||||
import { FeatureLike } from "ol/Feature";
|
||||
import { LineString, Point, Polygon } from "ol/geom";
|
||||
import Geometry, { Type } from "ol/geom/Geometry";
|
||||
import { Fill, RegularShape, Stroke, Style, Text } from "ol/style";
|
||||
import CircleStyle from "ol/style/Circle";
|
||||
import { getArea, getLength } from 'ol/sphere'
|
||||
import { Modify } from "ol/interaction";
|
||||
import { getMeasureShowSegments } from "../../../store/map";
|
||||
|
||||
export const style = new Style({
|
||||
fill: new Fill({
|
||||
color: 'rgba(255, 255, 255, 0.2)',
|
||||
}),
|
||||
stroke: new Stroke({
|
||||
color: 'rgba(0, 0, 0, 0.5)',
|
||||
lineDash: [10, 10],
|
||||
width: 2,
|
||||
}),
|
||||
image: new CircleStyle({
|
||||
radius: 5,
|
||||
stroke: new Stroke({
|
||||
color: 'rgba(0, 0, 0, 0.7)',
|
||||
}),
|
||||
fill: new Fill({
|
||||
color: 'rgba(255, 255, 255, 0.2)',
|
||||
}),
|
||||
}),
|
||||
});
|
||||
|
||||
export const labelStyle = new Style({
|
||||
text: new Text({
|
||||
font: '14px Calibri,sans-serif',
|
||||
fill: new Fill({
|
||||
color: 'rgba(255, 255, 255, 1)',
|
||||
}),
|
||||
backgroundFill: new Fill({
|
||||
color: 'rgba(0, 0, 0, 0.7)',
|
||||
}),
|
||||
padding: [3, 3, 3, 3],
|
||||
textBaseline: 'bottom',
|
||||
offsetY: -15,
|
||||
}),
|
||||
image: new RegularShape({
|
||||
radius: 8,
|
||||
points: 3,
|
||||
angle: Math.PI,
|
||||
displacement: [0, 10],
|
||||
fill: new Fill({
|
||||
color: 'rgba(0, 0, 0, 0.7)',
|
||||
}),
|
||||
}),
|
||||
});
|
||||
|
||||
export const tipStyle = new Style({
|
||||
text: new Text({
|
||||
font: '12px Calibri,sans-serif',
|
||||
fill: new Fill({
|
||||
color: 'rgba(255, 255, 255, 1)',
|
||||
}),
|
||||
backgroundFill: new Fill({
|
||||
color: 'rgba(0, 0, 0, 0.4)',
|
||||
}),
|
||||
padding: [2, 2, 2, 2],
|
||||
textAlign: 'left',
|
||||
offsetX: 15,
|
||||
}),
|
||||
});
|
||||
|
||||
export const modifyStyle = new Style({
|
||||
image: new CircleStyle({
|
||||
radius: 5,
|
||||
stroke: new Stroke({
|
||||
color: 'rgba(0, 0, 0, 0.7)',
|
||||
}),
|
||||
fill: new Fill({
|
||||
color: 'rgba(0, 0, 0, 0.4)',
|
||||
}),
|
||||
}),
|
||||
text: new Text({
|
||||
text: 'Drag to modify',
|
||||
font: '12px Calibri,sans-serif',
|
||||
fill: new Fill({
|
||||
color: 'rgba(255, 255, 255, 1)',
|
||||
}),
|
||||
backgroundFill: new Fill({
|
||||
color: 'rgba(0, 0, 0, 0.7)',
|
||||
}),
|
||||
padding: [2, 2, 2, 2],
|
||||
textAlign: 'left',
|
||||
offsetX: 15,
|
||||
}),
|
||||
});
|
||||
|
||||
export const segmentStyle = new Style({
|
||||
text: new Text({
|
||||
font: '12px Calibri,sans-serif',
|
||||
fill: new Fill({
|
||||
color: 'rgba(255, 255, 255, 1)',
|
||||
}),
|
||||
backgroundFill: new Fill({
|
||||
color: 'rgba(0, 0, 0, 0.4)',
|
||||
}),
|
||||
padding: [2, 2, 2, 2],
|
||||
textBaseline: 'bottom',
|
||||
offsetY: -12,
|
||||
}),
|
||||
image: new RegularShape({
|
||||
radius: 6,
|
||||
points: 3,
|
||||
angle: Math.PI,
|
||||
displacement: [0, 8],
|
||||
fill: new Fill({
|
||||
color: 'rgba(0, 0, 0, 0.4)',
|
||||
}),
|
||||
}),
|
||||
});
|
||||
|
||||
const formatLength = function (line: Geometry) {
|
||||
const length = getLength(line);
|
||||
let output;
|
||||
if (length > 100) {
|
||||
output = Math.round((length / 1000) * 100) / 100 + ' km';
|
||||
} else {
|
||||
output = Math.round(length * 100) / 100 + ' m';
|
||||
}
|
||||
return output;
|
||||
};
|
||||
|
||||
const formatArea = function (polygon: Geometry) {
|
||||
const area = getArea(polygon);
|
||||
let output;
|
||||
if (area > 10000) {
|
||||
output = Math.round((area / 1000000) * 100) / 100 + ' km\xB2';
|
||||
} else {
|
||||
output = Math.round(area * 100) / 100 + ' m\xB2';
|
||||
}
|
||||
return output;
|
||||
};
|
||||
|
||||
export function measureStyleFunction(
|
||||
feature: FeatureLike,
|
||||
drawType?: Type,
|
||||
tip?: string,
|
||||
setTipPoint?: React.Dispatch<React.SetStateAction<Point | null>>,
|
||||
modify?: React.MutableRefObject<Modify>
|
||||
) {
|
||||
const styles = [];
|
||||
const geometry = feature.getGeometry();
|
||||
const type = geometry?.getType();
|
||||
const segmentStyles = [segmentStyle];
|
||||
|
||||
const segments = getMeasureShowSegments()
|
||||
|
||||
if (!geometry) return
|
||||
|
||||
let point, label, line;
|
||||
if (!drawType || drawType === type || type === 'Point') {
|
||||
styles.push(style);
|
||||
if (type === 'Polygon') {
|
||||
point = (geometry as Polygon).getInteriorPoint();
|
||||
label = formatArea(geometry as Polygon);
|
||||
line = new LineString((geometry as Polygon).getCoordinates()[0]);
|
||||
} else if (type === 'LineString') {
|
||||
point = new Point((geometry as Polygon).getLastCoordinate());
|
||||
label = formatLength(geometry as LineString);
|
||||
line = geometry;
|
||||
}
|
||||
}
|
||||
if (segments && line) {
|
||||
let count = 0;
|
||||
(line as LineString).forEachSegment(function (a, b) {
|
||||
const segment = new LineString([a, b]);
|
||||
const label = formatLength(segment);
|
||||
if (segmentStyles.length - 1 < count) {
|
||||
segmentStyles.push(segmentStyle.clone());
|
||||
}
|
||||
const segmentPoint = new Point(segment.getCoordinateAt(0.5));
|
||||
segmentStyles[count].setGeometry(segmentPoint);
|
||||
segmentStyles[count].getText()?.setText(label);
|
||||
styles.push(segmentStyles[count]);
|
||||
count++;
|
||||
});
|
||||
}
|
||||
if (label) {
|
||||
labelStyle.setGeometry(point as Geometry);
|
||||
labelStyle.getText()?.setText(label);
|
||||
styles.push(labelStyle);
|
||||
}
|
||||
if (
|
||||
tip &&
|
||||
type === 'Point' &&
|
||||
!modify?.current.getOverlay()?.getSource()?.getFeatures().length
|
||||
) {
|
||||
setTipPoint?.(geometry as Point);
|
||||
tipStyle.getText()?.setText(tip);
|
||||
styles.push(tipStyle);
|
||||
}
|
||||
return styles;
|
||||
}
|
Reference in New Issue
Block a user