Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bubble markers map type #257

Merged
merged 58 commits into from
Aug 9, 2023
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
3ff0400
preliminary bubble marker component
moontrip May 25, 2023
2991c81
Merge branch 'main' into 95-bubble-marker-component
chowington Jun 8, 2023
e739bb3
Update bubble spec and design
chowington Jun 8, 2023
fc03c3e
Merge branch 'main' into 95-bubble-marker-component
chowington Jun 9, 2023
c207973
Merge branch 'main' into 95-bubble-marker-component
chowington Jun 13, 2023
9306842
Get working bubble markers on map
chowington Jun 14, 2023
3a324ad
Merge branch 'main' into 95-bubble-marker-component
chowington Jun 14, 2023
96ad6e9
Add dedicated bubble marker menu option
chowington Jun 14, 2023
0688eec
Make Bubble Marker Legend
chowington Jun 20, 2023
fb5e693
Merge branch 'main' into 95-bubble-marker-component
chowington Jun 20, 2023
d0a5f21
Add missing stuff related to bubble markers
chowington Jun 20, 2023
910286a
Add bubble marker legend to SAM
chowington Jun 20, 2023
764efb2
Set max bubble marker size
chowington Jun 20, 2023
e50b2e6
Merge branch 'main' into 95-bubble-marker-component
chowington Jun 26, 2023
3d0902a
Add outline to bubble markers and update legend tick calculation
chowington Jun 28, 2023
29b79a5
Fix bubble outline shape and draw smaller bubbles over bigger
chowington Jun 29, 2023
2a6aced
Clean up
chowington Jun 29, 2023
0cccd34
Merge branch 'main' into 95-bubble-marker-component
chowington Jul 5, 2023
e9891fc
Allow analysis backwards compatibility when adding new map types
chowington Jul 5, 2023
dba1a40
Merge branch 'main' into 95-bubble-marker-component
chowington Jul 24, 2023
709d508
Fix bugs from merge
chowington Jul 24, 2023
70f8236
Add aggregation input and use bubble endpoint for data
chowington Jul 25, 2023
8a01b1e
Use correct value for bubble size
chowington Jul 25, 2023
4942c67
Reintroduce appState backwards compatibility logic
chowington Jul 25, 2023
c49a557
Use bubble legend endpoint for bubble sizes
chowington Jul 26, 2023
5d328f3
Color bubbles according to overlayValue and legend endpoint data
chowington Jul 26, 2023
a08bfa1
Add gradient legend to bubble map mode
chowington Jul 28, 2023
fa1703d
Merge branch 'main' into 95-bubble-marker-component
chowington Jul 28, 2023
0c93414
Fix bubble menu icon sizing issue
chowington Jul 28, 2023
a54d45b
Align bubble menu inputs veertically
chowington Jul 28, 2023
de8d421
Improve proportion validation UX
chowington Jul 28, 2023
33b4a04
Improve gradient legend default position
chowington Jul 28, 2023
d5bb5dc
Factor out aggregation inputs in lineplot viz
chowington Jul 31, 2023
94f489b
Use refactored aggregation inputs in bubble menu
chowington Jul 31, 2023
520d88e
Merge branch 'main' into 95-bubble-marker-component
chowington Jul 31, 2023
50bdb5a
Add proportion error message back
chowington Jul 31, 2023
1a528ca
#BringBackThePieLegend >:(
chowington Jul 31, 2023
027de87
Reduce extra whitespace in gradient legend
chowington Jul 31, 2023
799f120
Clean up bubble marker datatype
chowington Aug 1, 2023
fa4d806
Refactor types and clean up PR
chowington Aug 1, 2023
cf437c4
Merge branch 'main' into 95-bubble-marker-component
chowington Aug 1, 2023
0279985
Add bubble popup and remove numbers in bubbles
chowington Aug 2, 2023
790c162
Increase width of size legend slightly
chowington Aug 2, 2023
3a8a3de
updated bubble marker
asizemore Aug 2, 2023
0f84a4b
Merge pull request #400 from VEuPathDB/add-bubble-icon
chowington Aug 2, 2023
91c3306
Change verbiage of bubble popup
chowington Aug 2, 2023
9285535
Add comments
chowington Aug 2, 2023
7db7cd3
Remove clear button from bubble menu variable input
chowington Aug 2, 2023
4e41f15
Use _.get() where possible to shorten expressions
chowington Aug 2, 2023
7d01ede
Change === null to == null to prevent error
chowington Aug 3, 2023
5618004
Fix incorrect bubble config input labels
chowington Aug 7, 2023
cb44ae2
Use sequential colormap when data is sequential
chowington Aug 7, 2023
aacff44
Refactor useStandaloneMapMarkers
chowington Aug 8, 2023
835d820
Fix issues when min and max bubble values are equal
chowington Aug 8, 2023
ef1580f
Add rest of bubble popup overlay label logic
chowington Aug 8, 2023
74cfc94
Simplify some bits of code
chowington Aug 8, 2023
f57339b
Merge branch 'main' into 95-bubble-marker-component
chowington Aug 8, 2023
ff12879
Remove unnecessary bubble size short circuit
chowington Aug 8, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
import React from 'react';
import { range } from 'd3';

// set props for custom legend function
export interface PlotLegendBubbleProps {
legendMax: number;
// legendMin: number;
valueToSizeMapper: (value: number) => number;
// nTicks?: number; // MUST be odd!
// showMissingness?: boolean;
}

// legend ellipsis function for legend title and legend items (from custom legend work)
// const legendEllipsis = (label: string, ellipsisLength: number) => {
// return (label || '').length > ellipsisLength
// ? (label || '').substring(0, ellipsisLength) + '...'
// : label;
// };

// make gradient colorscale legend into a component so it can be more easily incorporated into DK's custom legend if we need
export default function PlotBubbleLegend({
legendMax,
// legendMin,
valueToSizeMapper,
}: // nTicks = 5,
// showMissingness,
PlotLegendBubbleProps) {
// Declare constants
// const gradientBoxHeight = 150;
// const gradientBoxWidth = 20;
const tickFontSize = '0.8em';
const legendTextSize = '1.0em';
const circleStrokeWidth = 3;
const padding = 5;
// const largestDataCircleSize = valueToSizeMapper(legendMax);
const numCircles = 3;

// the value of the largest circle in the legend will be the smallest power of 10 that's larger than legendMax
const largestCircleValue = Math.pow(10, Math.ceil(Math.log10(legendMax)));
const largestCircleDiameter = valueToSizeMapper(largestCircleValue);
const largestCircleRadius = largestCircleDiameter / 2;
const circleValues = range(numCircles).map(
(i) => largestCircleValue / Math.pow(10, i)
);

console.log({ circleValues });

const tickLength = largestCircleRadius + 5;

// Create gradient stop points from the colorscale from values [legendMin TO legendMax] at an arbitrary 50 step resolution
// const numCircles = 3;
// const legendStep = legendMax / (numCircles - 1);
// // const fudge = legendStep / 10; // to get an inclusive range from d3 we have to make a slightly too-large max
// const stopPoints = range(legendStep, legendMax, legendStep).map(
// (value: number, index: number) => {
// const size = valueToSizeMapper(value);
// return (
// <stop
// offset={stopPercentage}
// stopColor={value}
// key={'gradientStop' + index}
// />
// );
// }
// );

// let svgHTML: string = '';
// set drawing area
// svgHTML +=
// '<svg width="' + largestCircleSize + '" height="' + largestCircleSize + '">'; // initiate svg marker icon

const BubbleLegendSVG = () => (
<svg
width={largestCircleDiameter + (tickLength - largestCircleRadius) + 40}
height={largestCircleDiameter + circleStrokeWidth * 2 + padding * 2}
>
{circleValues.map((value, i) => {
console.log({ value });
// const value = legendMax * (i / (numCircles - 1));
const circleDiameter = valueToSizeMapper(value);
const circleRadius = circleDiameter / 2;
const tickY =
padding + largestCircleDiameter + circleStrokeWidth - circleDiameter;
// const stopPercentage = (i / (numCircles - 1)) * 100;

return (
<>
<circle
cx={padding + largestCircleRadius + circleStrokeWidth}
cy={
padding +
largestCircleDiameter +
circleStrokeWidth -
circleRadius
}
r={circleRadius}
stroke="black"
stroke-width={circleStrokeWidth}
fill="white"
/>
<g className="axisTick" overflow="visible" key={'gradientTick' + i}>
<line
x1={padding + largestCircleRadius + circleStrokeWidth + 1}
x2={
padding +
largestCircleRadius +
circleStrokeWidth +
tickLength +
1
}
y1={tickY}
y2={tickY}
stroke="black"
strokeDasharray="2 2"
strokeWidth={2}
/>
<text
x={padding + largestCircleRadius + tickLength + 5}
y={tickY}
dominantBaseline="middle"
fontSize={tickFontSize}
>
{value}
</text>
</g>
</>
);
})}
</svg>
);
// '<circle cx="' +
// (largestCircleSize / 2) +
// '" cy="' +
// (largestCircleSize - (circleDiameter / 2)) +
// '" r="' +
// (circleDiameter / 2) +
// '" stroke="black" stroke-width="2" fill="white" />';

// </svg>
// );

// });

// for display, convert large value with k (e.g., 12345 -> 12k): return original value if less than a criterion
// const sumLabel = props.markerLabel ?? String(fullPieValue);

// draw a larger white-filled circle
// svgHTML +=
// '<circle cx="' +
// circleRadius +
// '" cy="' +
// circleRadius +
// '" r="' +
// circleRadius +
// '" stroke="green" stroke-width="0" fill="white" />';

// create bubble
//TODO: two things to consider: a) bubble size; b) bubble color
// svgHTML +=
// '<circle cx="' +
// circleRadius +
// '" cy="' +
// circleRadius +
// '" r="' +
// circleRadius +
// '" stroke="green" stroke-width="0" fill="' +
// // color is possibly undefined
// props.data[0].color +
// '" />';

//TODO: do we need to show total number for bubble marker?
// adding total number text/label and centering it
// svgHTML +=
// '<text x="50%" y="50%" dominant-baseline="middle" text-anchor="middle" opacity="1" fill="white" font-family="Arial, Helvetica, sans-serif" font-weight="bold" font-size="1em">' +
// props.data[0].value +
// '</text>';

// // check isAtomic: draw pushpin if true
// if (props.isAtomic) {
// let pushPinCode = '&#128392;';
// svgHTML +=
// '<text x="86%" y="14%" dominant-baseline="middle" text-anchor="middle" opacity="0.75" font-weight="bold" font-size="1.2em">' +
// pushPinCode +
// '</text>';
// }

// // closing svg tag
// svgHTML += '</svg>';

// Create ticks
// const ticks = range(nTicks).map((a: number) => {
// const location: number =
// gradientBoxHeight - gradientBoxHeight * (a / (nTicks! - 1)); // draw bottom to top
// return (
// <g className="axisTick" overflow="visible" key={'gradientTick' + a}>
// <line
// x1={gradientBoxWidth + 1}
// x2={gradientBoxWidth + tickLength + 1}
// y1={location}
// y2={location}
// stroke="black"
// strokeWidth="1px"
// ></line>
// <text
// x={gradientBoxWidth + 4 + tickLength}
// y={location}
// dominantBaseline="middle"
// fontSize={tickFontSize}
// >
// {(
// (a / (nTicks! - 1)) * (legendMax - legendMin) +
// legendMin
// ).toPrecision(3)}
// </text>
// </g>
// );
// });

return (
<div>
<BubbleLegendSVG />
</div>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import PlotListLegend, { PlotListLegendProps } from './PlotListLegend';
import PlotGradientLegend, {
PlotLegendGradientProps,
} from './PlotGradientLegend';
import PlotBubbleLegend, { PlotLegendBubbleProps } from './PlotBubbleLegend';

interface PlotLegendBaseProps extends ContainerStylesAddon {
legendTitle?: string;
Expand All @@ -13,6 +14,7 @@ export type PlotLegendProps = PlotLegendBaseProps &
(
| ({ type: 'list' } & PlotListLegendProps)
| ({ type: 'colorscale' } & PlotLegendGradientProps)
| ({ type: 'bubble' } & PlotLegendBubbleProps)
);

export default function PlotLegend({
Expand All @@ -29,7 +31,8 @@ export default function PlotLegend({
{((type === 'list' &&
((otherProps as PlotListLegendProps).legendItems.length > 1 ||
(otherProps as PlotListLegendProps).showOverlayLegend)) ||
type === 'colorscale') && (
type === 'colorscale' ||
type === 'bubble') && (
<div
style={{
display: 'inline-block', // for general usage (e.g., story)
Expand Down Expand Up @@ -63,6 +66,9 @@ export default function PlotLegend({
{type === 'colorscale' && (
<PlotGradientLegend {...(otherProps as PlotLegendGradientProps)} />
)}
{type === 'bubble' && (
<PlotBubbleLegend {...(otherProps as PlotLegendBubbleProps)} />
)}
</div>
)}
</>
Expand Down
Loading