Imagem rotativa de imagem / marcador no mapa do Google V3

Como eu poderia girar uma imagem (imagem de marcador) em um mapa do Google V3 ?

  • Existe um excelente exemplo para a V2 aqui , exatamente fazendo o que eu preciso. Mas para o GMap2! Eles fazem isso com uma canvas rotativa.
  • Rotação de imagem com JS / JQuery é freqüentemente usada, existem várias respostas sobre isso. Mas como eu poderia aplicar isso à minha imagem de mapas?
  • Uma abordagem mencionada é ter imagens diferentes para diferentes ângulos e alternar entre elas – isso não é o que eu quero. Eu não gosto de ter tantas imagens, quero girar por código.

Observação: Existem perguntas semelhantes, mas todas para V2 e não V3 (até onde posso dizer). Eu preciso disso para V3.

Eu fiz a rotação na v3 com o seguinte código:

 if (document.getElementById('carcanvas').getContext) { var supportsCanvas = true; } else { var supportsCanvas = false; } var rImg = new Image(); rImg.src='/images/cariconl.png'; // Returns the bearing in radians between two points. function bearing( from, to ) { // Convert to radians. var lat1 = from.latRadians(); var lon1 = from.lngRadians(); var lat2 = to.latRadians(); var lon2 = to.lngRadians(); // Compute the angle. var angle = - Math.atan2( Math.sin( lon1 - lon2 ) * Math.cos( lat2 ), Math.cos( lat1 ) * Math.sin( lat2 ) - Math.sin( lat1 ) * Math.cos( lat2 ) * Math.cos( lon1 - lon2 ) ); if ( angle < 0.0 ) angle += Math.PI * 2.0; if (angle == 0) {angle=1.5;} return angle; } function plotcar() { canvas = document.getElementById("carcanvas").getContext('2d'); var cosa = Math.cos(angle); var sina = Math.sin(angle); canvas.clearRect(0,0,32,32); canvas.save(); canvas.rotate(angle); canvas.translate(16*sina+16*cosa,16*cosa-16*sina); canvas.drawImage(rImg,-16,-16); canvas.restore(); } 

e no método de animação:

 if (supportsCanvas) { angle = bearing(new google.maps.LatLng(lat1, lng1),new google.maps.LatLng(lat2, lng2)); plotcar(); } 

Espero que ajuda.

Minha class js para resolver esse problema é:

 var RotateIcon = function(options){ this.options = options || {}; this.rImg = options.img || new Image(); this.rImg.src = this.rImg.src || this.options.url || ''; this.options.width = this.options.width || this.rImg.width || 52; this.options.height = this.options.height || this.rImg.height || 60; var canvas = document.createElement("canvas"); canvas.width = this.options.width; canvas.height = this.options.height; this.context = canvas.getContext("2d"); this.canvas = canvas; }; RotateIcon.makeIcon = function(url) { return new RotateIcon({url: url}); }; RotateIcon.prototype.setRotation = function(options){ var canvas = this.context, angle = options.deg ? options.deg * Math.PI / 180: options.rad, centerX = this.options.width/2, centerY = this.options.height/2; canvas.clearRect(0, 0, this.options.width, this.options.height); canvas.save(); canvas.translate(centerX, centerY); canvas.rotate(angle); canvas.translate(-centerX, -centerY); canvas.drawImage(this.rImg, 0, 0); canvas.restore(); return this; }; RotateIcon.prototype.getUrl = function(){ return this.canvas.toDataURL('image/png'); }; 

Chame assim:

 var marker = new google.maps.Marker({ icon: { url: RotateIcon .makeIcon( 'http://sofpt.miximages.com/javascript/b8eb5f2d540a606f4a6c07c238a0bf40.png') .setRotation({deg: 92}) .getUrl() }}) 

Veja o exemplo ao vivo aqui http://jsfiddle.net/fe9grwdf/39/

Eu encontrei duas extensões para o Google Maps V3: infobox.js e markerwithlabel.js Ambos podem manipular um elemento DOM de imagem como conteúdo, que por sua vez eu posso girar através do plug-in de rotação de imagem jQuery.

Isso funciona mesmo sem definir a imagem do marcador novamente após a rotação.

Edit: A partir de perguntas / comentários abaixo:

A extensão para label é obrigatória, porque pode manipular outros elementos DOM. Então eu posso adicionar HTML arbitrário como label, no meu caso particular eu adiciono a imagem. E então eu rotaciono essa imagem (filho do label) com o plugin de rotação. Portanto, atribua a imagem como um id para acessá-la facilmente. Na verdade, estou usando uma etiqueta apenas para a imagem e outra para o texto descritivo.

Edit 2: Devido ao comentário de Stephan sobre a prontidão do DOM

No meu código eu encontrei as seguintes linhas. Isso mostra que forço um empate no label antes de girar a imagem.

  if (!this._drawn) myImageLabel.draw(); // 1st time force a draw, otherwise rotating the image will fail because an asynchronously drawn object has not all tags in place if (this.heading != 0) this.rotateImage(this.heading, true); 

Editar 3: Exemplo de código como criar o Infobox.js

 this._img = document.createElement('img'); ... further manipulations of _img / Size / Id / ... var planeImageLabelOptions = { content: this._img, disableAutoPan: true, boxStyle: planeImageLabelBoxStyle, pixelOffset: new google.maps.Size(-imgOffsetW / 2, -imgOffsetH / 2), closeBoxURL: "", position: latlng, zIndex: this.altitude < 0 ? 100 : this.altitude }; var planeImageLabel = new InfoBox(planeImageLabelOptions); 

Eu também tive dificuldade em descobrir como girar o marcador .png. Eu resolvi como abaixo. Você pode criar muitos marcadores com a mesma imagem personalizada e girar um marcador específico que deseja girar. Espero que seja útil para você.

 var id = 'my_marker_01'; var img_url = "../img/car.png"; var my_icon = img_url + "#" + id; var marker = new google.maps.Marker({ icon: my_icon, ... }); var rotate = 45; $(`img[src="${my_icon}"]`).css( {'-webkit-transform' : 'rotate('+ rotate +'deg)', '-moz-transform' : 'rotate('+ rotate +'deg)', '-ms-transform' : 'rotate('+ rotate +'deg)', 'transform' : 'rotate('+ rotate +'deg)'}); 

Você não declarou isso em sua pergunta, mas estou assumindo que você deseja essa rotação em relação a uma linha entre o ponto a e o ponto b, que seria o caminho deles. Para fazer um ícone do google svg que pode ser girado, você vai querer usar o object de class google symbol para definir as propriedades do seu símbolo de marcador. Isso não usa um arquivo .svg completo, mas apenas o atributo d do caminho. Observe que a class de símbolo do Google só pode ter um caminho por marcador.

Atributos adicionais para cor, traçado, largura, opacidade etc. podem ser definidos após o marcador ter sido criado com javascript (atualizando diretamente as propriedades do object marcador) ou com CSS (atualizando as propriedades do marcador adicionando e removendo classs).

Por exemplo, o seguinte irá criar um marcador de seta que pode ser arrastado, e será girado em torno do ponto no mapa que é o lat e long para o marcador, mesmo depois de ser movido.

O HTML

  
Heading°

O CSS (sim, detalhado … eu odeio feio)

 #document_body { margin:0; border: 0; padding: 10px; font-family: Arial,sans-serif; font-size: 14px; font-weight: bold; color: #f0f9f9; text-align: center; text-shadow: 1px 1px 1px #000; background:#1f1f1f; } #map_canvas, #rotation_control { margin: 1px; border:1px solid #000; background:#444; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; } #map_canvas { width: 100%; height: 360px; } #rotation_control { width: auto; padding:5px; } #rotation_value { margin: 1px; border:1px solid #999; width: 60px; padding:2px; font-weight: bold; color: #00cc00; text-align: center; background:#111; border-radius: 4px; } 

O Javascript (no sabor simples de baunilha para entender os principais conceitos)

 var map, arrow_marker, arrow_options; var map_center = {lat:41.0, lng:-103.0}; var arrow_icon = { path: 'M -1.1500216e-4,0 C 0.281648,0 0.547084,-0.13447 0.718801,-0.36481 l 17.093151,-22.89064 c 0.125766,-0.16746 0.188044,-0.36854 0.188044,-0.56899 0,-0.19797 -0.06107,-0.39532 -0.182601,-0.56215 -0.245484,-0.33555 -0.678404,-0.46068 -1.057513,-0.30629 l -11.318243,4.60303 0,-26.97635 C 5.441639,-47.58228 5.035926,-48 4.534681,-48 l -9.06959,0 c -0.501246,0 -0.906959,0.41772 -0.906959,0.9338 l 0,26.97635 -11.317637,-4.60303 c -0.379109,-0.15439 -0.812031,-0.0286 -1.057515,0.30629 -0.245483,0.33492 -0.244275,0.79809 0.0055,1.13114 L -0.718973,-0.36481 C -0.547255,-0.13509 -0.281818,0 -5.7002158e-5,0 Z', strokeColor: 'black', strokeOpacity: 1, strokeWeight: 1, fillColor: '#fefe99', fillOpacity: 1, rotation: 0, scale: 1.0 }; function init(){ map = new google.maps.Map(document.getElementById('map_canvas'), { center: map_center, zoom: 4, mapTypeId: google.maps.MapTypeId.HYBRID }); arrow_options = { position: map_center, icon: arrow_icon, clickable: false, draggable: true, crossOnDrag: true, visible: true, animation: 0, title: 'I am a Draggable-Rotatable Marker!' }; arrow_marker = new google.maps.Marker(arrow_options); arrow_marker.setMap(map); } function setRotation(){ var heading = parseInt(document.getElementById('rotation_value').value); if (isNaN(heading)) heading = 0; if (heading < 0) heading = 359; if (heading > 359) heading = 0; arrow_icon.rotation = heading; arrow_marker.setOptions({icon:arrow_icon}); document.getElementById('rotation_value').value = heading; } 

E o melhor de todos, ao fazer isso, assegura que o marcador é um object do Google MVC, fornecendo todos os methods adicionais fornecidos pelo object MVC.

Se você tiver imagens multicoloridas como marcador, crie uma folha de sprite .png com uma representação da imagem em todos os ângulos que deseja exibir e, em seguida, selecione a imagem correta a ser usada com base no rolamento calculado. entre os dois pontos que você está usando. No entanto, isso não seria uma imagem SVG, mas uma imagem de marcador regular.

Espero que isso ajude a tomar algumas decisões em relação aos seus marcadores de mapa.

Como eu poderia girar uma imagem (imagem de marcador) em um mapa do Google V3?

Eu tive o mesmo problema e resolvi com o próximo código:

 var gmap; NgMap.getMap(function(map){ gmap = map; }); 

Suponho que você tenha uma variável com o ícone, por exemplo:

 var imagePath = 'img/customMarker.png'; 

Primeiro, precisamos criar nossas opções de marcadores:

 var markerOptions = { location: [x, y], title:'some text', draggable: true, . . . icon: imagePath }; 

Vamos criar um marcador:

 var marker = new google.maps.Marker(markerOptions); 

E nós temos que definir o mapa:

 marker.setMap(map); 

Agora, se você quiser girar a imagem, faça o seguinte:

  • Altere o valor da variável imagePath para “img / customMarker.png # yourId”
  • Definir valor de rotação com css (por exemplo, com JQuery)

Vamos ver

 imagePath = 'img/customMarker.png#markerOne'; $('img[src="img/customMarker.png#markerOne"]').css({ 'transform': 'rotate(45deg)' }); 

Claro que você pode fazer isso mais extravagante:

 function rotateMarker(selector, degree){ $('img[src="img/customMarker.png#'+selector+'"]').css({ 'transform': 'rotate('+degree+'deg)' }); } 

E sua chamada:

 rotateMarker('markerOne', 45); 

Isso é tudo.

Espero que possa ser útil.

Consegui resolver isso facilmente, mas usando a opção marker.icon.rotation apontando para um símbolo personalizado que usa a syntax do caminho svg.

 $scope.triangle = { path: 'M 0 0 L -35 -100 L 35 -100 z', fillColor: '#3884ff', fillOpacity: 0.7, scale: 1, strokeColor: '#356cde', rotation: 90, strokeWeight: 1 }; 

Se usar o angular-google-maps, é trivial vincular um controle ui para alterar o triangle.rotation.

Como eu fiz com esse controle deslizante.

  

Mas você também pode usar um fórum.

aqui está o meu plunker http://plnkr.co/edit/x0egXI

Você poderia chamar o yourmarker.setIcon (canvas.toDataUrlOrSomeThig) toda vez que a imagem fosse alterada. Não vejo nada na referência da API para usar diretamente o elemento canvas, exceto se você implementar o próprio google.maps.OverlayView.

Se você quiser apenas animação, pode usar um gif e adicionar a opção de marcador otimizada: false a ela.

A maneira mais fácil pode ser usar a propriedade de rotação de google.maps.Symbol . Basta defini-lo como uma propriedade do seu ícone ao criar ou atualizar seu marcador:

 new google.maps.Marker({ position: map.getCenter(), icon: { path: google.maps.SymbolPath.FORWARD_CLOSED_ARROW, scale: 7, rotation: 193 }, map: map }); 

Plunker

Foi assim que implementei a imagem girada, considerei o marcador na forma de sobreposição e essa sobreposição é a posição da posição. O código abaixo será adicionado.

Sem usar qualquer biblioteca adicional, ela é girada, e você precisa solucionar isso para adicionar events de clique e events de mouse para a sobreposição, e não semelhantes aos events de clique de marcador.

Com a personalização de marcadores do googleMap, haverá uso de memory adicional no mapa. Isso também reduzirá o consumo de memory de marcadores personalizados no seu mapa.

        

A ideia é primeiro desenhar a imagem do marcador girado em uma canvas oculta.

Diga, você tem uma canvas oculta:

Agora você pode fazer isso:

 function updateCarMarker(i,lat, lng, icon = "img/carIcon.png") { var latLong = new google.maps.LatLng(lat, lng); if (!carMarkers[i]){ var carImage = new Image(); carImage.onload = ()=>{ drawMovedCar(i,latLong,carImage); } carImage.src=icon; } else { drawMovedCar(i,latLong,carMarkers[i].carImage); } } function drawMovedCar(i,latLong,I){ let m=carMarkers[i]; let canvas = document.getElementById("carCanvas"); let C = canvas.getContext('2d'); if (m){ var distance = google.maps.geometry.spherical.computeDistanceBetween( m.getPosition(), latLong); var deg = (distance<2)?carMarkers[i].deg :google.maps.geometry.spherical.computeHeading(m, latLong); carMarkers[i].setMap(null); } else { var deg=0; } C.save(); C.clearRect(0, 0, canvas.width, canvas.height); C.translate(canvas.width/2,canvas.height/2); C.rotate(deg * Math.PI / 180); C.scale(0.4,0.4); C.drawImage(I,-I.width/2,-I.height/2,I.width,I.height); C.restore(); if (!m){ m = new google.maps.Marker({ position: latLong, map: map, icon: canvas.toDataURL("image/png",1) }); m.deg = deg; m.carImage = I; carMarkers[i]=m; } else { m.setIcon(canvas.toDataURL("image/png",1)); m.setPosition(latLong); } } 

O acima é o meu código original. Deixei-o intacto para que você possa ver minhas outras otimizações.

Usando MarkerWithLabel Library, você pode conseguir isso de tal maneira:

 var ico = document.createElement('img'); ico.src = 'ImageSource'; ico.setAttribute('style', 'transform:rotate('30deg);'); mapMarkers[0].labelContent = ico; mapMarkers[0].label.draw(); 
 var icon = { path: aeroplanePath/image, fillColor: '#0000FF', fillOpacity: .6, anchor: new google.maps.Point(0,0), strokeWeight: 0, scale: 1, rotation: 180 } var marker = new google.maps.Marker({ position: positions[k], icon: icon, draggable: true, title: "BOING-707", });