100DaysOfCode

Solutions Day 11-15: 100DaysOfCode

By Shruti Kuber | 17 April 2020

Week 3 of #100DaysOfCodeWithHERE! If you have no idea what I'm talking about, take a look at this blog which will tell you everything about #100DaysOfCode. In this blog, I will cover solutions for days 11 through 15. If you have missed the solutions for days 0-5 and days 6-10, you can read them in my previous blogs or in the video format.
Let's begin!

Day 11/100

In the last few days, we've rendered a map, placed a marker, created an event to click on the map and get the position from the screen. On day 11, we will put a marker as an image and use the data property of the marker. Take a look at this tutorial to add a custom marker to your map.
The image marker works in the same way as the SVG marker. Instead of the SVG icon name, you pass the path to the image in the object Icon. While you are at it, use the property data to set data to this marker to display it in the next tasks


<script>
...
var imageIcon = new H.map.Icon('robot.png'); // path of the stored image

// Add event listener:
map.addEventListener('tap', function(evt) {
    // Log 'tap' and 'mouse' events:
    let pointer = evt.currentPointer;
    let pointerPosition = map.screenToGeo(pointer.viewportX, pointer.viewportY);
    let pointerMarker = new H.map.Marker(pointerPosition,{icon:imageIcon}); 
    pointerMarker.setData("I'm Here");  // using function setData to set the property data of the map object 'marker'
    map.addObject(pointerMarker);
         
});
</script>

Day 12/100

Once we have set the data, we need a way to display it. In this task, we will display this data in an infobubble. Infobubble is a UI element where you can set the position of the bubble along with properties like content and state. You can find all the properties in the API reference for the Interactive Maps API documentation. Let's combine the task for day 11 and 12 and look at the code snippet.


<script>
...


var imageIcon = new H.map.Icon('robot.png');


// Add event listener:
map.addEventListener('tap', function(evt) {
    if(evt.target instanceof H.map.Marker){  // checking if the tapped obeject on the map is already a marker
        var bubble =  new H.ui.InfoBubble(evt.target.getGeometry(), {
        // read custom data
        content: evt.target.getData()  // data set while adding the marker object 
        });
        // show info bubble
        ui.addBubble(bubble);
    }
    else{
        // Log 'tap' and 'mouse' events:
        let pointer = evt.currentPointer;
        let pointerPosition = map.screenToGeo(pointer.viewportX, pointer.viewportY);
        let pointerMarker = new H.map.Marker(pointerPosition,{icon:imageIcon}); 
        pointerMarker.setData("I'm Here");
        map.addObject(pointerMarker);
    }  
         
});

</script>

Day 13/100

Before you can drag the marker, you need to make the marker volatile and enable the property 'draggable'.


<script>
...

        let pointerMarker = new H.map.Marker(pointerPosition,{icon:imageIcon,volatility:true}); 
        pointerMarker.draggable = true;

</script>

Dragging a marker is basically 3 steps. You start dragging the marker, you take it to a new position and then you place it at the new position by releasing the clicked button. This implies that these are 3 distinct events and you need to write event listeners for all 3 events.
The first event is 'dragstart'. Here you need to disable the default behavior on drag and calculate the offset between the current and new coordinates. Next is the 'drag' event itself where you provide this offset to your marker and move it's position. The third part is 'dragend' where you enable the default behavior of the map back again.


<script>
...
function clickDragMarkers(map, behavior){

    // disable the default draggability of the underlying map
    // and calculate the offset between mouse and target's position
    // when starting to drag a marker object:
    map.addEventListener('dragstart', function(ev) {
        var target = ev.target,
            pointer = ev.currentPointer;
        if (target instanceof H.map.Marker) {
        var targetPosition = map.geoToScreen(target.getGeometry());
        target['offset'] = new H.math.Point(pointer.viewportX - targetPosition.x, pointer.viewportY - targetPosition.y);
        behavior.disable();
        }
    }, false);


    // re-enable the default draggability of the underlying map
    // when dragging has completed
    map.addEventListener('dragend', function(ev) {
        var target = ev.target;
        if (target instanceof H.map.Marker) {
        behavior.enable();
        }
    }, false);

    // Listen to the drag event and move the position of the marker
    // as necessary
    map.addEventListener('drag', function(ev) {
        var target = ev.target,
            pointer = ev.currentPointer;
        if (target instanceof H.map.Marker) {
        target.setGeometry(map.screenToGeo(pointer.viewportX - target['offset'].x, pointer.viewportY - target['offset'].y));
        }
    }, false);

}

clickDragMarkers(map, behavior);

</script>

Day 14/100

Drawing a circle is kind of a breather after the slightly bigger task with the marker dragging. Like drawing a circle with your hand or in a drawing application, here too you need only two things: a center and the radius. The task is to center the circle where you end the dragging of the marker. This is a hint that we will add the circle in the 'dragend' event listener. As for the radius, it is represented in meters. This is a nice way to highlight areas in proximity based on distance.


<script>
    function clickDragMarkers(map, behavior){
        ...
        // re-enable the default draggability of the underlying map
        // when dragging has completed
        map.addEventListener('dragend', function(ev) {
            var target = ev.target;
            if (target instanceof H.map.Marker) {

                var circle = new H.map.Circle(target.getGeometry(), 10000);
                // Add the circle to the map:
                map.addObject(circle);
                behavior.enable();
            }
        }, false);
    }

</script>

Day 15/100

A circle is a geo shape, an object of the map where more shapes like rectangle, polygon, polyline can also be drawn. These geo shapes have points of the type 'geometry', and distances in meters. You can read about all the geo shapes in the JS API documentation under the Map Objects > Geo Shapes. These geo shapes, like the other map objects like a marker, can also be customized. As task for day 15, we will change the fill color, the border color and thickness of the circle. All of this is possible with the property style of the geo shapes.


    <script>
        ...
        var circleStyle ={
            fillColor: 'RGBA(153, 233, 242, 0.5)',strokeColor: 'RGB(11, 114, 133)',
            lineWidth:3
        };

        function clickDragMarkers(map, behavior){
            ...
            // re-enable the default draggability of the underlying map
            // when dragging has completed
            map.addEventListener('dragend', function(ev) {
                var target = ev.target;
                if (target instanceof H.map.Marker) {
    
                    var circle = new H.map.Circle(target.getGeometry(), 10000,{style: circleStyle});
                    // Add the circle to the map:
                    map.addObject(circle);
                    behavior.enable();
                }
            }, false);
        }
    
    </script>
    

Hope you enjoyed this week of 100DayOfCodeWithHERE. Keep following us on Twitter for more tasks and complete all 100 days. If you want to watch the video version of these solutions, take a look at our playlist for 100DaysOfCode on YouTube.
Happy coding!