logo
Tutorials Examples naver map js api v3 네이버 지도 API Markers

Markers

A marker is an overlay that indicates a location on a map with an icon. Images or vector graphic polygons can be used for icons.

Place a marker at a desired location

To use a marker, you need to create an object of the Marker class. Pass the MarkerOptions object literal as an argument to the constructor to specify properties of a marker.
A marker is an object that indicates a location on a map as an icon. So, the position property, which represents a location, must be specified. For other properties, default values are provided.

The following code example places a default marker for which only the position property is specified, at NAVER Green Factory.

var map = new naver.maps.Map('map', {
    center: new naver.maps.LatLng(37.3595704, 127.105399),
    zoom: 10
});

var marker = new naver.maps.Marker({
    position: new naver.maps.LatLng(37.3595704, 127.105399),
    map: map
});

Examples: Displaying a marker

The following code example moves a marker to a click point on the map by using the setPosition method of the marker.

var map = new naver.maps.Map('map', {
    center: new naver.maps.LatLng(37.3595704, 127.105399),
    zoom: 10
});

var marker = new naver.maps.Marker({
    position: new naver.maps.LatLng(37.3595704, 127.105399),
    map: map
});

naver.maps.Event.addListener(map, 'click', function(e) {
    marker.setPosition(e.latlng);
});

Examples: Moving a marker to a click point

Specify an image as a marker icon

The icon property of a marker is an object that defines an icon of the marker. The icon property is defined with two types of object literals.

  • ImageIcon: Specifies an icon with an image file.
  • SymbolIcon: Specifies an icon with a vector graphic (polygon).

In this section, we will show you some code examples that use an ImageIcon object literal to specify an image for a marker icon.

The following code example specifies an ImageIcon object literal in the icon property to create a marker with a specified image.

var position = new naver.maps.LatLng(37.3595704, 127.105399);

var map = new naver.maps.Map('map', {
    center: position,
    zoom: 10
});

var markerOptions = {
    position: position,
    map: map,
    icon: {
        url: './img/pin_default.png',
        size: new naver.maps.Size(22, 35),
        origin: new naver.maps.Point(0, 0),
        anchor: new naver.maps.Point(11, 35)
    }
};

var marker = new naver.maps.Marker(markerOptions);

Examples: Using an image icon

You can also specify a url of an image, instead of an ImageIcon object literal, in the icon property.
If you enter a url string in the icon property, the NAVER Maps API v3 automatically converts it into an ImageIcon object literal, and sets the size property of the ImageIcon to the size of image, the origin property to (0, 0), and the anchor property to the bottom center pointer by default.

var position = new naver.maps.LatLng(37.3595704, 127.105399);

var map = new naver.maps.Map('map', {
    center: position,
    zoom: 10
});

var markerOptions = {
    position: position,
    map: map,
    icon: './img/pin_default.png'
};

var marker = new naver.maps.Marker(markerOptions);

You can also create a marker with a sprite image combining various types of icons into one image.

var MARKER_ICON_URL = './img/sp_pins_spot_v2.png';

var MARKER_SPRITE_X_OFFSET = 29;
var MARKER_SPRITE_Y_OFFSET = 50;

var MARKER_SPRITE_POSITION = {

    "A0": [0, 0],
    "B0": [MARKER_SPRITE_X_OFFSET, 0],
    "C0": [MARKER_SPRITE_X_OFFSET*2, 0],
    "D0": [MARKER_SPRITE_X_OFFSET*3, 0],
    "E0": [MARKER_SPRITE_X_OFFSET*4, 0],
    "F0": [MARKER_SPRITE_X_OFFSET*5, 0],
    "G0": [MARKER_SPRITE_X_OFFSET*6, 0],
    "H0": [MARKER_SPRITE_X_OFFSET*7, 0],
    "I0": [MARKER_SPRITE_X_OFFSET*8, 0],

    "A1": [0, MARKER_SPRITE_Y_OFFSET],
    "B1": [MARKER_SPRITE_X_OFFSET, MARKER_SPRITE_Y_OFFSET],
    "C1": [MARKER_SPRITE_X_OFFSET*2, MARKER_SPRITE_Y_OFFSET],
    "D1": [MARKER_SPRITE_X_OFFSET*3, MARKER_SPRITE_Y_OFFSET],
    "E1": [MARKER_SPRITE_X_OFFSET*4, MARKER_SPRITE_Y_OFFSET],
    "F1": [MARKER_SPRITE_X_OFFSET*5, MARKER_SPRITE_Y_OFFSET],
    "G1": [MARKER_SPRITE_X_OFFSET*6, MARKER_SPRITE_Y_OFFSET],
    "H1": [MARKER_SPRITE_X_OFFSET*7, MARKER_SPRITE_Y_OFFSET],
    "I1": [MARKER_SPRITE_X_OFFSET*8, MARKER_SPRITE_Y_OFFSET],

    "A2": [0, MARKER_SPRITE_Y_OFFSET*2],
    "B2": [MARKER_SPRITE_X_OFFSET, MARKER_SPRITE_Y_OFFSET*2],
    "C2": [MARKER_SPRITE_X_OFFSET*2, MARKER_SPRITE_Y_OFFSET*2],
    "D2": [MARKER_SPRITE_X_OFFSET*3, MARKER_SPRITE_Y_OFFSET*2],
    "E2": [MARKER_SPRITE_X_OFFSET*4, MARKER_SPRITE_Y_OFFSET*2],
    "F2": [MARKER_SPRITE_X_OFFSET*5, MARKER_SPRITE_Y_OFFSET*2],
    "G2": [MARKER_SPRITE_X_OFFSET*6, MARKER_SPRITE_Y_OFFSET*2],
    "H2": [MARKER_SPRITE_X_OFFSET*7, MARKER_SPRITE_Y_OFFSET*2],
    "I2": [MARKER_SPRITE_X_OFFSET*8, MARKER_SPRITE_Y_OFFSET*2]
};

var myLatlng = new naver.maps.LatLng(37.3614483, 129.1114883);

var mapOptions = {
    zoom: 11,
    center: myLatlng
};

var map = new naver.maps.Map(document.getElementById('map'), mapOptions);

var bounds = map.getBounds(),
    southWest = bounds.getSW(),
    northEast = bounds.getNE(),
    lngSpan = northEast.lng() - southWest.lng(),
    latSpan = northEast.lat() - southWest.lat();

var markers = [], marker, position;

for (var key in MARKER_SPRITE_POSITION) {

    position = new naver.maps.LatLng(
        southWest.lat() + latSpan * Math.random(),
        southWest.lng() + lngSpan * Math.random());

    marker = new naver.maps.Marker({
        map: map,
        position: position,
        title: key,
        icon: {
            url: MARKER_ICON_URL,
            size: new naver.maps.Size(24, 37),
            anchor: new naver.maps.Point(12, 37),
            origin: new naver.maps.Point(MARKER_SPRITE_POSITION[key][0], MARKER_SPRITE_POSITION[key][1])
        }
    });
};

Examples: Using sprite image icons

Adjust image icons for retina displays

The ImageIcon object literal has a property called scaledSize. The scaledSize property forcibly adjusts the size of an image used as an icon. If the scaledSize property is not specified, the original size of the image is used by default.

For retina displays, you should prepare an image twice bigger than the image displayed on the screen and set the scaledSize property to half the size of the original image. Then, the image is normally displayed in retina displays because the bigger image is displayed in a small size.

The following code example creates a single image marker for retina displays.
It uses a 50 x 68 image for a 25 x 34 marker icon to display it clearly in retina displays.


var position = new naver.maps.LatLng(37.3595704, 127.105399);

var map = new naver.maps.Map('map', {
    center: position,
    zoom: 10
});

var marker = new naver.maps.Marker({
    position: position,
    map: map,
    icon: {
        url: './img/ico_pin.jpg',
        size: new naver.maps.Size(25, 34),
        scaledSize: new naver.maps.Size(25, 34),
        origin: new naver.maps.Point(0, 0),
        anchor: new naver.maps.Point(12, 34)
    }
});

Examples: Adjusting the size of image icons for retina displays

The following code example creates a sprite image marker for retina displays.


var map = new naver.maps.Map('map', {
    center: new naver.maps.LatLng(37.3595704, 127.105399),
    zoom: 10
});

makeMarker(map, new naver.maps.LatLng(37.3595704, 127.105399), 0);
makeMarker(map, new naver.maps.LatLng(37.3618025, 127.1153248), 1);
makeMarker(map, new naver.maps.LatLng(37.3561936, 127.0983706), 2);

function makeMarker(map, position, index) {

    var ICON_GAP = 31;
    var ICON_SPRITE_IMAGE_URL = './img/sp_pin_hd.png';
    var iconSpritePositionX = (index * ICON_GAP) + 1;
    var iconSpritePositionY = 1;

    var marker = new naver.maps.Marker({
        map: map,
        position: position,
        icon: {
          url: ICON_SPRITE_IMAGE_URL,
          size: new naver.maps.Size(26, 36), // Image size
          origin: new naver.maps.Point(iconSpritePositionX, iconSpritePositionY), // Clipping location of the sprite image
          anchor: new naver.maps.Point(13, 36), // Offset of the image location on the map
          scaledSize: new naver.maps.Size(395, 79)
        }
    });

    return marker;
}

Examples: Adjusting the size of sprite image icons for retina displays

Specify a polygon as a marker icon

As you can see in the examples above, you can set an ImageIcon object literal in the icon property of the MarkerOptions to use an image file as a marker icon.
If you set a SymbolIcon object literal in the icon property, you can use a polygon, instead of an image file, as a marker icon.


var position = new naver.maps.LatLng(37.3595704, 127.105399);

var map = new naver.maps.Map('map', {
    center: position,
    zoom: 10
});

var marker = new naver.maps.Marker({
    map: map,
    position: position,
    icon: {
        path: [
            new naver.maps.Point(0, 70), new naver.maps.Point(20, 100), new naver.maps.Point(40, 70),
            new naver.maps.Point(30, 70), new naver.maps.Point(70, 0), new naver.maps.Point(10, 70)
        ],
        anchor: new naver.maps.Point(23, 103),
        fillColor: '#ff0000',
        fillOpacity: 1,
        strokeColor: '#000000',
        strokeStyle: 'solid',
        strokeWeight: 3
    },
    shadow: {
        url: "./img/shadow-arrow.png",
        size: new naver.maps.Size(193, 128),
        origin: new naver.maps.Point(0, 0),
        anchor: new naver.maps.Point(62, 120)
    }
});

Examples: Using symbol icons

Specify HTML markup as a marker icon

You can also use HTML markup to create a marker. Set an HtmlIcon object literal in the 'icon' property, and a marker displaying the specified HTML content is created.

var boundary = naver.maps.LatLngBounds.bounds(new naver.maps.LatLng(37.3724620, 127.1051714), new naver.maps.LatLng(37.3542795, 127.1174332));
var unarySpot = new naver.maps.LatLng(37.3637770, 127.1174332);

var map = new naver.maps.Map(document.getElementById('map'), { zoom: 10 });
    map.fitBounds(boundary);

var unarySpotMarker = new naver.maps.Marker({
    position: unarySpot,
    map: map,
    title: 'Unary Spot!!',
    icon: {
        content: '<img src="./img/pin_default.png" alt="" style="margin: 0px; padding: 0px; border: 0px solid transparent; display: block; max-width: none; max-height: none; -webkit-user-select: none; position: absolute; width: 22px; height: 35px; left: 0px; top: 0px;">',
        size: new naver.maps.Size(22, 35),
        anchor: new naver.maps.Point(11, 35)
    }
});

Examples: Using HTML icons

Define interaction areas of a marker

The shape property of the MarkerOptions defines user interaction areas including mouse and touch events.
The default value is null, which specifies a user interaction area as follows.

  • If icon is ImageIcon, a user interaction area is set to a square shaped area as big as the size of a marker.
  • If icon is SymbolIcon, a user interaction area is set to a polygon shaped area.

If you need to specify a custom user interaction area, set a MarkerShape object literal in the shape property and enter coordinates of a desired shape.
The following code example specifies a user interaction area as a marker shape by using the shape property.

var position = new naver.maps.LatLng(37.3595704, 127.105399);

var map = new naver.maps.Map('map', {
    center: position,
    zoom: 10
});

var markerOptions = {
    position: position,
    map: map,
    icon: {
        url: './img/pin_default.png',
        size: new naver.maps.Size(22, 35),
        origin: new naver.maps.Point(0, 0),
        anchor: new naver.maps.Point(11, 35)
    },
    shadow: {
        url: './img/shadow-pin_default.png',
        size: new naver.maps.Size(40, 35),
        origin: new naver.maps.Point(0, 0),
        anchor: new naver.maps.Point(11, 35)
    },
    shape: {
        coords: [11, 0, 9, 0, 6, 1, 4, 2, 2, 4,
                0, 8, 0, 12, 1, 14, 2, 16, 5, 19,
                5, 20, 6, 23, 8, 26, 9, 30, 9, 34,
                13, 34, 13, 30, 14, 26, 16, 23, 17, 20,
                17, 19, 20, 16, 21, 14, 22, 12, 22, 12,
                22, 8, 20, 4, 18, 2, 16, 1, 13, 0],
        type: 'poly'
    }
};

var marker = new naver.maps.Marker(markerOptions);

Examples: Setting the interaction area of a marker

Animate markers

The animation property of the MarkerOptions defines an animation of a marker. Available animations are as follows:

  • BOUNCE: A marker bounces when it appears on the map. This animation continues until it is stopped by setting the animation property to null.
  • DROP: A marker drops from the top of the map when it appears on the map. This animation ends at the location of the marker. It plays only once, and after that, the animation property is changed to null.

The following code example adds the DROP animation to a marker.

var mapOptions = {
    zoom: 11
};

var map = new naver.maps.Map(document.getElementById('map'), mapOptions);
map.fitBounds(naver.maps.LatLngBounds.bounds(new naver.maps.LatLng(37.3724620, 127.1051714), new naver.maps.LatLng(37.3542795, 127.1174332)));

var urlMarker = new naver.maps.Marker({
    position: new naver.maps.LatLng(37.3542795, 127.1072556),
    map: map,
    title: 'urlMarker',
    icon: "./img/pin_default.png",
    animation: naver.maps.Animation.DROP
});

Examples: Displaying animated markers

Display visible markers only

The more overlays are added on the map, the more graphic resources of the browser are needed, causing poor performance. Therefore, it is better to put fewer overlays on the map.

The easiest way to do so is to put only the overlays that are currently visible on the screen and remove those that are not visible from the map. For this, you can use the hasLatLng and hasPoint methods of LatLngBounds and PointBounds objects.

LatLngBounds and PointBounds are classes that define specific bounds. If specific bounds are defined, you can use the hasLatLng and hasPoint methods to decide whether a certain location is in that bounds.

The Map object provides the getBounds method to return the bounds currently displayed on the map as a LatLngBounds object. Check if each marker is located in the bounds of the current screen by using the getBounds method of the Map object, and add it to the map if it is or remove it from the map if it is not.

The following code example implements what is described above. After initializing the map, it gets the map bounds with the getBounds method and adds several markers in the bounds. When the drag_end or the zoom_changed event, which changes the map bounds, is raised, it adds or removes each marker after checking if the marker is in the current map bounds or not.

var MARKER_ICON_URL = './img/sp_pins_spot_v3.png';

var MARKER_SPRITE_X_OFFSET = 29;
var MARKER_SPRITE_Y_OFFSET = 50;

var MARKER_SPRITE_POSITION = {

    "A0": [0, 0],
    "B0": [MARKER_SPRITE_X_OFFSET, 0],
    "C0": [MARKER_SPRITE_X_OFFSET*2, 0],
    "D0": [MARKER_SPRITE_X_OFFSET*3, 0],
    "E0": [MARKER_SPRITE_X_OFFSET*4, 0],
    "F0": [MARKER_SPRITE_X_OFFSET*5, 0],
    "G0": [MARKER_SPRITE_X_OFFSET*6, 0],
    "H0": [MARKER_SPRITE_X_OFFSET*7, 0],
    "I0": [MARKER_SPRITE_X_OFFSET*8, 0],

    "A1": [0, MARKER_SPRITE_Y_OFFSET],
    "B1": [MARKER_SPRITE_X_OFFSET, MARKER_SPRITE_Y_OFFSET],
    "C1": [MARKER_SPRITE_X_OFFSET*2, MARKER_SPRITE_Y_OFFSET],
    "D1": [MARKER_SPRITE_X_OFFSET*3, MARKER_SPRITE_Y_OFFSET],
    "E1": [MARKER_SPRITE_X_OFFSET*4, MARKER_SPRITE_Y_OFFSET],
    "F1": [MARKER_SPRITE_X_OFFSET*5, MARKER_SPRITE_Y_OFFSET],
    "G1": [MARKER_SPRITE_X_OFFSET*6, MARKER_SPRITE_Y_OFFSET],
    "H1": [MARKER_SPRITE_X_OFFSET*7, MARKER_SPRITE_Y_OFFSET],
    "I1": [MARKER_SPRITE_X_OFFSET*8, MARKER_SPRITE_Y_OFFSET],

    "A2": [0, MARKER_SPRITE_Y_OFFSET*2],
    "B2": [MARKER_SPRITE_X_OFFSET, MARKER_SPRITE_Y_OFFSET*2],
    "C2": [MARKER_SPRITE_X_OFFSET*2, MARKER_SPRITE_Y_OFFSET*2],
    "D2": [MARKER_SPRITE_X_OFFSET*3, MARKER_SPRITE_Y_OFFSET*2],
    "E2": [MARKER_SPRITE_X_OFFSET*4, MARKER_SPRITE_Y_OFFSET*2],
    "F2": [MARKER_SPRITE_X_OFFSET*5, MARKER_SPRITE_Y_OFFSET*2],
    "G2": [MARKER_SPRITE_X_OFFSET*6, MARKER_SPRITE_Y_OFFSET*2],
    "H2": [MARKER_SPRITE_X_OFFSET*7, MARKER_SPRITE_Y_OFFSET*2],
    "I2": [MARKER_SPRITE_X_OFFSET*8, MARKER_SPRITE_Y_OFFSET*2]
};

var map = new naver.maps.Map('map', {
    center: new naver.maps.LatLng(37.3595704, 127.105399),
    zoom: 10
});

var bounds = map.getBounds(),
    southWest = bounds.getSW(),
    northEast = bounds.getNE(),
    lngSpan = northEast.lng() - southWest.lng(),
    latSpan = northEast.lat() - southWest.lat();

var markers = [];

for (var key in MARKER_SPRITE_POSITION) {

    var position = new naver.maps.LatLng(
        southWest.lat() + (latSpan * Math.random()),
        southWest.lng() + (lngSpan * Math.random())
    );

    var marker = new naver.maps.Marker({
        map: map,
        position: position,
        title: key,
        icon: {
            url: MARKER_ICON_URL,
            size: new naver.maps.Size(24, 37),
            anchor: new naver.maps.Point(12, 37),
            origin: new naver.maps.Point(MARKER_SPRITE_POSITION[key][0], MARKER_SPRITE_POSITION[key][1])
        },
        zIndex: 100
    });

    markers.push(marker);
};

naver.maps.Event.addListener(map, 'zoom_changed', function() {
    updateMarkers(map, markers);

});

naver.maps.Event.addListener(map, 'dragend', function() {
    updateMarkers(map, markers);
});

function updateMarkers(map, markers) {

    var mapBounds = map.getBounds();
    var marker, position;

    for (var i = 0; i < markers.length; i++) {

        marker = markers[i]
        position = marker.getPosition();

        if (mapBounds.hasLatLng(position)) {
            showMarker(map, marker);
        } else {
            hideMarker(map, marker);
        }
    }
}

function showMarker(map, marker) {

    if (marker.setMap()) return;
    marker.setMap(map);
}

function hideMarker(map, marker) {

    if (!marker.setMap()) return;
    marker.setMap(null);
}

Examples: Displaying markers only on the visible area

Identify overlapping markers with the getDrawingRect method

Marker, Rectangle, Circle, Polyline, and Polygon overlays, among those provided by the NAVER Maps API v3, provide the getDrawingRect method. This method gets the bounds where an overlay is drawn on the current map. It returns a PointBounds object in pixels.

As described above, LatLngBounds and PointBounds provide the hasPoint method which checks if a certain location is within the specified bounds. They also provide the intersects method, which checks if two bounds are overlapped with each other. Using this method, you can easily check if two markers are overlapped with each other. Use the getDrawingRect method to get the bounds of two markers and check if they are overlapped. The following code example implements this.

var marker1 = new naver.maps.Marker({...});
var marker2 = new naver.maps.Marker({...});

marker1.setMap(map);
marker2.setMap(map);

function intersects() {
    var marker1Rect = marker1.getDrawingRect();
    var marker2Rect = marker2.getDrawingRect();

    // Return true or false after checking whether two markers are overlapped.
    return marker1Rect.intersects(marker2Rect);
}

The following code example places unspecified markers on the map and checks whether they are overlapped with the zoom_changed event handler to display them on the screen. Since locations of the markers in this example are not changed, it checks whether they are overlapped when the zoom level is changed.

After initializing the map, place a marker at a location in the currently visible map bounds. When the zoom level is changed, each marker checks whether it is overlapped with other markers and collects adjacent markers. Highlight overlapping markers, combine drawing bounds of adjacent markers to converts them into a LatLngBounds object, and draw a Rectangle to make overlapping markers visible.

var MARKER_ICON_URL = './img/sp_pins_spot_v3.png';
var MARKER_HIGHLIGHT_ICON_URL = './img/sp_pins_spot_v3_over.png';
var COLORS = ['#45ABD9', '#6154B6', '#E43736', '#44AE3F', '#F6D200', '#344554'];

var MARKER_SPRITE_X_OFFSET = 29;
var MARKER_SPRITE_Y_OFFSET = 50;

var MARKER_SPRITE_POSITION = {

    "A0": [0, 0],
    "B0": [MARKER_SPRITE_X_OFFSET, 0],
    "C0": [MARKER_SPRITE_X_OFFSET*2, 0],
    "D0": [MARKER_SPRITE_X_OFFSET*3, 0],
    "E0": [MARKER_SPRITE_X_OFFSET*4, 0],
    "F0": [MARKER_SPRITE_X_OFFSET*5, 0],
    "G0": [MARKER_SPRITE_X_OFFSET*6, 0],
    "H0": [MARKER_SPRITE_X_OFFSET*7, 0],
    "I0": [MARKER_SPRITE_X_OFFSET*8, 0],

    "A1": [0, MARKER_SPRITE_Y_OFFSET],
    "B1": [MARKER_SPRITE_X_OFFSET, MARKER_SPRITE_Y_OFFSET],
    "C1": [MARKER_SPRITE_X_OFFSET*2, MARKER_SPRITE_Y_OFFSET],
    "D1": [MARKER_SPRITE_X_OFFSET*3, MARKER_SPRITE_Y_OFFSET],
    "E1": [MARKER_SPRITE_X_OFFSET*4, MARKER_SPRITE_Y_OFFSET],
    "F1": [MARKER_SPRITE_X_OFFSET*5, MARKER_SPRITE_Y_OFFSET],
    "G1": [MARKER_SPRITE_X_OFFSET*6, MARKER_SPRITE_Y_OFFSET],
    "H1": [MARKER_SPRITE_X_OFFSET*7, MARKER_SPRITE_Y_OFFSET],
    "I1": [MARKER_SPRITE_X_OFFSET*8, MARKER_SPRITE_Y_OFFSET]

};

var map = new naver.maps.Map('map', {
    center: new naver.maps.LatLng(37.3595704, 127.105399),
    zoom: 10
});

var bounds = map.getBounds(),
    southWest = bounds.getSW(),
    northEast = bounds.getNE(),
    lngSpan = northEast.lng() - southWest.lng(),
    latSpan = northEast.lat() - southWest.lat();

var markers = [], markersMap = {};
var rectangles = [], colorIndex = 0;

for (var key in MARKER_SPRITE_POSITION) {

    var position = new naver.maps.LatLng(
        southWest.lat() + latSpan * Math.random(),
        southWest.lng() + lngSpan * Math.random());

    var marker = new naver.maps.Marker({
        map: map,
        position: position,
        title: key,
        icon: {
            url: MARKER_ICON_URL,
            size: new naver.maps.Size(24, 37),
            anchor: new naver.maps.Point(12, 37),
            origin: new naver.maps.Point(MARKER_SPRITE_POSITION[key][0], MARKER_SPRITE_POSITION[key][1])
        },
        zIndex: 100
    });

    markers.push(marker);
    markersMap[key] = marker;
};

naver.maps.Event.addListener(map, 'zoom_changed', function() {

    updateMarkersIntersectState();
});

function updateMarkersIntersectState() {

    var store = getIntersectMarkerStore(markers);
    var intersectMarkers = getMarkersByStore(store);
    var boundsList = getIntersectMarkerBounds(intersectMarkers);

    resetMarkers(markers);
    highlightMarkers(intersectMarkers);

    resetRectangles(rectangles);
    rectangles = drawRectangles(boundsList);
}

function resetRectangles(rectangles) {
    for (var i = 0; i < rectangles.length; i++) {
        rectangles[i].setMap(null);
    }
}

function drawRectangles(boundsList) {

    var rectangles = []

    for (var i = 0; i < boundsList.length; i++) {
        rectangles.push(new naver.maps.Rectangle({
            map: map,
            bounds: boundsList[i],
            strokeColor: COLORS[colorIndex % COLORS.length],
            strokeWeight: 2,
            strokeOpacity: 0.8,
            fillColor: COLORS[colorIndex % COLORS.length],
            fillOpacity: 0.4
        }));
        colorIndex++;
    }

    return rectangles;
}

function getIntersectMarkerStore(markers) {

    var store = [];
    var target, checked, targetBounds, checkedBounds;

    for (var i = 0; i < markers.length; i++) {

        target = markers[i];

        for (var j = 0; j < markers.length; j++) {

            checked = markers[j];

            if (target === checked) continue;

            targetBounds = target.getDrawingRect();
            checkedBounds = checked.getDrawingRect();

            if (targetBounds.intersects(checkedBounds)) {

                _inertToIntersectStore(store, target.getTitle(), checked.getTitle());
            }
        }
    }

    return store;
}

function getMarkersByStore(store) {

    var intersectMarkers = [];

    for (var i = 0; i < store.length; i++) {

        intersectMarkers[i] = [];

        for (var j = 0; j < store[i].length; j++) {
            intersectMarkers[i].push(markersMap[store[i][j]]);
        }
    }

    return intersectMarkers;
}

function getIntersectMarkerBounds(intersectMarkers) {

    var boundsList = [], bounds;

    for (var i = 0; i < intersectMarkers.length; i++) {

        for (var j = 0; j < intersectMarkers[i].length; j++) {

            if (j === 0) {
                bounds = intersectMarkers[i][j].getDrawingRect();
            } else {
                bounds = bounds.union(intersectMarkers[i][j].getDrawingRect());
            }
        }

        bounds = _pixelBoundsToLatLngBounds(map, bounds);
        boundsList.push(bounds);
    }

    return boundsList;
}

function resetMarkers(markers) {

    for (var i = 0; i < markers.length; i++) {
        var icon = markers[i].getIcon();
        icon.url = MARKER_ICON_URL;
        markers[i].setIcon(icon);
    }
}

function highlightMarkers(intersectMarkers) {

    for (var i = 0; i < intersectMarkers.length; i++) {

        for (var j = 0; j < intersectMarkers[i].length; j++) {

            var icon = intersectMarkers[i][j].getIcon();
            icon.url = MARKER_HIGHLIGHT_ICON_URL;
            intersectMarkers[i][j].setIcon(icon);
        }
    }
}

function _pixelBoundsToLatLngBounds(map, pixelBounds) {

    var zoom = map.getZoom();
    var proj = map.getProjection();

    var min = pixelBounds.getMin();
    var max = pixelBounds.getMax();

    min = proj.scaleDown(min, zoom);
    max = proj.scaleDown(max, zoom);

    min = proj.fromPointToCoord(min);
    max = proj.fromPointToCoord(max);

    return new naver.maps.LatLngBounds(min, max);
}

function _uniqueArray(a) {
    return a.reduce(function(p, c) {
        if (p.indexOf(c) < 0) p.push(c);
        return p;
    }, []);
}

function _inertToIntersectStore(store, value1, value2) {

    var index1 = _has(store, value1);
    var index2 = _has(store, value2);

    if (index1 !== -1 && index2 === -1) {
        index2 = index1;
    } else if (index1 === -1 && index2 !== -1) {
        index1 = index2;
    }

    if (index1 === -1 && index2 === -1) {
        store.push([value1, value2]);
    } else {
        store[index1].push(value1);
        store[index2].push(value2);

        if (index1 !== index2) {

            var low = Math.min(index1, index2);
            var high = Math.max(index1, index2);

            store[low] = store[low].concat(store[high]);
            store.splice(high, 1);
            store[low] = _uniqueArray(store[low]);
        } else {

            store[index1] = _uniqueArray(store[index1]);
        }
    }
}

function _has(store, value) {

    var array;

    for (var i = 0; i < store.length; i++) {

        array = store[i];

        if (array.indexOf(value) !== -1) {

            return i;
        }
    }

    return -1;
}

Examples: Handling overlapping markers

Other examples of using markers

Apart from what is described above, you can use markers in various ways. Refer to the following examples.

Examples: Clustering markers

Examples: Using an event handler for multiple markers