로드뷰에 커서를 올리기 전까진 깨진 상태가 유지되고, 커서를 올리면 정상적으로 돌아오네요.
window 창 크기를 축소시켰다가 최대화 시키면 지도와 로드뷰가 window 창 내부를 꽉 채우는 게 아니라
로드뷰 오른쪽에 검은 여백이 생깁니다. resizer를 mousedown 하기 전까지 그대로구요…
function getCoord(map2dCoord){
var center = ol.proj.transform(map2dCoord, map2d.crs, ‘EPSG:4326’);
const lat = center[1];
const lon = center[0];
var S = 37.36713295859407;
var W = 127.30632201199485;
var N = 37.67029926582917;
var E = 127.84867275688543;
if ((S < lat && lat < N) && (W < lon && lon < E)){
return center;
} else {
return false;
}
};
function changeZoom(type, zoom) {
const kakaoZoomMax = 1;
const kakaoZoomMin = 8;
const ypZoomMax = 19;
const ypZoomMin = 12;
// map2D → kakaoMap
if (type === “map2D”) {
const kakaoZoom = Math.round(((zoom - ypZoomMin) / (ypZoomMax - ypZoomMin)) * (kakaoZoomMax - kakaoZoomMin) + kakaoZoomMin);
// 카카오맵의 최소 및 최대 줌 레벨 범위를 벗어나면 해당 범위로 설정
return Math.min(Math.max(kakaoZoom, kakaoZoomMax), kakaoZoomMin);
}
// kakaoMap → map2D
else if (type === “kakaoMap”) {
const ypZoom = Math.round(((zoom - kakaoZoomMin) / (kakaoZoomMax - kakaoZoomMin)) * (ypZoomMax - ypZoomMin) + ypZoomMin);
// map2D의 최소 및 최대 줌 레벨 범위를 벗어나면 해당 범위로 설정
return Math.min(Math.max(ypZoom, ypZoomMin), ypZoomMax);
}
}
function bindCoord(type){
if(type === “off”){
if($(‘#kakaoMap .MapWalker’).length > 0) {
//마커의 좌표값 얻기 {La:경도,Ma:위도}
let latlon = mapWalker.walker.getPosition();
let lat = latlon.Ma;
let lon = latlon.La;
var S = 37.36713295859407;
var W = 127.30632201199485;
var N = 37.67029926582917;
var E = 127.84867275688543;
if ((S < lat && lat < N) && (W < lon && lon < E)){
// map2D 좌표 형태로 변환
let markerCoord = ol.proj.transform([lon, lat], ‘EPSG:4326’, map2d.crs);
//지도의 줌레벨 얻기
var kakaoZoom = map.getLevel();
var ypZoom = changeZoom(“kakaoMap”, kakaoZoom);
let options = {zoom : ypZoom};
map2d.setCenter(markerCoord, options);
} else {
toastr.info(‘’, ‘지도 범위를 벗어났으므로 지도 영역을 초기화합니다.’, {timeOut: 5000});
$(‘#toast-container > div’).css({width:‘350’});
dtmap.goHome();
}
}
}
if(type === “on”){
var ypZoom = map2d.view.getZoom();
var kakaoZoom = changeZoom(“map2D”, ypZoom);
return kakaoZoom;
}
}
function setMapCenter(target) {
if(target === “kakaoMap”) {
var xy = ol.proj.transform(map2d.getCenter(), map2d.crs, ‘EPSG:4326’);
var center = new kakao.maps.LatLng(xy[1], xy[0]);
var zoom = changeZoom(“map2D”, map2d.view.getZoom());
/* getNearestPanoId(카카오 좌표, 반경(미터 단위), callback); */
rvClient.getNearestPanoId(center, 100, function(panoId) {
if (panoId === null) {
toastr.error(‘로드뷰 정보가 존재하지 않습니다.’,‘’, {timeOut: 1000});
//map.relayout();
} else {
map.setLevel(zoom);
rv.setPanoId(panoId, center);
}
});
}
if(target === “map2D”) {
const position = map.getCenter();
const lat = position.Ma;
const lon = position.La;
const center = ol.proj.transform([lon, lat], ‘EPSG:4326’, map2d.crs);
const zoom = changeZoom(“kakaoMap”, map.getLevel());
const options = {zoom: zoom};
map2d.setCenter(center, options);
map2d.map.updateSize();
}
}
function syncMapCneter(e) {
$(‘#kakaoMap’).hasClass(‘active’) ? setMapCenter(“map2D”) : setMapCenter(“kakaoMap”);
}
function toggleKakaoMap() {
var btnToggle = $(‘#btn-toggle’);
var isToggleOff = btnToggle.hasClass(‘toggle-off’);
var parent = $(‘div#roadview’).children().eq(0).children().children().eq(0)
var kakaoMap = $(‘#kakaoMap’);
if (isToggleOff) {
btnToggle.removeClass(‘toggle-off’).addClass(‘toggle-on’);
kakaoMap.addClass(‘active’);
kakaoMap.toggle(200);
} else {
btnToggle.removeClass(‘toggle-on’).addClass(‘toggle-off’);
kakaoMap.removeClass(‘active’);
kakaoMap.toggle(200);
//parent.css({width:‘inherit’,height:‘inherit’});
//parent.children().css({width:‘inherit’,height:‘inherit’});
}
}
function toggleRoadview(mapCenter, zoom) {
if(($(‘#kakaoMap’).length === 0 && $(‘#roadview’).length === 0)) {
showHideRdvwElement(“show”);
selectRoadview(mapCenter, zoom);
} else {
bindCoord(“off”);
showHideRdvwElement(“hide”);
map2d.map.un(‘moveend’, syncMapCneter);
kakao.maps.event.removeListener(map, ‘center_changed’, syncMapCneter);
map2d.map.updateSize();
}
}
function selectRoadview(center, zoom){
var kakaoMapDiv = document.getElementById(‘kakaoMap’); // 지도를 표시할 div
var roadviewDiv = document.getElementById(‘roadview’); //로드뷰를 표시할 div
rv = new kakao.maps.Roadview(roadviewDiv); //로드뷰 객체
rvClient = new kakao.maps.RoadviewClient(); //좌표로부터 로드뷰 파노라마 ID를 가져올 로드뷰 helper객체
var mapCenter = new kakao.maps.LatLng(center[1], center[0]);
var mapOption = {
center: mapCenter, // 지도의 중심좌표
level: zoom // 지도의 확대 레벨
};
// 지도를 표시할 div와 지도 옵션으로 지도를 생성합니다
map = new kakao.maps.Map(kakaoMapDiv, mapOption);
map.setMaxLevel(8);
map.addOverlayMapTypeId(kakao.maps.MapTypeId.ROADVIEW); // 로드뷰 도로 추가
ctrlRoadview(mapCenter);
//로드뷰 toggle함수
function ctrlRoadview(position) {
//전달받은 좌표(position)에 가까운 로드뷰의 panoId를 추출하여 로드뷰를 띄웁니다
rvClient.getNearestPanoId(position, 50, function(panoId) {
if (panoId === null) {
toastr.error('로드뷰 정보가 존재하지 않습니다.','', {timeOut: 1000});
if($('#kakaoMap').width() === 310 && $('#kakaoMap').height() === 190) { //로드뷰 첫 실행 시
return toggleRoadview();
} else {
//roadviewDiv.style.display = 'none'; //로드뷰를 넣은 컨테이너를 숨깁니다
//kakaoMapDiv.style.width = '100%';
map.relayout();
}
} else {
//kakaoMapDiv.style.width = '50%';
map.relayout(); //지도를 감싸고 있는 영역이 변경됨에 따라, 지도를 재배열합니다
roadviewDiv.style.display = 'block'; //로드뷰를 넣은 컨테이너를 보이게합니다
rv.setPanoId(panoId, position); //panoId를 통한 로드뷰 실행
rv.relayout(); //로드뷰를 감싸고 있는 영역이 변경됨에 따라, 로드뷰를 재배열합니다
}
});
}
var startX, startY, startOverlayPoint;
function MapWalker(mapCenter){
//커스텀 오버레이에 사용할 map walker 엘리먼트
var content = document.createElement('div');
var figure = document.createElement('div');
var angleBack = document.createElement('div');
//map walker를 구성하는 각 노드들의 class명을 지정 - style셋팅을 위해 필요
content.className = 'MapWalker';
figure.className = 'figure';
angleBack.className = 'angleBack';
content.appendChild(angleBack);
content.appendChild(figure);
//커스텀 오버레이 객체를 사용하여, map walker 아이콘을 생성
var walker = new kakao.maps.CustomOverlay({
position: mapCenter,
content: content,
yAnchor: 1,
});
this.walker = walker;
this.content = content;
// 커스텀 오버레이에 mousedown, mouseup 이벤트를 등록합니다
addEventHandle(this.content, 'mousedown', onMouseDown);
addEventHandle(this.content, 'mouseup', onMouseUp);
}
//로드뷰의 pan(좌우 각도)값에 따라 map walker의 백그라운드 이미지를 변경 시키는 함수
//background로 사용할 sprite 이미지에 따라 계산 식은 달라 질 수 있음
MapWalker.prototype.setAngle = function(angle){
var threshold = 22.5; //이미지가 변화되어야 되는(각도가 변해야되는) 임계 값
for(var i=0; i<16; i++){ //각도에 따라 변화되는 앵글 이미지의 수가 16개
if(angle > (threshold * i) && angle < (threshold * (i + 1))){
//각도(pan)에 따라 아이콘의 class명을 변경
var className = 'm' + i;
this.content.className = this.content.className.split(' ')[0];
this.content.className += (' ' + className);
break;
}
}
};
//map walker의 위치를 가져오는 함수
MapWalker.prototype.getPosition = function() {
return this.walker.getPosition();
};
//map walker의 위치를 변경시키는 함수
MapWalker.prototype.setPosition = function(position){
this.walker.setPosition(position);
};
//map walker를 지도위에 올리는 함수
MapWalker.prototype.setMap = function(map){
this.walker.setMap(map);
};
// 로드뷰가 초기화 되었을 때 map walker를 생성한다.
kakao.maps.event.addListener(rv, 'init', function() {
// map walker를 생성한다. 생성시 지도의 중심좌표를 넘긴다.
mapWalker = new MapWalker(mapCenter);
mapWalker.setMap(map); // map walker를 지도에 설정한다.
// 로드뷰가 초기화 된 후, 추가 이벤트를 등록한다.
// 로드뷰에서 상,하,좌,우,줌인,줌아웃 이동을 할 경우 발생한다.
// 로드뷰를 조작할 때 발생하는 값을 받아 map walker의 상태를 변경해 준다.
kakao.maps.event.addListener(rv, 'viewpoint_changed', function(){
// 이벤트가 발생할 때마다 로드뷰의 viewpoint값을 읽어, map walker에 반영
var viewpoint = rv.getViewpoint();
mapWalker.setAngle(viewpoint.pan);
});
// 로드뷰에서 화살표나 점프를 하였을 경우 발생한다.
// position값이 바뀔 때마다 map walker의 상태를 변경해 준다.
kakao.maps.event.addListener(rv, 'position_changed', function(){
// 이벤트가 발생할 때마다 로드뷰의 position값을 읽어, map walker에 반영
let position = rv.getPosition();
let lat = position.Ma;
let lon = position.La;
dtmap.setCenter(ol.proj.transform([lon, lat], 'EPSG:4326', map2d.crs), {});
mapWalker.setPosition(position);
map.setCenter(position);
});
});
mapWalker = new MapWalker();
//지도에 클릭 이벤트를 할당합니다
kakao.maps.event.addListener(map, 'click', function(mouseEvent){
// 현재 클릭한 부분의 좌표를 리턴
var position = mouseEvent.latLng;
rvClient.getNearestPanoId(position, 30, function(panoId) {
if (panoId === null) {
toastr.error('로드뷰 정보가 존재하지 않습니다.','', {timeOut: 1000});
} else{
mapWalker.setPosition(position);
ctrlRoadview(position); // 로드뷰를 토글합니다
}
});
});
// 이동,확대,축소로 인해 지도의 중심좌표가 변경될 때마다 양평맵 <-> 카카오맵 싱크 맞추기
if(($('#kakaoMap').length > 0 && $('#roadview').length > 0)) {
kakao.maps.event.addListener(map, 'center_changed', syncMapCneter);
map2d.map.on('moveend', syncMapCneter)
}
function onMouseDown(e) {
// 커스텀 오버레이를 드래그 할 때, 내부 텍스트가 영역 선택되는 현상을 막아줍니다.
if (e.preventDefault) {
e.preventDefault();
} else {
e.returnValue = false;
}
var proj = map.getProjection(),
overlayPos = mapWalker.getPosition(); // 커스텀 오버레이의 현재 위치를 가져옵니다
// 커스텀오버레이에서 마우스 관련 이벤트가 발생해도 지도가 움직이지 않도록 합니다
kakao.maps.event.preventMap();
startX = e.clientX;
startY = e.clientY;
// mousedown됐을 때의 커스텀 오버레이의 좌표를
// 지도 컨테이너내 픽셀 좌표로 변환합니다
startOverlayPoint = proj.containerPointFromCoords(overlayPos);
// document에 mousemove 이벤트를 등록합니다
addEventHandle(document, 'mousemove', onMouseMove);
}
// mouseup 했을 때 호출되는 핸들러 입니다
function onMouseUp(e) {
// 등록된 mousemove 이벤트 핸들러를 제거합니다
removeEventHandle(document, 'mousemove', onMouseMove);
//이동한 마커 위치의 panoId를 가져올 수 있도록 toggleRoadview를 호출합니다.
var position = mapWalker.getPosition();
ctrlRoadview(position); // 로드뷰를 토글합니다
}
function onMouseMove(e) {
// 커스텀 오버레이를 드래그 할 때, 내부 텍스트가 영역 선택되는 현상을 막아줍니다.
if (e.preventDefault) {
e.preventDefault();
} else {
e.returnValue = false;
}
var proj = map.getProjection(),// 지도 객체로 부터 화면픽셀좌표, 지도좌표간 변환을 위한 MapProjection 객체를 얻어옵니다
deltaX = startX - e.clientX, // mousedown한 픽셀좌표에서 mousemove한 좌표를 빼서 실제로 마우스가 이동된 픽셀좌표를 구합니다
deltaY = startY - e.clientY,
// mousedown됐을 때의 커스텀 오버레이의 좌표에 실제로 마우스가 이동된 픽셀좌표를 반영합니다
newPoint = new kakao.maps.Point(startOverlayPoint.x - deltaX, startOverlayPoint.y - deltaY),
// 계산된 픽셀 좌표를 지도 컨테이너에 해당하는 지도 좌표로 변경합니다
newPos = proj.coordsFromContainerPoint(newPoint);
mapWalker.setPosition(newPos);
}
// target node에 이벤트 핸들러를 등록하는 함수힙니다
function addEventHandle(target, type, callback) {
if (target.addEventListener) {
target.addEventListener(type, callback);
} else {
target.attachEvent('on' + type, callback);
}
}
// target node에 등록된 이벤트 핸들러를 제거하는 함수힙니다
function removeEventHandle(target, type, callback) {
if (target.removeEventListener) {
target.removeEventListener(type, callback);
} else {
target.detachEvent('on' + type, callback);
}
}
initResizable();
}
function initResizable() {
// div 요소 선택
const kakaoMap = document.querySelector(‘#kakaoMap’);
const roadview = document.querySelector(‘#roadview’);
// resizer 핸들러 요소를 선택
const resizer = document.querySelector(‘#kakaoMap .resizer’);
// 최소 사이즈 설정
const min_width = 170;
const min_height = 130;
// 최대 사이즈 설정
//const max_width = 2134.17;
//const max_height = 1046.67;
let max_width = window.innerWidth;
let max_height = window.innerHeight;
/** 초기 너비와 높이
* original_width = 310;
* original_height = 190;
*/
//초기 위치 설정
let original_x = 0;
let original_y = 0;
// 마우스 초기 위치 설정
let original_mouse_x = 0;
let original_mouse_y = 0;
// 마우스 다운 이벤트 핸들러 등록
resizer.addEventListener('mousedown', function(e) {
// 기본 이벤트 방지
e.preventDefault();
// resizable 이전의 요소의 현재 스타일 값을 가져와서 파싱하여 초기 값 설정
original_width = parseFloat(getComputedStyle(kakaoMap, null).getPropertyValue('width').replace('px', ''));
original_height = parseFloat(getComputedStyle(kakaoMap, null).getPropertyValue('height').replace('px', ''));
// 요소의 초기 위치 설정
original_x = kakaoMap.getBoundingClientRect().left;
original_y = kakaoMap.getBoundingClientRect().top;
// 초기 마우스 위치 설정
original_mouse_x = e.pageX;
original_mouse_y = e.pageY;
// 마우스 이동 이벤트 리스너 등록
window.addEventListener('mousemove', resize);
// 마우스 업 이벤트 리스너 등록
window.addEventListener('mouseup', stopResize);
});
// 마우스 이동 이벤트 핸들러 함수 정의
function resize(e) {
// 새로운 너비 계산
let width = original_width + (e.pageX - original_mouse_x);
// 새로운 높이 계산
let height = original_height - (e.pageY - original_mouse_y);
// 너비 조정
if (width <= min_width) {
width = min_width;
// 최대 넓이는 로드뷰와 1:1
} else if (width >= max_width / 2) {
width = max_width / 2;
}
// 높이 조정
if (height <= min_height) {
height = min_height;
// 최상단에 닿아있을 때
} else if (height >= max_height) {
// 카카오맵은 최대 높이로 설정
height = max_height;
// 로드뷰 위치 조정
const rv_width = window.innerWidth - width;
roadview.style.width = rv_width + 'px';
roadview.style.left = width + 'px';
// 내려와있을 때는 카카오맵에 맞추기
} else if (height < max_height) {
roadview.style.width = 'auto';
roadview.style.left = 'auto';
}
kakaoMap.style.width = width + 'px';
kakaoMap.style.height = height + 'px';
rv.relayout();
map.relayout();
map.setCenter(mapWalker.walker.getPosition());
}
// 마우스 업 이벤트 핸들러 함수 정의
function stopResize() {
// 마우스 이동 및 업 이벤트 리스너 제거
window.removeEventListener('mousemove', resize);
window.removeEventListener('mouseup', stopResize);
}
}
// display 전환 함수
function showHideRdvwElement(display) {
if(display === “show”) {
$(‘#rightPopup.popup-panel’).removeClass(‘opened’);
$(‘#map2D’).addClass(‘split-main-map’);
$(‘
’).insertAfter($(‘
#map3D’));
$(‘
’).insertAfter($(‘
#map3D’));
$(‘
’).insertAfter($(‘
#roadview’));
$(‘
’).insertAfter($(‘
#btn-close’));
$(‘
#container .logo’).hide();
$(‘
#container .util-box’).hide();
$(‘
#container #warningText’).hide();
$(‘
#map-aside .map-control’).hide();
$(‘
#map-aside .map-util’).hide();
$(‘
#side .twdcvlnService’).hide();
$(‘
#side #lnb’).hide();
let resizeHtml =
<div class="frame"><div class="drag"><span class="resizer"></span></div></div>
;
$(resizeHtml).prependTo($(‘
#kakaoMap’));
} else if(display === “hide”) {
$(‘
#map2D’).removeClass(‘split-main-map’);
$(‘
#kakaoMap’).remove();
$(‘
#roadview’).remove();
$(‘
#btn-close’).remove();
$(‘
#btn-toggle’).remove();
$(‘
#container .logo’).show();
$(‘
#container .util-box’).show();
$(‘
#container #warningText’).show();
$(‘
#map-aside .map-control’).show();
$(‘
#map-aside .map-util’).show();
$(‘
#side .twdcvlnService’).show();
$(‘
#side #lnb’).show();
}
}