import * as am4core from "@amcharts/amcharts4/core" ; import * as am4charts from "@amcharts/amcharts4/charts" ; import * as am4maps from "@amcharts/amcharts4/maps" ; import am4themes_animated from "@amcharts/amcharts4/themes/animated" ; import am4geodata_worldLow from "@amcharts/amcharts4-geodata/worldLow" ; am4core . useTheme ( am4themes_animated ) ; let chart = am4core . create ( "chartdiv" , am4maps . MapChart ) ; try { chart . geodata = am4geodata_worldLow ; } catch ( e ) { chart . raiseCriticalError ( new Error ( "Map geodata could not be loaded. Please download the latest <a href=\"https://www.amcharts.com/download/download-v4/\">amcharts geodata</a> and extract its contents into the same directory as your amCharts files." ) ) ; } chart . projection = new am4maps . projections . Mercator ( ) ; chart . chartContainer . background . events . on ( "hit" , ( ) => { zoomOut ( ) ; } ) ; let colorSet = new am4core . ColorSet ( ) ; let morphedPolygon ; let polygonSeries = chart . series . push ( new am4maps . MapPolygonSeries ( ) ) ; polygonSeries . useGeodata = true ; polygonSeries . include = [ "IT" , "CH" , "FR" , "DE" , "GB" , "ES" , "PT" , "IE" , "NL" , "LU" , "BE" , "AT" , "DK" ] ; let polygonTemplate = polygonSeries . mapPolygons . template ; polygonTemplate . strokeOpacity = 1 ; polygonTemplate . stroke = am4core . color ( "#ffffff" ) ; polygonTemplate . fillOpacity = 0.5 ; polygonTemplate . tooltipText = "{name}" ; let desaturateFilter = new am4core . DesaturateFilter ( ) ; desaturateFilter . saturation = 0.25 ; polygonTemplate . filters . push ( desaturateFilter ) ; polygonTemplate . adapter . add ( "fill" , ( fill , target ) => { return colorSet . getIndex ( target . dataItem . index + 1 ) ; } ) ; let hoverState = polygonTemplate . states . create ( "hover" ) ; hoverState . properties . fillOpacity = 1 ; polygonTemplate . events . on ( "hit" , ( event ) => { event . target . zIndex = Number . MAX_VALUE ; selectPolygon ( event . target ) ; } ) ; let pieChart = chart . seriesContainer . createChild ( am4charts . PieChart ) ; pieChart . width = 100 ; pieChart . height = 100 ; pieChart . hidden = true ; pieChart . chartContainer . minHeight = 1 ; pieChart . chartContainer . minWidth = 1 ; let pieSeries = pieChart . series . push ( new am4charts . PieSeries ( ) ) ; pieSeries . dataFields . value = "value" ; pieSeries . dataFields . category = "category" ; pieSeries . data = [ { value : 100 , category : "First" } , { value : 20 , category : "Second" } , { value : 10 , category : "Third" } ] ; let dropShadowFilter = new am4core . DropShadowFilter ( ) ; dropShadowFilter . blur = 4 ; pieSeries . filters . push ( dropShadowFilter ) ; let sliceTemplate = pieSeries . slices . template ; sliceTemplate . fillOpacity = 1 ; sliceTemplate . strokeOpacity = 0 ; let activeState = sliceTemplate . states . getKey ( "active" ) ; activeState . properties . shiftRadius = 0 ; let sliceHoverState = sliceTemplate . states . getKey ( "hover" ) ; sliceHoverState . properties . shiftRadius = 0 ; let hiddenState = pieSeries . hiddenState ; hiddenState . properties . startAngle = pieSeries . startAngle ; hiddenState . properties . endAngle = pieSeries . endAngle ; hiddenState . properties . opacity = 0 ; hiddenState . properties . visible = false ; let labelTemplate = pieSeries . labels . template ; labelTemplate . nonScaling = true ; labelTemplate . fill = am4core . color ( "#FFFFFF" ) ; labelTemplate . fontSize = 10 ; labelTemplate . background = new am4core . RoundedRectangle ( ) ; labelTemplate . background . fillOpacity = 0.9 ; labelTemplate . padding ( 4 , 9 , 4 , 9 ) ; labelTemplate . background . fill = am4core . color ( "#7678a0" ) ; pieSeries . hiddenState . transitionDuration = 200 ; let countryLabel = chart . chartContainer . createChild ( am4core . Label ) ; countryLabel . text = "Select a country" ; countryLabel . fill = am4core . color ( "#7678a0" ) ; countryLabel . fontSize = 40 ; countryLabel . hiddenState . properties . dy = 1000 ; countryLabel . defaultState . properties . dy = 0 ; countryLabel . valign = "middle" ; countryLabel . align = "right" ; countryLabel . paddingRight = 50 ; countryLabel . hide ( 0 ) ; countryLabel . show ( ) ; function selectPolygon ( polygon ) { if ( morphedPolygon != polygon ) { let animation = pieSeries . hide ( ) ; if ( animation ) { animation . events . on ( "animationended" , ( ) => { morphToCircle ( polygon ) ; } ) ; } else { morphToCircle ( polygon ) ; } } } function fadeOut ( exceptPolygon ? ) { for ( let i = 0 ; i < polygonSeries . mapPolygons . length ; i ++ ) { let polygon = polygonSeries . mapPolygons . getIndex ( i ) ; if ( polygon != exceptPolygon ) { polygon . defaultState . properties . fillOpacity = 0.5 ; polygon . animate ( [ { property : "fillOpacity" , to : 0.5 } , { property : "strokeOpacity" , to : 1 } ] , polygon . polygon . morpher . morphDuration ) ; } } } function zoomOut ( ) { if ( morphedPolygon ) { pieSeries . hide ( ) ; morphBack ( ) ; fadeOut ( ) ; countryLabel . hide ( ) ; morphedPolygon = undefined ; } } function morphBack ( ) { if ( morphedPolygon ) { morphedPolygon . polygon . morpher . morphBack ( ) ; let dsf = morphedPolygon . filters . getIndex ( 0 ) ; dsf . animate ( { property : "saturation" , to : 0.25 } , morphedPolygon . polygon . morpher . morphDuration ) ; } } function morphToCircle ( polygon ) { let animationDuration = polygon . polygon . morpher . morphDuration ; morphBack ( ) ; polygon . toFront ( ) ; polygon . polygon . morpher . morphToSingle = true ; let morphAnimation = polygon . polygon . morpher . morphToCircle ( ) ; polygon . strokeOpacity = 0 ; polygon . defaultState . properties . fillOpacity = 1 ; polygon . animate ( { property : "fillOpacity" , to : 1 } , animationDuration ) ; let filter = polygon . filters . getIndex ( 0 ) ; filter . animate ( { property : "saturation" , to : 1 } , animationDuration ) ; morphedPolygon = polygon ; fadeOut ( polygon ) ; countryLabel . hide ( ) ; if ( morphAnimation ) { morphAnimation . events . on ( "animationended" , ( ) => { zoomToCountry ( polygon ) ; } ) ; } else { zoomToCountry ( polygon ) ; } } function zoomToCountry ( polygon ) { let zoomAnimation = chart . zoomToMapObject ( polygon , 2 , true ) ; if ( zoomAnimation ) { zoomAnimation . events . on ( "animationended" , ( ) => { showPieChart ( polygon ) ; } ) ; } else { showPieChart ( polygon ) ; } } function showPieChart ( polygon ) { polygon . polygon . measure ( ) ; let radius = polygon . polygon . measuredWidth / 2 * polygon . globalScale / chart . seriesContainer . scale ; pieChart . width = radius * 2 ; pieChart . height = radius * 2 ; pieChart . radius = radius ; let centerPoint = am4core . utils . spritePointToSvg ( polygon . polygon . centerPoint , polygon . polygon ) ; centerPoint = am4core . utils . svgPointToSprite ( centerPoint , chart . seriesContainer ) ; pieChart . x = centerPoint . x - radius ; pieChart . y = centerPoint . y - radius ; let fill = < am4core . Color > polygon . fill ; let desaturated = fill . saturate ( 0.3 ) ; for ( let i = 0 ; i < pieSeries . dataItems . length ; i ++ ) { let dataItem = pieSeries . dataItems . getIndex ( i ) ; dataItem . value = Math . round ( Math . random ( ) * 100 ) ; dataItem . slice . fill = am4core . color ( am4core . colors . interpolate ( fill . rgb , am4core . color ( "#ffffff" ) . rgb , 0.2 * i ) ) ; dataItem . label . background . fill = desaturated ; dataItem . tick . stroke = fill ; } pieSeries . show ( ) ; pieChart . show ( ) ; countryLabel . text = "{name}" ; countryLabel . dataItem = polygon . dataItem ; countryLabel . fill = desaturated ; countryLabel . show ( ) ; }