From bbdb820b4a479f834608ad10c8f2f4ee45d125fc Mon Sep 17 00:00:00 2001 From: thkim Date: Wed, 26 Nov 2025 14:30:36 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EC=A7=80=EB=8F=84=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=ED=99=94=EB=A9=B4=EC=A0=80=EC=9E=A5=20=EC=8B=9C=20=EA=B7=B8?= =?UTF-8?q?=EB=A6=AC=EA=B8=B0=20=EB=8F=84=EA=B5=AC=EA=B0=80=20=ED=8F=AC?= =?UTF-8?q?=ED=95=A8=EB=90=98=EB=8F=84=EB=A1=9D=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../geoinfo/map/main/MapMainController.java | 2 +- .../WEB-INF/views/map/index20220726.jsp | 222 ----- .../WEB-INF/views/map/index20230106-2.jsp | 868 ------------------ .../WEB-INF/views/map/index20230106.jsp | 619 ------------- .../WEB-INF/views/map/index20230207-2.jsp | 654 ------------- .../WEB-INF/views/map/index20230207.jsp | 599 ------------ .../WEB-INF/views/map/index_2021_back.jsp | 179 ---- src/main/webapp/js/map/main/map.js | 388 +++++++- 8 files changed, 369 insertions(+), 3162 deletions(-) delete mode 100644 src/main/webapp/WEB-INF/views/map/index20220726.jsp delete mode 100644 src/main/webapp/WEB-INF/views/map/index20230106-2.jsp delete mode 100644 src/main/webapp/WEB-INF/views/map/index20230106.jsp delete mode 100644 src/main/webapp/WEB-INF/views/map/index20230207-2.jsp delete mode 100644 src/main/webapp/WEB-INF/views/map/index20230207.jsp delete mode 100644 src/main/webapp/WEB-INF/views/map/index_2021_back.jsp diff --git a/src/main/java/geoinfo/map/main/MapMainController.java b/src/main/java/geoinfo/map/main/MapMainController.java index df46276f..8137b2e0 100644 --- a/src/main/java/geoinfo/map/main/MapMainController.java +++ b/src/main/java/geoinfo/map/main/MapMainController.java @@ -238,7 +238,7 @@ public class MapMainController { public void getMineInfo(HttpServletRequest request, HttpServletResponse response, @RequestParam HashMap params) throws Exception { // 1. 서비스 키 & 파라미터 설정 - String serviceKey = "L1z0zEpxNLB0Sqwv97WAIyL1lB+shPemDLNaG9hy9g3BzbkXRVG2/aSTZ7PiAAivgaCYn, 9p1tLmq2keiC4yFZA=="; + String serviceKey = "L1z0zEpxNLB0Sqwv97WAIyL1lB+shPemDLNaG9hy9g3BzbkXRVG2/aSTZ7PiAAivgaCYn9p1tLmq2keiC4yFZA=="; String mgtNo = request.getParameter("mgtNo"); // 2. API URL 생성 (JSON 요청) diff --git a/src/main/webapp/WEB-INF/views/map/index20220726.jsp b/src/main/webapp/WEB-INF/views/map/index20220726.jsp deleted file mode 100644 index 777363d0..00000000 --- a/src/main/webapp/WEB-INF/views/map/index20220726.jsp +++ /dev/null @@ -1,222 +0,0 @@ -<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> -<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> - -<%@ include file="/include/inc_map_head_2021_new.jsp" %> - - - - - - - - - - - - - - -<%-- --%> - - - - - - -<% -String pcode = request.getParameter("pcode"); -System.out.println("pCode : " + pcode); - -if(pcode != null){ -%> - -<%}%> - - - - - -
- "/> -
- - - - - -
- -
- - - - - - -
- -
- -
- - - - - -
- - - - -
-
지도제어
- -
- - -
-
그리기도구
- -
- -
- -
- -
- - -
-
-
- - -
- - -
- -
- - - - - \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/views/map/index20230106-2.jsp b/src/main/webapp/WEB-INF/views/map/index20230106-2.jsp deleted file mode 100644 index f18f92b4..00000000 --- a/src/main/webapp/WEB-INF/views/map/index20230106-2.jsp +++ /dev/null @@ -1,868 +0,0 @@ -<%@ page language="java" contentType="text/html; charset=UTF-8" - pageEncoding="UTF-8"%> -<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> - -<%@ include file="/include/inc_map_head_2021_new.jsp"%> - - - - - - - - - - - - - - - - - - - - - - - - - -<% - String pcode = request.getParameter("pcode"); - String mapGbn = request.getParameter("mapGbn"); - System.out.println("pCode : " + pcode); - - if (pcode != null) { -%> - - - -<% - } -%> - -
- " /> -
- - -
- -
- - - - - - - - - -
- -
- - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/views/map/index20230106.jsp b/src/main/webapp/WEB-INF/views/map/index20230106.jsp deleted file mode 100644 index 31dec73e..00000000 --- a/src/main/webapp/WEB-INF/views/map/index20230106.jsp +++ /dev/null @@ -1,619 +0,0 @@ -<%@ page language="java" contentType="text/html; charset=UTF-8" - pageEncoding="UTF-8"%> -<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> - -<%@ include file="/include/inc_map_head_2021_new.jsp"%> - - - - - - - - - - - - - - - - - - - - - - - - - -<% - String pcode = request.getParameter("pcode"); - String mapGbn = request.getParameter("mapGbn"); - System.out.println("pCode : " + pcode); - - if (pcode != null) { -%> - - - -<% - } -%> - -
- " /> -
- - -
- -
- - - - - - - - - -
- -
- - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/views/map/index20230207-2.jsp b/src/main/webapp/WEB-INF/views/map/index20230207-2.jsp deleted file mode 100644 index 45ffb2b7..00000000 --- a/src/main/webapp/WEB-INF/views/map/index20230207-2.jsp +++ /dev/null @@ -1,654 +0,0 @@ -<%@ page language="java" contentType="text/html; charset=UTF-8" - pageEncoding="UTF-8"%> -<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> - -<%@ include file="/include/inc_map_head_2021_new.jsp"%> - - - - - - - - - - - - - - - - - - - - - - - -<% - String pcode = request.getParameter("pcode"); - String mapGbn = request.getParameter("mapGbn"); - System.out.println("pCode : " + pcode); - - if (pcode != null) { -%> - - - -<% - } -%> - -
- " /> -
- - -
- - - -
- - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/views/map/index20230207.jsp b/src/main/webapp/WEB-INF/views/map/index20230207.jsp deleted file mode 100644 index dd0772de..00000000 --- a/src/main/webapp/WEB-INF/views/map/index20230207.jsp +++ /dev/null @@ -1,599 +0,0 @@ -<%@ page language="java" contentType="text/html; charset=UTF-8" - pageEncoding="UTF-8"%> -<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> - -<%@ include file="/include/inc_map_head_2021_new.jsp"%> - - - - - - - - - - - - - - - - - - - - - - - -<% - String pcode = request.getParameter("pcode"); - String mapGbn = request.getParameter("mapGbn"); - System.out.println("pCode : " + pcode); - - if (pcode != null) { -%> - - - -<% - } -%> - -
- " /> -
- - -
- - - -
- - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/views/map/index_2021_back.jsp b/src/main/webapp/WEB-INF/views/map/index_2021_back.jsp deleted file mode 100644 index 9dea381c..00000000 --- a/src/main/webapp/WEB-INF/views/map/index_2021_back.jsp +++ /dev/null @@ -1,179 +0,0 @@ -<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> -<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> - - - - -국토지반정보 포털시스템 - - - - - - - - - - - - - - - - - - - - - - - -<% -String pcode = request.getParameter("pcode"); -System.out.println("pCode : " + pcode); - -if(pcode != null){ -%> - -<%}%> - -
- "/> -
- - - - - - - - - - -
- - - - -
-
-
-
-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - -
-
- - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - - - - - - - -
- - - - - - - - - - - - - -
-
-
-
- - \ No newline at end of file diff --git a/src/main/webapp/js/map/main/map.js b/src/main/webapp/js/map/main/map.js index 5eca5dcb..c767ec49 100644 --- a/src/main/webapp/js/map/main/map.js +++ b/src/main/webapp/js/map/main/map.js @@ -30,6 +30,79 @@ if(document.getElementById("cls").value == '2'){ addLoadEvent(initApp); } +function showToast(message) { + // 1. 요소를 생성합니다. + var toast = document.createElement("div"); + + // 2. 텍스트를 넣습니다. + toast.innerHTML = message; + + // 3. 스타일을 자바스크립트로 직접 입힙니다. (CSS 의존성 제거) + // 주의: CSS 속성명은 카멜 표기법(camelCase)으로 작성해야 합니다. + // 예: background-color -> backgroundColor + toast.style.position = "fixed"; + toast.style.left = "50%"; + toast.style.bottom = "130px"; + toast.style.width = "500px"; + toast.style.marginLeft = "-166px"; // (width 300 + padding 좌우 32) / 2 의 근사값 + toast.style.padding = "16px"; + toast.style.backgroundColor = "#333333"; + toast.style.color = "#ffffff"; + toast.style.textAlign = "center"; + toast.style.fontSize = "14px"; + toast.style.zIndex = "9999"; + + // 테두리 둥글게 (구형 브라우저는 무시됨) + toast.style.borderRadius = "4px"; + toast.style.MozBorderRadius = "4px"; + toast.style.WebkitBorderRadius = "4px"; + + // 4. 초기 투명도 설정 (투명하게 시작) + toast.style.opacity = "0"; + toast.style.filter = "alpha(opacity=0)"; // IE8 이하 + + // 5. body에 추가 + document.body.appendChild(toast); + + // 6. 애니메이션 (Fade-In) + var opacity = 0; + var fadeInInterval = setInterval(function() { + if (opacity < 1) { + opacity += 0.1; + // 부동소수점 오차 보정을 위해 약간의 처리가 필요할 수 있으나 단순 예제이므로 생략 + if(opacity > 1) opacity = 1; + + toast.style.opacity = opacity; + toast.style.filter = "alpha(opacity=" + (opacity * 100) + ")"; + } else { + clearInterval(fadeInInterval); + + // 7. 3초 유지 후 제거 시작 + setTimeout(function() { + removeToast(toast); + }, 6000); + } + }, 30); +} + +// 제거 함수 (Fade-Out) +function removeToast(element) { + var opacity = 1; + var fadeOutInterval = setInterval(function() { + if (opacity > 0) { + opacity -= 0.1; + element.style.opacity = opacity; + element.style.filter = "alpha(opacity=" + (opacity * 100) + ")"; + } else { + clearInterval(fadeOutInterval); + // DOM에서 완전히 제거 + if (element.parentNode) { + element.parentNode.removeChild(element); + } + } + }, 30); +} + //커스텀 DragPopup 컨트롤 정의 OpenLayers.Control.DragPopup = OpenLayers.Class(OpenLayers.Control, { popup: null, @@ -694,18 +767,40 @@ function initApp(param){ HOLE_DRILLING = new OpenLayers.Layer.Vector("DRILLING"); } */ - HOLE_DRILLING = new OpenLayers.Layer.Vector("DRILLING"); + HOLE_DRILLING = new OpenLayers.Layer.Vector("DRILLING", { + renderers: ['Canvas', 'SVG'] + }); - HOLE_BOUNDARY[0] = new OpenLayers.Layer.Vector("HOLE_BOUNDARY_0"); - HOLE_BOUNDARY[1] = new OpenLayers.Layer.Vector("HOLE_BOUNDARY_1"); - HOLE_BOUNDARY[2] = new OpenLayers.Layer.Vector("HOLE_BOUNDARY_2"); - HOLE_BOUNDARY[3] = new OpenLayers.Layer.Vector("HOLE_BOUNDARY_3"); - HOLE_BOUNDARY[4] = new OpenLayers.Layer.Vector("HOLE_BOUNDARY_4"); - HOLE_BOUNDARY[5] = new OpenLayers.Layer.Vector("HOLE_BOUNDARY_5"); - HOLE_BOUNDARY[6] = new OpenLayers.Layer.Vector("HOLE_BOUNDARY_6"); - HOLE_BOUNDARY[7] = new OpenLayers.Layer.Vector("HOLE_BOUNDARY_7"); - HOLE_BOUNDARY[8] = new OpenLayers.Layer.Vector("HOLE_BOUNDARY_8"); - HOLE_BOUNDARY[9] = new OpenLayers.Layer.Vector("HOLE_BOUNDARY_9"); + HOLE_BOUNDARY[0] = new OpenLayers.Layer.Vector("HOLE_BOUNDARY_0", { + renderers: ['Canvas', 'SVG'] + }); + HOLE_BOUNDARY[1] = new OpenLayers.Layer.Vector("HOLE_BOUNDARY_1", { + renderers: ['Canvas', 'SVG'] + }); + HOLE_BOUNDARY[2] = new OpenLayers.Layer.Vector("HOLE_BOUNDARY_2", { + renderers: ['Canvas', 'SVG'] + }); + HOLE_BOUNDARY[3] = new OpenLayers.Layer.Vector("HOLE_BOUNDARY_3", { + renderers: ['Canvas', 'SVG'] + }); + HOLE_BOUNDARY[4] = new OpenLayers.Layer.Vector("HOLE_BOUNDARY_4", { + renderers: ['Canvas', 'SVG'] + }); + HOLE_BOUNDARY[5] = new OpenLayers.Layer.Vector("HOLE_BOUNDARY_5", { + renderers: ['Canvas', 'SVG'] + }); + HOLE_BOUNDARY[6] = new OpenLayers.Layer.Vector("HOLE_BOUNDARY_6", { + renderers: ['Canvas', 'SVG'] + }); + HOLE_BOUNDARY[7] = new OpenLayers.Layer.Vector("HOLE_BOUNDARY_7", { + renderers: ['Canvas', 'SVG'] + }); + HOLE_BOUNDARY[8] = new OpenLayers.Layer.Vector("HOLE_BOUNDARY_8", { + renderers: ['Canvas', 'SVG'] + }); + HOLE_BOUNDARY[9] = new OpenLayers.Layer.Vector("HOLE_BOUNDARY_9", { + renderers: ['Canvas', 'SVG'] + }); HOLE_LAYER_M = new OpenLayers.Layer.WMS( "HOLES_M", @@ -889,6 +984,7 @@ function initApp(param){ }); MINE_LAYER = new OpenLayers.Layer.Vector("Mine Map", { + renderers: ['Canvas', 'SVG'], strategies: [new OpenLayers.Strategy.BBOX({ ratio: 1.1, resFactor: 1 @@ -1206,7 +1302,73 @@ function initApp(param){ fillOpacity: 0 }); + if (OpenLayers.Renderer.Canvas) { + OpenLayers.Renderer.Canvas.prototype.drawText = function(location, style) { + + if (!location) { + return; + } + + // 1. 좌표 변환 (결과는 [x, y] 배열임) + var pt = this.getLocalXY(location); + + // 2. 유효성 검사 (배열 인덱스로 접근) + if (isNaN(pt[0]) || isNaN(pt[1])) { + return; + } + + // 3. Offset 적용 + if (style.labelXOffset || style.labelYOffset) { + pt[0] += parseFloat(style.labelXOffset || 0); + pt[1] += parseFloat(style.labelYOffset || 0); + } + + this.setCanvasStyle("fill", style); + this.setCanvasStyle("stroke", style); + + var label = String(style.label); + var context = this.canvas; // this.canvas는 Context 객체임 + + // 4. 스타일 적용 + if (style.fontColor) { + context.fillStyle = style.fontColor; + } + if (style.fontOpacity) { + context.globalAlpha = style.fontOpacity; + } + + var fontStyle = [ + style.fontStyle ? style.fontStyle : "normal", + "normal", + style.fontWeight ? style.fontWeight : "normal", + style.fontSize ? style.fontSize : "10px", + style.fontFamily ? style.fontFamily : "sans-serif" + ].join(" "); + context.font = fontStyle; + + // 5. 정렬 설정 + var align = style.labelAlign || "cm"; + var alignMap = { 'l': 'left', 'r': 'right', 'c': 'center' }; + var valignMap = { 't': 'top', 'b': 'bottom', 'm': 'middle' }; + + context.textAlign = alignMap[align.charAt(0)] || "center"; + context.textBaseline = valignMap[align.charAt(1)] || "middle"; + + // 6. 그리기 (배열 인덱스 사용) + // 외곽선 + if (style.labelOutlineWidth) { + context.lineWidth = style.labelOutlineWidth; + context.strokeStyle = style.labelOutlineColor; + context.strokeText(label, pt[0], pt[1]); + } + + // 텍스트 + context.fillText(label, pt[0], pt[1]); + }; + } + TEXT_LABEL_LAYER = new OpenLayers.Layer.Vector("Text Labels", { + renderers: ['Canvas', 'SVG'], styleMap: new OpenLayers.StyleMap({'default': textStyle}) }); BASE_MAP.addLayer(TEXT_LABEL_LAYER); @@ -1219,6 +1381,14 @@ function initApp(param){ PATH : new OpenLayers.Control.DynamicMeasure( OpenLayers.Handler.Path, { persist: true, + handlerOptions: { + layerOptions: { + renderers: ['Canvas', 'SVG'] + } + }, + layerSegmentsOptions: { renderers: ['Canvas', 'SVG'] }, + layerLengthOptions: { renderers: ['Canvas', 'SVG'] }, + layerHeadingOptions: { renderers: ['Canvas', 'SVG'] }, styles : { 'Line' : { strokeWidth: 3, @@ -1233,6 +1403,14 @@ function initApp(param){ AREA : new OpenLayers.Control.DynamicMeasure( OpenLayers.Handler.Polygon, { persist: true, + handlerOptions: { + layerOptions: { + renderers: ['Canvas', 'SVG'] + } + }, + layerSegmentsOptions: { renderers: ['Canvas', 'SVG'] }, + layerLengthOptions: { renderers: ['Canvas', 'SVG'] }, + layerHeadingOptions: { renderers: ['Canvas', 'SVG'] }, styles : { 'Polygon' : { strokeWidth: 2, @@ -1250,6 +1428,14 @@ function initApp(param){ PATH : new OpenLayers.Control.DynamicMeasure( OpenLayers.Handler.Path, { persist: true, + handlerOptions: { + layerOptions: { + renderers: ['Canvas', 'SVG'] + } + }, + layerSegmentsOptions: { renderers: ['Canvas', 'SVG'] }, + layerLengthOptions: { renderers: ['Canvas', 'SVG'] }, + layerHeadingOptions: { renderers: ['Canvas', 'SVG'] }, styles : { 'Line' : { strokeWidth: 3, @@ -1268,6 +1454,14 @@ function initApp(param){ PATH : new OpenLayers.Control.DynamicMeasure( OpenLayers.Handler.Path, { persist: true, + handlerOptions: { + layerOptions: { + renderers: ['Canvas', 'SVG'] + } + }, + layerSegmentsOptions: { renderers: ['Canvas', 'SVG'] }, + layerLengthOptions: { renderers: ['Canvas', 'SVG'] }, + layerHeadingOptions: { renderers: ['Canvas', 'SVG'] }, styles : { 'Line' : { strokeWidth: 3, @@ -1325,10 +1519,94 @@ function initApp(param){ BASE_MAP.addLayer(HOLE_BOUNDARY[8]); BASE_MAP.addLayer(HOLE_BOUNDARY[9]); + + if (OpenLayers.Renderer.Canvas) { + // 이미지 캐시 저장소 초기화 + OpenLayers.Renderer.Canvas.prototype.imageCache = {}; + + OpenLayers.Renderer.Canvas.prototype.drawExternalGraphic = function(geometry, style, featureId) { + var url = style.externalGraphic; + var t = this; + + // 1. 캐시된 이미지가 있는지 확인 + var img = this.imageCache[url]; + + // 2. 그리기 함수 정의 + var draw = function(imageObj) { + // feature가 삭제되었거나, 렌더러가 초기화되었으면 중단 + if(!t.features[featureId]) return; + + var pt = t.getLocalXY(geometry); + var p0 = pt[0]; + var p1 = pt[1]; + + if(!isNaN(p0) && !isNaN(p1)) { + var width = style.graphicWidth || style.graphicHeight; + var height = style.graphicHeight || style.graphicWidth; + width = width ? width : style.pointRadius * 2; + height = height ? height : style.pointRadius * 2; + + var xOffset = (style.graphicXOffset != undefined) ? style.graphicXOffset : -(0.5 * width); + var yOffset = (style.graphicYOffset != undefined) ? style.graphicYOffset : -(0.5 * height); + var x = (p0 + xOffset) | 0; + var y = (p1 + yOffset) | 0; + + // 투명도 적용 + var opacity = style.graphicOpacity || style.fillOpacity; + if (opacity !== undefined) { + t.canvas.globalAlpha = opacity; + } else { + t.canvas.globalAlpha = 1; + } + + // 이미지 그리기 + t.canvas.drawImage(imageObj, x, y, width, height); + + // Hit Detection (클릭 감지용) + if (t.hitDetection) { + t.setHitContextStyle("fill", featureId); + t.hitContext.fillRect(x, y, width, height); + } + + // 스타일 복구 + t.canvas.globalAlpha = 1; + } + }; + + // 3. 이미지 로딩 및 캐싱 처리 + if (!img) { + // 처음 로딩하는 이미지 + img = new Image(); + img.src = url; + img.onload = function() { + t.imageCache[url] = img; // 로딩 완료 후 캐시에 저장 + draw(img); // 그리기 + // 비동기 로딩이므로 완료 후 화면 갱신 요청 + t.map.layerContainerDiv.style.display = "none"; + t.map.layerContainerDiv.style.display = ""; + }; + } else { + // 이미 캐시된 이미지 -> 즉시 그리기 (깜빡임 해결) + if (img.complete) { + draw(img); + } else { + // 로딩 중이면 onload에 위임 + img.onload = function() { + draw(img); + }; + } + } + }; + } + // 객체 선택 - HOLE_SELECT = new OpenLayers.Layer.Vector("SELECT"); - HOLE_SELECT.styleMap = new OpenLayers.StyleMap(getStyleSELECT()); - BASE_MAP.addLayer(HOLE_SELECT); + HOLE_SELECT = new OpenLayers.Layer.Vector("SELECT", { + renderers: ['Canvas', 'SVG'], // 캡처 및 깜빡임 방지용 + styleMap: new OpenLayers.StyleMap(getStyleSELECT()) + }); + BASE_MAP.addLayer(HOLE_SELECT); + // 레이어를 최상단으로 올리기 (다른 레이어에 가려지지 않도록) + //BASE_MAP.setLayerIndex(HOLE_SELECT, 2000); @@ -1360,12 +1638,16 @@ function initApp(param){ BASE_MAP.addControl(CTL_SELECT_SLOPE); - HOLE_SELECT2 = new OpenLayers.Layer.Vector("SELECT"); + HOLE_SELECT2 = new OpenLayers.Layer.Vector("SELECT", { + renderers: ['Canvas', 'SVG'] + }); HOLE_SELECT2.styleMap = new OpenLayers.StyleMap(getStyleSELECT()); BASE_MAP.addLayer(HOLE_SELECT2); // 영역 선택 - HOLE_AREA = new OpenLayers.Layer.Vector("AREA"); + HOLE_AREA = new OpenLayers.Layer.Vector("AREA", { + renderers: ['Canvas', 'SVG'] + }); HOLE_AREA.styleMap = new OpenLayers.StyleMap(getStyleAREA()); HOLE_AREA.events.register("beforefeatureadded", HOLE_AREA, HOLE_AREA.removeAllFeatures); BASE_MAP.addLayer(HOLE_AREA); @@ -1525,7 +1807,10 @@ function initApp(param){ BASE_MAP.addControl(CTL_SELECT_JIBAN); // 그리기 도구 - HOLE_DRAW = new OpenLayers.Layer.Vector("DRAW"); + HOLE_DRAW = new OpenLayers.Layer.Vector("DRAW", { + renderers: ['Canvas', 'SVG'] + }); + HOLE_DRAW.styleMap = getStyleDRAW(); BASE_MAP.addLayer(HOLE_DRAW); @@ -1727,7 +2012,9 @@ function initApp(param){ // 툴팁 표시 - HOLE_TOOLTIP = new OpenLayers.Layer.Vector("SELECT"); + HOLE_TOOLTIP = new OpenLayers.Layer.Vector("SELECT", { + renderers: ['Canvas', 'SVG'] + }); HOLE_TOOLTIP.styleMap = new OpenLayers.StyleMap(new OpenLayers.Style({ fillColor: "#ee9900", fillOpacity: 0, @@ -2815,7 +3102,7 @@ function addHoleNames(feature) { labelAlign: "cb", // 라벨 정렬 (cm = center-middle) labelOutlineColor: "#52770a", // 테두리 색상 labelOutlineWidth: 3, // 테두리 두께 - labelYOffset: 25, // 포인트로부터 10px 위로 더 밀어냅니다. + labelYOffset: -25, // 음수이면 위로 올라간다. // pointSymbolizer를 'none'으로 설정하여 점 아이콘은 숨깁니다. pointRadius: 0, fillOpacity: 0 @@ -3317,7 +3604,7 @@ function move(){ // ---------------------------- // 함수 : 현재화면 저장 // ---------------------------- -function saveToImage(){ +function saveToImage_old_삭제요망_20251126(){ // 필요라이브러리 : html2canvas.min.js / html2canvas.svg.min.js / download.min.js / jquery.min.js var realHeight = $("#map").height(); @@ -3338,6 +3625,62 @@ function saveToImage(){ $("#map").css("height", "100%"); } +//---------------------------- +//함수 : 현재화면 저장 (개선됨) +//---------------------------- +function saveToImage() { + // 1. 로딩 이미지 추가 (사용자 정의 위치) + if( LoadingShow ) { + LoadingShow(); + showToast("웹 특성상 오래 걸립니다. 필요 시 윈도우키+shift+s 키로 직접 캡쳐해주세요."); + } + + // 2. 브라우저가 로딩 이미지를 그릴 시간을 주기 위해 setTimeout 사용 + setTimeout(function() { + var mapDiv = $("#map"); + var realHeight = mapDiv.height(); + mapDiv.css("height", realHeight); + + // 3. 캡처 시작 + html2canvas(mapDiv[0], { + useCORS: true, // WMS 레이어 캡처 필수 옵션 + allowTaint: false, + logging: false, // 로그 끔 (필요시 true) + proxy: "/map/proxy.do", + + onrendered: function(canvas) { + try { + var imageData = canvas.toDataURL("image/png"); + + // 4. 날짜 포맷 생성 (yyyymmdd_HHMMSS) + var now = new Date(); + var year = now.getFullYear(); + var month = ('0' + (now.getMonth() + 1)).slice(-2); + var day = ('0' + now.getDate()).slice(-2); + var hours = ('0' + now.getHours()).slice(-2); + var minutes = ('0' + now.getMinutes()).slice(-2); + var seconds = ('0' + now.getSeconds()).slice(-2); + + var timestamp = year + month + day + "_" + hours + minutes + seconds; + var fileName = "geoinfo_map_" + timestamp + ".png"; + + // 5. 다운로드 실행 + download(imageData, fileName, "image/png"); + + } catch (e) { + console.error("이미지 저장 오류:", e); + alert("이미지 저장에 실패했습니다."); + } finally { + // 6. 뒷정리 (높이 원복 및 로딩바 제거) + mapDiv.css("height", "100%"); + if( Loading ) { + Loading(); + } + } + } + }); + }, 500); // 0.5초 딜레이 (로딩바 렌더링 보장) +} // ---------------------------- // 함수 : 거리 면적 측정 관리 @@ -3470,6 +3813,7 @@ function onOverviewMap(){ // Sync Event ----------------------- var boxLayer = new OpenLayers.Layer.Vector("BOX", { + renderers: ['Canvas', 'SVG'], styleMap: new OpenLayers.StyleMap({ "line" : new OpenLayers.Style({ fillColor: "#ffcc66", @@ -4230,6 +4574,7 @@ function locationMap(loList) { // The overlay layer for our marker, with a simple diamond as symbol var overlay = new OpenLayers.Layer.Vector('Overlay', { + renderers: ['Canvas', 'SVG'], styleMap: new OpenLayers.StyleMap({ externalGraphic: '/images/map/preview/dot2.gif', graphicWidth: 20, graphicHeight: 24, graphicYOffset: -24, @@ -4364,6 +4709,7 @@ function subsidenceLonLat(lon, lat, subsidenceInfo){ function addSubsidenceMarker(subsidenceLocation,subsidenceInfo){ var subsidence = new OpenLayers.Layer.Vector('Subsidence', { + renderers: ['Canvas', 'SVG'], eventListeners : subsidenceListeners, attributes : subsidenceInfo, styleMap: new OpenLayers.StyleMap({ @@ -4581,6 +4927,7 @@ function jihaanjeonLonLat(lon, lat, jihaanjeonInfo){ function addJihaanjeonMarker(jihaanjeonLocation,jihaanjeonInfo){ var jihaanjeon = new OpenLayers.Layer.Vector('Jihaanjeon', { + renderers: ['Canvas', 'SVG'], eventListeners : jihaanjeonListeners, attributes : jihaanjeonInfo, styleMap: new OpenLayers.StyleMap({ @@ -4817,6 +5164,7 @@ function jibanLonLat(lon, lat, jibanInfo){ function addJibanMarker(jibanLocation,jibanInfo){ var jiban = new OpenLayers.Layer.Vector('JibanModel', { + renderers: ['Canvas', 'SVG'], eventListeners : jibanListeners, attributes : jibanInfo, styleMap: new OpenLayers.StyleMap({