본문 바로가기
블로그 이미지

방문해 주셔서 감사합니다! 항상 행복하세요!

  
   - 문의사항은 메일 또는 댓글로 언제든 연락주세요.
   - "해줘","답 내놔" 같은 질문은 답변드리지 않습니다.
   - 메일주소 : lts06069@naver.com


Html 캔버스/Html 캔버스 에니메이션

Html Korea map, Html 캔버스 대한민국 지도 제작(이벤트 포함)

야근없는 행복한 삶을 위해 ~
by 마샤와 곰 2020. 10. 21.

우리나라의 위도와 경도값을 토대로 캔버스에 그려준 뒤에 이벤트를 부여하는 기능입니다.

우리나라 지도의 차트기능 만들 때 사용하였습니다.

 

우리나라의 위도경도 값은 구글링하면 쉽게 받을 수 있습니다.

"대한민국 최신 행정구역(shp)" 이라는 주제로 검색하면 다양한 정보를 받을 수 있습니다.

 

해당 shp파일은 웹에서 표현하기 어려운 값으로 되어 있습니다.

shp to geojson이라는 내용으로 검색하여 json형식의 위도, 경도값으로 나오도록 파싱하여 줍니다.

* 예 : mygeodata.cloud/converter/shp-to-geojson

파싱을 도와주는 대표적인 사이트 입니다.

 

파싱을 하고난 뒤에 json 내용을 열어보았습니다.

엄청난 위도 경도 값 입니다...

 

이제 위도 경도 값을 가져왔으니 캔버스에 그려주어야 합니다.

위도와 경도값을 평면에 나타 내려면 각 값에서 일정한 계산법이 들어가야 합니다.

function makeLine(data){  //data는 위도경도 지점 입니다.
    var x = data[0] / 360 * 500;  //경도는 180 ~ -180까지이며 구면체에 대한 500을 곱해줍니다.
    var y = data[1] / 180 * 500;  //위도는 90~ -90까지이며 구면체에 대한 500을 곱해줍니다.
    var finalX = canvas.width - canvas.width*0.2 - - Math.abs((x - 180) * 100 *  0.55); //그리는 화면에 대한 비율계산
    var finalY = canvas.height -Math.abs((y - 90) * 100 * 0.55);//그리는 화면에 대한 비율계산
    return {x:finalX, y : finalY};
}

 

위 makeLine함수를 토대로 위경도 값을 캔버스에서 적용하는 값으로 변환하여 줍니다.

캔버스에서 그릴 때는 moveTo와 lineTo로 구현하였습니다.

그리고 선 그리기가 끝난 이후에는 색상을 fill 함수를 통해서 채워 주었습니다.

저 json이 2중 3중 배열로 되어있었습니다..ㅠㅠ

 

이렇게 그려주면..아래 사진처럼 캔버스에 우리나라 지도를 나타낼 수 있습니다.

짜잔~ 선을 그린다음에 fill을 통해서 색상을 부여하였습니다.

 

이제 그러면 각 지역별 이름을 달아주어야됩니다.

이름을 넣어주는 방법은 각 x점과 y점의 최대값과 최소값을 구한뒤에 절반으로 나누어 구할 수 있습니다.

서울을 예로들면,

서울을 그릴 때 모든 x와 모든 y를 가져와서 해당 값에서 가장 작은 x와 y를 넣어줍니다.

그리고 가장 큰 x와 가장 큰y를 넣어준 뒤에 두 합을 구해서 절반되는 값을 가져오면 됩니다.

    function innerDataArrayMaker(inner_dataArray, textJson, finalX, finalY){
        var center = _getCenterPos(textJson.minX, textJson.minY, finalX, finalY);
        textJson.minX = center.x;
        textJson.minY = center.y;
        center = _getCenterPos2(textJson.maxX, textJson.maxY, finalX, finalY);
        textJson.maxX = center.x;
        textJson.maxY = center.y;
        inner_dataArray.push({ x: finalX, y: finalY });        
        return textJson;
    }
    //innerDataArrayMaker 종속 함수1
    function _getCenterPos(inn_x, inn_y, data_x, data_y){
        if(data_x < inn_x){
            inn_x = data_x;
        }
        if(data_y < inn_y){
            inn_y = data_y;
        }
        return {x : inn_x, y : inn_y};
    }
    //innerDataArrayMaker 종속 함수2
    function _getCenterPos2(inn_x, inn_y, data_x, data_y){
        if(data_x > inn_x){
            inn_x = data_x;
        }
        if(data_y > inn_y){
            inn_y = data_y;
        }
        return {x : inn_x, y : inn_y};
    }    

 

이름이 겹치는 부분이 존재한다면 해당 값을 조금씩 조정해주면 아래사진처럼 이름이 들어가 모양을 볼 수 있습니다.

쫜~ 이름도 들어갔네요.^^

 

여기까지 하고나면 뭔가 허전한게...

마우스를 올리면 이벤트가 좀 나타났으면 좋겠습니다(?)

마우스 이벤트를 적용하려면 다각형에 대한 이벤트를 적용하는 계산방법이 들어가야 합니다.

예전에 포스팅한 글을 참조하여주세요~

* 참조 : lts0606.tistory.com/286

 

Html Canvas (Html 캔버스) 튜토리얼 (차트만들기!) - 12

이벤트를 부여하는 방법 세번째 시간이다. 앞선 시간에는 사각형, 원에대해서 알아보았다면 여러 모양을 지닌 다각형에 대해서 이벤트를 주는 방법이다. 다각형은 말 그대로 여러 각을 지닌 도�

lts0606.tistory.com

 

어떤분인지 몰라도 저러한 계산방법을 구했다는 것에 대해서 정말 대단함을 느꼈습니다.

계산하는 함수의 내용은 아래와 같습니다.

    //다각형에서의 접선 구하는 함수
    function isInside(event) {
        //crosses는 점과 오른쪽 반직선과 다각형과의 교점의 개수
        var result = false;
        for(var mm = 0 ; mm < dataArray.length; mm++){
            var cross = 0;
            var position = dataArray[mm];
            for (var i = 0; i < position.value.length; i++) {
                var pos = position.value[i];
                var j = (i + 1) % position.value.length;  //교점구할 j값, 1,2,3..순으로 인덱스가 증가하다 마지막은 초기값 0이 나와 비교를 함.
                var otherPos = position.value[j];
                if ((pos.y > event.y) != (otherPos.y > event.y)) {  //점 event가 선분에 있는지 여부
                    var visit = (otherPos.x - pos.x) * (event.y - pos.y) / (otherPos.y - pos.y) + pos.x; 
                    if (event.x < visit){
                        cross++;
                    }
                }
            }
            if(cross % 2 > 0){
                result = position.key;
            }
        }
        return result;  //홀짝 후 리턴
    }

 

위 함수를 캔버스에 적용한 뒤에, 마우스의 위치가 이벤트 지점에 도달하면 캔버스를 지우고 해당 이벤트 지역에 대해서 배경색이 바뀌면서 글씨가 굵어지도록 하게 하였습니다.

지역에 마우스를 올리면 색과 선이 변하게 하였습니다.

 

나름 괜찮은 작업이였던 것 같습니다.

물론, 마우스를 통해서 zoom 이벤트와 zoom이 된 이후에 drag이벤트 기능은 추가적인 공수(?)가 많이 들어서 포기하였던 것 같습니다...ㅠㅠ

역시 이래서 상용화된 차트를 많이 쓰는가 봅니다.

 

해당 포스팅은 코드를 전부 공개하지 않고 개념만 정리한 내용입니다.

이상으로 Html 캔버스를 활용하여 우리나라 지도를 그리는 내용에 대해서 살펴 보았습니다.

문의사항이나 궁금한 점은 댓글 또는 메일로 연락주세요 :)

 

반응형
* 위 에니메이션은 Html의 캔버스(canvas)기반으로 동작하는 기능 입니다. Html 캔버스 튜토리얼 도 한번 살펴보세요~ :)
* 직접 만든 Html 캔버스 애니메이션 도 한번 살펴보세요~ :)

댓글