1

I am currently trying to make it so that my JavaScript file will run an <input> button that is hidden when a user places a marker on a leaflet map (or begins the process of placing it). I followed the example found here to help with this. Unfortunately, it seems that the code I added is not doing anything when I run it.

What I want to have happen: User clicks to place marker and file explorer opens up for them to select an image file.

What actually happens: The user clicks the map to place a marker and this code seems to be ignored as file explorer does not open up.

I am fairly new to HTML and JavaScript so I apologize if this is and easy to resolve issue. My code can be found below:

var map = L.map('map').setView([0, 0], 3);
var markersArray = new Array();
var marker
var counter = 0;
var markerLayer = L.layerGroup([]);
var buttons = [];

L.tileLayer('https://api.maptiler.com/maps/streets-v2/{z}/{x}/{y}.png?key=TUHtC4pfxR178kXfCmqg', {
  attribution: '<a href="https://www.maptiler.com/copyright/" target="_blank">&copy; MapTiler</a> <a href="https://www.openstreetmap.org/copyright" target="_blank">&copy; OpenStreetMap contributors</a>'
}).addTo(map)

var markerOptions = {
  draggable: false
}

function createMarkerOnClick(evt) {
  document.getElementById('imgUpload').click;
  img = document.getElementById('imgUpload').value;
  let description = prompt("Please add your description for this marker below");
  if (description == null) {
    description = "No desceiption added.";
  }
  marker = new L.Marker([evt.latlng.lat, evt.latlng.lng], markerOptions).addTo(map);
  marker.bindPopup(description);
  markersArray[counter] = marker;
  marker.addTo(markerLayer);
  markerLayer.addTo(map);
  counter++;
  toggleMarker.state('disable-markers');
}
//Delete options
function delAllMarkers() {
  for (i = 0; i < markersArray.length; i++) {
    map.removeLayer(markersArray[i]);
  }
}

function delLastMarker() {
  map.removeLayer(markersArray[counter - 1])
}


//Buttons
var toggleMarker = L.easyButton({
  states: [{
    stateName: 'enable-markers',
    icon: '<center><img src="I:\\maps\\leafmap\\location-pin.png" style="width:26px"></center>',
    title: 'Enable markers on click',
    onClick: function(control) {
      control.state('disable-markers');
      map.on('click', createMarkerOnClick);
    }
  }, {
    icon: '<center><img src="I:\\maps\\leafmap\\location-pin.png" style="width:26px"></center>',
    stateName: 'disable-markers',
    title: 'Disable markers on click',
    onClick: function(control) {
      control.state('enable-markers');
      map.off('click', createMarkerOnClick)
    }
  }]
})
buttons.push(toggleMarker);

var removeAllMarkers = L.easyButton('del-all-markers', function(btn, map) {
  delAllMarkers();
})
buttons.push(removeAllMarkers);

var removeLastMarker = L.easyButton('del-last-marker', function(btn, map) {
  delLastMarker();
})
buttons.push(removeLastMarker);

var toolbar = L.easyBar(buttons, {
  id: 'toolbar'
}).addTo(map);
.disable-markers-active {
  background-color: #FFFF99 !important;
}

#map {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
}

#imgUpload {
  position: absolute;
  top: 20px;
  right: 20px;
  padding: 10px;
  z-index: 400;
}
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.3/dist/leaflet.css" integrity="sha256-kLaT2GOSpHechhsozzB+flnD+zUyjE2LlfWPgU04xyI=" crossorigin="" />
<link rel="stylesheet" link href="https://cdn.jsdelivr.net/npm/leaflet-easybutton@2.4.0/src/easy-button.min.css" />

<div id="map">
  <input type="file" accept="image/*" name="imgUpload" id="imgUpload" onchange="loadFile(event)" hidden/>
</div>

<script src="https://unpkg.com/leaflet@1.9.3/dist/leaflet.js" integrity="sha256-WBkoXOwTeyKclOHuWtc+i2uENFpDZ9YPdf5Hf+D7ewM=" crossorigin=""></script>
<script src="https://cdn.jsdelivr.net/npm/leaflet-easybutton@2.4.0/src/easy-button.min.js"></script>
isherwood
  • 58,414
  • 16
  • 114
  • 157
Buzzkillionair
  • 319
  • 3
  • 18

1 Answers1

1

There were a few issues with your code. A full solution that meets your stated goal "User clicks to place marker and file explorer opens up for them to select an image file" is in a code snippet at the end of this post.

The general breakdown of the solution:

The first issue encountered with your code is this error:

PlaceMarkerLeaflet:1
Not allowed to load local resource: file:///I:/maps/leafmap/location-pin.png

You need to set the src attribute on an <img> tag to relative path to a file on the web server (e.g. "/images/location-pin.png") or an absolute path to a web URL like below.

`https://upload.wikimedia.org/wikipedia/commons/thumb/e/ed/Map_pin_icon.svg/1024px-Map_pin_icon.svg.png?20131230201244`

The listener function for the click event on the map (while in add marker mode toggled by the tool bar at the right of the map) needs to first trigger the input file dialog.

function addMarkerModeMapClick(evt) {
    coords = [evt.latlng.lat, evt.latlng.lng];
    fileInputEl.click(); // Open file dialog
}

In the listener function for the file input change event, the file contents of the selected image file needs to be read. After the reading the contents, call the create marker function to add the selected image file as an icon.

    fileInputEl.addEventListener('change', function () {
    // 'this' in the code below refers to the 'fileInputEl' object
    // Add first image, if available
    if (this.files.length) {
        const file = this.files[0];
        // Read the image file content. See Stack Overflow answer:
        // https://stackoverflow.com/a/34840295
        const reader = new FileReader();
        reader.onloadend = function () {
            const imgSrc = reader.result;
        }
        if (file) {
            reader.readAsDataURL(file);
        }
        // From answer:
        // https://stackoverflow.com/a/54633061
        // "clear value of target input, each time user clicks
        // on field. This ensures that the onChange event will
        // be triggered for the same file as well."
        this.value = "";
    }
});

Before calling the create marker function, one more piece of data is required: the dimensions of the selected image. These dimensions are used to make the proportions of the icon equal to the original image.

let imgWidth = 0, imgHeight = 0;
// Get the dimensions of the selected image
// https://stackoverflow.com/questions/62574897/jquery-file-input-read-image-width-height
let image = new Image();
image.src = imgSrc;
image.onload = function () {
    imgWidth = this.naturalWidth || this.width;
    imgHeight = this.naturalHeight || this.height;
    createMarker(imgSrc, imgWidth, imgHeight);
    image = undefined;
}

Everything above put together:

Display selected image as map marker icon

const map = L.map('map').setView([0, 0], 3);
const markersArray = new Array();
const markerLayer = L.layerGroup([]);
const buttons = [];

let fileInputEl = document.getElementById('imgUpload');
let coords; // Store the coordinates from the map click event
let marker;
let counter = 0;

// Set the 'src' attribute on an '<img>' tag
// to relative path to a file on the web server
// (e.g. "/images/location-pin.png")
// or an absolute path to a web URL like below.
// The 'locationPinUrl' constant is used in a
//const locationPinUrl = `/images/Map_pin_icon.png`;

const locationPinSvg = getPinSvg();

L.tileLayer('https://api.maptiler.com/maps/streets-v2/{z}/{x}/{y}.png?key=TUHtC4pfxR178kXfCmqg', {
  attribution: '<a href="https://www.maptiler.com/copyright/" target="_blank">&copy; MapTiler</a> <a href="https://www.openstreetmap.org/copyright" target="_blank">&copy; OpenStreetMap contributors</a>'
}).addTo(map);

const markerOptions = {
  draggable: false
};

// Store the latitude and longitude coordinates as it will be
// used in the 'createMarker()' function after the user selects
// a location pin image file.
function addMarkerModeMapClick(evt) {
  coords = [evt.latlng.lat, evt.latlng.lng];
  fileInputEl.click(); // Open file dialog
}

function createMarker(imgSrc, imgWidth, imgHeight) {
  let description = prompt("Please add your description for this marker below");
  if (description == null) {
    description = "No description added.";
  }

  if (imgSrc) {
    const width = 26;
    // Set the icon size based on the proportions
    // of the original location pin image file selected
    // by the user.
    const height = width * imgHeight / imgWidth;

    // https://leafletjs.com/examples/custom-icons
    const icon = L.icon({
      iconUrl: imgSrc,
      iconSize: [width, height], // size of the icon
      //shadowSize: [50, 64], // size of the shadow
      //iconAnchor: [22, 94], // point of the icon which will correspond to marker's location
      //shadowAnchor: [4, 62],  // the same for the shadow
      //popupAnchor: [-3, -76] // point from which the popup should open relative to the iconAnchor
    });

    // Add custom icon to marker options object
    markerOptions.icon = icon;
  }

  marker = new L.Marker(coords, markerOptions).addTo(map);
  marker.bindPopup(description);
  markersArray[counter] = marker;
  marker.addTo(markerLayer);
  markerLayer.addTo(map);
  counter++;
  toggleMarker.state('disable-markers');
}

//Delete options
function delAllMarkers() {
  for (i = 0; i < markersArray.length; i++) {
    map.removeLayer(markersArray[i]);
  }
}

function delLastMarker() {
  map.removeLayer(markersArray[counter - 1]);
}

// Removed the hardcoded width of the '<img>' element
// and set the width in CSS.
// Note the use of the tick (`) instead of the single quote (')
// so that the variable 'locationPinUrl' can be set inside 
// the string. See:
// https://stackoverflow.com/questions/27678052/usage-of-the-backtick-character-in-javascript

// Buttons
const toggleMarker = L.easyButton({
  states: [{
      stateName: 'enable-markers',
      //icon: `<center><img src="${locationPinUrl}"></center>`,
      icon: `<center>${locationPinSvg}></center>`,
      title: 'Enable markers on click',
      onClick: function(control) {
        control.state('disable-markers');
        map.on('click', addMarkerModeMapClick);
      }
    },
    {
      //icon: `<center><img src="${locationPinUrl}"></center>`,
      icon: `<center>${locationPinSvg}></center>`,
      stateName: 'disable-markers',
      title: 'Disable markers on click',
      onClick: function(control) {
        control.state('enable-markers');
        map.off('click', addMarkerModeMapClick);
      }
    }
  ]
});
buttons.push(toggleMarker);

const removeAllMarkers = L.easyButton('del-all-markers', function(btn, map) {
  delAllMarkers();
});
buttons.push(removeAllMarkers);

const removeLastMarker = L.easyButton('del-last-marker', function(btn, map) {
  delLastMarker();
});
buttons.push(removeLastMarker);

const toolbar = L.easyBar(buttons, {
  id: 'toolbar'
}).addTo(map);

// Add an event handler for the 'onchange' event on
// '<input type="file" />' element.

// Function taken from SO answer: https://stackoverflow.com/a/56607553
// (cancel will not trigger 'change')
fileInputEl.addEventListener('change', function() {
  // 'this' in the code below refers to the 'fileInputEl' object
  // Add first image, if available
  if (this.files.length) {
    const file = this.files[0];
    // Check if the user selected an image file
    if (!file.type.includes('image')) {
      alert("Please select an image file.");
      return;
    }
    // Read the image file content. See Stack Overflow answer:
    // https://stackoverflow.com/a/34840295
    const reader = new FileReader();
    reader.onloadend = function() {
      const imgSrc = reader.result;

      let imgWidth = 0,
        imgHeight = 0;
      // Get the dimensions of the selected image
      // https://stackoverflow.com/questions/62574897/jquery-file-input-read-image-width-height
      let image = new Image();
      image.src = imgSrc;
      image.onload = function() {
        imgWidth = this.naturalWidth || this.width;
        imgHeight = this.naturalHeight || this.height;
        createMarker(imgSrc, imgWidth, imgHeight);
        image = undefined;
      }
    }
    if (file) {
      reader.readAsDataURL(file);
    }
    // From answer:
    // https://stackoverflow.com/a/54633061
    // "clear value of target input, each time user clicks
    // on field. This ensures that the onChange event will
    // be triggered for the same file as well."
    this.value = "";
  }
});

// Map pin icon
// https://www.svgrepo.com/svg/38705/location-pin
// LICENSE: CC0 License (https://www.svgrepo.com/page/licensing#CC0)
// "The person who associated a work with this deed
// has dedicated the work to the public domain by
// waiving all of his or her rights to the work
// worldwide under copyright law, including all
// related and neighboring rights, to the extent
// allowed by law."
// "You are free: to share – to copy, distribute 
// and transmit the work"
function getPinSvg(className) {
  if (!className) {
    className = "svg-pin-icon";
  }
  return `<svg class="${className}" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="#000000" height="24px" width="20px" version="1.1" id="Capa_1" viewBox="20 0 280 280" xml:space="preserve">
            <g>
                <path d="M148.5,0C87.43,0,37.747,49.703,37.747,110.797c0,91.026,99.729,179.905,103.976,183.645   c1.936,1.705,4.356,2.559,6.777,2.559c2.421,0,4.841-0.853,6.778-2.559c4.245-3.739,103.975-92.618,103.975-183.645   C259.253,49.703,209.57,0,148.5,0z M148.5,272.689c-22.049-21.366-90.243-93.029-90.243-161.892   c0-49.784,40.483-90.287,90.243-90.287s90.243,40.503,90.243,90.287C238.743,179.659,170.549,251.322,148.5,272.689z"/>
                <path d="M148.5,59.183c-28.273,0-51.274,23.154-51.274,51.614c0,28.461,23.001,51.614,51.274,51.614   c28.273,0,51.274-23.153,51.274-51.614C199.774,82.337,176.773,59.183,148.5,59.183z M148.5,141.901   c-16.964,0-30.765-13.953-30.765-31.104c0-17.15,13.801-31.104,30.765-31.104c16.964,0,30.765,13.953,30.765,31.104   C179.265,127.948,165.464,141.901,148.5,141.901z"/>
            </g>
        </svg>`;
}
.disable-markers-active {
  background-color: #FFFF99 !important;
}

#map {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
}

#imgUpload {
  position: absolute;
  top: 20px;
  right: 20px;
  padding: 10px;
  z-index: 400;
}


/* Added the following styles so that the
    location pin image fits within the button.
    These styles override 'easy-button.css'
    loaded by the Leaflet plugin.
*/

.easy-button-button .button-state img {
  width: 100% !important;
}
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.3/dist/leaflet.css" integrity="sha256-kLaT2GOSpHechhsozzB+flnD+zUyjE2LlfWPgU04xyI=" crossorigin="" />
<link rel="stylesheet" link href="https://cdn.jsdelivr.net/npm/leaflet-easybutton@2.4.0/src/easy-button.min.css" />

<div id="map"></div>

<input type="file" accept="image/*" name="imgUpload" id="imgUpload" hidden />

<script src="https://unpkg.com/leaflet@1.9.3/dist/leaflet.js" integrity="sha256-WBkoXOwTeyKclOHuWtc+i2uENFpDZ9YPdf5Hf+D7ewM=" crossorigin=""></script>
<script src="https://cdn.jsdelivr.net/npm/leaflet-easybutton@2.4.0/src/easy-button.min.js"></script>

Display selected image within popup

The following code snippet was added per the comment thread: Instead of setting the user selected image in place of the default map marker icon, the selected image should be displayed inside the popup, inline with the description text.

const map = L.map('map').setView([0, 0], 3);
const markersArray = new Array();
const markerLayer = L.layerGroup([]);
const buttons = [];

let fileInputEl = document.getElementById('imgUpload');
let coords; // Store the coordinates from the map click event
let marker;
let counter = 0;

// Set the 'src' attribute on an '<img>' tag
// to relative path to a file on the web server
// (e.g. "/images/location-pin.png")
// or an absolute path to a web URL like below.
// The 'locationPinUrl' constant is used in a
//const locationPinUrl = `/images/Map_pin_icon.png`;

const locationPinSvg = getPinSvg();

// https://docs.maptiler.com/cloud/api/authentication-key
// https://documentation.maptiler.com/hc/en-us/articles/360020806037-How-to-protect-your-map-key
L.tileLayer('https://api.maptiler.com/maps/streets-v2/{z}/{x}/{y}.png?key=TUHtC4pfxR178kXfCmqg', {
  attribution: '<a href="https://www.maptiler.com/copyright/" target="_blank">&copy; MapTiler</a> <a href="https://www.openstreetmap.org/copyright" target="_blank">&copy; OpenStreetMap contributors</a>'
}).addTo(map);

const markerOptions = {
  draggable: false
};

// Store the latitude and longitude coordinates as it will be
// used in the 'createMarker()' function after the user selects
// a location pin image file.
function addMarkerModeMapClick(evt) {
  coords = [evt.latlng.lat, evt.latlng.lng];
  fileInputEl.click(); // Open file dialog
}

function createMarker(imgSrc) {
  let description = prompt("Please add your description for this marker below");
  // The value of the variable 'description' is 'null'
  // when the user click the 'Cancel' button in the
  // Prompt dialog box. The value of 'description' is
  // an empty string ("") when the user does not enter
  // text in the input field of the Prompt dialog box
  // but clicks the 'OK' button.
  if (description === null || description === "") {
    description = "No description added.";
  }

  //const imgElem = document.createElement('img');
  //imgElem.src = imgSrc;
  //imgElem.className = "popup-image";
  //const imgHtml = imgElem.outerHTML;

  // https://leafletjs.com/reference.html#popup
  const popupContent = `<div class="popup-image-container">
            <img class="popup-image" src="${imgSrc}" title="" />
        </div>
        <span class="popup-desc">${description}</span>`;

  marker = new L.Marker(coords, markerOptions).addTo(map);
  marker.bindPopup(popupContent);
  markersArray[counter] = marker;
  marker.addTo(markerLayer);
  markerLayer.addTo(map);
  counter++;
  toggleMarker.state('disable-markers');
}

// Delete options
function delAllMarkers() {
  for (i = 0; i < markersArray.length; i++) {
    map.removeLayer(markersArray[i]);
  }
}

function delLastMarker() {
  map.removeLayer(markersArray[counter - 1]);
}

// Removed the hardcoded width of the '<img>' element
// and set the width in CSS.
// Note the use of the tick (`) instead of the single quote (')
// so that the variable 'locationPinUrl' can be set inside 
// the string. See:
// https://stackoverflow.com/questions/27678052/usage-of-the-backtick-character-in-javascript

// Buttons
const toggleMarker = L.easyButton({
  states: [{
      stateName: 'enable-markers',
      //icon: `<center><img src="${locationPinUrl}"></center>`,
      icon: `<center>${locationPinSvg}></center>`,
      title: 'Enable markers on click',
      onClick: function(control) {
        control.state('disable-markers');
        map.on('click', addMarkerModeMapClick);
      }
    },
    {
      //icon: `<center><img src="${locationPinUrl}"></center>`,
      icon: `<center>${locationPinSvg}></center>`,
      stateName: 'disable-markers',
      title: 'Disable markers on click',
      onClick: function(control) {
        control.state('enable-markers');
        map.off('click', addMarkerModeMapClick);
      }
    }
  ]
});
buttons.push(toggleMarker);

const removeAllMarkers = L.easyButton('del-all-markers', function(btn, map) {
  delAllMarkers();
});
buttons.push(removeAllMarkers);

const removeLastMarker = L.easyButton('del-last-marker', function(btn, map) {
  delLastMarker();
});
buttons.push(removeLastMarker);

const toolbar = L.easyBar(buttons, {
  id: 'toolbar'
}).addTo(map);

// Add an event handler for the 'onchange' event on
// '<input type="file" />' element.

// Function taken from SO answer: https://stackoverflow.com/a/56607553
// (cancel will not trigger 'change')
fileInputEl.addEventListener('change', function() {
  if (this.files.length === 0) {
    return;
  }

  // 'this' in the code below refers to the 'fileInputEl' object
  // Add first image, if available
  const file = this.files[0];

  // From answer:
  // https://stackoverflow.com/a/54633061
  // "clear value of target input, each time user clicks
  // on field. This ensures that the onChange event will
  // be triggered for the same file as well."
  this.value = "";

  // Check if the user selected an image file
  if (!file.type.includes('image')) {
    alert("Please select an image file.");
    return;
  }
  if (!file) {
    return;
  }
  // Read the image file content. See Stack Overflow answer:
  // https://stackoverflow.com/a/34840295
  const reader = new FileReader();
  reader.onloadend = function() {
    // The value of 'reader.result' is the image itself
    createMarker(reader.result);
  }
  // https://developer.mozilla.org/en-US/docs/Web/API/FileReader/readAsDataURL
  // "The readAsDataURL method is used to read the contents
  // of the specified Blob or File. When the read operation
  // is finished, the readyState becomes DONE, and the 
  // loadend is triggered."
  reader.readAsDataURL(file);
});

// Map pin icon
// https://www.svgrepo.com/svg/38705/location-pin
// LICENSE: CC0 License (https://www.svgrepo.com/page/licensing#CC0)
// "The person who associated a work with this deed
// has dedicated the work to the public domain by
// waiving all of his or her rights to the work
// worldwide under copyright law, including all
// related and neighboring rights, to the extent
// allowed by law."
// "You are free: to share – to copy, distribute 
// and transmit the work"
function getPinSvg(className) {
  if (!className) {
    className = "svg-pin-icon";
  }
  return `<svg class="${className}" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="#000000" height="24px" width="20px" version="1.1" id="Capa_1" viewBox="20 30 280 280" xml:space="preserve">
            <g>
                <path d="M148.5,0C87.43,0,37.747,49.703,37.747,110.797c0,91.026,99.729,179.905,103.976,183.645   c1.936,1.705,4.356,2.559,6.777,2.559c2.421,0,4.841-0.853,6.778-2.559c4.245-3.739,103.975-92.618,103.975-183.645   C259.253,49.703,209.57,0,148.5,0z M148.5,272.689c-22.049-21.366-90.243-93.029-90.243-161.892   c0-49.784,40.483-90.287,90.243-90.287s90.243,40.503,90.243,90.287C238.743,179.659,170.549,251.322,148.5,272.689z"/>
                <path d="M148.5,59.183c-28.273,0-51.274,23.154-51.274,51.614c0,28.461,23.001,51.614,51.274,51.614   c28.273,0,51.274-23.153,51.274-51.614C199.774,82.337,176.773,59.183,148.5,59.183z M148.5,141.901   c-16.964,0-30.765-13.953-30.765-31.104c0-17.15,13.801-31.104,30.765-31.104c16.964,0,30.765,13.953,30.765,31.104   C179.265,127.948,165.464,141.901,148.5,141.901z"/>
            </g>
        </svg>`;
}
.disable-markers-active {
  background-color: #FFFF99 !important;
}

#map {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
}

#imgUpload {
  position: absolute;
  top: 20px;
  right: 20px;
  padding: 10px;
  z-index: 400;
}


/* Added the following styles so that the
    location pin image fits within the button.
    These styles override 'easy-button.css'
    loaded by the Leaflet plugin.
*/

.easy-button-button .button-state img {
  width: 100% !important;
}

.popup-image-container {
  width: auto;
  height: auto;
}


/* Auto-resize an image while maintaining aspect ratio 
    https://stackoverflow.com/questions/3029422/how-to-auto-resize-an-image-while-maintaining-aspect-ratio
    Answer: https://stackoverflow.com/a/15355474
*/

.popup-image {
  max-width: 100%;
  max-height: 100%;
  margin: auto;
  display: block;
}

.popup-desc {}
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.3/dist/leaflet.css" integrity="sha256-kLaT2GOSpHechhsozzB+flnD+zUyjE2LlfWPgU04xyI=" crossorigin="" />
<link rel="stylesheet" link href="https://cdn.jsdelivr.net/npm/leaflet-easybutton@2.4.0/src/easy-button.min.css" />

<div id="map"></div>
<input type="file" accept="image/*" name="imgUpload" id="imgUpload" hidden />

<script src="https://unpkg.com/leaflet@1.9.3/dist/leaflet.js" integrity="sha256-WBkoXOwTeyKclOHuWtc+i2uENFpDZ9YPdf5Hf+D7ewM=" crossorigin=""></script>
<script src="https://cdn.jsdelivr.net/npm/leaflet-easybutton@2.4.0/src/easy-button.min.js"></script>
Dave B
  • 1,105
  • 11
  • 17
  • hey @Dave B rather than having the uploaded image be the icon for the marker, I am actually trying to have it appear on the marker of the popup. Do you know how I would do that instead? I am having some issues while trying to adapt your code for that use since im new with Image object and FileReader objects. – Buzzkillionair Mar 21 '23 at 14:06
  • 1
    @Buzzkillionair, can you clarify "appear on the marker of the popup"? Do you mean have the image displayed inside the popup and inline with the description text? – Dave B Mar 21 '23 at 14:56
  • that is exactly what I mean! I am not sure how possible that would be though. – Buzzkillionair Mar 21 '23 at 15:08
  • 1
    @Buzzkillionair I added a second code snippet that displays the selected image within the content of the map marker popup. – Dave B Mar 21 '23 at 16:49
  • This is great ! I have selected it as the answer, however, I was wondering if you'd know why on my end it causes the marker to not be place where the user has clicked? For example, if i click on the middle of the map, it places it in North America. – Buzzkillionair Mar 22 '23 at 12:58
  • 1
    This issue is likely the result of the value of the `coords` variable (defined at the top of the code) being changed between the time a click is captured and when the coordinates are used to create the marker pin. Use `console.log` to log the value of the `coords` variable when set by the code `coords = [evt.latlng.lat, evt.latlng.lng]` in the function `addMarkerModeMapClick()`. The value of `coords` is then used in the `createMarker()` function in the line `marker = new L.Marker(coords, markerOptions).addTo(map);`. – Dave B Mar 22 '23 at 14:53
  • 1
    Another debug path to take is to click close to southeast corner of Africa. This is where the equator meets the prime meridian. (https://en.wikipedia.org/wiki/Meridian_%28geography%29) The coordinates will be closest to the value of `0,0`. When the L.Marker line is executed, the `coords` variable should still remain close to `[0,0]`. If not, some code is changing the value of the `coords` variable. – Dave B Mar 22 '23 at 14:57
  • It seems like the value of the coordinates is changed between when it is set and when the marker is placed. It seems like the marker is always placed to the north west of where I click. If I zoom in and click, the amount the marker is off target is reduced as well. – Buzzkillionair Mar 22 '23 at 16:06
  • 1
    Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/252701/discussion-between-dave-b-and-buzzkillionair). – Dave B Mar 22 '23 at 17:13