Javascript + script 방식의 동적 지도 생성 문의

[FAQ] 지도/로컬 API 문의 전 꼭 읽어 주세요.

안녕하세요.
가이드대로 script 안에서 mapContainer와 map 객체를 생성하는 방식으로 구현해봤는데요,
이렇게 script 생성과 동시에 지도를 생성하는 대신, 이 객체들을 한 함수에 넣어 원하는 시점에 지도를 생성할 수 있을까요?
실제로 해보니 하얀 빈 공간만 나타나서요…

이미 SDK가 로드되었다면 원하는 시점에 지도를 생성하시면 됩니다.
스크립트를 동적으로 로드하는 방법은 아래 문서와 같이 autoload=false 파라미터를 사용해서
kakao.maps.load 콜백 함수 안에서 지도를 생성해주세요.
https://apis.map.kakao.com/web/documentation/#load_load

그리고 지도를 생성했지만 하얀 화면만 보이는 경우는
지도가 표시될 요소의 스타일이 모달, 탭처럼 display: none에서 block으로 변경되는 경우 또는
width/height등 다른 스타일 속성이 동적으로 변경되는 경우에 발생합니다.
이 경우에 해당된다면 지도가 보이는 시점에 map.relayout(); API를 호출해주세요.
https://apis.map.kakao.com/web/documentation/#Map_relayout

답변 감사드립니다만, 제가 원하는 기능은 mapOption 속 disableDoubleClick과 draggable 값을 미리 정하고 그 후 그 값에 따라 터치 가능 여부가 결정되는 지도를 생성하는 것인데요, 가능할까요? 혹시 가능하다면 간단한 예제 코드도 부탁드려도 될까요? 자바스크립트를 처음 접해봐서… 미리 감사드립니다!

어떤 값에 따라 터치 가능 여부가 결정되는지 알 수 없지만, draggable, disableDoubleClick이 계속 변한다면
두 값을 변수로 관리하고 값이 변경될 때마다 두 변수값을 체크해서 원하는 조건에 맞을 때 지도를 생성하는 방법이 있고

지도 생성 조건이 단순하게 판단 가능하다면 변수 없이 조건을 확인해서 지도를 생성하는 방법도 있습니다.
아래는 터치가 가능한 디바이스인 경우 지도를 생성하는 코드입니다.
참고만 해주세요.

let map = null;

function isTouchDevice() {
  return 'ontouchstart' in window || navigator.maxTouchPoints > 0 || navigator.msMaxTouchPoints > 0;
}

function init() {
    if(isTouchDevice()) { //true인 경우(터치가 되는 경우) 지도 표시
        if(map) { //지도가 이미 생성된 경우면 return;
            return;
        }

        let container = document.getElementById('map');
        let options = {
            center: new kakao.maps.LatLng(33.450701, 126.570667),
            level: 3
            //필요한 속성은 추가해주세요.
        };

        map = new kakao.maps.Map(container, options);
    }
}

init();

자세하게 알려주셔서 감사합니다. 하지만 안드로이드 웹뷰로 스크립트를 부른 다음 예시로 주신 코드 속 init() 함수를 언제 호출해야하는지 잘 감이 오질 않습니다. 제 스크립트는 다음과 같습니다.

<!DOCTYPE html>
<html>
<head>
    <script type="text/javascript"
            src="//dapi.kakao.com/v2/maps/sdk.js?appkey=f9fa76887058db0ceb622956fdea69f1&autoload=false"></script>
</head>
<body>
<div id="map" style="width:100%;height:100%;"></div>
<script type="text/javascript">

    var content = '<div class ="label"><sv width="40px" height="40px" viewBox="0 0 40 40" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><title>PNG/settingsic_location</title><g id="PNG/settingsic_location" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"><g id="Common/location" transform="translate(9.499700, 6.500000)" fill="#4D4D52" fill-rule="nonzero"><path d="M10.5,15.0002579 C8.0145,15.0002579 6,12.9857579 6,10.5002579 C6,8.0147579 8.0145,6.0002579 10.5,6.0002579 C12.9855,6.0002579 15,8.0147579 15,10.5002579 C15,12.9857579 12.9855,15.0002579 10.5,15.0002579 M20.9475,9.4367579 C20.466,4.5557579 16.56,0.597257901 11.6835,0.0647579013 C5.355,-0.626742099 0,4.3112579 0,10.5002579 C0,12.5822579 0.609,14.5217579 1.6545,16.1537579 L8.664,26.0507579 C9.561,27.3167579 11.439,27.3167579 12.336,26.0507579 L19.3455,16.1537579 C20.568,14.2457579 21.192,11.9207579 20.9475,9.4367579" id="Fill-1"></path></g></g></svg></div>';
    var customOverlay;
    let timer = null;
    const DELAY = 270; // 더블 클릭 감지 시간

    function setGestureEnabled(isGestureEnabled) {
        this.isGestureEnabled = isGestureEnabled;
    }

    function isTouchDevice() {
        return 'ontouchstart' in window || navigator.maxTouchPoints > 0 || navigator.msMaxTouchPoints > 0;
    }

    function init() {
        if(isTouchDevice()) {
            if(map) {
                return;
            }

            let container = document.getElementById('map');
            let options = {
                center: new kakao.maps.LatLng(33.450701, 126.570667),
                level: 5,
                draggable: isGestureEnabled,
                disableDoubleClick: !isGestureEnabled
            };

            map = new kakao.maps.Map(container, options);
        }
    }

    function handleClick(event) {
        if (timer === null) {
            timer = setTimeout(() => {
                timer = null;
                singleClickHandler(event);
            }, DELAY);
        } else {
            clearTimeout(timer);
            timer = null;
            doubleClickHandler(event);
        }
    }

    function singleClickHandler(event) {
        let latlng = event.latLng;
        KakaoInterface.onClick(latlng.getLat(), latlng.getLng());
    }

    function doubleClickHandler(event) {
        let latlng = event.latLng;
        console.log(`double click! ${latlng.toString()}`);
    }

    function panTo(latitude, longitude) {
        var moveLatLon = new kakao.maps.LatLng(latitude, longitude)

        map.panTo(moveLatLon)
    }

    function drawPin(latitude, longitude) {
        if (customOverlay != null) {
            customOverlay.setMap(null);
        }
        position = new kakao.maps.LatLng(latitude, longitude);
        customOverlay = new kakao.maps.CustomOverlay({
            position: position,
            content: content
        });
        customOverlay.setMap(map);
    }

    kakao.maps.event.addListener(map, 'click', handleClick);

    kakao.maps.load(function() {
        KakaoInterface.onMapReady();
    });

</script>
</body>
</html>

init() 함수를 저 에서 호출해야 하는 건가요, 아님 스크립트가 로드된 다음 호출해야 할까요?

autoload=false 파라미터를 사용하신 경우 SDK가 로드된 이후 실행해야 하기 때문에
kakao.maps.load 콜백함수에서 실행하거나 SDK 로드 상태를 따로 관리한다면 상태가 변한 후 실행하시면 될 것 같습니다.

도움 주셔서 성공했습니다. 감사합니다!

1개의 좋아요