팡이네

네이버 지도 마커에 원 도형과 텍스트를 함께 표시하기 위해 사용자 정의 오버레이를 사용해보자.

 

[사용자 정의 오버레이 설정]

//--------------------------------------
// 사용자 정의 오버레이 설정
//--------------------------------------
// 사용자 정의 오버레이
var CustomOverlay = function(options) {
	this._element = $('');
	
	this._code = options.code || null;
	this._position = options.position;
	this._radius = options.radius || 50;
	this._fillColor = options.fillColor || '#0385ff';
	this._fillOpacity = options.fillOpacity || 0.6;
	this._strokeColor = options.strokeColor || '#0385ff';
	this._strokeOpacity = options.strokeOpacity || 0.6;
	this._strokeWeight = 1;
	
	this._textColor = options.textColor || 'white';
};

// CustomOverlay는 OverlayView를 상속받습니다.
CustomOverlay.prototype = new naver.maps.OverlayView();
CustomOverlay.prototype.constructor = CustomOverlay;

[필수 메소드 재정의] onAdd(), onRemove(), draw()

//--------------------------------------
// 필수 메소드 재정의
//--------------------------------------
CustomOverlay.prototype.onAdd = function() {
	// 오버레이 표시 레이어(floatPane(정보 레이어, 상단)/overlayImage(마커 레이어, 중단)/overlayLayer(도형 레이어, 하단)
    var overlayLayer = this.getPanes().floatPane;
    
    this._element.appendTo(overlayLayer);
};

CustomOverlay.prototype.draw = function() {
    // 지도 객체가 설정되지 않았으면 draw 기능을 하지 않습니다.
    if (!this.getMap()) {
        return;
    }

    // projection 객체를 통해 LatLng 좌표를 화면 좌표로 변경합니다.
    var projection = this.getProjection();
    var position = this.getPosition();
    var pixelPosition = projection.fromCoordToOffset(position);
	
	var radius = this._radius;
	
	this._element.css('left', pixelPosition.x - radius);
    this._element.css('top', pixelPosition.y - radius);
	
	var cvs = this._element[0];
	cvs.width = radius * 2;
	cvs.height = radius * 2;
	
	var ctx = cvs.getContext('2d');
	
    // 원 그리기
	ctx.beginPath();
	
	ctx.arc(radius, radius, radius - this._strokeWeight, 0, Math.PI * 2);	// 반지름 = radius - this._strokeWeight
	ctx.fillStyle = hex2rgba(this._fillColor, this._fillOpacity);	//rgba(3, 133, 255, 0.5) #0385ff
	ctx.fill();
	
	ctx.lineWidth = this._strokeWeight;			// 기본값: lineWidth = 1
	ctx.strokeStyle = hex2rgba(this._strokeColor, this._strokeOpacity);	//기본값: strokeStyle = '#000000'
	ctx.stroke();
	
	ctx.closePath();
	
    // 원 내부에 텍스트 표시
	ctx.textAlign = 'center';
	//ctx.textBaseline = 'middle';						// 텍스트가 1줄일 경우 사용
	ctx.fillStyle = hex2rgba(this._textColor, null);	// text color
	ctx.font = '14px dotum bold';
	ctx.fillText(this._code.name, radius, radius - 4);		// 글꼴의 크기에 따라 세로 출력 위치 조정
	ctx.font = '20px dotum bold';
	ctx.fillText(this._code.count, radius, radius + 20 - 4);	// 글꼴의 크기에 따라 세로 출력 위치 조정
};

CustomOverlay.prototype.onRemove = function() {
    this._element.remove();
    
    // 이벤트 핸들러를 설정했다면 정리합니다.
    this._element.off();
};

[속성 메소드 정의]

//--------------------------------------
// 속성 메소드 정의
//--------------------------------------
CustomOverlay.prototype.getCode = function() {
    return this._code;
};

CustomOverlay.prototype.setCode = function(code) {
    this._code = code;
};

CustomOverlay.prototype.getPosition = function() {
    return this._position;
};

CustomOverlay.prototype.setPosition = function(position) {
    this._position = position;
};

CustomOverlay.prototype.getRadius = function() {
    return this._radius;
};

CustomOverlay.prototype.setRadius = function(radius) {
    this._radius = radius;
};

CustomOverlay.prototype.getFillColor = function() {
    return this._fillColor;
};

CustomOverlay.prototype.setFillColor = function(color) {
    this._fillColor = color;
};

[hex to rgb, colorname to hex]

//--------------------------------------
// hex to rgb, colorname to hex
//--------------------------------------
// 색깔코드를 rgba로 변경(color, opacity)
function hex2rgba(c, o) {
	if (c.charAt(0) == '#') {
        c = c.substr(1);
    } else {
		return colorName2Hex(c);	//색깔명 사용할 경우 opacity 무시
	}
	
	if (o == null || o > 1.0 || o < 0) o = 1.0;
	
	if (c.length == 3) {
        c = c.substr(0,1) + c.substr(0,1) + c.substr(1,2) + c.substr(1,2) + c.substr(2,3) + c.substr(2,3);
    }
	
	var r = c.charAt(0) + '' + c.charAt(1); r = parseInt(r, 16);
    var g = c.charAt(2) + '' + c.charAt(3); g = parseInt(g, 16);
    var b = c.charAt(4) + '' + c.charAt(5); b = parseInt(b, 16);
    
    return 'rgba(' + r + ',' + g + ',' + b + ','+ o +')';
}

// 색깔명을 색깔코드로 변경
function colorName2Hex(color) {
    var colors = {"aliceblue":"#f0f8ff","antiquewhite":"#faebd7","aqua":"#00ffff","aquamarine":"#7fffd4","azure":"#f0ffff",
    "beige":"#f5f5dc","bisque":"#ffe4c4","black":"#000000","blanchedalmond":"#ffebcd","blue":"#0000ff","blueviolet":"#8a2be2","brown":"#a52a2a","burlywood":"#deb887",
    "cadetblue":"#5f9ea0","chartreuse":"#7fff00","chocolate":"#d2691e","coral":"#ff7f50","cornflowerblue":"#6495ed","cornsilk":"#fff8dc","crimson":"#dc143c","cyan":"#00ffff",
    "darkblue":"#00008b","darkcyan":"#008b8b","darkgoldenrod":"#b8860b","darkgray":"#a9a9a9","darkgreen":"#006400","darkkhaki":"#bdb76b","darkmagenta":"#8b008b","darkolivegreen":"#556b2f",
    "darkorange":"#ff8c00","darkorchid":"#9932cc","darkred":"#8b0000","darksalmon":"#e9967a","darkseagreen":"#8fbc8f","darkslateblue":"#483d8b","darkslategray":"#2f4f4f","darkturquoise":"#00ced1",
    "darkviolet":"#9400d3","deeppink":"#ff1493","deepskyblue":"#00bfff","dimgray":"#696969","dodgerblue":"#1e90ff",
    "firebrick":"#b22222","floralwhite":"#fffaf0","forestgreen":"#228b22","fuchsia":"#ff00ff",
    "gainsboro":"#dcdcdc","ghostwhite":"#f8f8ff","gold":"#ffd700","goldenrod":"#daa520","gray":"#808080","green":"#008000","greenyellow":"#adff2f",
    "honeydew":"#f0fff0","hotpink":"#ff69b4",
    "indianred ":"#cd5c5c","indigo":"#4b0082","ivory":"#fffff0","khaki":"#f0e68c",
    "lavender":"#e6e6fa","lavenderblush":"#fff0f5","lawngreen":"#7cfc00","lemonchiffon":"#fffacd","lightblue":"#add8e6","lightcoral":"#f08080","lightcyan":"#e0ffff","lightgoldenrodyellow":"#fafad2",
    "lightgrey":"#d3d3d3","lightgreen":"#90ee90","lightpink":"#ffb6c1","lightsalmon":"#ffa07a","lightseagreen":"#20b2aa","lightskyblue":"#87cefa","lightslategray":"#778899","lightsteelblue":"#b0c4de",
    "lightyellow":"#ffffe0","lime":"#00ff00","limegreen":"#32cd32","linen":"#faf0e6",
    "magenta":"#ff00ff","maroon":"#800000","mediumaquamarine":"#66cdaa","mediumblue":"#0000cd","mediumorchid":"#ba55d3","mediumpurple":"#9370d8","mediumseagreen":"#3cb371","mediumslateblue":"#7b68ee",
    "mediumspringgreen":"#00fa9a","mediumturquoise":"#48d1cc","mediumvioletred":"#c71585","midnightblue":"#191970","mintcream":"#f5fffa","mistyrose":"#ffe4e1","moccasin":"#ffe4b5",
    "navajowhite":"#ffdead","navy":"#000080",
    "oldlace":"#fdf5e6","olive":"#808000","olivedrab":"#6b8e23","orange":"#ffa500","orangered":"#ff4500","orchid":"#da70d6",
    "palegoldenrod":"#eee8aa","palegreen":"#98fb98","paleturquoise":"#afeeee","palevioletred":"#d87093","papayawhip":"#ffefd5","peachpuff":"#ffdab9","peru":"#cd853f","pink":"#ffc0cb","plum":"#dda0dd","powderblue":"#b0e0e6","purple":"#800080",
    "rebeccapurple":"#663399","red":"#ff0000","rosybrown":"#bc8f8f","royalblue":"#4169e1",
    "saddlebrown":"#8b4513","salmon":"#fa8072","sandybrown":"#f4a460","seagreen":"#2e8b57","seashell":"#fff5ee","sienna":"#a0522d","silver":"#c0c0c0","skyblue":"#87ceeb","slateblue":"#6a5acd","slategray":"#708090","snow":"#fffafa","springgreen":"#00ff7f","steelblue":"#4682b4",
    "tan":"#d2b48c","teal":"#008080","thistle":"#d8bfd8","tomato":"#ff6347","turquoise":"#40e0d0",
    "violet":"#ee82ee",
    "wheat":"#f5deb3","white":"#ffffff","whitesmoke":"#f5f5f5",
    "yellow":"#ffff00","yellowgreen":"#9acd32"};

    if (typeof colors[color.toLowerCase()] != 'undefined')
        return colors[color.toLowerCase()];

    return false;
}

[오버레이 표시 및 이벤트 설정]

//--------------------------------------
// 오버레이 표시 및 이벤트 설정
//--------------------------------------
var options = [
	{ position: TEST1, radius: 50, code: { name: '숙소',   count: '5',  city: '11', sig: '11290', emd: '11200104', text: '테스트1' } },
	{ position: TEST2, radius: 50, code: { name: '사무실', count: '99', city: '11', sig: '11290', emd: '11200104', text: '테스트2' } },
	{ position: TEST3, radius: 50, code: { name: '맛집',   count: '3',  city: '11', sig: '11290', emd: '11200104', text: '테스트3' } },
];

var markers = [];

// 오버레이 생성
for (var idx in options) {
	markers.push(new CustomOverlay(options[idx]));
}

// 오버레이 표시, 이벤트 설정
for (var idx in markers) {
	markers[idx].setMap(map);
	
	markers[idx]._element.on('mouseover', changeRadius(idx, 100));
	markers[idx]._element.on('mouseout',  changeRadius(idx, 50));
	markers[idx]._element.on('click',     clickMarker(idx));
}

function changeRadius(idx, r) {
	return function(e) {
		var marker = markers[idx];
		marker.setRadius(r);
		marker.draw();
	}
}

function clickMarker(idx) {
	return function(e) {
		console.log(markers[idx].getCode());
	}
}

[참고]

https://navermaps.github.io/maps.js.ncp/docs/naver.maps.OverlayView.html

https://navermaps.github.io/maps.js.ncp/docs/tutorial-6-CustomOverlay.html

https://navermaps.github.io/maps.js.ncp/docs/tutorial-custom-overlay.example.html