Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 5 of 5
  1. #1
    New to the CF scene
    Join Date
    May 2011
    Posts
    3
    Thanks
    2
    Thanked 0 Times in 0 Posts

    best way to create an interactive map with javascript

    I need to create an interactive map similar to the one on this site:
    http://viewers-guide.hbo.com/game-of-thrones/#!/map/

    It is a map of a fictional area ( a real area but there are fictional
    buildings and characters on it) so I don't think google maps plugins
    are suitable.

    I don't want to reinvent the wheel, so if anybody has a good
    suggestion of a good jquery/javascript solution for interactive maps,
    please refer me to the relevant information.

    In other words, I need a map where by clicking the objects on the map,
    a popup window pops up with additional information about the 'scene'
    or a 'character'.
    In addition, the map will be dark from the beginning and more and more
    sites and characters will be revealed on it every week.
    Thanks for any tips!

  • #2
    Senior Coder
    Join Date
    Apr 2011
    Location
    London, England
    Posts
    2,120
    Thanks
    15
    Thanked 354 Times in 353 Posts
    Here is a straight-forward example which uses HTML image maps and a little bit of JavaScript with this code:
    Code:
    <img src="image.gif" alt="Image" width="367" height="106" border="0" usemap="#mapname"><br>
    <br>
    <form name="myform">
    <input type="text" name="display" size="20">
    </form>
    </div>
    
    <script language="javascript">
    function showtext(place){
        document.myform.display.value = place
    }
    </script>
    
    <map name="mapname">
    <area shape="polygon" onMouseOver="showtext('Cash_Register')" onMouseOut="showtext('')" alt="Cash" coords="94,10,95,25" href="file1.html">
    <area shape="polygon" onMouseOver="showtext('Cellular_Phone')" onMouseOut="showtext('')" alt="Cell Phone" coords="206,2,209,19" href="file2.html">
    <area shape="polygon" onMouseOver="showtext('Toy_Box')" onMouseOut="showtext('')" alt="box" coords="356,25,359,75" href="file3.html">
    <area shape="default" nohref>
    </map>
    This could be modified to also use 'onClick' to produce popup windows or tooltips.

    I noticed a number of JS/jQuery plug-ins when searching but the basis for them still seems to be HTML image maps.
    "I'm here to save your life. But if I'm going to do that, I'll need total uninanonynymity." Me Myself & Irene.
    Validate your HTML and CSS

  • Users who have thanked AndrewGSW for this post:

    agkn0001 (05-23-2011)

  • #3
    New to the CF scene
    Join Date
    May 2011
    Posts
    3
    Thanks
    2
    Thanked 0 Times in 0 Posts

    image maps

    thanks.
    I still haven't decided whether I want to develop my own plugin for this specific task, or use an existing more generic solution, such as jmapping, or openlayers, or something like this: /www.gethifi.com/blog/a-jquery-plugin-for-zoomable-interactive-maps#zip.
    i guess I will have to start with deciding on all the functionalities I need first but image maps seem like a good option.

  • #4
    Senior Coder
    Join Date
    Mar 2005
    Location
    Portsmouth UK
    Posts
    4,522
    Thanks
    3
    Thanked 508 Times in 495 Posts
    Code:
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    
    <head>
      <title></title>
    <style type="text/css">
    /*<![CDATA[*/
    
    #tst {
      position:absolute;overflow:hidden;left:100px;top:100px;width:600px;height:500px;border:solid red 1px;
    }
    
    .img {
      position:absolute;left:-600px;top:-100px;width:2800px;height:3076px;border:solid red 1px;
    }
    
    .img IMG {
      float:left;
    }
    
    #nav {
      position:absolute;z-Index:2;left:0px;top:308px;width:175px;height:192px;border:solid red 1px;background-Image:url(http://i.cdn.hbo.com/custom-assets/enrichments/series/game-of-thrones/images/map-navigator.jpg);
    }
    
    .nav {
      border:solid red 1px;
    }
    
    .m1 {
      position:absolute;width:80px;height:20px;border:solid red 1px;background-Color:#FFFFCC;
    }
    
    .m2 {
      position:absolute;width:80px;height:20px;border:solid red 1px;background-Color:#FF3366;
    }
    
    .pop {
      position:absolute;visibility:hidden;width:200px;height:120px;border:solid red 1px;background-Color:#FFFFCC;
    }
    
    /*]]>*/
    </style>
    
    
    </head>
    
    <body>
     <div id="tst" >
      <div class="img" >
       <img src="http://i.cdn.hbo.com/custom-assets/enrichments/series/game-of-thrones/images/map/x2-images-3-1.png" />
       <img src="http://i.cdn.hbo.com/custom-assets/enrichments/series/game-of-thrones/images/map/x2-images-3-2.png"/>
       <img src="http://i.cdn.hbo.com/custom-assets/enrichments/series/game-of-thrones/images/map/x2-images-3-3.png" />
       <img src="http://i.cdn.hbo.com/custom-assets/enrichments/series/game-of-thrones/images/map/x2-images-3-4.png" />
       <div id="pop1" class="pop" >Pop 1</div>
       <div id="pop2" class="pop" >Pop 2</div>
      </div>
      <div id="nav" >
       <div class="nav" ></div>
      </div>
     </div>
    
    <script type="text/javascript">
    /*<![CDATA[*/
    // MapNavigator (23-May-2011) DRAFT
    // by Vic Phillips http://www.vicsjavascripts.org.uk
    
    function zxcMapNavigator(o){
     var pobj=document.getElementById(o.ID),img=pobj.getElementsByTagName('DIV')[0],nav=document.getElementById(o.NavID),nobj=nav.getElementsByTagName('DIV')[0],r=img.offsetWidth/nav.offsetWidth,marks=o.Markers,mark,pop,z0=0;
     img.style.position='absolute';
     nobj.style.position='absolute';
     nobj.style.width=pobj.offsetWidth/r+'px';
     nobj.style.height=pobj.offsetHeight/r+'px';
     for (;z0<marks.length;z0++){
      mark=document.createElement('DIV');
      mark.className=marks[z0][0];
      img.appendChild(mark);
      mark.style.left=marks[z0][1]-mark.offsetWidth/2+'px';
      mark.style.top=marks[z0][2]-mark.offsetHeight/2+'px';
      pop=document.getElementById(marks[z0][3]);
      if (pop){
       pop.style.left=marks[z0][1]-pop.offsetWidth/2+'px';
       pop.style.top=marks[z0][2]+marks[z0][4]+'px';
       this.addevt(pop,'mouseup','popclose');
      }
      this.addevt(mark,'mouseup','markpos',[mark,pop]);
     }
     this.lst=false;
     this.img=img;
     this.pobj=pobj;
     this.nav=nav;
     this.nobj=nobj;
     this.r=r;
     this.navpos();
     this.drag=false;
     this.addevt(nobj,'mousedown','ndown');
     this.addevt(img,'mousedown','down');
     this.addevt(document,'mousemove','move');
     this.addevt(document,'mousemove','nmove');
     this.addevt(document,'mouseup','up');
    }
    
    zxcMapNavigator.prototype={
    
     markpos:function(e,mark){
      this.popclose();
      var img=this.img,pobj=this.pobj,m=mark[0],lft=-m.offsetLeft-m.offsetWidth/2+pobj.offsetWidth/2,top=-m.offsetTop+100;
      img.style.left=-m.offsetLeft-m.offsetWidth/2+pobj.offsetWidth/2+'px';
      img.style.top=-m.offsetTop-m.offsetHeight/2+100+'px';
      if (mark[1]){
       mark[1].style.visibility='visible';
       this.lst=mark[1];
      }
      this.navpos();
     },
    
     popclose:function(){
      if (this.lst){
       this.lst.style.visibility='hidden';
      }
     },
    
     navpos:function(){
      var img=this.img,nobj=this.nobj,r=this.r;
      nobj.style.left=-img.offsetLeft/r+'px';
      nobj.style.top=-img.offsetTop/r+'px';
     },
    
     imgpos:function(){
      var img=this.img,nobj=this.nobj,r=this.r;
      img.style.left=-nobj.offsetLeft*r+'px';
      img.style.top=-nobj.offsetTop*r+'px';
     },
    
     addevt:function(o,t,f,p){
      var oop=this;
      if (o.addEventListener) o.addEventListener(t,function(e){ return oop[f](e,p);}, false);
      else if (o.attachEvent) o.attachEvent('on'+t,function(e){ return oop[f](e,p); });
     },
    
     mse:function(e){
      if (window.event){
       var docs=[document.body.scrollLeft,document.body.scrollTop];
       if (!document.body.scrollTop){
        docs=[document.documentElement.scrollLeft,document.documentElement.scrollTop];
       }
       return [e.clientX+docs[0],e.clientY+docs[1]];
      }
      return [e.pageX,e.pageY];
     },
    
     style:function(obj,p){
      if (obj.currentStyle){
       return parseInt(obj.currentStyle[p.replace(/-/g,'')]);
      }
      return parseInt(document.defaultView.getComputedStyle(obj,null).getPropertyValue(p));
     },
    
    
     down:function(e){
      document.onselectstart=function(event){
       window.event.returnValue=false;
      }
      this.minX=-this.img.offsetWidth+this.pobj.offsetWidth;
      this.minY=-this.img.offsetHeight+this.pobj.offsetHeight;
      this.lastXY=[e.clientX,e.clientY];
      this.drag=true;
      if (!window.event){
       e.preventDefault();
      }
      return false;
     },
    
     move:function(e){
      if (this.drag){
       var mse=[e.clientX,e.clientY],lft=this.style(this.img,'left')+mse[0]-this.lastXY[0],top=this.style(this.img,'top')+mse[1]-this.lastXY[1];
       this.img.style.left=Math.max(Math.min(lft,0),this.minX)+'px';
       this.img.style.top=Math.max(Math.min(top,0),this.minY)+'px';
       this.lastXY=mse;
       this.navpos();
      }
      if (!window.event){
       e.preventDefault();
      }
      return false;
     },
    
     ndown:function(e){
      document.onselectstart=function(event){
       window.event.returnValue=false;
      }
      this.maxX=this.nav.offsetWidth-this.nobj.offsetWidth;
      this.maxY=this.nav.offsetHeight-this.nobj.offsetHeight;
      this.lastXY=[e.clientX,e.clientY];
      this.ndrag=true;
      if (!window.event){
       e.preventDefault();
      }
      return false;
     },
    
     nmove:function(e){
      if (this.ndrag){
       var mse=[e.clientX,e.clientY],lft=this.style(this.nobj,'left')+mse[0]-this.lastXY[0],top=this.style(this.nobj,'top')+mse[1]-this.lastXY[1];
       this.nobj.style.left=Math.max(Math.min(lft,this.maxX),0)+'px';
       this.nobj.style.top=Math.max(Math.min(top,this.maxY),0)+'px';
       this.lastXY=mse;
       this.imgpos();
      }
      if (!window.event){
       e.preventDefault();
      }
      return false;
     },
    
     up:function(e){
      if (this.drag||this.ndrag){
       this.drag=false;
       this.ndrag=false;
       document.onselectstart=null;
      }
     }
    
    }
    
    new zxcMapNavigator({
     ID:'tst',
     NavID:'nav',
     Markers:[
      ['m1',1200,290,'pop1',50],
      ['m2',1200,1290,'pop2',50]
     ]
    });
    /*]]>*/
    </script>
    
    
    </body>
    
    </html>
    the animation and resizing should be easy to add
    Vic

    God Loves You and will never love you less.

    http://www.vicsjavascripts.org/Home.htm

    If my post has been useful please donate to http://www.operationsmile.org.uk/

  • Users who have thanked vwphillips for this post:

    agkn0001 (05-25-2011)

  • #5
    New to the CF scene
    Join Date
    May 2011
    Posts
    3
    Thanks
    2
    Thanked 0 Times in 0 Posts
    Quote Originally Posted by vwphillips View Post
    Code:
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    
    <head>
      <title></title>
    <style type="text/css">
    /*<![CDATA[*/
    
    #tst {
      position:absolute;overflow:hidden;left:100px;top:100px;width:600px;height:500px;border:solid red 1px;
    }
    
    .img {
      position:absolute;left:-600px;top:-100px;width:2800px;height:3076px;border:solid red 1px;
    }
    
    .img IMG {
      float:left;
    }
    
    #nav {
      position:absolute;z-Index:2;left:0px;top:308px;width:175px;height:192px;border:solid red 1px;background-Image:url(http://i.cdn.hbo.com/custom-assets/enrichments/series/game-of-thrones/images/map-navigator.jpg);
    }
    
    .nav {
      border:solid red 1px;
    }
    
    .m1 {
      position:absolute;width:80px;height:20px;border:solid red 1px;background-Color:#FFFFCC;
    }
    
    .m2 {
      position:absolute;width:80px;height:20px;border:solid red 1px;background-Color:#FF3366;
    }
    
    .pop {
      position:absolute;visibility:hidden;width:200px;height:120px;border:solid red 1px;background-Color:#FFFFCC;
    }
    
    /*]]>*/
    </style>
    
    
    </head>
    
    <body>
     <div id="tst" >
      <div class="img" >
       <img src="http://i.cdn.hbo.com/custom-assets/enrichments/series/game-of-thrones/images/map/x2-images-3-1.png" />
       <img src="http://i.cdn.hbo.com/custom-assets/enrichments/series/game-of-thrones/images/map/x2-images-3-2.png"/>
       <img src="http://i.cdn.hbo.com/custom-assets/enrichments/series/game-of-thrones/images/map/x2-images-3-3.png" />
       <img src="http://i.cdn.hbo.com/custom-assets/enrichments/series/game-of-thrones/images/map/x2-images-3-4.png" />
       <div id="pop1" class="pop" >Pop 1</div>
       <div id="pop2" class="pop" >Pop 2</div>
      </div>
      <div id="nav" >
       <div class="nav" ></div>
      </div>
     </div>
    
    <script type="text/javascript">
    /*<![CDATA[*/
    // MapNavigator (23-May-2011) DRAFT
    // by Vic Phillips http://www.vicsjavascripts.org.uk
    
    function zxcMapNavigator(o){
     var pobj=document.getElementById(o.ID),img=pobj.getElementsByTagName('DIV')[0],nav=document.getElementById(o.NavID),nobj=nav.getElementsByTagName('DIV')[0],r=img.offsetWidth/nav.offsetWidth,marks=o.Markers,mark,pop,z0=0;
     img.style.position='absolute';
     nobj.style.position='absolute';
     nobj.style.width=pobj.offsetWidth/r+'px';
     nobj.style.height=pobj.offsetHeight/r+'px';
     for (;z0<marks.length;z0++){
      mark=document.createElement('DIV');
      mark.className=marks[z0][0];
      img.appendChild(mark);
      mark.style.left=marks[z0][1]-mark.offsetWidth/2+'px';
      mark.style.top=marks[z0][2]-mark.offsetHeight/2+'px';
      pop=document.getElementById(marks[z0][3]);
      if (pop){
       pop.style.left=marks[z0][1]-pop.offsetWidth/2+'px';
       pop.style.top=marks[z0][2]+marks[z0][4]+'px';
       this.addevt(pop,'mouseup','popclose');
      }
      this.addevt(mark,'mouseup','markpos',[mark,pop]);
     }
     this.lst=false;
     this.img=img;
     this.pobj=pobj;
     this.nav=nav;
     this.nobj=nobj;
     this.r=r;
     this.navpos();
     this.drag=false;
     this.addevt(nobj,'mousedown','ndown');
     this.addevt(img,'mousedown','down');
     this.addevt(document,'mousemove','move');
     this.addevt(document,'mousemove','nmove');
     this.addevt(document,'mouseup','up');
    }
    
    zxcMapNavigator.prototype={
    
     markpos:function(e,mark){
      this.popclose();
      var img=this.img,pobj=this.pobj,m=mark[0],lft=-m.offsetLeft-m.offsetWidth/2+pobj.offsetWidth/2,top=-m.offsetTop+100;
      img.style.left=-m.offsetLeft-m.offsetWidth/2+pobj.offsetWidth/2+'px';
      img.style.top=-m.offsetTop-m.offsetHeight/2+100+'px';
      if (mark[1]){
       mark[1].style.visibility='visible';
       this.lst=mark[1];
      }
      this.navpos();
     },
    
     popclose:function(){
      if (this.lst){
       this.lst.style.visibility='hidden';
      }
     },
    
     navpos:function(){
      var img=this.img,nobj=this.nobj,r=this.r;
      nobj.style.left=-img.offsetLeft/r+'px';
      nobj.style.top=-img.offsetTop/r+'px';
     },
    
     imgpos:function(){
      var img=this.img,nobj=this.nobj,r=this.r;
      img.style.left=-nobj.offsetLeft*r+'px';
      img.style.top=-nobj.offsetTop*r+'px';
     },
    
     addevt:function(o,t,f,p){
      var oop=this;
      if (o.addEventListener) o.addEventListener(t,function(e){ return oop[f](e,p);}, false);
      else if (o.attachEvent) o.attachEvent('on'+t,function(e){ return oop[f](e,p); });
     },
    
     mse:function(e){
      if (window.event){
       var docs=[document.body.scrollLeft,document.body.scrollTop];
       if (!document.body.scrollTop){
        docs=[document.documentElement.scrollLeft,document.documentElement.scrollTop];
       }
       return [e.clientX+docs[0],e.clientY+docs[1]];
      }
      return [e.pageX,e.pageY];
     },
    
     style:function(obj,p){
      if (obj.currentStyle){
       return parseInt(obj.currentStyle[p.replace(/-/g,'')]);
      }
      return parseInt(document.defaultView.getComputedStyle(obj,null).getPropertyValue(p));
     },
    
    
     down:function(e){
      document.onselectstart=function(event){
       window.event.returnValue=false;
      }
      this.minX=-this.img.offsetWidth+this.pobj.offsetWidth;
      this.minY=-this.img.offsetHeight+this.pobj.offsetHeight;
      this.lastXY=[e.clientX,e.clientY];
      this.drag=true;
      if (!window.event){
       e.preventDefault();
      }
      return false;
     },
    
     move:function(e){
      if (this.drag){
       var mse=[e.clientX,e.clientY],lft=this.style(this.img,'left')+mse[0]-this.lastXY[0],top=this.style(this.img,'top')+mse[1]-this.lastXY[1];
       this.img.style.left=Math.max(Math.min(lft,0),this.minX)+'px';
       this.img.style.top=Math.max(Math.min(top,0),this.minY)+'px';
       this.lastXY=mse;
       this.navpos();
      }
      if (!window.event){
       e.preventDefault();
      }
      return false;
     },
    
     ndown:function(e){
      document.onselectstart=function(event){
       window.event.returnValue=false;
      }
      this.maxX=this.nav.offsetWidth-this.nobj.offsetWidth;
      this.maxY=this.nav.offsetHeight-this.nobj.offsetHeight;
      this.lastXY=[e.clientX,e.clientY];
      this.ndrag=true;
      if (!window.event){
       e.preventDefault();
      }
      return false;
     },
    
     nmove:function(e){
      if (this.ndrag){
       var mse=[e.clientX,e.clientY],lft=this.style(this.nobj,'left')+mse[0]-this.lastXY[0],top=this.style(this.nobj,'top')+mse[1]-this.lastXY[1];
       this.nobj.style.left=Math.max(Math.min(lft,this.maxX),0)+'px';
       this.nobj.style.top=Math.max(Math.min(top,this.maxY),0)+'px';
       this.lastXY=mse;
       this.imgpos();
      }
      if (!window.event){
       e.preventDefault();
      }
      return false;
     },
    
     up:function(e){
      if (this.drag||this.ndrag){
       this.drag=false;
       this.ndrag=false;
       document.onselectstart=null;
      }
     }
    
    }
    
    new zxcMapNavigator({
     ID:'tst',
     NavID:'nav',
     Markers:[
      ['m1',1200,290,'pop1',50],
      ['m2',1200,1290,'pop2',50]
     ]
    });
    /*]]>*/
    </script>
    
    
    </body>
    
    </html>
    the animation and resizing should be easy to add


    wow Thank you for all the work you put into this! - it is a great way to solve this problem.
    my map will have a few more functionalities, such that we will add more details and more info weekly to the map - or more precisely we will display more and more elements on the map --
    so I have to give some more thought to my requirements and functionalities, but your help saved me a lot of time with this thinking process.
    thanks again


  •  

    Tags for this Thread

    Posting Permissions

    • You may not post new threads
    • You may not post replies
    • You may not post attachments
    • You may not edit your posts
    •