sue
  • amCharts5 세계 지도 - 나라별
    2022년 06월 09일 21시 24분 24초에 업로드 된 글입니다.
    작성자: sue24

    한국을 확대해봤습니다

    map chart

    세계지도 불러오기!

    불러올 지도는 클릭하면 해당 국가의 도시를 보여주는 지도다

    country data

    <script src="https://cdn.amcharts.com/lib/5/geodata/data/countries.js"></script>
    <script src="https://cdn.amcharts.com/lib/5/geodata/data/countries2.js"></script>
    • root

      var root = am5.Root.new("chartdiv");
      
      var colors = am5.ColorSet.new(root, {});
      
      root.setThemes([
          am5themes_Animated.new(root)
      ]);
    • chart

      var chart = root.container.children.push(
          am5map.MapChart.new(root, {
              panX: "rotateX",
              projection: am5map.geoMercator()
          })
      )
      chart.set("zoomControl", am5map.ZoomControl.new(root, {}));
      chart.chartContainer.set("background", am5.Rectangle.new(root, {
          fill: am5.color(0xdeeaf4),
          fillOpacity: 1
      }));

      panning이랑 zooming은 추후 더 상세 기능 설정을 해야겠다

    • world view

      var worldSeries = chart.series.push(
          am5map.MapPolygonSeries.new(root, {
            geoJSON: am5geodata_worldLow,
            exclude: ["AQ"]
          })
        );
      
      worldSeries.mapPolygons.template.setAll({
          tooltipText: "{name}",
          interactive: true,
          stroke: am5.color(0xe3e3e3),
          strokeWidth: 2,
          fillOpacity: 0.5,
          templateField: "polygonSettings"
        });
      
      worldSeries.mapPolygons.template.states.create("hover", {
      // fill: am5.color(0x034221)
      fill: colors.getIndex(9)
      });

      exclude: ["AQ"]는 남극 대륙을 제외한 세계지도를 보여주기 위함이다

      세계 지도에서 각 나라 위로 마우스를 올리면 색깔이 변하고

      (am5.color(0x034221)처럼 해도 되고 colors.getIndex(9)처럼 해도 된다)

      툴팁으로 해당 나라의 이름을 알려준다

    • country

      나라를 클릭하면 그 나라가 커지면서 도시 구분이 된 지도가 보인다

      var continents = {
          "AF": 0,
          "AN": 1,
          "AS": 2,
          "EU": 3,
          "NA": 4,
          "OC": 5,
          "SA": 6
      }
      
      worldSeries.mapPolygons.template.events.on("click", (e) => {
          var dataItem = e.target.dataItem;
          var data = dataItem.dataContext;
          var zoomAnimation = worldSeries.zoomToDataItem(dataItem);
      
          Promise.all([
              zoomAnimation.waitForStop(),
              am5.net.load("https://cdn.amcharts.com/lib/5/geodata/json/"+ data.map + ".json", chart)
          ]).then((results) => {
              var geodata = am5.JSONParser.parse(results[1].response);
              countrySeries.setAll({
                  geoJSON: geodata,
                  fill: data.polygonSettings.fill
              });
              countrySeries.show()
              worldSeries.hide(100);
              backContainer.show();
          });
      });
      
      var countrySeries = chart.series.push(am5map.MapPolygonSeries.new(root, {
          visible: false
      }));
      
      countrySeries.mapPolygons.template.setAll({
          tooltipText: "{name}",
          interactive: true,
          fill: am5.color(0xaaaaaa)
      });
      
      countrySeries.mapPolygons.template.states.create("hover", {
          fill: colors.getIndex(9)
      });
      
      var data = [];
      for (var id in am5geodata_data_countries2) {
          if (am5geodata_data_countries2.hasOwnProperty(id)) {
              var country = am5geodata_data_countries2[id];
              if (country.maps.length) {
                  data.push({
                      id: id,
                      map: country.maps[0],
                      polygonSettings: {
                          fill: colors.getIndex(continents[country.continent_code]),
                      }
                  });
              }
          }
      }
      
      worldSeries.data.setAll(data);
      
      // back to continents view button
      var backContainer = chart.children.push(am5.Container.new(root, {
          x: am5.p100,
          centerX: am5.p100,
          dx: -10,
          paddingTop: 5,
          paddingRight: 10,
          paddingBottom: 5,
          y: 30,
          interactiveChildren: false,
          layout: root.horizontalLayout,
          cursorOverStyle: "pointer",
          background: am5.RoundedRectangle.new(root, {
              fill: am5.color(0xffffff),
              fillOpacity: 0.2
          }),
          visible: false
      }));
      
      // var backLabel = backContainer.children.push(am5.Label.new(root, {
      //     text: "world map",
      //     centerY: am5.p50
      // }));
      
      var backButton = backContainer.children.push(am5.Graphics.new(root, {
          width: 32,
          height: 32,
          centerY: am5.p50,
          fillGradient: am5.LinearGradient.new(root, {
              stops: [{
                color: am5.color(0x654ea3)
              }, {
                color: am5.color(0xeaafc8)
              }],
              rotation: 0
          }),
          svgPath: "M44 40.8361C39.1069 34.8632 34.7617 31.4739 30.9644 30.6682C27.1671 29.8625 23.5517 29.7408 20.1182 30.303V41L4 23.5453L20.1182 7V17.167C26.4667 17.2172 31.8638 19.4948 36.3095 24C40.7553 28.5052 43.3187 34.1172 44 40.8361Z"
      }));
      
      backContainer.events.on("click", function() {
          chart.goHome();
          worldSeries.show();
          countrySeries.hide();
          backContainer.hide();
      });

      나라 뷰가 뜨면 우측 상단에 다시 월드 뷰로 돌아갈 수 있는 버튼을 만든다

      주석 처리된 backLabel은 버튼 라벨을 만드는 코드다

      버튼은 이미지는 못 띄우고 svg path로만 가능한 것 같다

      이 버튼은 월드 뷰로 돌아가면 안 보인다

      그냥 fill로만 할 수도 있지만

      여기서는 버튼을 그라디언트로 채웠다(아마 %를 지정해서 위치를 다르게는 못하는 모양이다)

    'JS' 카테고리의 다른 글

    new FormData는 <form> submit과 다를까?  (0) 2023.11.01
    amCharts5 지도 줌, overlay  (0) 2022.06.10
    amCharts5 튜토리얼  (0) 2022.06.08
    함수도 오브젝트!  (0) 2020.11.03
    Objects and the dot  (0) 2020.08.25
    댓글