Skip to content

Commit

Permalink
feat(web): preset layer style (#1156)
Browse files Browse the repository at this point in the history
  • Loading branch information
mkumbobeaty authored Sep 30, 2024
1 parent 43ad72e commit 67cad92
Show file tree
Hide file tree
Showing 5 changed files with 392 additions and 16 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
import {
IconButton,
PopupMenu,
PopupMenuItem
} from "@reearth/beta/lib/reearth-ui";
import { LayerStyle } from "@reearth/services/api/layerStyleApi/utils";
import { useT } from "@reearth/services/i18n";
import { useState, useEffect, FC, useCallback } from "react";

import { LayerStyleAddProps } from "../../../hooks/useLayerStyles";

import {
defaultStyle,
professionalStyle,
pointStyle,
pointWithLabelStyle,
polylineStyle,
polygonStyle,
extrudedPolygonStyle,
threeDTilesStyle,
simpleStyle,
colorBuildingsByHeight,
getLayerStyleName
} from "./presetLayerStyles";

type PresetLayerStyleProps = {
layerStyles: LayerStyle[] | undefined;
onLayerStyleAdd: (inp: LayerStyleAddProps) => void;
onLayerStyleSelect: (id: string | undefined) => void;
};

const PresetLayerStyle: FC<PresetLayerStyleProps> = ({
layerStyles,
onLayerStyleAdd,
onLayerStyleSelect
}) => {
const t = useT();
const [layerStyleAdded, setLayerStyleAdded] = useState<string | undefined>(
undefined
);

const handleLayerStyleAddition = useCallback(
(value?: Record<string, unknown>, styleName?: string) => {
const name = getLayerStyleName(
styleName ? styleName : t("Style"),
layerStyles
);
onLayerStyleAdd({
name,
value: value || {}
});
setLayerStyleAdded(name);
},
[t, layerStyles, onLayerStyleAdd]
);

useEffect(() => {
if (layerStyleAdded && layerStyles) {
const addedStyle = layerStyles.find(
(style) => style.name === layerStyleAdded
);
onLayerStyleSelect(addedStyle?.id);
}
}, [layerStyles, onLayerStyleSelect, layerStyleAdded]);

const menuItems: PopupMenuItem[] = [
{
id: "empty",
title: t("Empty"),
onClick: () => handleLayerStyleAddition({})
},
{
id: "default",
title: t("Default"),
onClick: () => handleLayerStyleAddition(defaultStyle, "Default")
},
{
id: "professional",
title: t("Professional"),
onClick: () => handleLayerStyleAddition(professionalStyle, "Professional")
},
{
id: "basicGeometry",
title: t("Basic Geometry"),
icon: "folderSimple",
subItem: [
{
id: "point",
title: t("Points"),
onClick: () => handleLayerStyleAddition(pointStyle, "Points")
},
{
id: "pointWithLabel",
title: t("Point with label"),
onClick: () =>
handleLayerStyleAddition(pointWithLabelStyle, "Point_with_label")
},
{
id: "polyline",
title: t("Polyline"),
onClick: () => handleLayerStyleAddition(polylineStyle, "Polyline")
},
{
id: "polygon",
title: t("Polygon"),
onClick: () => handleLayerStyleAddition(polygonStyle, "Polygon")
},
{
id: "extrudedPolygon",
title: t("Extruded polygon"),
onClick: () =>
handleLayerStyleAddition(extrudedPolygonStyle, "Extruded_polygon")
},
{
id: "threedTiles",
title: t("3D Tiles"),
onClick: () => handleLayerStyleAddition(threeDTilesStyle, "3D_tiles")
}
]
},
{
id: "geometry",
title: t("Geometry"),
icon: "folderSimple",
subItem: [
{
id: "simpleStyle",
title: t("Simple Style"),
onClick: () => handleLayerStyleAddition(simpleStyle, "Simple_style")
}
]
},
{
id: "plateau",
title: t("Plateau"),
icon: "folderSimple",
subItem: [
{
id: "colorBuilding",
title: t("Color buildings by height"),
onClick: () =>
handleLayerStyleAddition(
colorBuildingsByHeight,
"Color_buildings_by_height"
)
}
]
}
];

return (
<PopupMenu
menu={menuItems}
label={<IconButton icon="plus" size="large" />}
/>
);
};

export default PresetLayerStyle;
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
import { LayerStyle } from "@reearth/services/api/layerStyleApi/utils";

export const defaultStyle = {
marker: {
heightReference: "clamp"
},
polygon: {
extrudedHeight: {
expression: "${extrudedHeight}"
},
fillColor: {
expression: "color('#ffffff',0.8)"
},
heightReference: "clamp"
},
polyline: {
clampToGround: true,
strokeColor: "#FFFFFF",
strokeWidth: 2
}
};

export const professionalStyle = {
marker: {
heightReference: "clamp",
hideIndicator: false,
pointColor: "#E9373D",
pointOutlineColor: "white",
pointOutlineWidth: 1,
pointSize: 12,
selectedFeatureColor: "#F1AF02",
style: "point"
},
polygon: {
extrudedHeight: {
expression: "${extrudedHeight}"
},
fillColor: {
expression: "color('#E9373D',0.6)"
},
heightReference: "clamp",
hideIndicator: false,
selectedFeatureColor: {
expression: "color('#F1AF02',0.6)"
}
},
polyline: {
clampToGround: true,
hideIndicator: false,
selectedFeatureColor: "#F1AF02",
strokeColor: "#E9373D",
strokeWidth: 2
}
};

export const pointStyle = {
marker: {
height: 0,
heightReference: "relative",
pointColor: "#E9373D",
pointOutlineColor: "white",
pointOutlineWidth: 1,
pointSize: 12,
style: "point"
}
};

export const pointWithLabelStyle = {
marker: {
height: 0,
heightReference: "relative",
label: true,
labelPosition: "right",
labelText: "text",
pointColor: "#E9373D",
pointOutlineColor: "white",
pointOutlineWidth: 1,
pointSize: 12,
style: "point"
}
};

export const polylineStyle = {
polyline: {
clampToGround: true,
hideIndicator: false,
selectedFeatureColor: "#F1AF02",
strokeColor: "#E9373D",
strokeWidth: 2
}
};

export const polygonStyle = {
polygon: {
fillColor: "#E9373D",
heightReference: "clamp",
hideIndicator: false,
selectedFeatureColor: "#F1AF02"
}
};

export const extrudedPolygonStyle = {
polygon: {
extrudedHeight: {
expression: "${extrudedHeight}"
},
fillColor: "#E9373D",
heightReference: "clamp",
hideIndicator: false,
selectedFeatureColor: "#F1AF02"
}
};

export const threeDTilesStyle = {
"3dtiles": {
color: "#FFFFFF",
colorBlendMode: "highlight",
pbr: false
}
};

export const simpleStyle = {
marker: {
pointColor: {
expression: "${marker-color}"
},
pointOutlineColor: {
expression: "${marker-color}"
},
pointSize: {
expression: {
conditions: [
["${marker-size}==='small'", "8"],
["${marker-size}==='medium'", "12"],
["${marker-size}==='large'", "16"]
]
}
},
style: "point"
},
polygon: {
fillColor: {
expression: "color(${fill},${fill-opacity})"
},
heightReference: "clamp",
stroke: "true",
strokeColor: {
expression: "${stroke}"
},
strokeWidth: {
expression: "${stroke-width}"
}
},
polyline: {
clampToGround: true,
strokeColor: {
expression: "color(${stroke},${stroke-opacity})"
},
strokeWidth: {
expression: "${stroke-width}"
}
}
};

export const colorBuildingsByHeight = {
"3dtiles": {
color: {
expression: {
conditions: [
["${計測高さ}>=180", "color('#F9FD4C')"],
["${計測高さ}>=120", "color('#F6CD3D')"],
["${計測高さ}>=60", "color('#EBD384')"],
["${計測高さ}>=31", "color('#9E79BA')"],
["${計測高さ}>=12", "color('#5230C2')"],
["true", "color('#362C52')"]
]
}
},
colorBlendMode: "highlight",
pbr: false,
shadows: "disabled"
}
};

export const getLayerStyleName = (
baseName: string,
layerStyles?: LayerStyle[]
) => {
if (!layerStyles) return `${baseName}.01`;
const nextNumber =
layerStyles.reduce((max, style) => {
const escapedBaseName = baseName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
const match = style.name?.match(
new RegExp(`^${escapedBaseName}\\.(\\d+)$`)
);
return match ? Math.max(max, parseInt(match[1], 10)) : max;
}, 0) + 1;

return `${baseName}.${nextNumber.toString().padStart(2, "0")}`;
};
17 changes: 5 additions & 12 deletions web/src/beta/features/Editor/Map/LayerStylePanel/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { useMapPage } from "../context";

import LayerStyleEditor from "./Editor";
import LayerStyleItem from "./LayerStyleItem";
import PresetLayerStyle from "./PresetLayerStyle";

type Props = Pick<PanelProps, "showCollapseArea" | "areaRef">;

Expand All @@ -26,13 +27,6 @@ const StylesPanel: FC<Props> = ({ showCollapseArea, areaRef }) => {

const t = useT();

const handleLayerStyleAddition = useCallback(() => {
handleLayerStyleAdd({
name: `${t("Style_")}${layerStyles?.length ?? 0 + 1}`,
value: {}
});
}, [layerStyles?.length, t, handleLayerStyleAdd]);

const handleSelectLayerStyle = useCallback(
(id?: string) => {
handleLayerStyleSelect(id);
Expand Down Expand Up @@ -67,11 +61,10 @@ const StylesPanel: FC<Props> = ({ showCollapseArea, areaRef }) => {
>
<LayerStyleManager onClick={() => handleSelectLayerStyle(undefined)}>
<ActionsWrapper>
<IconButton
icon="plus"
size="large"
onClick={handleLayerStyleAddition}
stopPropagationOnClick
<PresetLayerStyle
layerStyles={layerStyles}
onLayerStyleAdd={handleLayerStyleAdd}
onLayerStyleSelect={handleSelectLayerStyle}
/>
<IconButton
icon="return"
Expand Down
Loading

0 comments on commit 67cad92

Please sign in to comment.