Skip to content
This repository has been archived by the owner on Nov 4, 2024. It is now read-only.

Commit

Permalink
Feature/COR-1149 adjust hoverstate styling of choropleth (#4522)
Browse files Browse the repository at this point in the history
*  feat(COR-1149): Added border logic for outside borders and applied drop-shadow

* feat(COR-1149): Implements same design for tabstate as hover. Attempts to fix bug related to waterbodies in Zeeland.

* feat(COR-1149): Added a comment.

* Update packages/app/src/components/choropleth/components/canvas-choropleth-map.tsx

* feat(choropleth): PR feedback adjustments

Co-authored-by: VWSCoronaDashboard18 <[email protected]>
  • Loading branch information
APW26 and Jorrik-Klijnsma-Work authored Dec 6, 2022
1 parent 2d77492 commit 855e52c
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 73 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import type { AnchorEventHandler } from './choropleth-map';

Konva.pixelRatio = typeof window !== 'undefined' ? Math.min(window.devicePixelRatio, 2) : 1;

export type CanvasChoroplethMapProps = {
export interface CanvasChoroplethMapProps {
anchorEventHandlers: AnchorEventHandler;
annotations: AccessibilityAnnotations;
choroplethFeatures: ChoroplethFeatures;
Expand All @@ -33,7 +33,7 @@ export type CanvasChoroplethMapProps = {
mapProjection: () => GeoProjection;
tooltipTrigger: ChoroplethTooltipHandlers[2];
width: number;
};
}

/**
* This is one transparent pixel encoded in a dataUrl. This is used for the image overlay on top of the canvas that
Expand Down Expand Up @@ -181,12 +181,12 @@ export const CanvasChoroplethMap = (props: CanvasChoroplethMapProps) => {
);
};

type HighlightedFeatureProps = {
interface HighlightedFeatureProps {
feature: [number, number][][] | undefined;
featureProps: FeatureProps;
code: string | undefined;
hoverCode: string | undefined;
};
}

const HighlightedFeature = memo((props: HighlightedFeatureProps) => {
const { feature, featureProps, code, hoverCode } = props;
Expand All @@ -212,13 +212,13 @@ const HighlightedFeature = memo((props: HighlightedFeatureProps) => {
);
});

type HoveredFeatureProps = {
interface HoveredFeatureProps {
hoveredRef: RefObject<Konva.Group>;
hover: [number, number][][] | undefined;
hoverCode: string | undefined;
featureProps: FeatureProps;
isKeyboardActive?: boolean;
};
}

const HoveredFeature = memo((props: HoveredFeatureProps) => {
const { hoveredRef, hover, hoverCode, featureProps, isKeyboardActive } = props;
Expand All @@ -227,30 +227,58 @@ const HoveredFeature = memo((props: HoveredFeatureProps) => {
return null;
}

/**
* The code in the condition below is a workaround.
*
* This is required as for some reason, the water bodies also get rendered as a Feature (you can see another fix for this in the
* Features component below). As a consequence, when making the fix introduced in COR-1149 which required adding an additional
* line to the HoveredFeature, the water bodies ended up receiving the same fill colour as the land around them and thereby masking
* the white water body.
*
* To fix this, there are now two maps iterating over two arrays for Zeeland. One represents land and the other, water.
*/
let landCoords: [number, number][][] = [...hover];
let waterCoords: [number, number][][] | undefined;
if (hoverCode === 'VR19') {
landCoords = hover.filter((_, index) => index === 0 || index === 5);
waterCoords = hover.filter((_, index) => !(index === 0 || index === 5));
}

return (
<Layer listening={false}>
<Group ref={hoveredRef} listening={false}>
{hover.map((x, i) => (
<Line
listening={false}
key={i}
x={0}
y={0}
points={x.flat()}
strokeWidth={featureProps.hover.strokeWidth(hoverCode, true)}
closed
stroke={featureProps.hover.stroke(hoverCode, true, isKeyboardActive)}
/>
{landCoords.map((coordinates, index) => (
<>
<Line
listening={false}
key={index}
x={0}
y={0}
points={coordinates.flat()}
strokeWidth={featureProps.hover.strokeWidth(hoverCode, true)}
closed
stroke={featureProps.hover.stroke(hoverCode, true, isKeyboardActive)}
shadowColor={colors.black}
shadowOpacity={0.5}
shadowBlur={6}
shadowOffset={{ x: 0, y: 3 }}
/>
{/* The additional line is used as an overlay on the original to make it seem like the stroke on the original line is on the outside */}
<Line key={`hover-${index}`} x={0} y={0} points={coordinates.flat()} closed fill={featureProps.hover.fill(hoverCode, true)} />
</>
))}
{waterCoords?.map((coordinates, index) => (
<Line listening={false} key={index} x={0} y={0} points={coordinates.flat()} closed stroke={colors.transparent} fill={colors.white} />
))}
</Group>
</Layer>
);
});

type OutlinesProps = {
interface OutlinesProps {
geoInfo: ProjectedGeoInfo[];
featureProps: FeatureProps;
};
}

const Outlines = memo((props: OutlinesProps) => {
const { geoInfo, featureProps } = props;
Expand All @@ -276,11 +304,11 @@ const Outlines = memo((props: OutlinesProps) => {
);
});

type FeaturesProps = {
interface FeaturesProps {
geoInfo: ProjectedGeoInfo[];
featureProps: FeatureProps;
children: React.ReactNode;
};
}

const Features = memo((props: FeaturesProps) => {
const { geoInfo, featureProps, children } = props;
Expand Down Expand Up @@ -336,7 +364,7 @@ const Features = memo((props: FeaturesProps) => {
);
});

type AreaMapProps = {
interface AreaMapProps {
isTabInteractive: boolean;
geoInfo: ProjectedGeoInfo[];
getLink?: (code: string) => string;
Expand All @@ -347,7 +375,7 @@ type AreaMapProps = {
handleMouseOver: (event: MouseEvent<HTMLElement>) => void;
height: number;
width: number;
};
}

type GeoInfoGroup = {
code: string;
Expand Down Expand Up @@ -383,6 +411,7 @@ function AreaMap(props: AreaMapProps) {
<area
style={{
cursor: isDefined(getLink) ? 'pointer' : undefined,
outline: 'none',
}}
tabIndex={index === 0 ? 2 : -1}
aria-label={getFeatureName(geoInfoGroup.code)}
Expand Down
63 changes: 13 additions & 50 deletions packages/app/src/components/choropleth/logic/use-feature-props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,7 @@ import { DataConfig, DataOptions } from '..';
import { ChoroplethDataItem } from './types';

type GetFeatureProp<T = string> = (code: string) => T;
type GetHoverFeatureProp<T = string> = (
code: string,
isActivated?: boolean,
isKeyboardActive?: boolean
) => T;
type GetHoverFeatureProp<T = string> = (code: string, isActivated?: boolean, isKeyboardActive?: boolean) => T;

export type FeatureProps = {
/**
Expand Down Expand Up @@ -39,7 +35,7 @@ type FeaturePropFunctions = {

export const DEFAULT_STROKE_WIDTH = 0.5;

export const DEFAULT_HOVER_STROKE_WIDTH = 3;
export const DEFAULT_HOVER_STROKE_WIDTH = 6;

/**
* This hook returns the visual props for the map features based on the specified map type.
Expand All @@ -60,10 +56,7 @@ export function useFeatureProps<T extends ChoroplethDataItem>(
dataOptions: DataOptions,
dataConfig: DataConfig<T>
): FeatureProps {
return useMemo(
() => getFeatureProps(map, getFillColor, dataOptions, dataConfig),
[map, getFillColor, dataOptions, dataConfig]
);
return useMemo(() => getFeatureProps(map, getFillColor, dataOptions, dataConfig), [map, getFillColor, dataOptions, dataConfig]);
}

export function getFeatureProps<T extends ChoroplethDataItem>(
Expand All @@ -83,38 +76,17 @@ export function getFeatureProps<T extends ChoroplethDataItem>(
strokeWidth: () => dataConfig.areaStrokeWidth,
},
hover: {
fill: (_code: string, isHover?: boolean) =>
isHover ? dataConfig.hoverFill : 'none',
fill: (_code: string) => getFillColor(_code),
stroke:
!dataOptions.highlightSelection || !dataOptions.selectedCode
? (
_code: string,
isActivated?: boolean,
isKeyboardActive?: boolean
) =>
isActivated
? isKeyboardActive
? dataConfig.highlightStroke
: dataConfig.hoverStroke
: 'none'
? (_code: string, isActivated?: boolean, isKeyboardActive?: boolean) =>
isActivated ? (isKeyboardActive ? dataConfig.highlightStroke : dataConfig.hoverStroke) : 'none'
: (code: string, isActivated?: boolean) =>
code === dataOptions.selectedCode
? isActivated
? dataConfig.hoverStroke
: dataConfig.highlightStroke
: isActivated
? dataConfig.hoverStroke
: 'none',
code === dataOptions.selectedCode ? (isActivated ? dataConfig.hoverStroke : dataConfig.highlightStroke) : isActivated ? dataConfig.hoverStroke : 'none',
strokeWidth:
!dataOptions.highlightSelection || !dataOptions.selectedCode
? (_code: string, isActivated?: boolean) =>
isActivated ? dataConfig.hoverStrokeWidth : 0
: (code: string, isActivated?: boolean) =>
code === dataOptions.selectedCode
? dataConfig.highlightStrokeWidth
: isActivated
? dataConfig.hoverStrokeWidth
: 0,
? (_code: string, isActivated?: boolean) => (isActivated ? dataConfig.hoverStrokeWidth : 0)
: (code: string, isActivated?: boolean) => (code === dataOptions.selectedCode ? dataConfig.highlightStrokeWidth : isActivated ? dataConfig.hoverStrokeWidth : 0),
},
outline: {
fill: () => 'transparent',
Expand All @@ -133,19 +105,10 @@ export function getFeatureProps<T extends ChoroplethDataItem>(
strokeWidth: () => dataConfig.areaStrokeWidth,
},
hover: {
fill: () => 'none',
stroke: (
_code: string,
isActivated?: boolean,
isKeyboardActive?: boolean
) =>
isActivated
? isKeyboardActive
? dataConfig.highlightStroke
: dataConfig.hoverStroke
: 'none',
strokeWidth: (_code: string, isActivated?: boolean) =>
isActivated ? dataConfig.hoverStrokeWidth : 0,
fill: (_code: string) => getFillColor(_code),
stroke: (_code: string, isActivated?: boolean, isKeyboardActive?: boolean) =>
isActivated ? (isKeyboardActive ? dataConfig.highlightStroke : dataConfig.hoverStroke) : 'none',
strokeWidth: (_code: string, isActivated?: boolean) => (isActivated ? dataConfig.hoverStrokeWidth : 0),
},
outline: {
fill: () => 'none',
Expand Down

0 comments on commit 855e52c

Please sign in to comment.