2011-05-11 55 views
7

我想創建一個HTML5畫布作爲OverlayView地圖的大小,將其定位到top:0; left:0;,在其上繪製一些東西,並添加它到地圖。無論何時地圖放大或平移,我想從地圖中移除舊的畫布,並在其上創建新的畫布繪製,將其定位到0,0並將其添加到地圖。然而,地圖從不重新定位到頂端:0;左:0。有人可以幫忙嗎?HTML畫布作爲覆蓋視圖在Google地圖中是固定的相對於地圖畫布

function CustomLayer(map){ 
this.latlngs = new Array(); 
this.map_ = map; 

this.addMarker = function(position){ 
this.latlngs.push(position); 
} 

this.drawCanvas = function(){ 
this.setMap(this.map_); 
//google.maps.event.addListener(this.map_, 'bounds_changed',this.reDraw()); 
} 

} 

function defineOverlay() { 

CustomLayer.prototype = new google.maps.OverlayView(); 

CustomLayer.prototype.onAdd = function() { 
    console.log("onAdd()"); 
    if(this.canvas){  
    var panes = this.getPanes(); 
    panes.overlayLayer.appendChild(this.canvas); 
    } 
} 


CustomLayer.prototype.remove = function() { 
    console.log("onRemove()"); 
    if(this.canvas) 
    this.canvas.parentNode.removeChild(this.canvas); 
} 


CustomLayer.prototype.draw = function() { 
    console.log("draw()"); 
     this.remove(); 
      this.canvas = document.createElement("canvas"); 
      this.canvas.setAttribute('width', '800px'); 
      this.canvas.setAttribute('height', '480px'); 
      this.canvas.setAttribute('top', '30px'); 
      this.canvas.setAttribute('left', '30px'); 
      this.canvas.setAttribute('position', 'absolute'); 
      this.canvas.setAttribute('border', '1px solid red'); 
      this.canvas.style.border = '1px solid red'; 

      //using this way for some reason scale up the images and mess up the positions of the markers 
      /*this.canvas.style.position = 'absolute'; 
      this.canvas.style.top = '0px'; 
      this.canvas.style.left = '0px'; 
      this.canvas.style.width = '800px'; 
      this.canvas.style.height = '480px'; 
      this.canvas.style.border = '1px solid red';*/ 

      //get the projection from this overlay 
      overlayProjection = this.getProjection(); 
      //var mapproj = this.map_.getProjection(); 

       if(this.canvas.getContext) { 
        var context = this.canvas.getContext('2d'); 
        context.clearRect(0,0,800,480); 

        for(i=0; i<this.latlngs.length; i++){ 

         p = overlayProjection.fromLatLngToDivPixel(this.latlngs[i]); 
         //p = mapproj.fromLatLngToPoint(this.latlngs[i]); 
         img = new Image(); 
         img.src = "standardtick.png"; 
          console.log(Math.floor(p.x)+","+Math.floor(p.y)); 
        context.drawImage(img,p.x,p.y); 
        } 
       } 
    this.onAdd();   
    console.log("canvas width:"+this.canvas.width+" canvas height: "+this.canvas.height); 
    console.log("canvas top:"+this.canvas.getAttribute("top")+" left: "+this.canvas.getAttribute("left")); 
} 
} 

回答

0

一旦地圖移動,繪圖上下文需要知道它已經移動。

CustomOverlayView.prototype.alignDrawingPane = function(force) { 
    window.mapProjection = this.getProjection(); 
    var center = window.mapProjection.fromLatLngToDivPixel(map.getCenter()); 
    //My drawing container is dragged along with the map when panning 
    //this.drawPane refers to any node in MapPanes retrieved via this.getPanes() 
    this.drawPane.css({left:center.x - (mapWidth/2), top:center.y-(mapHeight/2)}); 
}; 

在draw()方法中調用此方法。確保當你做拖動繪製被調用:

google.maps.event.addListener(map, 'dragend', function() { 
    myCustomOverlay.draw(); 
}); 
5

在這個例子 - 我想提請注意projection.fromLatLngToDivPixel和projection.fromLatLngToContainerPixel之間的區別是很重要的。在這種情況下,DivPixel用於保持畫布的位置位於地圖視圖的中心 - 而ContainerPixel用於查找您正在繪製到畫布的形狀的位置。

接下來是我自己解決這個問題時所制定的一個完整的工作示例。

必需的CSS屬性的疊加:

.GMAPS_OVERLAY 
    { 
    border-width: 0px; 
    border: none; 
    position:absolute; 
    padding:0px 0px 0px 0px; 
    margin:0px 0px 0px 0px; 
    } 

初始化地圖,並創建一個測試基於谷歌標記

var mapsize = { width: 500, height: 500 }; 
    var mapElement = document.getElementById("MAP"); 

    mapElement.style.height = mapsize.width + "px"; 
    mapElement.style.width = mapsize.width + "px"; 

    var map = new google.maps.Map(document.getElementById("MAP"), { 
    mapTypeId: google.maps.MapTypeId.TERRAIN, 
    center: new google.maps.LatLng(0, 0), 
    zoom:  2 
    }); 

    // Render G-Markers to Test Proper Canvas-Grid Alignment 
    for (var lng = -180; lng < 180; lng += 10) 
    { 
    var marker = new google.maps.Marker({ 
     position: new google.maps.LatLng(0, lng), 
     map: map 
    }); 
    } 

定義自定義疊加

var CanvasOverlay = function(map) { 
    this.canvas   = document.createElement("CANVAS"); 
    this.canvas.className = "GMAPS_OVERLAY"; 
    this.canvas.height = mapsize.height; 
    this.canvas.width  = mapsize.width; 
    this.ctx    = null; 
    this.map    = map; 

    this.setMap(map); 
    }; 
    CanvasOverlay.prototype = new google.maps.OverlayView(); 

    CanvasOverlay.prototype.onAdd = function() { 
    this.getPanes().overlayLayer.appendChild(this.canvas); 
    this.ctx = this.canvas.getContext("2d"); 
    this.draw(); 
    }; 

    CanvasOverlay.prototype.drawLine = function(p1, p2) { 
    this.ctx.beginPath(); 
    this.ctx.moveTo(p1.x, p1.y); 
    this.ctx.lineTo(p2.x, p2.y); 
    this.ctx.closePath(); 
    this.ctx.stroke(); 
    }; 

    CanvasOverlay.prototype.draw = function() { 
    var projection = this.getProjection(); 

    // Shift the Canvas 
    var centerPoint = projection.fromLatLngToDivPixel(this.map.getCenter()); 
    this.canvas.style.left = (centerPoint.x - mapsize.width/2) + "px"; 
    this.canvas.style.top = (centerPoint.y - mapsize.height/2) + "px"; 

    // Clear the Canvas 
    this.ctx.clearRect(0, 0, mapsize.width, mapsize.height); 

    // Draw Grid with Canvas 
    this.ctx.strokeStyle = "#000000"; 
    for (var lng = -180; lng < 180; lng += 10) 
    { 
     this.drawLine(
     projection.fromLatLngToContainerPixel(new google.maps.LatLng(-90, lng)), 
     projection.fromLatLngToContainerPixel(new google.maps.LatLng(90, lng)) 
    ); 
    } 
    }; 

初始化畫布

我發現我喜歡添加額外的呼叫吸取「dragend」事件 - 但測試一下,看看有什麼你認爲你的需要。

var customMapCanvas = new CanvasOverlay(map); 
    google.maps.event.addListener(map, "drawend", function() { 
    customMapCanvas.draw(); 
    }; 

在情況下,繪圖畫布放緩地圖

在我一起工作的應用程序,我發現地圖框架所說的「」的方法過於頻繁在畫布上的哪些是繪製需要花費一秒左右才能完成的事情。在這種情況下,我定義「」原型函數是簡單的空函數而命名我真正吸引功能「canvasDraw」 - 然後添加事件偵聽器「zoomend」和「dragend」。您在這裏獲得的是隻在用戶更改縮放級別或地圖拖動操作結束後更新的畫布。

CanvasOverlay.prototype.draw = function() { };  

    ... 

    google.maps.event.addListener(map, "dragend", function() { 
    customMapCanvas.canvasDraw(); 
    }); 

    google.maps.event.addListener(map, "zoom_changed", function() { 
    customMapCanvas.canvasDraw(); 
    }); 

現場演示:Complete Example - All Inline Source

+0

約翰,這是一個很好的例子。你有沒有把它更新到谷歌地圖V3?我試圖在這裏: http://jsfiddle.net/rogerguess/Lxdqtqdn/11/ 縮放正在工作,但拖動不是 – Roger 2015-01-29 22:26:06