majic / src /sections /map /control-panel.tsx
nolual's picture
Upload 55 files
0c20ea8
import React, { useState, useEffect } from "react";
import { fromJS, Map } from "immutable";
import MAP_STYLE from "./map-style-basic-v8.json";
const defaultMapStyle: Map<string, any> = fromJS(MAP_STYLE);
const defaultLayers = defaultMapStyle.get("layers");
const categories: string[] = [
"labels",
"roads",
"buildings",
"parks",
"water",
"background",
];
// Layer id patterns by category
const layerSelector: { [key: string]: RegExp } = {
background: /background/,
water: /water/,
parks: /park/,
buildings: /building/,
roads: /bridge|road|tunnel/,
labels: /label|place|poi/,
};
// Layer color class by type
const colorClass: { [key: string]: string } = {
line: "line-color",
fill: "fill-color",
background: "background-color",
symbol: "text-color",
};
function getMapStyle({ visibility, color }: MapStyleOptions): Map<string, any> {
const layers = defaultLayers
.filter((layer: any) => {
const id = layer.get("id");
return categories.every(
(name) => visibility[name] || !layerSelector[name].test(id)
);
})
.map((layer: any) => {
const id = layer.get("id");
const type = layer.get("type");
const category = categories.find((name) => layerSelector[name].test(id));
if (category && colorClass[type]) {
return layer.setIn(["paint", colorClass[type]], color[category]);
}
return layer;
});
return defaultMapStyle.set("layers", layers);
}
interface MapStyleOptions {
visibility: { [key: string]: boolean };
color: { [key: string]: string };
}
interface StyleControlsProps {
onChange: (style: Map<string, any>) => void;
}
function StyleControls(props: StyleControlsProps) {
const [visibility, setVisibility] = useState<any>({
water: true,
parks: true,
buildings: true,
roads: true,
labels: true,
background: true,
});
const [color, setColor] = useState<any>({
water: "#DBE2E6",
parks: "#E6EAE9",
buildings: "#c0c0c8",
roads: "#ffffff",
labels: "#78888a",
background: "#EBF0F0",
});
useEffect(() => {
props.onChange(getMapStyle({ visibility, color }));
}, [visibility, color]);
const onColorChange = (name: string, value: string) => {
setColor({ ...color, [name]: value });
};
const onVisibilityChange = (name: string, value: boolean) => {
setVisibility({ ...visibility, [name]: value });
};
return (
<div className="control-panel">
<h3>Dynamic Styling</h3>
<hr />
{categories.map((name) => (
<div
key={name}
className="input"
style={{
display: "flex",
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
}}
>
<label>{name}</label>
<input
type="checkbox"
checked={visibility[name]}
onChange={(evt) => onVisibilityChange(name, evt.target.checked)}
/>
<input
type="color"
value={color[name]}
disabled={!visibility[name]}
onChange={(evt) => onColorChange(name, evt.target.value)}
/>
</div>
))}
</div>
);
}
export default React.memo(StyleControls);