Skip to content

Commit

Permalink
[disasters] event map updates (#2060)
Browse files Browse the repository at this point in the history
- add tooltip that shows place name when hovering over a region
- make dot size match severity
<img width="1256" alt="Screenshot 2023-01-18 at 2 59 44 PM"
src="https://user-images.githubusercontent.com/69875368/213313864-06701b07-5faf-43c2-81f3-9e69855479ba.png">
  • Loading branch information
chejennifer authored Jan 19, 2023
1 parent dfb266b commit fea1172
Show file tree
Hide file tree
Showing 6 changed files with 181 additions and 35 deletions.
1 change: 0 additions & 1 deletion static/css/shared/_tiles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,6 @@ $border-radius: 0.5rem;

.dot {
stroke-width: 0.3px;
r: 1.2px !important;
opacity: .7;
}

Expand Down
8 changes: 5 additions & 3 deletions static/js/chart/draw_d3_map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -473,14 +473,16 @@ export function drawD3Map(
* @param projection geo projection used by the map
* @param getPointColor function to get the color for each map point
* @param getTooltipHtml function to get the html content for the tooltip
* @param minDotRadius smallest radius to use for the map points
*/
export function addMapPoints(
domContainerId: string,
mapPoints: Array<MapPoint>,
mapPointValues: { [placeDcid: string]: number },
projection: d3.GeoProjection,
getPointColor?: (point: MapPoint) => string,
getTooltipHtml?: (place: NamedPlace) => string
getTooltipHtml?: (place: NamedPlace) => string,
minDotRadius?: number
): d3.Selection<SVGCircleElement, MapPoint, SVGGElement, unknown> {
// get the smallest diagonal length of a region on the d3 map.
let minRegionDiagonal = Number.MAX_VALUE;
Expand All @@ -495,7 +497,7 @@ export function addMapPoints(
Math.pow(pathClientRect.height, 2) + Math.pow(pathClientRect.width, 2)
);
});
const minDotSize = Math.max(minRegionDiagonal * 0.02, 1.1);
const minDotSize = minDotRadius || Math.max(minRegionDiagonal * 0.02, 1.1);
const filteredMapPoints = mapPoints.filter((point) => {
return !_.isNull(projection([point.longitude, point.latitude]));
});
Expand Down Expand Up @@ -533,7 +535,7 @@ export function addMapPoints(
)
.attr("r", (point: MapPoint) => {
if (_.isEmpty(pointSizeScale) || !mapPointValues[point.placeDcid]) {
return minDotSize * 2;
return minDotSize;
}
return pointSizeScale(mapPointValues[point.placeDcid]);
});
Expand Down
56 changes: 33 additions & 23 deletions static/js/components/tiles/disaster_event_map_tile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,21 +43,22 @@ import { isChildPlaceOf } from "../../tools/shared_util";
import {
DisasterEventMapPlaceInfo,
DisasterEventPoint,
MapPointsData,
} from "../../types/disaster_event_map_types";
import { EventTypeSpec } from "../../types/subject_page_proto_types";
import {
fetchDateList,
fetchDisasterEventPoints,
fetchGeoJsonData,
getDate,
getMapPointsData,
getSeverityFilters,
onPointClicked,
} from "../../utils/disaster_event_map_utils";
import {
getEnclosedPlacesPromise,
getParentPlacesPromise,
} from "../../utils/place_utils";
import { getPlaceNames } from "../../utils/place_utils";
import { ReplacementStrings } from "../../utils/tile_utils";
import { ChartTileContainer } from "./chart_tile";
import { DisasterEventMapFilters } from "./disaster_event_map_filters";
Expand All @@ -70,6 +71,7 @@ const CSS_SELECTOR_PREFIX = "disaster-event-map";
const DATE_SUBSTRING_IDX = 10;
// TODO: make this config driven
const REDIRECT_URL_PREFIX = "/disasters/";
const MAP_POINTS_MIN_RADIUS = 0.8;

interface DisasterEventMapTilePropType {
// Id for this tile
Expand All @@ -86,8 +88,10 @@ interface DisasterEventMapTilePropType {

interface MapChartData {
geoJson: GeoJsonData;
disasterEventPoints: DisasterEventPoint[];
sources: Set<string>;
// key is disaster type and value is the map points data for that disaster
// type
mapPointsData: Record<string, MapPointsData>;
}

export function DisasterEventMapTile(
Expand Down Expand Up @@ -338,10 +342,14 @@ export function DisasterEventMapTile(
Object.values(disasterEventData.provenanceInfo).forEach((provInfo) => {
sources.add(provInfo.provenanceUrl);
});
const mapPointsData = getMapPointsData(
disasterEventData.eventPoints,
props.eventTypeSpec
);
setMapChartData({
geoJson,
disasterEventPoints: disasterEventData.eventPoints,
sources,
mapPointsData,
});
})
.catch(() => {
Expand Down Expand Up @@ -380,8 +388,7 @@ export function DisasterEventMapTile(
null /* colorScale: no color scale since no data shown on the base map */,
(geoDcid: GeoJsonFeatureProperties) =>
redirectAction(geoDcid.geoDcid) /* redirectAction */,
() =>
"" /* getTooltipHtml: no tooltips to be shown on hover over a map region */,
(place: NamedPlace) => place.name || place.dcid /* getTooltipHtml */,
() => true /* canClickRegion: allow all regions to be clickable */,
false /* shouldGenerateLegend: no legend needs to be generated since no data for base map */,
true /* shouldShowBoundaryLines */,
Expand All @@ -390,24 +397,27 @@ export function DisasterEventMapTile(
"" /* zoomDcid: no dcid to zoom in on */,
zoomParams
);
const pointValues = {};
const pointsLayer = addMapPoints(
props.id,
mapChartData.disasterEventPoints,
pointValues,
projection,
(point: DisasterEventPoint) => {
return props.eventTypeSpec[point.disasterType].color;
}
);
pointsLayer.on("click", (point: DisasterEventPoint) =>
onPointClicked(
infoCardRef.current,
svgContainerRef.current,
point,
d3.event
)
);
for (const mapPointsData of Object.values(mapChartData.mapPointsData)) {
const pointsLayer = addMapPoints(
props.id,
mapPointsData.points,
mapPointsData.values,
projection,
(point: DisasterEventPoint) => {
return props.eventTypeSpec[point.disasterType].color;
},
undefined,
MAP_POINTS_MIN_RADIUS
);
pointsLayer.on("click", (point: DisasterEventPoint) =>
onPointClicked(
infoCardRef.current,
svgContainerRef.current,
point,
d3.event
)
);
}
}

/**
Expand Down
6 changes: 6 additions & 0 deletions static/js/types/disaster_event_map_types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,9 @@ export interface DisasterEventPointData {
eventPoints: DisasterEventPoint[];
provenanceInfo: Record<string, EventApiProvenanceInfo>;
}

// Data about a set of map points to show on a map.
export interface MapPointsData {
points: DisasterEventPoint[];
values: { [placeDcid: string]: number };
}
45 changes: 45 additions & 0 deletions static/js/utils/disaster_event_map_utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import {
DisasterEventDataApiResponse,
DisasterEventPoint,
DisasterEventPointData,
MapPointsData,
} from "../types/disaster_event_map_types";
import {
EventTypeSpec,
Expand Down Expand Up @@ -444,3 +445,47 @@ export function getSeverityFilters(
}
return severityFilters;
}

/**
* gets the severity value for a disaster event point
* @param eventPoint event point to get the severity value from
* @param eventTypeSpec event type spec used for the disaster event map
*/
function getSeverityValue(
eventPoint: DisasterEventPoint,
eventTypeSpec: Record<string, EventTypeSpec>
): number {
const severityFilter =
eventTypeSpec[eventPoint.disasterType].defaultSeverityFilter;
if (!severityFilter || !(severityFilter.prop in eventPoint.severity)) {
return null;
}
return eventPoint.severity[severityFilter.prop];
}

/**
* Gets the map points data for each disaster type for a list of disaster event
* points.
* @param eventPoints event points to use for the map points data
* @param eventTypeSpec the event type spec for the disaster event map
*/
export function getMapPointsData(
eventPoints: DisasterEventPoint[],
eventTypeSpec: Record<string, EventTypeSpec>
): Record<string, MapPointsData> {
const mapPointsData = {};
eventPoints.forEach((point) => {
if (!(point.disasterType in mapPointsData)) {
mapPointsData[point.disasterType] = {
points: [],
values: {},
};
}
mapPointsData[point.disasterType].points.push(point);
const severityValue = getSeverityValue(point, eventTypeSpec);
if (severityValue != null) {
mapPointsData[point.disasterType].values[point.placeDcid] = severityValue;
}
});
return mapPointsData;
}
Loading

0 comments on commit fea1172

Please sign in to comment.