PageSourceSearch

https://its.ulsan.kr/resource/openlayers/js/lsMap.js?v=2

js its.ulsan.kr collected 2026-10-07 23:50:38 UTC 38,051 bytes, 1,594 lines download raw bytes

1/*******************************************************************************
2 * 지도 관련 자바스크립트 *******************************
3 * 
4 * @base : openlayer.js v6.5.0
5 * 
6 * @author : (주)라임에스
7 * @since : 2020.09.15
8 */
9class LimesMap
10{
11	map;
12	srcproj;
13	desproj;
14	selbaselayer;
15	zoom;
16	measure;
17
18	constructor() {
19		this.map = null;
20		this.srcproj = null;
21		this.desproj = null;
22		this.selbaselayer = null;
23		this.zoom = null;
24		this.measure = {};
25	}
26
27	createMap(t, lyrs) {
28		let lsmap = this;
29		// 지도 생성
30		this.map = new ol.Map({
31			target: t,
32			layers:lyrs,
33			controls : ol.control.defaults({
34	           attribution : false,
35	           zoom : false,
36	           rotate: false,
37			}),
38			interactions : ol.interaction.defaults({
39				altShiftDragRotate:false,
40				pinchRotate:false
41			})
42		});
43		
44		
45	};
46	
47	setEventZoom(callback, startCallback) {
48		let t = this;
49		this.zoom = this.map.getView().getZoom();
50		this.map.on("movestart", function(e) {
51			if(startCallback !== undefined && startCallback !== null)
52				startCallback(e);
53		});
54		this.map.on("moveend", function(e) {
55			let newZoom = t.map.getView().getZoom();
56			if (t.zoom !== newZoom) {
57				t.zoom = newZoom;
58				t.autoChangeFeatures();
59			}
60			if(callback !== undefined && callback !== null)
61				callback(e);
62		});
63	};
64	
65	/*피처 조회*/
66	getFeatureC(obj) {
67		let layer = this.getLayerC(obj);
68		if(layer === null) return null;
69
70		let src = layer.getSource();
71		let ftrs = src.getFeatures();
72		
73		for(let i = 0; i < ftrs.length; i++){
74			if(ftrs[i].fid === obj.fid) return ftrs[i];
75		}
76		return null;
77	}
78	
79	/*레이어 조회*/
80	getLayerC(obj){ // obj = lid 
81		if(this.map === null) return null;
82		
83		let layers = this.map.getLayers().getArray();
84		for(let i = 0; i < layers.length; i++){
85			if(obj.lid === undefined) return null;
86			
87			if(layers[i].lid === obj.lid){
88				return layers[i];
89			}
90		}
91		
92		return null;
93	}
94	
95	/*geojson 읽기*/
96	readGeoJson(result, lyr){
97		var arr = new ol.format.GeoJSON().readFeatures(result);
98		return arr;
99	}
100	
101	/*레이어 추가*/
102	addLayerC(obj){ // obj = type / lid / name / urls / onSelect / minZoom / unSelect / onmouseenter / onmouseleave / styles
103		if(this.map === null) return null;
104		let layer = this.getLayer(obj);
105		if(layer !== null) return layer;
106
107		switch(obj.type){
108			case 'vector':
109				let vsrc = new ol.source.Vector({
110				    features: []
111				});
112				layer = new ol.layer.Vector({
113				    source: vsrc
114				});
115				layer.lid = obj.lid;
116				layer.istyle = [];
117				layer.minZoom = obj.minZoom;
118
119				layer.onSelect = obj.onSelect;
120				layer.unSelect = obj.unSelect;
121				layer.onmouseenter = obj.onmouseenter;
122				layer.onmouseleave = obj.onmouseleave;
123				this.map.addLayer(layer);
124
125				if(obj.styles){
126					if(!Array.isArray(obj.styles)) obj.styles = [obj.styles];
127					
128					for(let i = 0; i < obj.styles.length; i++){
129						let istyle = new ol.style.Style({
130							fill: new ol.style.Fill(obj.styles[i].fill),
131						    stroke: new ol.style.Stroke(obj.styles[i].stroke),
132						});
133						layer.istyle.push(istyle);
134						if(i==0) layer.setStyle(istyle);
135					}
136					
137					break;
138				}
139				if(obj.urls){
140					if(!Array.isArray(obj.urls)) obj.urls = [obj.urls];
141					
142					for(let i = 0; i < obj.urls.length; i++){
143						let istyle = new ol.style.Style({
144						    image: new ol.style.Icon(({
145						        anchor: [0.5, 0.5],
146						        anchorXUnits: "fraction",
147						        anchorYUnits: "fraction",
148						        src: obj.urls[i],
149						        scale: 1,
150						        opacity: 1
151						    }))
152						});
153						layer.istyle.push(istyle);
154						if(i==0) layer.setStyle(istyle);
155					}
156					break;
157				}
158				if(obj.colors){
159					if(!Array.isArray(obj.colors)) obj.colors = [obj.colors];
160					
161					for(let i = 0; i < obj.colors.length; i++){
162						let istyle = new ol.style.Style({
163							fill: new ol.style.Fill({
164								color: obj.colors[i],
165						    }),
166						});
167						layer.istyle.push(istyle);
168						if(i==0) layer.setStyle(istyle);
169					}
170					break;
171				}
172				if(layer.istyle.length>0){
173					layer.setStyle(layer.istyle[0]);
174				}
175				break;
176			default:
177				console.log(obj.type);
178		}
179		return layer;
180	}
181	
182	setEventZoom(callback) {
183		let t = this;
184		this.zoom = this.map.getView().getZoom();
185		this.map.on("moveend", function(e) {
186			let newZoom = t.map.getView().getZoom();
187			if (t.zoom !== newZoom) {
188				t.zoom = newZoom;
189				t.autoChangeFeatures();
190			}
191			
192			if(callback !== undefined && callback !== null)
193				callback(e);
194		});
195	};
196	setEventClick() {
197		let t = this;
198		this.map.on("click", function(e) {
199			console.dir(e);
200			let chk = true;
201			t.map.forEachFeatureAtPixel(e.pixel, function (ftr) {
202				if(ftr !== undefined && ftr !== null && ftr.onclick !== undefined && ftr.onclick !== null)
203					ftr.onclick(ftr, e);
204				
205				chk = false;
206				return ftr;
207			});
208			if(chk){
209				e.map.getOverlays().forEach(function(overlay){
210					if(overlay){
211						mainPg.removeTooltip(overlay.options.element.id);
212					}
213				});
214			}
215		});
216	};
217	setEventMouseMove(callback) {
218		let t = this;
219		this.map.on("pointermove", function(e) {
220			if(callback !== undefined && callback !== null)
221				callback(e);
222			
223			if(t.measure.callback !== undefined && t.measure.callback !== null)
224				t.measure.callback(e, t.measure);
225		});
226	};
227	setEventFeatureMouseMove(noftr_callback) {
228
229		let t = this;
230		let map = this.map;
231		this.map.on("pointermove", function(e) {
232			if(e.dragging) return;
233			
234			let ftr = map.forEachFeatureAtPixel(e.pixel, function (f) {
235				if(f.layer !== undefined) return f;
236				return null;
237			});
238			
239			if(ftr !== undefined && ftr !== null && ftr.onmousemove !== undefined){
240				ftr.onmousemove(ftr, e);
241			}else{
242				noftr_callback();
243			}
244		});
245	};
246	setEventLayersMouseMove(gid, callback) {
247
248		let t = this;
249		let map = this.map;
250		this.map.on("pointermove", function(e) {
251			
252			if(e.dragging)
253			{
254				callback(null, null);
255				return;
256			}
257			
258			let ftr = map.forEachFeatureAtPixel(e.pixel, function (f) {
259				
260				if(f.layer !== undefined && f.layer.gid !== undefined && f.layer.gid === gid)
261					return f;
262				
263				return null;
264			});
265			
266			callback(ftr, e.pixel);
267			
268			if(t.measure.callback !== undefined && t.measure.callback !== null)
269				t.measure.callback(e, t.measure);
270		});
271	};
272	setEventLayerMouseMove(lid, callback) {
273
274		let map = this.map;
275		this.map.on("pointermove", function(e) {
276			map.forEachFeatureAtPixel(e.pixel, function (f) {
277				
278				if(f.lid === lid)
279					callback(f, e.pixel);
280				
281				return true;
282			});
283		});
284	};
285
286	// 좌표계 등록
287	setProjDefs(p, v) {
288		proj4.defs(p, v);
289		ol.proj.proj4.register(proj4);
290	};
291	// 좌표계 설정
292	setProj(s, d) {
293		this.srcproj = s;
294		this.desproj = d;
295	};
296	// 좌표계 변환
297	transform(v) {
298		if(this.srcproj === null || this.desproj === null)
299			return v;
300
301		return ol.proj.transform(v, this.srcproj, this.desproj);
302	};
303	transform_(v, s, d) {
304		if(this.srcproj === null || this.desproj === null)
305			return v;
306
307		return ol.proj.transform(v, s, d);
308	};
309	oppTransfrom(v) {
310
311		if(this.srcproj === null || this.desproj === null)
312			return v;
313
314		return ol.proj.transform(v, this.desproj, this.srcproj);
315	};
316	
317	init_sellayer(l) {
318
319    	if(this.map.getLayers().getLength() === 0)
320    		this.selbaselayer = l;
321	}
322	addBaseLayerDaum(nm, url, min, max, visible) {
323		let ext = [-30000, -60000, 494288, 988576];
324		let prj = new ol.proj.Projection({
325			code: "EPSG:5181",
326            extent: ext,
327			units: "m"
328		});
329		let rslt = [ 2048, 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1, 0.5, 0.25 ];
330		let layer = new ol.layer.Tile({
331			visible: visible,
332			preload:Infinity,
333            source: new ol.source.XYZ({
334            	url: url,
335            	tileGrid: new ol.tilegrid.TileGrid({
336                    extent: ext,
337            		resolutions: rslt
338            	}),
339            	tileLoadFunction: function(imageTile, src) {
340            		var s = this.tileCoord[0];
341            		var d = 14 - this.tileCoord[0];
342            		
343            		imageTile.getImage().src = src.replace('/'+s+'/','/'+d+'/');
344            	},
345            	projection: prj
346            })
347      	});
348		layer.lid = nm; 
349		layer.base = true;
350		layer.minZoom = min;
351		layer.maxZoom = max;
352		return layer;
353		
354//		layer.type = "base";
355//		this.init_sellayer(layer);
356//    	this.map.addLayer(layer);
357	};
358	// TILE DAUM MAP
359	addLayerDaum(nm, url, min, max) {
360		let ext = [-30000, -60000, 494288, 988576];
361		let prj = new ol.proj.Projection({
362			code: "EPSG:5181",
363            extent: ext,
364			units: "m"
365		});
366		
367		let rslt = [ 2048, 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1, 0.5, 0.25 ];
368		let layer = new ol.layer.Tile({
369			visible: this.map.getLayers().getLength() === 0 ? true : false,
370            source: new ol.source.XYZ({
371            	url: url,
372            	tileGrid: new ol.tilegrid.TileGrid({
373                    extent: ext,
374            		resolutions: rslt
375            	}),
376            	tileLoadFunction: function(imageTile, src) {
377            		var s = 'L'+this.tileCoord[0];
378            		var d = 'L'+(14 - this.tileCoord[0]);
379            		imageTile.getImage().src = src.replace(s,d);
380            	},
381            	projection: prj,
382            })
383      	});
384		
385		layer.lid = nm;
386		layer.base = true;
387		layer.minZoom = min;
388		layer.maxZoom = max;
389		layer.type = "base";
390		this.init_sellayer(layer);
391    	this.map.addLayer(layer);
392	};
393	addLayerNgii(nm, url, min, max) {
394		let ext = [-200000, -28024123.6, 31824123.6, 4000000];
395		let prj = new ol.proj.Projection({
396			code: "EPSG:5179",
397            extent: ext,
398			units: "m"
399		});
400
401		let rslt = [ 122.1623368125, 61.08116840625, 30.540584203125, 15.2702921015625, 7.63514605078125,
402    		3.817573025390625, 1.9087865126953125, 0.9543932563476563, 0.47719662817382813, 0.23859831408691406 ];
403		
404		let layer = new ol.layer.Tile({
405			// type: "base",
406			// title: nm,
407			visible: this.map.getLayers().getLength() === 0 ? true : false,
408            source: new ol.source.XYZ({
409            	tileUrlFunction: function (coordinate) {
410                    if (coordinate == null) { 
411                        return "";
412                    }
413
414                    var z = coordinate[0] + 9;
415                    var x = coordinate[1];
416                    var y = coordinate[2];
417
418                    return url + "/" + z + "/" + y + "/" + x + ".png";
419                },
420            	tileGrid: new ol.tilegrid.TileGrid({
421                    extent: ext,
422            		resolutions: rslt
423            	}),
424            	projection: prj
425            })
426      	});
427
428		layer.lid = nm;
429		layer.base = true;
430		layer.minZoom = min;
431		layer.maxZoom = max;
432		layer.type = "base";
433		this.init_sellayer(layer);
434    	this.map.addLayer(layer);
435	};
436	addLayerVworld(nm, url, min, max) {
437
438    	let layer = new ol.layer.Tile({
439    		title: nm,
440    		type: "base",
441            source: new ol.source.XYZ({
442				url: url
443             })
444      	})
445    	
446		layer.lid = nm;
447		layer.base = true;
448		layer.minZoom = min;
449		layer.maxZoom = max;
450		layer.type = "base";
451		this.init_sellayer(layer);
452    	this.map.addLayer(layer);
453	};
454	addLayerXYZ(nm, url, ext, res, prj) {
455
456		let layer = new ol.layer.Tile({
457			title: nm,
458            source: new ol.source.XYZ({
459            	url: url,
460            	tileGrid: new ol.tilegrid.TileGrid({
461                    extent: ext,
462            		resolutions: res
463            	}),
464            	projection: prj
465            })
466      	});
467		layer.type = "base";
468    	this.map.addLayer(layer);
469	};
470	addLayerWMS(nm, urls, opt) {
471		if(!Array.isArray(urls)){
472			urls = [urls];
473		}
474		let layer = new ol.layer.Tile({
475    		source: new ol.source.TileWMS({
476    			urls: urls,
477		      	params: opt,
478		      	serverType: "geoserver",
479		      	transition: 0,
480		    	projection: this.srcproj
481	    	}),
482	    	opacity: opt.opacity ? opt.opacity : 0.8
483  		});
484		
485		layer.lid = nm;
486		layer.type = "base";
487    	this.map.addLayer(layer);
488    	return layer;
489	};
490	addLayerVectorIcon(lid, gid, urls, scale, opacity, func, autoscale) {
491		let layer = this.getLayer(lid);
492		if(layer !== null)
493			return;
494		
495		let vsrc = new ol.source.Vector({
496		    features: []
497		});
498
499		layer = new ol.layer.Vector({
500		    source: vsrc
501		});
502
503		layer.lid = lid;
504		layer.type = "VECTOR_ICON";
505		layer.gid = gid;
506		layer.istyle = [];
507		layer.func = func;
508		layer.autoScale = autoscale;
509		layer.txtDisplayLevel = 10; // 1102
510		
511		// 버스의 zIndex값 조정_1018
512		if(lid.indexOf("_BUS")!==-1){
513			layer.setZIndex(2);
514		}
515		
516		this.map.addLayer(layer);
517		
518		if(!Array.isArray(urls))
519			urls = [urls];
520		for(let i = 0; i < urls.length; i++)
521		{
522			let istyle = new ol.style.Style({
523			    image: new ol.style.Icon(({
524			        anchor: [0.5, 0.5],
525			        anchorXUnits: "fraction",
526			        anchorYUnits: "fraction",
527			        src: urls[i],
528			        scale: scale,
529			        opacity: opacity,
530			        
531			        // 버스사이즈 조정_0921 (사이즈 변화에 따른 버스번호의 위치 틀어짐현상이 발생)
532//			        size: [50, 70] // 50 70이 적절
533			    })),
534			});
535			
536			layer.istyle.push(istyle);
537		}
538	};
539	addLayerVector(lid, gid) {
540		let layer = this.getLayer(lid);
541		
542		if(layer !== null)
543			return;
544		
545		let src = new ol.source.Vector({
546		    features: []
547		});
548		
549		layer = new ol.layer.Vector({
550			source: src
551		});
552		
553		layer.lid = lid;
554		layer.gid = gid;
555		layer.type = "VECTOR";
556		
557		this.map.addLayer(layer);
558	};
559	addLayerVectorSvg(lid, svg, sz, opacity) {
560
561		let layer = this.getLayer(lid);
562		
563		if(layer !== null)
564			return;
565		
566		let src = new ol.source.Vector({
567		    features: []
568		});
569		
570		layer = new ol.layer.Vector({
571			source: src
572		});
573		
574		layer.lid = lid;
575		layer.type = "VECTOR";
576
577	    let style = new ol.style.Style({
578		    image: new ol.style.Icon({
579		        opacity: opacity,
580		        src: "data:image/svg+xml;utf8," + escape(svg),
581		        scale: 1,
582		        anchor: [0.5, 0.5],
583		        imgSize: sz
584		    })
585	    });
586
587	    layer.setStyle(style);
588		this.map.addLayer(layer);
589	};
590	addLayerVectorLine(lid, gid, color, scale, opacity, func, autoscale){
591		let layer = this.getLayer(lid);
592		
593		if(layer !== null)
594			return;
595		
596		let vsrc = new ol.source.Vector({
597		    features: []
598		});
599
600		layer = new ol.layer.Vector({
601		    source: vsrc
602		});
603
604		layer.lid = lid;
605		layer.type = "VECTOR_LINE";
606		layer.gid = gid;
607		layer.istyle = [];
608		layer.func = func;
609		layer.autoScale = autoscale;
610		
611		this.map.addLayer(layer);
612		
613		if(!Array.isArray(color))
614			color = [color];
615		
616		for(let i = 0; i < color.length; i++)
617		{
618			let istyle = new ol.style.Style({
619			    stroke: new ol.style.Stroke({
620			    	color: color[i],
621			    	width: 5
622			    }),
623			});
624			
625			layer.istyle.push(istyle);
626		}
627	};
628	addLayerVectorMeasure() {
629		let layer = new ol.layer.Vector({
630			source: new ol.source.Vector(),
631			style: new ol.style.Style({
632			    fill: new ol.style.Fill({
633			    	color: "rgba(255, 255, 255, 0.2)"
634			    }),
635			    stroke: new ol.style.Stroke({
636			    	color: "#ffcc33",
637			    	width: 2
638			    }),
639			    image: new ol.style.Circle({
640			    	radius: 7,
641			    	fill: new ol.style.Fill({
642			    		color: "#ffcc33",
643			    	})
644			    }),
645			})
646		});
647
648		layer.lid = "MEASURE";
649		let m = this.measure;
650		
651		this.map.getViewport().addEventListener("mouseout", function () {
652			if(m.helpTooltipElement)
653				m.helpTooltipElement.classList.add("hidden");
654		});
655		
656		this.map.addLayer(layer);
657	};
658	setBaseLayer(lid) {
659
660		if(this.map === null)
661			return null;
662
663    	let vw = this.map.getView();
664		let layers = this.map.getLayers().getArray();
665		let bmaxz = this.selbaselayer.maxZoom;
666    	let z = vw.getZoom() / bmaxz;
667
668		for(let i = 0; i < layers.length; i++)
669		{
670			if(layers[i].base !== undefined && layers[i].base)
671			{
672				if(layers[i].lid === lid)
673				{
674					this.selbaselayer = layers[i];
675					layers[i].setVisible(true);
676					
677			    	let prjC = layers[i].getSource().getProjection().getCode();
678					let c = this.transform_(vw.getCenter(), this.desproj, this.srcproj);
679					z = z * layers[i].maxZoom;
680					
681					if(z < layers[i].minZoom)
682						z = layers[i].minZoom;
683					
684					if(z > layers[i].maxZoom)
685						z = layers[i].maxZoom;
686
687			    	this.setProj(this.srcproj, prjC);
688					this.setView(c, z, layers[i].minZoom, layers[i].maxZoom, layers[i].getSource().getProjection());
689				}
690				else
691					layers[i].setVisible(false);
692			}
693		}
694	};
695	setLayerTextDispalyLevel(lid, lv) {
696		let layer = this.getLayer(lid);
697		
698		if(layer === null)
699			return;
700		
701		layer.txtDisplayLevel = lv;
702		layer.txtDisplay = true;
703	};
704	getLayer(lid) {
705
706		if(this.map === null)
707			return null;
708
709		let layers = this.map.getLayers().getArray();
710
711		for(let i = 0; i < layers.length; i++)
712		{
713			if(layers[i].lid === lid)
714				return layers[i];
715		}
716
717		return null;
718	};
719	getLayerGroup(gid) {
720
721		if(this.map === null)
722			return null;
723
724		let arr = [];
725		let layers = this.map.getLayers().getArray();
726
727		for(let i = 0; i < layers.length; i++)
728		{
729			if(layers[i].gid === gid)
730				arr.push(layers[i]);
731		}
732
733		return arr;
734	};
735	setView(cen, zoom, minZ, maxZ, prj) {
736		let vw = new ol.View({
737            center: this.transform(cen),
738            zoom: zoom,
739            minZoom: minZ,
740            maxZoom: maxZ,
741			projection: prj
742        });
743
744    	this.map.setView(vw);
745	};
746	
747	setZoom(z) {
748		let vw = this.map.getView();
749		vw.setZoom(z);
750	};
751	getView() {
752		let vw = this.map.getView();
753		return vw;
754	};
755	zoomIn() {
756		let vw = this.map.getView();
757		let z = vw.getZoom() + 1;
758		this.setZoom(z);
759	};
760	zoomOut() {
761		let vw = this.map.getView();
762		let z = vw.getZoom() - 1;
763		this.setZoom(z);
764	};
765	setCenter(c, z) {
766		let vw = this.map.getView();
767		vw.setCenter(this.transform(c));
768
769		if(z !== null && z !== undefined && z !== "undefined")
770			vw.setZoom(z);
771	};
772	setFit(x1, y1, x2, y2) {
773
774		let mvw = this.map.getView();
775		mvw.fit([x1, y1, x2, y2]);
776	}
777	
778	// 스케일 컨트롤 추가
779	addCtrlScale(s, w, px, py) {
780		// 축척 표기
781		let ctrl = new ol.control.ScaleLine({
782			units: "metric",
783			bar: true,
784			steps: s,
785			text: false,
786			minWidth: w
787		});
788		this.map.addControl(ctrl);
789		this.setScalePosition(px,py);
790	};
791	setScalePosition(px, py) {
792    	let osb = $(".ol-scale-bar");
793    	osb.css("left", px + "px");
794    	osb.css("bottom", py + "px");
795	};
796	
797	onMeasure(e, m) {
798
799		let helpMsg = "Click to start drawing";
800	
801		if (m.sketch !== undefined && m.sketch !== null)
802		{
803			var geom = m.sketch.getGeometry();
804			if (geom instanceof ol.geom.LineString)
805				helpMsg = "Click to continue drawing the line";
806		}
807	
808		m.helpTooltipElement.innerHTML = helpMsg;
809		m.helpTooltip.setPosition(e.coordinate);
810	
811		m.helpTooltipElement.classList.remove("hidden");
812	};
813	formatLength(line) {
814		var length = line.getLength();
815		var output;
816		
817		if (length > 100)
818			output = Math.round((length / 1000) * 100) / 100 + ' ' + 'km';
819		else
820			output = Math.round(length * 100) / 100 + ' ' + 'm';
821		
822		return output;
823	};
824	createHelpTooltip() {
825		let m = this.measure;
826		if (m.helpTooltipElement)
827			m.helpTooltipElement.parentNode.removeChild(m.helpTooltipElement);
828		
829		m.helpTooltipElement = document.createElement("div");
830		m.helpTooltipElement.className = "lsMap-measure-tooltip hidden";
831		m.helpTooltip = new ol.Overlay({
832			element: m.helpTooltipElement,
833			offset: [15, 0],
834			positioning: "center-left",
835		});
836		this.map.addOverlay(m.helpTooltip);
837	}
838	createMeasureTooltip() {
839		let m = this.measure;
840		if (m.measureTooltipElement)
841			m.measureTooltipElement.parentNode.removeChild(m.measureTooltipElement);
842		
843		m.measureTooltipElement = document.createElement("div");
844		m.measureTooltipElement.className = "lsMap-measure-tooltip lsMap-measure-tooltip-measure";
845		m.measureTooltip = new ol.Overlay({
846			element: m.measureTooltipElement,
847			offset: [0, -15],
848			positioning: "bottom-center",
849		});
850		this.map.addOverlay(m.measureTooltip);
851	};
852	addMeasure(src) {
853
854		let t = this;
855		let m = this.measure;
856		m.callback = this.onMeasure;
857		m.draw = new ol.interaction.Draw({
858		    source: src,
859		    type: "LineString",
860		    style: new ol.style.Style({
861		    	fill: new ol.style.Fill({
862		    		color: "rgba(255, 255, 255, 0.2)",
863		    	}),
864		    	stroke: new ol.style.Stroke({
865		    		color: "rgba(0, 0, 0, 0.5)",
866		    		lineDash: [10, 10],
867		    		width: 2,
868		    	}),
869		    	image: new ol.style.Circle({
870		    		radius: 5,
871		    		stroke: new ol.style.Stroke({
872		    			color: "rgba(0, 0, 0, 0.7)",
873		    		}),
874		    		fill: new ol.style.Fill({
875		    			color: "rgba(255, 255, 255, 0.2)",
876		    		}),
877		    	}),
878		    }),
879		 });
880		
881		this.map.addInteraction(m.draw);
882
883		this.createMeasureTooltip();
884		this.createHelpTooltip();
885		
886		m.draw.on("drawstart", function (evt) {
887			// set sketch
888			m.sketch = evt.feature;
889	
890			let tooltipCoord = evt.coordinate;
891	
892			m.listener = m.sketch.getGeometry().on("change", function (evt) {
893				var geom = evt.target;
894				var output;
895				
896				if (geom instanceof ol.geom.LineString)
897				{
898					output = t.formatLength(geom);
899					tooltipCoord = geom.getLastCoordinate();
900				}
901				
902				m.measureTooltipElement.innerHTML = output;
903				m.measureTooltip.setPosition(tooltipCoord);
904			});
905		});
906	
907		m.draw.on("drawend", function () {
908			m.measureTooltipElement.className = "lsMap-measure-tooltip lsMap-measure-tooltip-static";
909			m.measureTooltip.setOffset([0, -7]);
910			
911			m.sketch = null;
912			m.measureTooltipElement = null;
913			
914			t.createMeasureTooltip();
915			ol.Observable.unByKey(m.listener);
916		});
917	};
918	clearMeasure(src) {
919
920		let m = this.measure;
921		src.clear(m.measureTooltipElement);
922		this.map.removeInteraction(m.draw);
923		this.map.removeOverlay(m.measureTooltip);
924		
925		let ele = document.querySelectorAll(".lsMap-measure-tooltip");
926		
927		for(let i = 0; i < ele.length; i++)
928			ele[i].parentNode.removeChild(ele[i]);
929		
930		m.measureTooltipElement = null;
931		m.helpTooltipElement = null;
932		m.callback = null;
933		m.draw = null;
934	};
935	setMeasure(isMsr) {
936
937		let layer = this.getLayer("MEASURE");
938		
939		if(layer === null)
940			return;
941		
942		let src = layer.getSource();
943		
944		if(isMsr)
945			this.addMeasure(src);
946		else
947			this.clearMeasure(src);
948	};
949	
950	addfeature_(layer, lid, fid, xy, angl, state, func) {
951		let src = layer.getSource();
952		let ftr = new ol.Feature({ geometry: new ol.geom.Point(this.transform(xy)) });
953		ftr.fid = fid;
954		ftr.onclick = func;
955		ftr.layer = layer;
956		
957		let xy_ = this.transform(xy);
958		ftr.xy = [];
959		ftr.sxy = [];
960		ftr.xy[0] = xy_[0];
961		ftr.xy[1] = xy_[1];
962		ftr.sxy[0] = xy_[0];
963		ftr.sxy[1] = xy_[1];
964
965		this.changeFeature(layer, ftr, xy, angl, state);
966		
967		src.addFeature(ftr);
968		return ftr;
969	};
970	addFeature(lid, fid, xy, angl, state) {
971		let layer = this.getLayer(lid);
972
973		if(layer === null)
974			return 0;
975		let src = layer.getSource();
976		let ftrs = src.getFeatures();
977		let ftr = this.getFeature(ftrs, fid);
978		if(ftr === null)
979		{
980			ftr = this.addfeature_(layer, lid, fid, xy, angl, state, layer.func);
981		}
982
983		return ftr;
984	};
985	addFeatureCst(lid, ftr, state){
986		let layer = this.getLayer(lid);
987		if(layer === null){
988			return 0;
989		}
990		if(layer.istyle.length < state + 1){
991			state = 0;
992		}
993		let istyle = layer.istyle[state];
994		let src = layer.getSource();
995		let ftrs = src.getFeatures();
996		let bfFtr = this.getFeature(ftrs, ftr.fid);
997		if(bfFtr === null){
998			ftr.setStyle(istyle);
999			src.addFeature(ftr);
1000		}
1001	};
1002	changeFeature__(layer, ftr, angl, state) {
1003		if(layer.istyle.length < state + 1)
1004			return;
1005		let istyle = layer.istyle[state].clone();
1006		ftr.scale = istyle.getImage().getScale();
1007
1008		if(istyle !== undefined && angl !== null)
1009			istyle.getImage().setRotation(Math.PI * 2 * angl / 360);
1010
1011		if(layer.autoScale)
1012			this.autoScaleFeature(ftr.scale, istyle);
1013
1014		if(ftr.txtStyle !== undefined && ftr.txtStyle !== null && ftr.layer.txtDisplayLevel < this.zoom)
1015			istyle.setText(ftr.txtStyle);
1016		else
1017			istyle.setText(null);
1018		
1019		ftr.setStyle(istyle);
1020	};
1021	
1022	changeFeature_(layer, ftr, angl) {
1023		let istyle = ftr.getStyle();
1024
1025		if(istyle !== null && istyle !== undefined && angl !== null && ftr.angl !== angl)
1026			istyle.getImage().setRotation(Math.PI * 2 * angl / 360);
1027	};
1028	
1029	changeFeature(layer, ftr, xy, angl, state) {
1030		if(xy !== null)
1031		{
1032			let xy_ = this.transform(xy);
1033			if(ftr.xy[0] !== xy_[0] || ftr.xy[1] !== xy_[1])
1034				ftr.setGeometry(new ol.geom.Point(xy_));
1035			
1036			ftr.xy[0] = xy_[0];
1037			ftr.xy[1] = xy_[1];
1038			ftr.sxy[0] = xy_[0];
1039			ftr.sxy[1] = xy_[1];
1040		}
1041		
1042		if(ftr.state === undefined || ftr.state !== state)
1043			this.changeFeature__(layer, ftr, angl, state);
1044		else
1045			this.changeFeature_(layer, ftr, angl);
1046		
1047		ftr.angl = angl;
1048		ftr.state = state;
1049	};
1050	
1051	setFeature(lid, fid, xy, angl, state) {
1052		let layer = this.getLayer(lid);
1053
1054		if(layer === null || !layer.getVisible())
1055			return;
1056
1057		let src = layer.getSource();
1058		let ftrs = src.getFeatures();
1059		let ftr = this.getFeature(ftrs, fid);
1060
1061		if(ftr === null)
1062			ftr = this.addfeature_(layer, lid, fid, xy, angl, state, layer.func);
1063
1064		this.changeFeature(layer, ftr, xy, angl, state);
1065		return ftr;
1066	};
1067	setFeature_EventMouseMove(ftr, callback) {
1068		if(ftr !== undefined && ftr !== null){
1069			ftr.onmousemove = callback;
1070		}
1071	};
1072	setFeatureText(ftr, fnm, bgclr, sclr, w, txt, ox, oy) {
1073		if(ftr === null || ftr === undefined)
1074			return;
1075
1076        let style = ftr.getStyle();
1077        
1078        if(style === null || style === undefined)
1079        	return;
1080        
1081		let txt_ = new ol.style.Text({
1082            font: fnm,//'15px Nanum Square,sans-serif',
1083            fill: new ol.style.Fill({ color: bgclr }),
1084            stroke: new ol.style.Stroke({
1085              color: sclr, width: w
1086            }),
1087            offsetX: ox,
1088            offsetY: oy,
1089            text: txt
1090        });
1091		
1092		ftr.txtStyle = txt_;
1093		ftr.txt = txt;
1094		
1095		if(ftr.layer.txtDisplayLevel < this.zoom)
1096			style.setText(txt_);
1097		else
1098			style.setText(null);
1099	};
1100	setLayerFeatureText(lid, fid, fnm, bgclr, sclr, w, txt, ox, oy) {
1101
1102		let layer = this.getLayer(lid);
1103
1104		if(layer === null || !layer.getVisible())
1105			return;
1106
1107		let src = layer.getSource();
1108		let ftrs = src.getFeatures();
1109		let ftr = this.getFeature(ftrs, fid);
1110		
1111		if(ftr === null)
1112			return;
1113
1114        this.setFeatureText(ftr, fnm, bgclr, sclr, w, txt, ox, oy);
1115	};
1116	setFeatureState(lid, fid, state) {
1117
1118		let layer = this.getLayer(lid);
1119
1120		if(layer === null || !layer.getVisible())
1121			return;
1122
1123		let src = layer.getSource();
1124		let ftrs = src.getFeatures();
1125		let ftr = this.getFeature(ftrs, fid);
1126
1127		if(ftr !== null)
1128			this.changeFeature(layer, ftr, null, ftr.angl, state);
1129	};
1130	removeFeature(lid, fid) {
1131		let layer = this.getLayer(lid);
1132
1133		if(layer === null)
1134			return;
1135
1136		let src = layer.getSource();
1137		let ftrs = src.getFeatures();
1138
1139		for(let i = 0; i < ftrs.length; i++)
1140		{
1141			if(ftrs[i].fid === fid)
1142			{
1143				if(ftrs[i].interval !== undefined && ftrs[i].interval !== null)
1144					window.clearInterval(ftrs[i].interval);
1145					
1146				src.removeFeature(ftrs[i]);
1147				break;
1148			}
1149		}
1150	};
1151	removeFeatureLayerGroup(lid, gid) {
1152		let layer = this.getLayer(lid);
1153
1154		if(layer === null)
1155			return;
1156
1157		let src = layer.getSource();
1158		let ftrs = src.getFeatures();
1159
1160		for(let i = 0; i < ftrs.length; i++)
1161		{
1162
1163			if(ftrs[i].layer !== undefined && ftrs[i].layer.gid !== undefined && ftrs[i].layer.gid === gid)
1164			{
1165				if(ftrs[i].interval !== undefined && ftrs[i].interval !== null)
1166					window.clearInterval(ftrs[i].interval);
1167					
1168				src.removeFeature(ftrs[i]);
1169			}
1170		}
1171	};
1172	removeFeatureGroup(lid, gid) {
1173		let layer = this.getLayer(lid);
1174
1175		if(layer === null)
1176			return;
1177
1178		let src = layer.getSource();
1179		let ftrs = src.getFeatures();
1180
1181		for(let i = 0; i < ftrs.length; i++)
1182		{
1183
1184			if(ftrs[i].gid !== undefined && ftrs[i].gid === gid)
1185			{
1186				if(ftrs[i].interval !== undefined && ftrs[i].interval !== null)
1187					window.clearInterval(ftrs[i].interval);
1188					
1189				src.removeFeature(ftrs[i]);
1190			}
1191		}
1192	};
1193	removeLayer(layer) {
1194		this.map.removeLayer(layer);
1195	};
1196	removeFeatures(lid) {
1197		let layer = this.getLayer(lid);
1198		if(layer === null)
1199			return;
1200
1201		let src = layer.getSource();
1202		let ftrs = src.getFeatures();
1203		for(let i = 0; i < ftrs.length; i++)
1204		{
1205			if(ftrs[i].interval !== undefined && ftrs[i].interval !== null)
1206				window.clearInterval(ftrs[i].interval);
1207		}
1208		src.clear();
1209	};
1210	getFeature(ftrs, fid) {
1211
1212		for(let i = 0; i < ftrs.length; i++)
1213		{
1214			if(ftrs[i].fid === fid)
1215				return ftrs[i];
1216		}
1217
1218		return null;
1219	};
1220	getGroupFeature(ftrs, gid, fid) {
1221
1222		for(let i = 0; i < ftrs.length; i++)
1223		{
1224			if(ftrs[i].gid === gid && ftrs[i].fid === fid)
1225				return ftrs[i];
1226		}
1227
1228		return null;
1229	};
1230	visibleLayer(lid, v) {
1231		let layer = this.getLayer(lid);
1232
1233		if(layer === null)
1234			return;
1235
1236		layer.setVisible(v);
1237	};
1238	visiableFeature(lid, fid, v) {
1239			
1240	};
1241	visiableLayerGroup(gid, v) {
1242
1243		let layers = this.getLayerGroup(gid);
1244
1245		if(layers === null)
1246			return;
1247
1248		for(let i = 0; i < layers.length; i++)
1249			layers[i].setVisible(v);
1250	};
1251	
1252	autoScaleFeature(scale, istyle) {
1253		let mz = this.map.getView().getMaxZoom();
1254		let z = this.map.getView().getZoom();
1255		let s = scale * z / mz / (mz - z + 1);
1256		
1257		istyle.getImage().setScale(s);
1258	};
1259	autoChangeFeatures() {  // 1031
1260		let layers = this.map.getLayers().getArray();
1261		let scales = [1.2, 1.1, 1.0, 0.8, 0.7, 0.6, 0.5];
1262		for(let i = 0; i < layers.length; i++)
1263		{
1264			if(layers[i] !== null && layers[i].type == "VECTOR_ICON")
1265			{
1266				let src = layers[i].getSource(); 
1267				let ftrs = src.getFeatures();
1268				for(let j = 0; j < ftrs.length; j++){
1269		            let ftr = ftrs[j];
1270		            let istyle = ftr.getStyle();
1271	            	this.levelScaleFeature(scales, istyle);
1272
1273	            	if(layers[i].txtDisplayLevel < this.zoom){
1274	            		istyle.getText()?.setScale(1);
1275	            	} else{
1276	            		istyle.getText()?.setScale(0);
1277	            	}
1278	            	ftr.setStyle(istyle);
1279				}
1280			}
1281		}
1282	};
1283	
1284	autoScaleFeature(scale, istyle) {
1285		let mz = this.map.getView().getMaxZoom();
1286		let z = this.map.getView().getZoom();
1287		let s = scale * z / mz / (mz - z + 1);
1288		if(istyle !== null && istyle.getImage() !== null)
1289			istyle.getImage().setScale(s*3.5);
1290	};
1291	
1292	levelScaleFeature(scales, istyle) {		
1293		let zoomLv = this.map.getView().getZoom();
1294		let realLv = 0;
1295		if(zoomLv>12.2){ // 최대 줌인
1296			realLv = 0;
1297		}else if(zoomLv<9.8){ // 최대 줌아웃
1298			realLv = 6;
1299		}else{ // 나머지
1300			realLv = Math.floor((122 - Math.floor(zoomLv*10))/4);
1301		}
1302		let s = scales[realLv];
1303		
1304		if(istyle !== null && istyle.getImage() !== null)
1305			istyle.getImage().setScale(s);
1306		
1307	};
1308	
1309	isVectorCircleXY(ftrs, xy) {
1310		let xy_ = this.transform(xy);
1311		for(let i = 0; i < ftrs.length; i++)
1312		{
1313			if(ftrs[i].xy[0] === xy_[0] && ftrs[i].xy[1] === xy_[1])
1314				return true;
1315		}
1316		
1317		return false;
1318	};
1319	
1320	addVectorCircle(lid, gid, fid, xy, sz, r, g, b, opacity) {
1321
1322		let layer = this.getLayer(lid);
1323
1324		if(layer === null)
1325			return;
1326
1327		let src = layer.getSource();
1328		let ftrs = src.getFeatures();
1329		let ftr = this.getFeature(ftrs, fid);
1330
1331		if(ftr === null)
1332		{
1333			ftr = new ol.Feature({ geometry: new ol.geom.Circle(this.transform(xy), sz) });
1334	
1335		    let style = new ol.style.Style({
1336		        fill: new ol.style.Fill({
1337		        	color: "rgba(" + r + ", " + g + ", " + b + ", " + opacity + ")"
1338		        })
1339		    });
1340		    
1341			ftr.setStyle(style);
1342			ftr.gid = gid;
1343			ftr.fid = fid;
1344			ftr.xy = this.transform(xy);
1345			ftr.bsz = sz;
1346			ftr.csz = sz;
1347			ftr.layer = layer;
1348			src.addFeature(ftr);
1349		}
1350	};
1351	
1352	setAnimateSize(lid, gid, fid, size, cycle) {
1353
1354		let layer = this.getLayer(lid);
1355
1356		if(layer === null)
1357			return;
1358
1359		let src = layer.getSource();
1360		let ftrs = src.getFeatures();
1361		let ftr = this.getGroupFeature(ftrs, gid, fid);
1362		
1363		if(ftr === null)
1364			return;
1365
1366		if(ftr.interval === null || ftr.interval === undefined)
1367		{	
1368			let t = this;
1369			ftr.msz = size;
1370			ftr.interval = window.setInterval(function(){ t.animateSize(ftr); }, cycle);
1371		}
1372	};
1373	
1374	animateSize(ftr)
1375	{
1376		ftr.csz = ftr.csz + 1;
1377		
1378		if(ftr.csz > ftr.msz)
1379			ftr.csz = ftr.bsz;
1380		
1381		ftr.setGeometry(new ol.geom.Circle(ftr.xy, ftr.csz));
1382		//window.clearInterval(ftr.interval);
1383	};
1384		
1385	
1386	setAnimateMove(lid, fid, xy, angl, state, cycle, repeat, div) {
1387
1388		let layer = this.getLayer(lid);
1389
1390		if(layer === null || !layer.getVisible())
1391			return;
1392
1393		let src = layer.getSource();
1394		let ftrs = src.getFeatures();
1395		let ftr = this.getFeature(ftrs, fid);
1396		
1397		if(ftr === null)
1398			return ftr;
1399
1400		let t = this;
1401		
1402		if(ftr.xy !== undefined && ftr.xy !== null)
1403		{
1404			ftr.sxy[0] = ftr.xy[0];
1405			ftr.sxy[1] = ftr.xy[1];
1406		}
1407		
1408		if(ftr.c_angl !== undefined && ftr.c_angl !== ftr.angl)
1409			ftr.angl = ftr.c_angl;
1410		
1411		ftr.exy = this.transform(xy);
1412		ftr.repeat = repeat;
1413		ftr.cycle = cycle;
1414		ftr.toAngl = angl;
1415		ftr.div = div;
1416		
1417		//this.changeFeature_(null, ftr, angl);
1418		
1419		if(ftr.sxy[0] !== ftr.exy[0] || ftr.sxy[1] !== ftr.exy[1])
1420		{
1421			ftr.midx = 0;
1422			if(ftr.interval === undefined || ftr.interval === null)
1423				ftr.interval = setInterval(function() { t.animateMove(ftr); }, cycle);
1424		}
1425		
1426		return ftr;
1427	};
1428	
1429	animateMove(ftr)
1430	{
1431		if(ftr.interval === null)
1432			return;
1433		
1434		let div = ftr.div;
1435		let x = -(ftr.sxy[0] - ftr.exy[0]);
1436		let y = -(ftr.sxy[1] - ftr.exy[1]);
1437		
1438		let xg = x / div;
1439		let yg = y / div;
1440		
1441		ftr.midx++;
1442		ftr.xy[0] = ftr.sxy[0] + xg * ftr.midx;
1443		ftr.xy[1] = ftr.sxy[1] + yg * ftr.midx;
1444
1445		ftr.setGeometry(new ol.geom.Point(ftr.xy));
1446		
1447		
1448		// 각도 계산
1449		// 350 → 10 도 이동시
1450		let ag1 = ftr.toAngl - ftr.angl;		// -340 반대인 경우 340
1451		let ag2 = ftr.toAngl - ftr.angl + 360; 	// 20도  반대인 경우 -20
1452		
1453		let ag = (Math.abs(ag1) < Math.abs(ag2) ? ag1 : ag2) / ftr.div;
1454		//let ag = (-(ftr.angl - ftr.toAngl)) / div;
1455		ftr.c_angl = ftr.angl + ag * ftr.midx;
1456		
1457		if(ftr.c_angl >= 360)
1458			ftr.c_angl -= 360;
1459		else if(ftr.c_angl < 0)
1460			ftr.c_angl += 360;
1461		
1462		this.changeFeature_(null, ftr, ftr.c_angl);
1463		
1464		if(ftr.midx % div === 0)
1465		{
1466			let txy = [];
1467
1468			txy[0] = ftr.sxy[0];
1469			txy[1] = ftr.sxy[1];
1470			
1471			ftr.midx = 0;
1472			ftr.sxy[0] = ftr.exy[0];
1473			ftr.sxy[1] = ftr.exy[1];
1474			ftr.exy[0] = txy[0];
1475			ftr.exy[1] = txy[1];
1476			ftr.angl = ftr.toAngl;
1477
1478			if(!ftr.repeat)
1479			{
1480				if(ftr.interval !== null)
1481					clearInterval(ftr.interval);
1482				ftr.interval = null;
1483				return;
1484			}
1485		}
1486		
1487//		if(ftr.duration !== undefined && ftr.duration !== null && ftr.duration !== 0)
1488//		{
1489//			if(ftr.midx * ftr.cycle > ftr.duration)
1490//			{
1491//				if(ftr.interval !== null)
1492//				{
1493//					window.clearInterval(ftr.interval);
1494//					ftr.interval = null;
1495//				}
1496//			}
1497//		}
1498	};
1499	
1500	stopAnimateMove(lid) {
1501
1502		let layer = this.getLayer(lid);
1503
1504		if(layer === null)
1505			return;
1506
1507		let src = layer.getSource();
1508		let ftrs = src.getFeatures();
1509		
1510		for(let i = 0; i < ftrs.length; i++)
1511		{
1512			if(ftrs[i].interval !== undefined && ftrs[i].interval !== null)
1513			{
1514				clearInterval(ftrs[i].interval);
1515				ftrs[i].interval = null;
1516				ftrs[i].sxy[0] = ftrs[i].exy[0];
1517				ftrs[i].sxy[1] = ftrs[i].exy[1];
1518				ftrs[i].xy[0] = ftrs[i].exy[0];
1519				ftrs[i].xy[1] = ftrs[i].exy[1];
1520			}
1521		}
1522	};
1523	
1524	addFeatureSvg(lid, fid, xy, svg, sz, opacity) {
1525		let layer = this.getLayer(lid);
1526
1527		if(layer === null)
1528			return;
1529
1530		let src = layer.getSource();
1531		let ftrs = src.getFeatures();
1532		let ftr = this.getFeature(ftrs, fid);
1533		
1534		if(ftr !== null && ftr !== undefined)
1535		{
1536
1537			src.removeFeature(ftr);
1538			ftr = null;
1539		}
1540		
1541		if(ftr === null || ftr === undefined)
1542		{
1543			ftr = new ol.Feature({ geometry: new ol.geom.Point(this.transform(xy)) });
1544			ftr.scale = 1;
1545			ftr.fid = fid;
1546			src.addFeature(ftr);
1547		}
1548
1549	    let style = new ol.style.Style({
1550		    image: new ol.style.Icon({
1551		        opacity: opacity,
1552		        src: "data:image/svg+xml;utf8," + escape(svg),
1553		        scale: 1,
1554		        anchor: [0.5, 0.5],
1555		        imgSize: sz
1556		    })
1557	    });
1558
1559		layer.autoScale = true;
1560	    //layer.setStyle(style);
1561		ftr.setStyle(style);
1562		
1563        if(layer.autoScale)
1564        	this.autoScaleFeature(ftr.scale, style);
1565        
1566		return ftr;
1567	};
1568	
1569	addTransferFeature(lid, ftr, state){
1570		let layer = this.getLayer(lid);
1571		if(layer === null){ return 0; }
1572		if(layer.istyle.length < state + 1){
1573			state = 0;
1574		}
1575		let istyle = layer.istyle[state];
1576		let src = layer.getSource();
1577		let ftrs = src.getFeatures();
1578		let bfFtr = this.getFeature(ftrs, ftr.fid);
1579		ftr.setStyle(istyle);
1580		src.addFeature(ftr);
1581	};
1582	
1583	addBusstopFeature(lid, fid, xy, angl, state) {
1584		let layer = this.getLayer(lid);
1585
1586		if(layer === null) return 0;
1587		let src = layer.getSource();
1588		let ftrs = src.getFeatures();
1589		let ftr = this.getFeature(ftrs, fid);
1590		ftr = this.addfeature_(layer, lid, fid, xy, angl, state, layer.func);
1591
1592		return ftr;
1593	};
1594}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.