Get image click/touch coordinates

Here's a ui_template that displays an image with a draggable overlayed icon. On either a mouse click/drag or mobile touch events, it returns the relative normalized (from 0 to 1) coordinates. template here, example flow below:


<img id="imgmap" style="position: absolute; top: 0px; left: 0px;" src="https://upload.wikimedia.org/wikipedia/en/2/26/Black_and_white_political_map_of_the_world.png" draggable="false">
<img id="imgcursor" style="position: absolute; top: 0px; left: 0px; height: 40px; width: 40px " src="http://www.pngall.com/wp-content/uploads/2017/05/Map-Marker-PNG-File.png">
<div id="coords" style="color: black; z-index: 100; pointer-events:none;"></div>

<script>

(function($scope) {

    $('#imgmap').on('touchstart touchmove',function(e){
    e.preventDefault();
    const map = document.getElementById("imgmap");
    let rect = map.getBoundingClientRect();
    let xCoordinate = ((e.touches[0].clientX - rect.left)/ (rect.right- rect.left)).toFixed(4);
    let yCoordinate = ((e.touches[0].clientY - rect.top)/(rect.bottom - rect.top)).toFixed(4);
    if (xCoordinate < 1 && xCoordinate > 0 && yCoordinate < 1 && yCoordinate > 0){
        $("#coords").text( "X: " + xCoordinate + ", Y: " + yCoordinate);
        $("#imgcursor").css( "left", (e.touches[0].clientX - rect.left) - 20 ); // offset to half of the cursor's width
        $("#imgcursor").css( "top", (e.touches[0].clientY - rect.top) - 20 );  // offset to half of the cursor's height
        $scope.send({"payload":{"coordX": xCoordinate, "coordY": yCoordinate}});
    }
    });

    $('#imgmap').on('mousemove mousedown mouseup',function(e){
    e.preventDefault();
    const map = document.getElementById("imgmap");
    let rect = map.getBoundingClientRect();
    let xCoordinate = ((e.clientX - rect.left)/ (rect.right- rect.left)).toFixed(4);
    let yCoordinate = ((e.clientY - rect.top)/(rect.bottom - rect.top)).toFixed(4);
    if (xCoordinate < 1 && xCoordinate > 0 && yCoordinate < 1 && yCoordinate > 0 && e.buttons == 1){ 
        $("#coords").text( "X: " + xCoordinate + ", Y: " + yCoordinate);
        $("#imgcursor").css( "left", (e.clientX - rect.left)  - 20); // offset to half of the cursor's width
        $("#imgcursor").css( "top", (e.clientY - rect.top) - 20 ); // offset to half of the cursor's height
        
        $scope.send({"payload":{"coordX": xCoordinate, "coordY": yCoordinate}});
    }
    });

})(scope);
</script>
[{"id":"f26a59b.bdf94a8","type":"ui_template","z":"9f1175b5.c05ee8","group":"4ba5d415.d302ec","name":"Get image click/touch coordinates","order":0,"width":"16","height":"8","format":"<img id=\"imgmap\" style=\"position: absolute; top: 0px; left: 0px;\" src=\"https://upload.wikimedia.org/wikipedia/en/2/26/Black_and_white_political_map_of_the_world.png\" draggable=\"false\">\n<img id=\"imgcursor\" style=\"position: absolute; top: 0px; left: 0px; height: 40px; width: 40px \" src=\"http://www.pngall.com/wp-content/uploads/2017/05/Map-Marker-PNG-File.png\">\n<div id=\"coords\" style=\"color: black; z-index: 100; pointer-events:none;\"></div>\n\n<script>\n\n(function($scope) {\n\n    $('#imgmap').on('touchstart touchmove',function(e){\n    e.preventDefault();\n    const map = document.getElementById(\"imgmap\");\n    let rect = map.getBoundingClientRect();\n    let xCoordinate = ((e.touches[0].clientX - rect.left)/ (rect.right- rect.left)).toFixed(4);\n    let yCoordinate = ((e.touches[0].clientY - rect.top)/(rect.bottom - rect.top)).toFixed(4);\n    if (xCoordinate < 1 && xCoordinate > 0 && yCoordinate < 1 && yCoordinate > 0){\n        $(\"#coords\").text( \"X: \" + xCoordinate + \", Y: \" + yCoordinate);\n        $(\"#imgcursor\").css( \"left\", (e.touches[0].clientX - rect.left) - 20 ); // offset to half of the cursor's width\n        $(\"#imgcursor\").css( \"top\", (e.touches[0].clientY - rect.top) - 20 );  // offset to half of the cursor's height\n        $scope.send({\"payload\":{\"coordX\": xCoordinate, \"coordY\": yCoordinate}});\n    }\n    });\n\n    $('#imgmap').on('mousemove mousedown mouseup',function(e){\n    e.preventDefault();\n    const map = document.getElementById(\"imgmap\");\n    let rect = map.getBoundingClientRect();\n    let xCoordinate = ((e.clientX - rect.left)/ (rect.right- rect.left)).toFixed(4);\n    let yCoordinate = ((e.clientY - rect.top)/(rect.bottom - rect.top)).toFixed(4);\n    if (xCoordinate < 1 && xCoordinate > 0 && yCoordinate < 1 && yCoordinate > 0 && e.buttons == 1){ \n        $(\"#coords\").text( \"X: \" + xCoordinate + \", Y: \" + yCoordinate);\n        $(\"#imgcursor\").css( \"left\", (e.clientX - rect.left)  - 20); // offset to half of the cursor's width\n        $(\"#imgcursor\").css( \"top\", (e.clientY - rect.top) - 20 ); // offset to half of the cursor's height\n        \n        $scope.send({\"payload\":{\"coordX\": xCoordinate, \"coordY\": yCoordinate}});\n    }\n    });\n\n})(scope);\n</script>","storeOutMessages":true,"fwdInMessages":true,"templateScope":"local","x":540,"y":300,"wires":[["670ae86f.3e0ce8"]]},{"id":"670ae86f.3e0ce8","type":"debug","z":"9f1175b5.c05ee8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":750,"y":300,"wires":[]},{"id":"4ba5d415.d302ec","type":"ui_group","z":"","name":"Control","tab":"47f0556b.db072c","disp":true,"width":"16","collapse":false},{"id":"47f0556b.db072c","type":"ui_tab","z":"","name":"ICM","icon":"dashboard"}]

Flow Info

Created 5 years, 10 months ago
Rating: 5 2

Owner

Actions

Rate:

Node Types

Core
  • debug (x1)
Other
  • ui_group (x1)
  • ui_tab (x1)
  • ui_template (x1)

Tags

  • touchstart
  • touchmove
  • click
  • mousemove
  • coordinates
  • ui-template
  • dashboard
  • map
  • x
  • y
Copy this flow JSON to your clipboard and then import into Node-RED using the Import From > Clipboard (Ctrl-I) menu option