Skip to content

Commit f6bcd07

Browse files
committed
style model icons
1 parent cfd916b commit f6bcd07

9 files changed

Lines changed: 87 additions & 36 deletions

File tree

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/* eslint-disable max-len */
2+
import React from 'react';
3+
import { IIconProps } from '../../types';
4+
5+
interface Props extends IIconProps {
6+
fill?: string; // transparent inner color
7+
stroke?: string; // border color
8+
opacity?: number; // inner transparency
9+
size?: number;
10+
}
11+
12+
export const IconCircle: React.FC<Props> = ({
13+
size = 40,
14+
fill = '#d22819ff',
15+
stroke = '#d21919ff',
16+
opacity = 0.35,
17+
}) => {
18+
const cx = size / 2;
19+
const cy = size / 2;
20+
const r = size / 2 - 2;
21+
22+
return (
23+
<svg
24+
width={size}
25+
height={size}
26+
viewBox={`0 0 ${size} ${size}`}
27+
xmlns="http://www.w3.org/2000/svg"
28+
>
29+
<circle
30+
cx={cx}
31+
cy={cy}
32+
r={r}
33+
fill={fill}
34+
fillOpacity={opacity}
35+
stroke={stroke}
36+
strokeWidth={2}
37+
/>
38+
39+
{/* center dot */}
40+
<circle
41+
cx={cx}
42+
cy={cy}
43+
r={3}
44+
fill="red"
45+
/>
46+
</svg>
47+
);
48+
};

src/components/map/markers/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@ export * from './IconScooter';
77
export * from './IconQuestion';
88
export * from './IconTruck';
99
export * from './IconVehicle';
10-
export * from './IconWalk';
10+
export * from './IconWalk';
11+
export * from './IconCircle';

src/components/model/JunctionRadiusPicker.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,16 @@ export const JunctionRadiusPicker: React.FC<JunctionRadiusPickerProps> = ({
2323
<Form.Label className="fw-semibold mb-0">
2424
{text}
2525
</Form.Label>
26-
26+
<div style={{ width: 100 }}>
2727
<Form.Range
28+
2829
min={min}
2930
max={max}
3031
step={step}
3132
value={value}
3233
onChange={e => onChange(Number(e.target.value))}
3334
/>
34-
35+
</div>
3536
<span className="fw-bold">{value}m</span>
3637
</Form.Group>
3738
);

src/components/model/MaxClustersPicker.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export const MaxClustersPicker: React.FC<Props> = ({
1616
<Form.Group>
1717
<Form.Label>Max clusters</Form.Label>
1818
<Form.Select
19+
size="sm"
1920
value={value}
2021
onChange={e => onChange(Number(e.target.value))}
2122
>

src/components/model/ModelClusterMarkers.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
import React, { FC } from 'react';
22
import { observer } from 'mobx-react';
33
import { ClusterRow } from '../../types';
4-
import MarkerSvg from '../map/MarkerSvg';
54
import { useSelector } from 'react-redux';
65
import { RootState } from '../../stores/types';
76
import ModelMarker from './ModelMarker';
87
import { buildSeveritySectors, getSeverityColor, getSeverityMinMax } from './modelhelper';
98

109
type Props = {
1110
clusters: ClusterRow[];
12-
colorBy?: string;
11+
colorBy?: string;
12+
isHeat: boolean;
1313
};
1414

1515
const ModelClusterMarkers: FC<Props> = observer(
16-
({ clusters, colorBy }) => {
16+
({ clusters, colorBy, isHeat }) => {
1717
const { language } = useSelector((state: RootState) => state.appUi);
1818
const { min, max } = getSeverityMinMax(clusters);
1919
const sectors = buildSeveritySectors(min, max);
@@ -28,6 +28,7 @@ const ModelClusterMarkers: FC<Props> = observer(
2828
data = {cluster}
2929
language={language}
3030
color={color}
31+
isHeat={isHeat}
3132
markerIconsType={'general'}
3233
/>
3334
);

src/components/model/ModelMap.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import ModelClusterMarkers from './ModelClusterMarkers';
99

1010
type Props = {
1111
clusters: ClusterRow[];
12+
isHeat: boolean;
1213
};
1314

1415
/** ---------- Auto-fit map to clusters ---------- */
@@ -28,7 +29,7 @@ const FitBounds: React.FC<{ clusters: ClusterRow[] }> = ({ clusters }) => {
2829
return null;
2930
};
3031

31-
export const ModelMap: React.FC<Props> = ({ clusters }) => {
32+
export const ModelMap: React.FC<Props> = ({ clusters, isHeat}) => {
3233
const mapRef = useRef<LeafletMap | null>(null);
3334
return (
3435
<Card style={{ height: '100%', padding: '0' }}>
@@ -43,7 +44,7 @@ export const ModelMap: React.FC<Props> = ({ clusters }) => {
4344
attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
4445
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
4546
/>
46-
<ModelClusterMarkers clusters={clusters} colorBy='1' />
47+
<ModelClusterMarkers clusters={clusters} colorBy='1' isHeat={isHeat} />
4748
</MapContainer>
4849
</div>
4950
</Card>

src/components/model/ModelMarker.tsx

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,34 +2,33 @@ import React from 'react';
22
import { divIcon, LatLngExpression } from 'leaflet';
33
import { Marker } from 'react-leaflet';
44
import { renderToStaticMarkup } from 'react-dom/server';
5-
import { getColors, getNumSeverity } from '../../utils/mapUtils';
6-
import { Accident, ClusterRow } from '../../types';
7-
// import { getColorByVehicle } from '../../../services/mapUtils';
8-
import {IconBike, IconBus, IconCar, IconEmpty, IconMotorcycle, IconQuestion, IconScooter, IconTruck, IconWalk } from '../map/markers';
5+
import { ClusterRow } from '../../types';
6+
import { IconEmpty, IconCircle } from '../map/markers';
97
import ModelMarkerPopUp from './ModelMarkerPopUp';
10-
//import AccidentPopUp from './AccidentPopUp';
118

129
// const iconSize = {
1310
// iconSize: [25, 41], iconAnchor: [12, 41], popupAnchor: [1, -34], shadowSize: [41, 41],
1411
// };
1512

16-
const customMarketIcon = (iconMarkup:any, isSmall :boolean = false) => {
17-
const size = isSmall? 9:22;
13+
const customMarketIcon = (iconMarkup:any, size :number = 40) => {
14+
const half = size / 2;
1815
const res = divIcon({
1916
html: iconMarkup,
2017
className: 'ship-div-icon',
21-
iconAnchor: [0, size],
22-
popupAnchor: [2, -(size-2)],
18+
iconAnchor: [-2, half],
19+
popupAnchor: [0, -half]
2320
});
2421
return res;
2522
};
2623

27-
const getEmptyIcon = (color: string, isAccuratePos: boolean) => {
28-
const pin = <IconEmpty fill={color} isAccuratePos={isAccuratePos}/>;
24+
const getEmptyIcon = (color: string, isHeat: boolean) => {
25+
const opacity = isHeat? 0.35: 0.8;
26+
const size = isHeat? 40: 30;
27+
const pin = <IconCircle fill={color} size={size} opacity={opacity} isAccuratePos={false}/>;
2928
const iconMarkup = renderToStaticMarkup(
3029
pin,
3130
);
32-
const res = customMarketIcon(iconMarkup);
31+
const res = customMarketIcon(iconMarkup, size);
3332
return res;
3433
};
3534

@@ -39,15 +38,13 @@ interface IProps {
3938
language: string,
4039
color : string,
4140
markerIconsType: string,
41+
isHeat: boolean
4242
}
4343
const ModelMarker: React.FC<IProps> = (({
44-
data, position, language, color, markerIconsType,
44+
data, position, language, color, isHeat,
4545
}) => {
46-
//const lPoint = new L.LatLng(data.latitude, data.longitude);
47-
//const color = (data.roadType=="junction")? '#D87F1D':'#A0202F'; //getColors(colorBy, data);
4846
const severity = 1;// getNumSeverity(data.injury_severity_hebrew);
49-
//const isSmall = severity === 3;
50-
const icon = getEmptyIcon(color, true);
47+
const icon = getEmptyIcon(color, isHeat);
5148
return (
5249
<Marker position={position} icon={icon}
5350
// @ts-ignore to allow custom props in Marker options

src/components/model/ModelTabs.tsx

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -80,11 +80,6 @@ const ModelTabs: React.FC<IProps> = () => {
8080
<Card.Body>
8181
{/* -------- Controls -------- */}
8282
<div className="d-flex flex-wrap gap-4 mb-3">
83-
<JunctionRadiusPicker
84-
value={junctionRadius}
85-
onChange={setJunctionRadius}
86-
text = "Junction radius"
87-
/>
8883
<JunctionRadiusPicker
8984
value={heatmapRadius}
9085
onChange={setHeatmapRadius}
@@ -93,6 +88,12 @@ const ModelTabs: React.FC<IProps> = () => {
9388
max = {200}
9489
step = {50}
9590
/>
91+
<JunctionRadiusPicker
92+
value={junctionRadius}
93+
onChange={setJunctionRadius}
94+
text = "Junction radius"
95+
/>
96+
9697

9798
<SeverityModePicker
9899
value={severityMode}
@@ -120,15 +121,15 @@ const ModelTabs: React.FC<IProps> = () => {
120121
<ClusterTable clusterTable={clusterTableDensity} />
121122
</Tab>
122123
<Tab eventKey="hetmap" title={t('HeatMap')}>
123-
<ModelMap clusters={clusterTableDensity}/>
124+
<ModelMap clusters={clusterTableDensity} isHeat={true}/>
124125
</Tab>
125126

126127
<Tab eventKey="table" title={t('Table')}>
127128
<ClusterTable clusterTable={clusterTable} />
128129
</Tab>
129130

130131
<Tab eventKey="map" title={t('Map')}>
131-
<ModelMap clusters={clusterTable}/>
132+
<ModelMap clusters={clusterTable} isHeat={false}/>
132133
</Tab>
133134
</Tabs>
134135
</Card.Body>

src/components/model/SeverityModePicker.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,16 @@ export const SeverityModePicker: React.FC<SeverityModePickerProps> = ({
1919

2020
<Form.Select
2121
size="sm"
22-
style={{ width: 260 }}
22+
style={{ width: 170 }}
2323
value={value}
2424
onChange={e =>
2525
onChange(Number(e.target.value) as ModelSeverityMode)
2626
}
2727
>
2828
<option value={1}>All accidents equal</option>
29-
<option value={2}>Pedestrian weighted</option>
30-
<option value={3}>Pedestrian + electric</option>
31-
<option value={4}>Fatal override</option>
29+
<option value={2}>Pedestrian*2</option>
30+
<option value={3}>Pedestrian*2, Bike*1.5</option>
31+
<option value={4}>Fatal*2</option>
3232
</Form.Select>
3333
</Form.Group>
3434
);

0 commit comments

Comments
 (0)