@@ -34,19 +34,49 @@ function formatLargeMoney(value: number) {
3434 return `$${ valueTo100ths } ${ specifier } ` ;
3535}
3636
37- type AmChartsData = ( { id : Valid2DigitCountryCodesWithoutUSA , approxValueFormatted ?: string } & Partial < Pick < FlattenedTariffDataEntry , Exclude < keyof FlattenedTariffDataEntry , "id" | "date" | "type" > > > ) & IComponentDataItem ;
37+ interface AmChartsData extends IComponentDataItem , Partial < Pick < FlattenedTariffDataEntry , Exclude < keyof FlattenedTariffDataEntry , "id" | "date" | "type" | "color" > > > {
38+ id : Valid2DigitCountryCodesWithoutUSA ;
39+ approxValueFormatted ?: string ;
40+ }
3841
3942function AmChartsMap ( ) {
40- const [ field , setField ] = useState < Exclude < keyof FlattenedTariffDataEntry , "id" | "date" | "type" > > ( "percentValue" ) ;
43+ const [ field , setField ] = useState < Exclude < keyof FlattenedTariffDataEntry , "id" | "date" | "type" | "color" > > ( "percentValue" ) ;
4144 const [ type , setType ] = useState < TariffType > ( "announced" ) ;
4245 const [ dateIndex , setDateIndex ] = useState < number > ( - 1 ) ;
4346 const [ polygonSeries , setPolygonSeries ] = useState < am5map . MapPolygonSeries | null > ( null ) ;
47+ const [ heatLegend , setHeatLegend ] = useState < HeatLegend | null > ( null ) ;
4448 const dateIndexRef = useRef ( dateIndex ) ; // Need to pass this value into a callback in the use effect
4549 const oldData = useRef < AmChartsData [ ] > ( [ ] ) ;
50+ const fieldRef = useRef ( field ) ;
51+
52+ useEffect ( ( ) => {
53+ if ( polygonSeries ) {
54+ polygonSeries . set ( "valueField" , field ) ;
55+ polygonSeries . mapPolygons . template . set ( "tooltipText" , field === "percentValue" ? `{name}: {${ field } }%` : `{name}: {approxValueFormatted}` ) ;
56+ const originalHeatRule = polygonSeries . get ( "heatRules" ) ! [ 0 ] ;
57+ const newHeatRule = {
58+ ...originalHeatRule ,
59+ maxValue : field === "percentValue" ? 150 : undefined ,
60+ } ;
61+ polygonSeries . set ( "heatRules" , [ newHeatRule ] ) ;
62+ }
63+ if ( heatLegend ) {
64+ heatLegend . setAll ( {
65+ endValue : field === "percentValue" ? 150 : undefined ,
66+ startText : field === "percentValue" ? "0% Tariff" : "$0 Tariffed" ,
67+ stepCount : field === "percentValue" ? 15 : 100 ,
68+ } )
69+ if ( field === "percentValue" ) {
70+ heatLegend . set ( "endText" , "150% Tariff" ) ;
71+ }
72+ }
73+ } , [ field ] ) ;
4674
4775 useEffect ( ( ) => {
76+ let maxValue = 0 ;
4877 if ( polygonSeries ) {
4978 const mappedData : AmChartsData [ ] = dateIndex === - 1 ? [ ] : FLATTENED_TARIFF_DATA . get ( dates [ dateIndex ] ) ! . filter ( ( d ) => d . type === type ) . map ( d => {
79+ maxValue = Math . max ( maxValue , d [ field ] ) ;
5080 return {
5181 id : d . id ,
5282 [ field ] : d [ field ] ,
@@ -62,10 +92,23 @@ function AmChartsMap() {
6292 const isDifferent = oldItem [ field ] !== d [ field ] ;
6393 return isDifferent ;
6494 } ) . map ( d => d . id ) ;
95+ console . log ( {
96+ mappedData, diffItems,
97+ filtered : mappedData . filter ( d => diffItems . includes ( d . id ) ) ,
98+ } ) ;
6599 oldData . current = mappedData ;
66100 polygonSeries . mapPolygons . values
67101 . filter ( polygon => polygon . dataItem && diffItems . includes ( ( polygon . dataItem as DataItem < AmChartsData > ) . get ( "id" ) ) )
68- . forEach ( polygon => polygon . appear ( 1000 ) ) ;
102+ . forEach ( ( polygon ) => {
103+ polygon . appear ( 1000 ) ;
104+ } ) ;
105+ if ( field !== "percentValue" ) {
106+ const endValue = Math . max ( maxValue , 1_000_000 ) ;
107+ heatLegend ! . setAll ( {
108+ endValue,
109+ endText : `${ formatLargeMoney ( endValue ) } Tariffed` ,
110+ } ) ;
111+ }
69112 }
70113 } , [ polygonSeries , dateIndex , field , type ] ) ;
71114
@@ -79,6 +122,10 @@ function AmChartsMap() {
79122 dateIndexRef . current = dateIndex ;
80123 } , [ dateIndex ] ) ;
81124
125+ useEffect ( ( ) => {
126+ fieldRef . current = field ;
127+ } , [ field ] ) ;
128+
82129 useEffect ( ( ) => {
83130 // Create root
84131 const root = Root . new ( "chartdiv" , { } ) ;
@@ -93,7 +140,6 @@ function AmChartsMap() {
93140 panX : "rotateX" ,
94141 panY : "none" ,
95142 projection : am5map . geoMercator ( ) ,
96- // projection: am5map.geoAlbersUsa(),
97143 layout : root . horizontalLayout ,
98144 } ) ) ;
99145
@@ -102,27 +148,25 @@ function AmChartsMap() {
102148 // geoJSON: am5geodataUSALow,
103149 geoJSON : am5geodataWorldLow ,
104150 valueField : field ,
105- calculateAggregates : true
151+ calculateAggregates : true ,
152+ exclude : [ "AQ" ] , // Hide Antarctica
106153 } ) ) ;
154+ // chart.seriesContainer.set("paddingBottom", 50);
107155
108156 setPolygonSeries ( polygonSeries ) ;
109157
110- // Hide antartica
111- polygonSeries . set ( "exclude" , [ "AQ" ] ) ;
112- polygonSeries . mapPolygons . template . setAll ( {
113- tooltipText : field === "percentValue" ? `{name}: {${ field } }%` : `{name}: {approxValueFormatted}`
114- } ) ;
115-
116158 polygonSeries . set ( "heatRules" , [ {
117159 target : polygonSeries . mapPolygons . template ,
118160 dataField : "value" ,
119161 min : am5color ( 0xd3a29f ) , // Green
120- max : am5color ( 0x6f0600 ) , // Red
162+ max : am5color ( 0x330000 ) , // Red
121163 key : "fill" ,
122164 minValue : 0 ,
123- maxValue : field === "percentValue" ? 50 : undefined ,
165+ maxValue : field === "percentValue" ? 150 : undefined ,
124166 } ] ) ;
125167
168+ polygonSeries . mapPolygons . template . set ( "tooltipText" , field === "percentValue" ? `{name}: {${ field } }%` : `{name}: {approxValueFormatted}` ) ;
169+
126170 const heatLegendContainer = chart . children . push ( Container . new ( root , {
127171 layout : root . horizontalLayout ,
128172 // Make this container be on the top of the page (y=0)
@@ -137,15 +181,17 @@ function AmChartsMap() {
137181 orientation : "horizontal" ,
138182 startColor : am5color ( 0xd3a29f ) ,
139183 startValue : 0 ,
140- endValue : field === "percentValue" ? 50 : undefined ,
141- endColor : am5color ( 0x6f0600 ) ,
142- startText : "No Tariff",
143- endText : field === "percentValue" ? "50 % Tariff" : "Most Tariffed" ,
144- stepCount : field === "percentValue" ? 5 : 100 ,
184+ endValue : field === "percentValue" ? 150 : undefined ,
185+ endColor : am5color ( 0x330000 ) ,
186+ startText : field === "percentValue" ? "0% Tariff" : "$0 Tariffed ",
187+ endText : field === "percentValue" ? "150 % Tariff" : "Most Tariffed" ,
188+ stepCount : field === "percentValue" ? 15 : 100 ,
145189 } ) ) ;
146190
191+ setHeatLegend ( heatLegend ) ;
192+
147193 polygonSeries . mapPolygons . template . events . on ( "pointerover" , function ( ev ) {
148- heatLegend . showValue ( Number ( ( ev . target . dataItem as DataItem < AmChartsData > ) . get ( field ) ) ) ;
194+ heatLegend . showValue ( Number ( ( ev . target . dataItem as DataItem < AmChartsData > ) . get ( fieldRef . current ) ) ) ;
149195 } ) ;
150196
151197 heatLegend . startLabel . setAll ( {
@@ -158,22 +204,6 @@ function AmChartsMap() {
158204 fill : heatLegend . get ( "endColor" )
159205 } ) ;
160206
161- // change this to template when possible
162- polygonSeries . events . on ( "datavalidated" , function ( ) {
163- // console.log({ low: polygonSeries.getPrivate("valueLow"), high: polygonSeries.getPrivate("valueHigh") });
164- // const low = polygonSeries.getPrivate("valueLow")!;
165- const high = polygonSeries . getPrivate ( "valueHigh" ) ?? 0 ;
166- // heatLegend.set("startValue", polygonSeries.getPrivate("valueLow"));
167- // heatLegend.set("endValue", Math.max(polygonSeries.getPrivate("valueHigh") ?? 0, 100));
168- if ( field !== "percentValue" ) {
169- const endValue = Math . max ( high , 1_000_000 ) ;
170- heatLegend . setAll ( {
171- endValue,
172- endText : formatLargeMoney ( endValue ) ,
173- } ) ;
174- }
175- } )
176-
177207 // Set clicking on "water" to zoom out
178208 chart . chartContainer . get ( "background" ) ! . events . on ( "click" , function ( ) {
179209 chart . goHome ( ) ;
@@ -184,12 +214,12 @@ function AmChartsMap() {
184214
185215 const container = chart . children . push ( Container . new ( root , {
186216 y : am5p100 ,
187- centerX : am5p50 ,
217+ centerX : am5percent ( 55 ) ,
188218 centerY : am5p100 ,
189- x : am5percent ( 50 ) ,
219+ x : am5percent ( 55 ) ,
190220 width : am5percent ( 135 ) ,
191221 layout : root . horizontalLayout ,
192- paddingBottom : 10
222+ dy : - 10 ,
193223 } ) ) ;
194224
195225 const playButton = container . children . push ( Button . new ( root , {
@@ -204,7 +234,7 @@ function AmChartsMap() {
204234 const slider = container . children . push ( Slider . new ( root , {
205235 orientation : "horizontal" ,
206236 start : 0 ,
207- centerY : am5p50
237+ centerY : am5p50 ,
208238 } ) ) ;
209239
210240 playButton . events . on ( "click" , function ( ) {
@@ -285,7 +315,7 @@ function AmChartsMap() {
285315
286316 const fieldContainer = chart . children . push ( Container . new ( root , {
287317 layout : root . horizontalLayout ,
288- x : am5percent ( 15 ) ,
318+ x : am5percent ( 25 ) ,
289319 centerX : am5p100 ,
290320 y : am5percent ( 100 ) ,
291321 dy : - 40
@@ -324,15 +354,21 @@ function AmChartsMap() {
324354 return ( ) => {
325355 root . dispose ( ) ;
326356 }
327- } , [ field ] ) ;
357+ } , [ ] ) ;
328358
329- return < div style = { { width : "100%" , height : "95vh " } } id = "chartdiv" />
359+ return < div style = { { width : "100%" , height : "75vh " } } id = "chartdiv" />
330360}
331361
332362
333363function App ( ) {
334364 return (
335- < AmChartsMap />
365+ < div >
366+ < div style = { { textAlign : "center" , fontSize : "2rem" , marginBottom : "1rem" , width : "75%" , marginLeft : "auto" , marginRight : "auto" } } >
367+ < h1 > The Effect of Trump Tariffs</ h1 >
368+ < p > In under 3 months, Trump has announced and implemented radical tariffs that affect the entire rest of the world. The map shows the approximate value of the tariffs, and attempts to put the insane numbers to scale.</ p >
369+ </ div >
370+ < AmChartsMap />
371+ </ div >
336372 )
337373}
338374
0 commit comments