안드로이드폰에서 web [원의 반경 계산하기] api 를 사용시 문의합니다

[FAQ] 지도/로컬 API 문의 전 꼭 읽어 주세요.
https://devtalk.kakao.com/t/faq-api/125610
확인했습니다.
////

안녕하세요… 카카오 api를 잘 활용하고 있는 회원입니다. 저는 경기경찰청에서 근무하고 있는 송현준연구사라고 하는데요… 카카오 api 를 통해서 치안, 대테러 분야에 활용하여 테러 대응 및 예방활동을 하고 있습니다.

그래서… 지도를 통한 대응을 할 수 있도록 모바일 web으로 제작을 하였는데요…
그중 원의 반경 구현을 하는데…

문제는 아이폰은 구현이 잘 됩니다. 하지만 안드로이드 폰은 반경이 구현이 이상하게 되더라구요…

그래서… 이 오류를 해결 요청을 희망합니다… 감사합니다.

@q7410

안녕하세요,

구현이 이상하게 된다는 것이 어떤 현상인 지 좀 더 자세하게 설명해주세요.

감사합니다.

안드로이드 폰으로 원의 반경을 구현시 한손가락으로 터치하고 두손가락으로 확장을 하는데… 아이폰은 원만하게 되는 반면 안드로이드 폰은 확장이 안되는 현상이 발생합니다.

현상을 확인할 수 있는 소스 코드 첨부 부탁드립니다.

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>원의 반경 계산하기</title>
    <style>
.info {position:relative;top:5px;left:5px;border-radius:6px;border: 1px solid #ccc;border-bottom:2px solid #ddd;font-size:12px;padding:5px;background:#fff;list-style:none;margin:0;} 
.info:nth-of-type(n) {border:0; box-shadow:0px 1px 2px #888;}    
.info .label {display:inline-block;width:50px;}
.number {font-weight:bold;color:#00a0e9;} 
</style>
</head>
<body>
<div id="map" style="width:100%;height:350px;"></div>  
<p>
    <button onclick="removeCircles()">모두 지우기</button> <br>  
</p>  
<em>
    지도를 마우스로 클릭하면 원 그리기가 시작되고 <br>
    오른쪽 마우스를 클릭하면 원 그리기가 종료됩니다    
</em>
 
<script type="text/javascript" src="//dapi.kakao.com/v2/maps/sdk.js?appkey=발급받은 APP KEY를 사용하세요"></script>
<script>
var mapContainer = document.getElementById('map'), // 지도를 표시할 div  
    mapOption = { 
        center: new kakao.maps.LatLng(33.450701, 126.570667), // 지도의 중심좌표
        level: 2 // 지도의 확대 레벨  
    };

var map = new kakao.maps.Map(mapContainer, mapOption); // 지도를 생성합니다

var drawingFlag = false; // 원이 그려지고 있는 상태를 가지고 있을 변수입니다
var centerPosition; // 원의 중심좌표 입니다
var drawingCircle; // 그려지고 있는 원을 표시할 원 객체입니다
var drawingLine; // 그려지고 있는 원의 반지름을 표시할 선 객체입니다
var drawingOverlay; // 그려지고 있는 원의 반경을 표시할 커스텀오버레이 입니다
var drawingDot; // 그려지고 있는 원의 중심점을 표시할 커스텀오버레이 입니다

var circles = []; // 클릭으로 그려진 원과 반경 정보를 표시하는 선과 커스텀오버레이를 가지고 있을 배열입니다

// 지도에 클릭 이벤트를 등록합니다
kakao.maps.event.addListener(map, 'click', function(mouseEvent) {
        
    // 클릭 이벤트가 발생했을 때 원을 그리고 있는 상태가 아니면 중심좌표를 클릭한 지점으로 설정합니다
    if (!drawingFlag) {    
        
        // 상태를 그리고있는 상태로 변경합니다
        drawingFlag = true; 
        
        // 원이 그려질 중심좌표를 클릭한 위치로 설정합니다 
        centerPosition = mouseEvent.latLng; 

        // 그려지고 있는 원의 반경을 표시할 선 객체를 생성합니다
        if (!drawingLine) {
            drawingLine = new kakao.maps.Polyline({
                strokeWeight: 3, // 선의 두께입니다
                strokeColor: '#00a0e9', // 선의 색깔입니다
                strokeOpacity: 1, // 선의 불투명도입니다 0에서 1 사이값이며 0에 가까울수록 투명합니다
                strokeStyle: 'solid' // 선의 스타일입니다
            });    
        }
        
        // 그려지고 있는 원을 표시할 원 객체를 생성합니다
        if (!drawingCircle) {                    
            drawingCircle = new kakao.maps.Circle({ 
                strokeWeight: 1, // 선의 두께입니다
                strokeColor: '#00a0e9', // 선의 색깔입니다
                strokeOpacity: 0.1, // 선의 불투명도입니다 0에서 1 사이값이며 0에 가까울수록 투명합니다
                strokeStyle: 'solid', // 선의 스타일입니다
                fillColor: '#00a0e9', // 채우기 색깔입니다
                fillOpacity: 0.2 // 채우기 불투명도입니다 
            });     
        }
        
        // 그려지고 있는 원의 반경 정보를 표시할 커스텀오버레이를 생성합니다
        if (!drawingOverlay) {
            drawingOverlay = new kakao.maps.CustomOverlay({
                xAnchor: 0,
                yAnchor: 0,
                zIndex: 1
            });              
        }
    }
    });

// 지도에 마우스무브 이벤트를 등록합니다
// 원을 그리고있는 상태에서 마우스무브 이벤트가 발생하면 그려질 원의 위치와 반경정보를 동적으로 보여주도록 합니다
kakao.maps.event.addListener(map, 'mousemove', function (mouseEvent) {
        
    // 마우스무브 이벤트가 발생했을 때 원을 그리고있는 상태이면
    if (drawingFlag) {

        // 마우스 커서의 현재 위치를 얻어옵니다 
        var mousePosition = mouseEvent.latLng; 
        
        // 그려지고 있는 선을 표시할 좌표 배열입니다. 클릭한 중심좌표와 마우스커서의 위치로 설정합니다
        var linePath = [centerPosition, mousePosition];     
        
        // 그려지고 있는 선을 표시할 선 객체에 좌표 배열을 설정합니다
        drawingLine.setPath(linePath);
        
        // 원의 반지름을 선 객체를 이용해서 얻어옵니다 
        var length = drawingLine.getLength();
        
        if(length > 0) {
            
            // 그려지고 있는 원의 중심좌표와 반지름입니다
            var circleOptions = { 
                center : centerPosition, 
            radius: length,                 
            };
            
            // 그려지고 있는 원의 옵션을 설정합니다
            drawingCircle.setOptions(circleOptions); 
                
            // 반경 정보를 표시할 커스텀오버레이의 내용입니다
            var radius = Math.round(drawingCircle.getRadius()),   
            content = '<div class="info">반경 <span class="number">' + radius + '</span>m</div>';
            
            // 반경 정보를 표시할 커스텀 오버레이의 좌표를 마우스커서 위치로 설정합니다
            drawingOverlay.setPosition(mousePosition);
            
            // 반경 정보를 표시할 커스텀 오버레이의 표시할 내용을 설정합니다
            drawingOverlay.setContent(content);
            
            // 그려지고 있는 원을 지도에 표시합니다
            drawingCircle.setMap(map); 
            
            // 그려지고 있는 선을 지도에 표시합니다
            drawingLine.setMap(map);  
            
            // 그려지고 있는 원의 반경정보 커스텀 오버레이를 지도에 표시합니다
            drawingOverlay.setMap(map);
            
        } else { 
            
            drawingCircle.setMap(null);
            drawingLine.setMap(null);    
            drawingOverlay.setMap(null);
            
        }
    }     
});     

// 지도에 마우스 오른쪽 클릭이벤트를 등록합니다
// 원을 그리고있는 상태에서 마우스 오른쪽 클릭 이벤트가 발생하면
// 마우스 오른쪽 클릭한 위치를 기준으로 원과 원의 반경정보를 표시하는 선과 커스텀 오버레이를 표시하고 그리기를 종료합니다
kakao.maps.event.addListener(map, 'rightclick', function (mouseEvent) {

    if (drawingFlag) {

        // 마우스로 오른쪽 클릭한 위치입니다 
        var rClickPosition = mouseEvent.latLng; 

        // 원의 반경을 표시할 선 객체를 생성합니다
        var polyline = new kakao.maps.Polyline({
            path: [centerPosition, rClickPosition], // 선을 구성하는 좌표 배열입니다. 원의 중심좌표와 클릭한 위치로 설정합니다
            strokeWeight: 3, // 선의 두께 입니다
            strokeColor: '#00a0e9', // 선의 색깔입니다
            strokeOpacity: 1, // 선의 불투명도입니다 0에서 1 사이값이며 0에 가까울수록 투명합니다
            strokeStyle: 'solid' // 선의 스타일입니다
        });
        
        // 원 객체를 생성합니다
        var circle = new kakao.maps.Circle({ 
            center : centerPosition, // 원의 중심좌표입니다
            radius: polyline.getLength(), // 원의 반지름입니다 m 단위 이며 선 객체를 이용해서 얻어옵니다
            strokeWeight: 1, // 선의 두께입니다
            strokeColor: '#00a0e9', // 선의 색깔입니다
            strokeOpacity: 0.1, // 선의 불투명도입니다 0에서 1 사이값이며 0에 가까울수록 투명합니다
            strokeStyle: 'solid', // 선의 스타일입니다
            fillColor: '#00a0e9', // 채우기 색깔입니다
            fillOpacity: 0.2  // 채우기 불투명도입니다 
        });
        
        var radius = Math.round(circle.getRadius()), // 원의 반경 정보를 얻어옵니다
            content = getTimeHTML(radius); // 커스텀 오버레이에 표시할 반경 정보입니다

        
        // 반경정보를 표시할 커스텀 오버레이를 생성합니다
        var radiusOverlay = new kakao.maps.CustomOverlay({
            content: content, // 표시할 내용입니다
            position: rClickPosition, // 표시할 위치입니다. 클릭한 위치로 설정합니다
            xAnchor: 0,
            yAnchor: 0,
            zIndex: 1 
        });  

        // 원을 지도에 표시합니다
        circle.setMap(map); 
        
        // 선을 지도에 표시합니다
        polyline.setMap(map);
        
        // 반경 정보 커스텀 오버레이를 지도에 표시합니다
        radiusOverlay.setMap(map);
        
        // 배열에 담을 객체입니다. 원, 선, 커스텀오버레이 객체를 가지고 있습니다
        var radiusObj = {
            'polyline' : polyline,
            'circle' : circle,
            'overlay' : radiusOverlay
        };
        
        // 배열에 추가합니다
        // 이 배열을 이용해서 "모두 지우기" 버튼을 클릭했을 때 지도에 그려진 원, 선, 커스텀오버레이들을 지웁니다
        circles.push(radiusObj);   
    
        // 그리기 상태를 그리고 있지 않는 상태로 바꿉니다
        drawingFlag = false;
        
        // 중심 좌표를 초기화 합니다  
        centerPosition = null;
        
        // 그려지고 있는 원, 선, 커스텀오버레이를 지도에서 제거합니다
        drawingCircle.setMap(null);
        drawingLine.setMap(null);   
        drawingOverlay.setMap(null);
    }
});    
    
// 지도에 표시되어 있는 모든 원과 반경정보를 표시하는 선, 커스텀 오버레이를 지도에서 제거합니다
function removeCircles() {         
    for (var i = 0; i < circles.length; i++) {
        circles[i].circle.setMap(null);    
        circles[i].polyline.setMap(null);
        circles[i].overlay.setMap(null);
    }         
    circles = [];
}

// 마우스 우클릭 하여 원 그리기가 종료됐을 때 호출하여 
// 그려진 원의 반경 정보와 반경에 대한 도보, 자전거 시간을 계산하여
// HTML Content를 만들어 리턴하는 함수입니다
function getTimeHTML(distance) {

    // 도보의 시속은 평균 4km/h 이고 도보의 분속은 67m/min입니다
    var walkkTime = distance / 67 | 0;
    var walkHour = '', walkMin = '';

    // 계산한 도보 시간이 60분 보다 크면 시간으로 표시합니다
    if (walkkTime > 60) {
        walkHour = '<span class="number">' + Math.floor(walkkTime / 60) + '</span>시간 '
    }
    walkMin = '<span class="number">' + walkkTime % 60 + '</span>분'

    // 자전거의 평균 시속은 16km/h 이고 이것을 기준으로 자전거의 분속은 267m/min입니다
    var bycicleTime = distance / 227 | 0;
    var bycicleHour = '', bycicleMin = '';

    // 계산한 자전거 시간이 60분 보다 크면 시간으로 표출합니다
    if (bycicleTime > 60) {
        bycicleHour = '<span class="number">' + Math.floor(bycicleTime / 60) + '</span>시간 '
    }
    bycicleMin = '<span class="number">' + bycicleTime % 60 + '</span>분'

    // 거리와 도보 시간, 자전거 시간을 가지고 HTML Content를 만들어 리턴합니다
    var content = '<ul class="info">';
    content += '    <li>';
    content += '        <span class="label">총거리</span><span class="number">' + distance + '</span>m';
    content += '    </li>';
    content += '    <li>';
    content += '        <span class="label">도보</span>' + walkHour + walkMin;
    content += '    </li>';
    content += '    <li>';
    content += '        <span class="label">자전거</span>' + bycicleHour + bycicleMin;
    content += '    </li>';
    content += '</ul>'

    return content;
}
</script>
</body>
</html>

보시는 코드가 pc와 아이폰에서는 반경구현이 잘되는 반면 안드로이드(삼성폰)에서는 손가락으로 터치시 반경 조절이 안되는 현상이 있네요.

예제는 PC 웹 브라우저에 대응하는 코드로 모바일에서 그대로 사용하면 원하는 방향으로 동작하지 않을 수 있습니다.

예제와 동일한 코드를 사용하고 계신 걸로 보이는데 해당 코드는 모바일에 대응하는 코드가 아니기 때문에
그대로 사용하면 PC 웹 브라우저와 달리 원을 그리고 종료하는 기능이 정상 동작되지 않습니다.
모바일 기기는 rightclick 이벤트를 지원하지 않아 rightclick 이벤트가 호출되지 않는 부분도 같은 부분으로 보시면 됩니다.

예제는 참고로만 봐주시고 모바일 기기에 대응하는 코드(멀티터치, 그리기 종료 이벤트 변경 등)로 수정해주세요.

멀티터치, 그리기 종료 이벤트 오픈 소스는 없는지요? 있으면 소개 좀 부탁합니다. 제가 치안 테러방지 관련 어플리케인션을 개발중인데요… 비전문가로서 현재 이렇게 이용하는 수준밖에 안됩니다. 초보 개발자라서… 혼자서 해야 하는 상황이에요… 여기서 모르면 해결하기 힘든상황입니다. 간곡히 부탁드립니다. (저는 경기남부경찰청 대테러계 송현준연구사라고 합니다.)

말씀주신 내용에 대한 코드는 제공하고 있지 않습니다.
예제 코드를 참고해서 직접 구현해주세요.