Web Analytics Made Easy -
StatCounter Javascript dragging map images issue - CodingForum

Announcement

Collapse
No announcement yet.

Javascript dragging map images issue

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Javascript dragging map images issue

    Attempting to make a draggable zoomed in image of a map with a preview showing whole map in the top right with a highlighted area that shows which part of the part is currently being viewed.

    The main draggable image works, but struggling to get the highlighted area on the smaller map to move?

    <div id="mapWrapper">
    <div id="mapImage">
    <div id="mapAll">
    <div id="mapHighlight"></div>
    </div>
    </div>
    </div>
    <script type="text/javascript">

    var draggable = function(element) {
    element.addEventListener('mousedown', function(e) {
    e.stopPropagation();
    if (e.target != element)
    return;
    var offsetX = e.pageX - element.offsetLeft;
    var offsetY = e.pageY - element.offsetTop;
    function move(e) {
    var mapImage = document.getElementById('mapImage');
    var width = 2560-mapImage.clientWidth;
    var height = 2043-mapImage.clientHeight;
    element.style.left = (e.pageX - offsetX) + 'px';
    element.style.top = (e.pageY - offsetY) + 'px';
    var mapHighlight = document.getElementById('mapHighlight');
    var width = 45-mapHighlight.clientWidth;
    var height = 30-mapHighlight.clientHeight;
    element.style.left = (e.pageX - offsetX) + 'px';
    element.style.top = (e.pageY - offsetY) + 'px';
    }
    function stop(e) {
    document.removeEventListener('mousemove', move);
    document.removeEventListener('mouseup', stop);
    }
    document.addEventListener('mousemove', move);
    document.addEventListener('mouseup', stop);
    });
    }

    function init() {
    var mapImage = document.getElementById('mapImage');
    draggable(mapImage);
    var mapHighlight = document.getElementById('mapHighlight');
    draggable(mapHighlight);
    }

    </script>

    <style media="screen" type="text/css">
    #mapWrapper { position:relative;overflow:hidden;border:1px solid #ccc;max-width:100%;min-width:460px;min-height:400px;max-height:60%; background-color:#6aadda; }
    #mapImage { overflow:hidden; width:2560px; height:2043px; background-color:#6aadda; position:absolute; background-image:url('world-map.jpg.jpg'); }
    #mapAll { overflow:hidden; border:1px solid #ccc; width:200px; height:160px; background-color:#6aadda; background-image:url('world-map.jpg-thumbnail'); position:absolute; top:20px; right:20px; float:right; z-index:99;}
    #mapHighlight { position:abolute; border:2px solid red; height:30px; width:45px; z-index:100; }
    </style>

  • #2
    Interesting issue! I would like to create a test page but would need the images for doing so. Can you provide them, e. g. as attachments?

    Comment


    • #3
      The main map screen is working fine, it's the small thumbnail with a highlighted area, which I can not get to work
      Code:
      <div id="mapWrapper">
      <div id="mapImage">
      <div id="mapAll">
      <div id="mapHighlight"></div>
      </div>
      </div>
      </div>
      <script type="text/javascript">
      
      var draggable = function(element) {
      element.addEventListener('mousedown', function(e) {
      e.stopPropagation();
      if (e.target != element)
      return;
      var offsetX = e.pageX - element.offsetLeft;
      var offsetY = e.pageY - element.offsetTop;
      function move(e) {
      var mapImage = document.getElementById('mapImage');
      var width = 2560-mapImage.clientWidth;
      var height = 2043-mapImage.clientHeight;
      element.style.left = (e.pageX - offsetX) + 'px';
      element.style.top = (e.pageY - offsetY) + 'px';
      var mapHighlight = document.getElementById('mapHighlight');
      var width = 45-mapHighlight.clientWidth;
      var height = 30-mapHighlight.clientHeight;
      element.style.left = (e.pageX - offsetX) + 'px';
      element.style.top = (e.pageY - offsetY) + 'px';
      }
      function stop(e) {
      document.removeEventListener('mousemove', move);
      document.removeEventListener('mouseup', stop);
      }
      document.addEventListener('mousemove', move);
      document.addEventListener('mouseup', stop);
      });
      }
      
      function init() {
      var mapImage = document.getElementById('mapImage');
      draggable(mapImage);
      var mapHighlight = document.getElementById('mapHighlight');
      draggable(mapHighlight);
      }
      
      </script>
      
      <style media="screen" type="text/css">
      #mapWrapper { position:relative;overflow:hidden;border:1px solid #ccc;max-width:100%;min-width:460px;min-height:400px;max-height:60%; background-color:#6aadda; }
      #mapImage { overflow:hidden; width:2560px; height:2043px; background-color:#6aadda; position:absolute; background-image:url('https://s13.postimg.org/87bng72sn/world_map.jpg'); }
      #mapAll { overflow:hidden; border:1px solid #ccc; width:200px; height:160px; background-color:#6aadda; background-image:url('https://s18.postimg.org/dz1nzl72x/world_map_thumbnail.jpg'); position:absolute; top:20px; right:20px; float:right; z-index:99;}
      #mapHighlight { position:abolute; border:2px solid red; height:30px; width:45px; z-index:100; }
      </style>

      Comment


      • #4
        First, there is an error in #mapHighlight, typo in the position: abolute (absolute).

        This is what I did, see if this is what you need. (starting from style)

        Code:
        <style media="screen" type="text/css">
        #mapWrapper { position:relative;overflow:hidden;border:1px solid #ccc;max-width:100%;min-width:460px;min-height:400px;max-height:60%; background-color:#6aadda; }
        #mapImage { overflow:hidden; width:2560px; height:2043px; background-color:#6aadda; position:absolute; background-image:url('https://s13.postimg.org/87bng72sn/world_map.jpg'); }
        
        /* #mapAll { overflow:hidden; border:1px solid #ccc; width:200px; height:160px; background-color:#6aadda; background-image:url('https://s18.postimg.org/dz1nzl72x/world_map_thumbnail.jpg'); position:absolute; top:20px; right:20px; float:right; z-index:99;}
        #mapHighlight { position:abolute; border:2px solid red; height:30px; width:45px; z-index:100; }
        */
        
        #mapHighlight { position:absolute; border:2px solid red; height:30px; width:45px; z-index:100; background-image:url('https://s18.postimg.org/dz1nzl72x/world_map_thumbnail.jpg'); }
        </style>
        I commented out mapAll's style, then forced the background-image of mapHighlight.

        Comment


        • #5
          I figured out this, which seems to work fine:
          Code:
                  <div id="mapWrapper">
                      <div id="mapAll">
                          <div id="mapHighlight"></div>
                      </div>
                      <div id="mapImage">
                      </div>
                  </div>
                  <img id="refimg" src="https://s13.postimg.org/87bng72sn/world_map.jpg">
                  <style media="screen" type="text/css">
                      #mapWrapper { position:relative;overflow:hidden;border:1px solid #ccc;width:501px;height:400px; background-color:#6aadda; }
                      #mapImage { overflow:hidden; width:2560px; height:2043px; background-color:#6aadda; position:absolute; background-image:url('https://s13.postimg.org/87bng72sn/world_map.jpg'); }
                      #mapAll { overflow:hidden; border:1px solid #ccc; width:200px; height:160px; background-color:#6aadda; background-image:url('https://s18.postimg.org/dz1nzl72x/world_map_thumbnail.jpg'); position:absolute; top:20px; right:20px; z-index:99;}
                      #mapHighlight { position:absolute; border:2px solid red; height:30px; width:45px; z-index:100; }
                  </style>
                  <script type="text/javascript">
                      var factor;
                      var draggable = function (element) {
                          element.addEventListener('mousedown', function (e) {
                              e.stopPropagation();
                              if (e.target != element)
                                  return;
                              var offsetX = e.pageX - element.offsetLeft;
                              var offsetY = e.pageY - element.offsetTop;
          
                              function move(e) {
                                  var mapImage = document.getElementById('mapImage');
                                  element.style.left = (e.pageX - offsetX) + 'px';
                                  element.style.top = (e.pageY - offsetY) + 'px';
                                  var xHighlight = -(e.pageX - offsetX) * factor;
                                  var yHighlight = -(e.pageY - offsetY) * factor;
                                  var mapHighlight = document.getElementById('mapHighlight');
                                  mapHighlight.style.left = xHighlight + "px";
                                  mapHighlight.style.top = yHighlight + "px";
                                  //var width = 45 - mapHighlight.clientWidth;
                                  //var height = 30 - mapHighlight.clientHeight;
                                  element.style.left = (e.pageX - offsetX) + 'px';
                                  element.style.top = (e.pageY - offsetY) + 'px';
                              }
          
                              function stop(e) {
                                  document.removeEventListener('mousemove', move);
                                  document.removeEventListener('mouseup', stop);
                              }
                              document.addEventListener('mousemove', move);
                              document.addEventListener('mouseup', stop);
                          });
                      }
          
                      function init() {
                          var mapImage = document.getElementById('mapImage');
                          var mapAll = document.getElementById("mapAll");
                          var mapHighlight = document.getElementById('mapHighlight');
                          draggable(mapImage);
                          draggable(mapHighlight);
                          var refimg = document.getElementById("refimg");
                          var wlarge = refimg.width;
                          var wthumb = mapAll.offsetWidth;
                          factor = wthumb / wlarge;
                          factor2 = mapWrapper.offsetWidth / wlarge;
                          mapHighlight.style.width = mapAll.offsetWidth * factor2 + "px";
                          mapHighlight.style.height = mapAll.offsetHeight * factor2 + "px";
                          refimg.style.display = "none";
                      }
                      init();            
                  </script>
          Limitation: I set the wrapper to fixed dimensions having the same aspect ratio as the image. If the aspect ration is not kept you would have to use diffent factor2 variables for x and y.

          Comment


          • #6
            Thanks Sempervivum,
            The smaller map highlight area moves now!,
            The issue now is attempting to have the highlight move together with the main view, I have searched for code trying to find where the move drag effects 2 images but not been successful yet.

            So how to make an image from a move drag on a different image?

            Comment


            • #7
              This should work as intended. Because both draggable objects have to be synced, the seperate instantiation of them as a draggable object was making it complicated. So I rewrote to script to have them combined.
              Code:
              <!DOCTYPE html>
              
              <html>
              <head>
              <style media="screen" type="text/css">
              /*
              html, body{
               height: 100%;
              }
              */
              #mapWrapper {
               position: relative;
               overflow: hidden;
               border: 1px solid #ccc;
               width: 100%;
               height: 60%;
               min-width: 460px;
               min-height: 400px;
               max-width: 100%;
               max-height: 60%;
               background-color: #6aadda;
              }
              
              #mapImage {
               width: 2560px;
               height: 2048px;								/**/
               background-color: #6aadda;
               background-image: url('https://s13.postimg.org/87bng72sn/world_map.jpg');
               background-size: contain;
               background-repeat: no-repeat;
              position: absolute;
              }
              
              #mapAll {
               overflow: hidden;
               border: 1px solid #ccc;
               width: 200px;
               height: 160px;
               position: absolute;
               top: 20px;
               right: 20px;
               z-index: 99;
               background-color: #6aadda;
               background-image: url('https://s18.postimg.org/dz1nzl72x/world_map_thumbnail.jpg');
               background-size: contain;
               background-repeat: no-repeat;
              }
              
              #mapHighlight {
               position: absolute;
               border: 2px solid red;
              /* dimensions relative to #mapWrapper
               height: 30px;
               width: 45px;
              */
               z-index: 100;
              }
              
              </style>
              </head>
              
              <body>
              
              <div id="mapWrapper">
              <div id="mapAll"><div id="mapHighlight"></div></div>
              <div id="mapImage"></div>
              </div>
              
              <script>
              
              (function() {
               var mw = document.getElementById('mapWrapper'),
                   ma = document.getElementById('mapAll'),
                   mi = document.getElementById('mapImage'),
                   hl = document.getElementById('mapHighlight'),
                   factor = mi.clientWidth / ma.clientWidth,
                   offsetX,
                   offsetY,
                   listener;
              
               window.addEventListener('resize', setMapHighlight);
               mi.addEventListener('mousedown', down);
               hl.addEventListener('mousedown', down);
              
               setMapHighlight();
              
               function setMapHighlight() {
                var border = parseInt(window.getComputedStyle(hl).borderLeftWidth); // assuming equal width borders
                hl.style.width =  -2 * border + mw.clientWidth / factor + 'px';
                hl.style.height = -2 * border + mw.clientHeight / factor + 'px';
               };
              
               function down(e){
                e.preventDefault();
                e.stopPropagation();
                offsetX = e.pageX - e.target.offsetLeft;
                offsetY = e.pageY - e.target.offsetTop;
                listener = move.bind(this);
                document.addEventListener('mousemove', listener);
                document.addEventListener('mouseup', stop);
               };
              
               function stop(e) {
                document.removeEventListener('mousemove', listener);
                document.removeEventListener('mouseup', stop);
               };
              
               function move(e) {
                if(e.target != this){
                 return;
                }
                var a, b, c, d, e, f,
                    left = e.pageX - offsetX,
                    top = e.pageY - offsetY;
              
                if(this == mi){
                 a = 1;
                 b = -factor;
                 c = 0;
                 d = -(mi.clientWidth - mw.offsetWidth);
                 e = 0;
                 f = -(mi.clientHeight - mw.offsetHeight);
                }
              
                if(this == hl){
                 a = -factor;
                 b = 1;
                 c = ma.clientWidth - hl.offsetWidth;
                 d = 0
                 e = ma.clientHeight - hl.offsetHeight;
                 f = 0;
                }
              
                left = Math.min(left, c);
                left = Math.max(left, d);
                top  = Math.min(top, e);
                top  = Math.max(top, f);
              
                mi.style.left = left * a + 'px';
                mi.style.top  = top  * a + 'px';
                hl.style.left = left / b + 'px';
                hl.style.top  = top  / b + 'px';
               };
              }());
              
              </script>
              </body>
              </html>
              Last edited by Goos; Oct 5, 2016, 05:15 PM. Reason: Fixed code after testing in MS Edge. Changed .getComputedStyle(hl).borderWidth); to .getComputedStyle(hl).borderLeftWidth

              Comment


              • #8
                Hallo Goos, this script does exactly the same as mine does.
                Hallo JosephM, I don't understand what's the remaining issue. You write:
                The issue now is attempting to have the highlight move together with the main view, I have searched for code trying to find where the move drag effects 2 images but not been successful yet.

                So how to make an image from a move drag on a different image?
                but I don't understand what you mean. Was quite sure that what my script and Gooses do is what you wished.

                Comment


                • #9
                  Hi Sempervivum, when I tried your script the large map and the minimap highlight were draggable but didn't move in sync and the dimensions of the highlight were incorrect. I noticed the cause was refimg.clientWidth returning 0 (meaning the image hadn't loaded yet) and therfor factor and factor2 became NaN. I fixed that by changing init() to document.getElementById("refimg").onload = init; but it only synced the position of the highlight when dragging the large map, not the other way around.
                  When I tried to fix that I found the double call to the function 'draggable' was complicating things. So I rewrote the script to have all functionality inside a single wrapper, added boundaries to the draggable objects and a function to resize the minimap highlight when the window is resized.

                  PS. Just tried my code in ms Edge and noticed the dimensions of the minimap highlight are not calculated correctly, so I made a small change to my code.
                  Last edited by Goos; Oct 5, 2016, 05:17 PM.

                  Comment


                  • #10
                    I noticed the cause was refimg.clientWidth returning 0 (meaning the image hadn't loaded yet) and therfor factor and factor2 became NaN.
                    Yes, you are right, placing the script below the definition of the img tag is not sufficient as the dimensions are available only when the image is loaded.

                    Did your script work finally?
                    Last edited by Sempervivum; Oct 5, 2016, 05:44 PM.

                    Comment


                    • #11
                      PS:
                      it only synced the position of the highlight when dragging the large map, not the other way around.
                      I wasn't aware of this requirement.

                      Comment

                      Working...
                      X