João Fagner
João Fagner

Reputation: 129

How to create custom clusters showing the numbers inside the Icons - Here map Javascript API?

I created MY clustering showing my custom Icons, but how can I show the numbers on my custom clustering?

I want to show my custom marker cluster with the number inside. Does anyone have any idea?

//Global use
var vm = this;

 var dataSource = [{
    "coords": {
        "lat": "-16.41666667",
        "lng": "-39.58469444"
    }
},
{

    "coords": {
        "lat": "-17.24038900",
        "lng": "-39.00000000"

    }
},
{
    "coords": {
        "lat": "-21.52413889",
        "lng": "-42.65197222"
    }
},
{

    "coords": {
        "lat": "-5.06508333",
        "lng": "-42.72744444"
    }
},
{

    "coords": {
        "lat": "-16.31358333",
        "lng": "-48.83638889"
    }
},
{

    "coords": {
        "lat": "-20.03941667",
        "lng": "-44.25702778"
    }
},
{
    "coords": {
        "lat": "-16.76830556",
        "lng": "-43.88361111"
    }
}
];

function startClustering(map, ui, getBubbleContent, data) {
  var dataPoints = data.map(function (item) {
      return new H.clustering.DataPoint(item.coords.lat, item.coords.lng, null, item);
    });

        var clusteredDataProvider = new H.clustering.Provider(dataPoints, {
            clusteringOptions: {
            eps: 32,
            minWeight: 2
            },
            theme: CUSTOM_THEME
        });

        var layer = new H.map.layer.ObjectLayer(clusteredDataProvider);
        map.addLayer(layer);
    }

var CUSTOM_THEME = {
  getClusterPresentation: function (cluster) {
    // Get random DataPoint from our cluster
    var randomDataPoint = getPoints(cluster),
      // Get a reference to data object that DataPoint holds
    data = randomDataPoint;

    var svgMarkerStyle =
        '<div class="camera-marker-position" style="position: absolute;left: -8px;top: -8px;">' +
        '<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="26px" height="26px" version="1.1" style="shape-rendering:geometricPrecision; text-rendering:geometricPrecision; image-rendering:optimizeQuality; fill-rule:evenodd; clip-rule:evenodd"' +
        'viewBox="0 0 5400 5400"' +
        'xmlns:xlink="http://www.w3.org/1999/xlink">' +
        '<defs>' +
        '<style type="text/css"><![CDATA[.str0Camera {stroke:#00A859;stroke-width:400;stroke-miterlimit:22.9256} .fil0Camera {fill:#FEFEFE} .fil1Camera {fill:#00A859}]]></style>' +
        '</defs>' +
        '<g id="Camada_x0020_1">' +
        '<metadata id="CorelCorpID_0Corel-Layer"/>' +
        '<rect class="fil0Camera str0Camera" x="250" y="216" width="4950" height="4950" rx="724" ry="724"/>' +
        '<g id="_1548656424592">' +
        '<path class="fil1Camera" d="M3721 3165l-1 -899c-2,-218 47,-472 -217,-584 -76,-32 -148,-23 -250,-23l-1611 0c-213,0 -334,-23 -447,90 -130,128 -117,180 -117,421l0 1083c0,239 -16,297 112,425 116,116 225,94 443,94l1612 0c177,0 275,16 402,-134 102,-120 70,-267 74,-473z"/>' +
        '<path class="fil1Camera" d="M3720 2266l1 899c31,7 78,41 108,59l550 330c75,45 146,90 222,130l0 -1937c-180,95 -566,337 -767,457 -28,17 -82,55 -114,62z"/>' +
        '</g>' +
        '</g>' +
        '</svg>' +
        '</div>';

        var outerElement = document.createElement('div'),
            innerElement = document.createElement('div');
            outerElement.appendChild(innerElement);

            // Add text to the DOM element
            innerElement.innerHTML = svgMarkerStyle;

        var domIcon = new H.map.DomIcon(outerElement);

        // Create a marker from a random point in the cluster
        var clusterMarker = new H.map.DomMarker(cluster.getPosition(), {
            icon: domIcon,
        min: cluster.getMinZoom(),
        max: cluster.getMaxZoom()
        });

        clusterMarker.setData(data)
        // Show a bubble on marker click/tap
        .addEventListener('tap', onMarkerClick);

        return clusterMarker;
  },
  getNoisePresentation: function (noisePoint) {
    var svgMarkerStyle =
        '<div class="camera-marker-position" style="position: absolute;left: -8px;top: -8px;">' +
        '<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="26px" height="26px" version="1.1" style="shape-rendering:geometricPrecision; text-rendering:geometricPrecision; image-rendering:optimizeQuality; fill-rule:evenodd; clip-rule:evenodd"' +
        'viewBox="0 0 5400 5400"' +
        'xmlns:xlink="http://www.w3.org/1999/xlink">' +
        '<defs>' +
        '<style type="text/css"><![CDATA[.str0Camera {stroke:#00A859;stroke-width:400;stroke-miterlimit:22.9256} .fil0Camera {fill:#FEFEFE} .fil1Camera {fill:#00A859}]]></style>' +
        '</defs>' +
        '<g id="Camada_x0020_1">' +
        '<metadata id="CorelCorpID_0Corel-Layer"/>' +
        '<rect class="fil0Camera str0Camera" x="250" y="216" width="4950" height="4950" rx="724" ry="724"/>' +
        '<g id="_1548656424592">' +
        '<path class="fil1Camera" d="M3721 3165l-1 -899c-2,-218 47,-472 -217,-584 -76,-32 -148,-23 -250,-23l-1611 0c-213,0 -334,-23 -447,90 -130,128 -117,180 -117,421l0 1083c0,239 -16,297 112,425 116,116 225,94 443,94l1612 0c177,0 275,16 402,-134 102,-120 70,-267 74,-473z"/>' +
        '<path class="fil1Camera" d="M3720 2266l1 899c31,7 78,41 108,59l550 330c75,45 146,90 222,130l0 -1937c-180,95 -566,337 -767,457 -28,17 -82,55 -114,62z"/>' +
        '</g>' +
        '</g>' +
        '</svg>' +
        '</div>';

        var outerElement = document.createElement('div'),
            innerElement = document.createElement('div');

            outerElement.appendChild(innerElement);

            // Add text to the DOM element
            innerElement.innerHTML = svgMarkerStyle;

        var domIcon = new H.map.DomIcon(outerElement);

    var data = noisePoint.getData(),

    noiseMarker =  new H.map.DomMarker(noisePoint.getPosition(), {
        icon: domIcon,
        min: noisePoint.getMinZoom(),
      });

    noiseMarker.setData(data);

    // Show a bubble on marker click/tap
    noiseMarker.addEventListener('tap', onMarkerClick);

    return noiseMarker;
  }
};

/**
 * Boilerplate map initialization code starts below:
 */
// Helper function for getting a random point from a cluster object
function getPoints(cluster) {
  var dataPoints = [];

  cluster.forEachDataPoint(dataPoints.push.bind(dataPoints));

  return dataPoints;
}

function onMarkerClick() {
    // Get position of the "clicked" marker
    var position = this.getPosition(),
        // Get the data associated with that marker
        data = this.getData(),
        // Merge default template with the data and get HTML
        bubbleContent = getBubbleContent(data),
        bubble = onMarkerClick.bubble;

    // For all markers create only one bubble, if not created yet
    if (!bubble) {
        bubble = new H.ui.InfoBubble(position, {
        content: bubbleContent
        });
        vm.ui.addBubble(bubble);
        // Cache the bubble object
        onMarkerClick.bubble = bubble;
    } else {
        // Reuse existing bubble object
        bubble.setPosition(position);
        bubble.setContent(bubbleContent);
        bubble.open();
    }
        // Move map's center to a clicked marker
        vm.map.setCenter(position, true);
    }

    // Initialize the platform object:
    const platform = new H.service.Platform({
        app_id: 'nyKybJs4fZYfMCd7jfsx',
        app_code: 'E_xE5837hGk33SL8M6hWIg',
        useCIT: true,
        useHTTPS: true,
    });

    //Boilerplate map initialization code starts below:
    var defaultLayers = platform.createDefaultLayers();

    // initialize a map - this map is centered over Europe
    vm.map = new H.Map(document.getElementById('map'),
        defaultLayers.normal.map, {
            center: {
                lat: -19.9211375,
                lng: -43.9490617,
            },
            zoom: 6
        });

    var behavior = new H.mapevents.Behavior(new H.mapevents.MapEvents(vm.map));

    // create default UI with layers provided by the platform
    vm.ui = H.ui.UI.createDefault(vm.map, defaultLayers, 'pt-BR');

    function getCameraData() {
        vm.$http.get('/operation/camera').then((res) =>{
            vm.cameraData = res.body;   
        }).catch((res) =>{
            alertify.error(res.body.error);
        });
    }

function getBubbleContent(data) {
  return [
    '<div class="bubble">',
      '<a class="bubble-image" ',
        'style="background-image: url(', data.fullurl, ')" ',
        'href="', data.url, '" target="_blank">',
      '</a>',
      '<span>',
        // Author info may be missing
        data.author ? ['Photo by: ', '<a href="//commons.wikimedia.org/wiki/User:',
          encodeURIComponent(data.author), '" target="_blank">',
          data.author, '</a>'].join(''):'',
        '<hr/>',
        '<a class="bubble-footer" href="//commons.wikimedia.org/" target="_blank">',
          '<img class="bubble-logo" src="https://raw.githubusercontent.com/heremaps/jsfiddle-github/master/custom-cluster-theme/img/wikimedia-logo.png" />',
          '<span class="bubble-desc">',
          'Photos provided by Wikimedia Commons are <br/>under the copyright of their owners.',
          '</span>',
        '</a>',
      '</span>',
    '</div>'
  ].join('');
}

setTimeout(() => {
        //startClustering(map, ui, getBubbleContent, data);
        startClustering(vm.map, vm.ui, getBubbleContent, DataSource);
    }, 500);

  }//end

This code Works, but the problem was that I still without know how insert the numbers

Upvotes: 3

Views: 1760

Answers (2)

linuxoid
linuxoid

Reputation: 1447

Here's how I make the circles in the getClusterPresentation:

let weight = cluster.getWeight();
let radius_small = weight * 5;
let radius_big = weight * 5 + 5;
let diameter = radius_big * 2;

let clusterSvg = '<svg xmlns="http://www.w3.org/2000/svg" height="'+diameter+'" width="'+diameter+'">' + 
    '<circle cx="'+radius_big+'px" cy="'+radius_big+'px" r="'+radius_big+'px" fill="#5c85ec" fill-opacity="0.3" />' + 
    '<circle cx="'+radius_big+'px" cy="'+radius_big+'px" r="'+radius_small+'px" fill="#5c85ec" />' + 
    '<text x="'+(radius_big - 1)+'" y="'+(radius_big + 6)+'" font-size="16px" font-weight="bold" text-anchor="middle" fill="#ffffff">'+weight+'</text>' + 
    '</svg>';

Note: event.target.getPosition() must be replaced for event.target.getGeometry() in the Jithin's code.

Upvotes: 0

Jithin Krishnan
Jithin Krishnan

Reputation: 1044

You can get the weight of the clsuter and populate it into the SVG of the cluster, something as follows should work.

    var clusterSvgTemplate =
'<svg xmlns="http://www.w3.org/2000/svg" height="50px" width="50px"><circle cx="25px" cy="25px" r="20" fill="red" stroke-opacity="0.5" />' +
'<text x="24" y="32" font-size="14pt" font-family="arial" font-weight="bold" text-anchor="middle" fill="white">{text}</text>' +
'</svg>';
var clusteringProvider = new mapsjs.clustering.Provider(dataPoints, {
    min: 1,
    max: 15,
    clusteringOptions: {
        minWeight: 1,
        eps: 32
    },
    theme: {
        getClusterPresentation: function (markerCluster) {

            // Use cluster weight to change icon size:
            var svgString = clusterSvgTemplate.replace('{radius}', markerCluster.getWeight() * 5);
            svgString = svgString.replace('{text}', + markerCluster.getWeight());

            var w, h;
            var weight = markerCluster.getWeight();

            //Set cluster size depending on the weight
            if (weight <= 6)
            {
                w = 35;
                h = 35;
            }
            else if (weight <= 12) {
                w = 50;
                h = 50;
            }
            else {
                w = 75;
                h = 75;
            }

            var clusterIcon = new H.map.Icon(svgString, {
                size: { w: w, h: h },
                anchor: { x: (w/2), y: (h/2) }
            });

            // Create a marker for clusters:
            var clusterMarker = new H.map.Marker(markerCluster.getPosition(), {
                icon: clusterIcon,
                // Set min/max zoom with values from the cluster, otherwise
                // clusters will be shown at all zoom levels:
                min: markerCluster.getMinZoom(),
                max: markerCluster.getMaxZoom()
            });

            // Bind cluster data to the marker:
            clusterMarker.setData(markerCluster);

            clusterMarker.addEventListener("pointerenter", function (event) {

                var point = event.target.getPosition(),
                    screenPosition = map.geoToScreen(point),
                    t = event.target,
                    data = t.getData(),
                    tooltipContent = ""; 
                data.forEachEntry(
                    function(p) 
                    { 
                        tooltipContent += p.getPosition().lat + " " + p.getPosition().lng + "</br>";
                    }
                ); 
                infoBubble = new H.ui.InfoBubble(map.screenToGeo(screenPosition.x, screenPosition.y), { content: tooltipContent });
                ui.addBubble(infoBubble);
            });

            clusterMarker.addEventListener("pointerleave", function (event) { 
                if(infoBubble)
                {
                    ui.removeBubble(infoBubble);
                    infoBubble = null;
                }
            });             

            return clusterMarker;
        },
        getNoisePresentation: function (noisePoint) {

            // Create a marker for noise points:
            var noiseMarker = new H.map.Marker(noisePoint.getPosition(), {
                icon: noiseIcon,

                // Use min zoom from a noise point to show it correctly at certain
                // zoom levels:
                min: noisePoint.getMinZoom(),
                max: 20
            });

            // Bind cluster data to the marker:
            noiseMarker.setData(noisePoint);

            noiseMarker.addEventListener("pointerenter", function (event) { 

                var point = event.target.getPosition();
                var tooltipContent = ["Latitude: ", point.lat, ", Longitude: ", point.lng].join("");

                var screenPosition = map.geoToScreen(point);

                infoBubble = new H.ui.InfoBubble(map.screenToGeo(screenPosition.x, screenPosition.y), { content: tooltipContent });
                ui.addBubble(infoBubble);

            });
            noiseMarker.addEventListener("pointerleave", function (event) { 
                if(infoBubble)
                {
                    ui.removeBubble(infoBubble);
                    infoBubble = null;
                }
            });


            return noiseMarker;
        }
    }

});

Upvotes: 5

Related Questions