Вращающееся изображение / изображение маркера на карте Google V3 - PullRequest
26 голосов
/ 23 июля 2011

Как можно повернуть изображение (маркерное изображение) на карте Google V3 ?

  • Отличный пример для V2 здесь , именно то, что мне нужно. Но для GMap2! Они делают это с помощью вращающегося холста.
  • Изображение часто вращается с помощью JS / JQuery, несколько ответов . Но как я могу применить это к изображению моей карты?
  • Один из упомянутых подходов - иметь разные изображения под разными углами и переключаться между ними - это НЕ то, что я хочу. Мне не нравится иметь так много изображений, я хочу повернуть по коду.

Примечание: есть похожие вопросы, но все для V2, а не для V3 (насколько я могу судить). Мне это нужно для V3.

Ответы [ 14 ]

16 голосов
/ 02 апреля 2015

Мой класс js для решения этой проблемы:

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');
};

Назовите это так:

var marker = new google.maps.Marker({
    icon: {
        url: RotateIcon
            .makeIcon(
                'https://ru.gravatar.com/userimage/54712272/b8eb5f2d540a606f4a6c07c238a0bf40.png')
            .setRotation({deg: 92})
            .getUrl()
    }})

Смотрите пример в реальном времени здесь http://jsfiddle.net/fe9grwdf/39/

11 голосов
/ 25 июля 2011

Я нашел два расширения для Google MAP V3: infobox.js и markerwithlabel.js Оба могут обрабатывать DOM-элемент изображения как контент, который я, в свою очередь, могу вращать с помощью плагина jQuery image rotate .

Это работает даже без повторной установки изображения маркера после поворота.

Редактировать: По состоянию на вопросы / комментарии ниже:

Требуется расширение для метки, поскольку оно может обрабатывать другие элементы DOM. Таким образом, я могу добавить произвольный HTML в качестве метки, в моем конкретном случае я добавляю изображение. И затем я поворачиваю это изображение (дочерний элемент метки) с помощью плагина поворота. Так что присвойте изображению идентификатор, чтобы легко получить к нему доступ. На самом деле я использую одну метку только для изображения, а другую для описательного текста.

Редактировать 2: из-за комментария Стефана о готовности DOM

В моем коде я нашел следующие строки. Это показывает, что я заставляю рисовать метку перед поворотом изображения.

    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);

Редактировать 3: Пример кода, как создать 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);
8 голосов
/ 25 октября 2016

Мне также было трудно найти способ поворота маркера .png.Я решил это, как показано ниже.Вы можете создать множество маркеров с одним и тем же пользовательским изображением и вращать определенный маркер, который вы хотите повернуть.Я надеюсь, что это полезно для вас.

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)'}); 
5 голосов
/ 11 декабря 2015

Как можно повернуть изображение (маркерное изображение) на карте Google V3?

У меня была такая же проблема, и я решил ее с помощью следующего кода:

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

Полагаю, у вас есть переменная со значком, например:

var imagePath = 'img/customMarker.png';

Сначала нам нужно создать параметры нашего маркера:

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

Давайте создадим маркер:

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

И мы должны установить карту:

marker.setMap(map);

Теперь, если вы хотите повернуть изображение, вам нужно сделать следующее:

  • Измените значение переменной imagePath на 'img / customMarker.png # yourId'
  • Установить значение вращения с помощью css (например, с JQuery)

Посмотрим

imagePath = 'img/customMarker.png#markerOne';

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

Конечно, вы можете сделать это более изящно:

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

И ваш звонок:

rotateMarker('markerOne', 45);

Вот и все.

Надеюсь, это может быть полезно.

5 голосов
/ 02 марта 2015

Вы не указали это в своем вопросе, но я предполагаю, что вы хотите, чтобы это вращение было связано с линией между точкой а и точкой b, которая будет их траекторией.Чтобы сделать значок Google SVG, который можно вращать, вы хотите использовать объект класса символа Google, чтобы определить свойства вашего символа маркера.При этом используется не полный файл .svg, а только атрибут d пути.Обратите внимание, что класс символов Google может использовать только один путь для каждого маркера.

Дополнительные атрибуты для цвета, обводки, ширины, непрозрачности и т. Д. Могут быть установлены после создания маркера с помощью JavaScript (обновление свойств объекта маркеранапрямую) или с помощью CSS (обновление свойств маркера путем добавления и удаления классов).

В качестве примера ниже будет создан маркер стрелки, который можно перетаскивать, и он будет вращаться вокруг точки накарта, которая является последней и длинной для маркера даже после его перемещения.

HTML

<body id="document_body" onload="init();">
  <div id="rotation_control">
    Heading&deg;<input id="rotation_value" type="number" size="3" value="0" onchange="setRotation();" />
  </div>
  <div id="map_canvas"></div>
</body>

CSS (да, многословно ... я ненавижу безобразно)

#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;
  }

Javascript (в простом ванильном понимании для понимания основных понятий)

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;
}

И самое лучшее, делая это таким образом, гарантирует, что маркер является объектом Google MVC, предоставляя ему все дополнительные методыпредоставляется объектом MVC.

Если в качестве маркера необходимо использовать разноцветные изображения, то создайте спрайт-лист .png с отображением изображения ввсе углы, которые вы хотите, чтобы он был показан, а затем проблематично выбрать правильное изображение для использования на основе вычисленного ориентира между двумя точками, которые вы используете.Однако это будет не изображение SVG, а обычное изображение маркера.

Надеюсь, это поможет принять некоторые решения относительно маркеров вашей карты.

4 голосов
/ 03 апреля 2014

Я сделал ротацию в v3 со следующим кодом:

<canvas id="carcanvas" width="1" height="1"></canvas>


    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();
    }

и в методе анимации:

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

Надеюсь, это поможет.

3 голосов
/ 05 апреля 2016

Так я реализовал свое изображение повернутым, я рассмотрел маркер в виде наложения, и это наложение - это позиция в позиции, будет добавлен код ниже.

Без использования какой-либо дополнительной библиотеки оно поворачивается, И вам нужно обойти, чтобы добавить события щелчка и события мыши для наложения, не похожие на события щелчка маркера.

С настройкой маркеров googleMap будет дополнительное использование памяти на карте.Это также уменьшит потребление памяти пользовательскими маркерами на вашей карте.

 <html>
    <head>
    <script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
    <style>html, body {
        height: 100%;
        margin: 0;
        padding: 0;
    }
    #map_canvas {
        height: 100%;
    }
    div.htmlMarker {
        color: red;
        cursor: pointer;
    }

    </style>
    </head>
    <body onload="initialize()">
        <div id="map_canvas"></div>
    </body>

    <script>
    var overlay;

    function initialize() {
        var myLatLng = new google.maps.LatLng(40, -100);
        var mapOptions = {
            zoom: 10,
            center: myLatLng,
            mapTypeId: google.maps.MapTypeId.ROADMAP
        };

        var gmap = new google.maps.Map(document.getElementById('map_canvas'), mapOptions);

        function HTMLMarker(lat, lng, rotation) {
            this.lat = lat;
            this.lng = lng;
             this.rotation = rotation;
            this.pos = new google.maps.LatLng(lat, lng);
        }

        HTMLMarker.prototype = new google.maps.OverlayView();
        HTMLMarker.prototype.onRemove = function () {}

        //Initilize your html element here
        HTMLMarker.prototype.onAdd = function () {
            div = document.createElement('DIV');
            div.style.position='absolute';
            div.style.transform='rotate('+this.rotation +'deg)';
            div.style.MozTransform='rotate('+this.rotation +'deg)';
            div.className = "htmlMarker";
           //image source use your own image in src
            div.innerHTML = '<img src="prudvi.png" alt="Mountain View" style="width:25px;height:22px">' ;
            var panes = this.getPanes();
            panes.overlayImage.appendChild(div);
            this.div=div;
        }

        HTMLMarker.prototype.draw = function () {
            var overlayProjection = this.getProjection();
            var position = overlayProjection.fromLatLngToDivPixel(this.pos);
            var panes = this.getPanes();
            this.div.style.left = position.x + 'px';
            this.div.style.top = position.y - 30 + 'px';
        }

        //Added 50 marker with random latlng location and random rotation,
        for (i = 0; i < 50; i++) {
        var PoslatLng = new google.maps.LatLng(myLatLng.lat() + Math.random() - 0.5, myLatLng.lng() + Math.random() - 0.5);
        var htmlMarker = new HTMLMarker(myLatLng.lat() + Math.random() - 0.5,myLatLng.lng() + Math.random() - 0.5, Math.floor(Math.random() * 359));
        htmlMarker.setMap(gmap);
    google.maps.event.addListener(htmlMarker, 'click', function() {
        console.log('clciked')
        gmap.setZoom(8);
        gmap.setCenter(htmlMarker.getPosition());
      });
        }
    }
    </script>
  </html>
3 голосов
/ 25 июля 2014

Я смог решить эту проблему довольно легко, но с помощью параметра marker.icon.rotation, указывающей на пользовательский символ, который использует синтаксис пути 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

}; 

При использовании angular-google-maps этотривиально привязать элемент управления пользовательского интерфейса для изменения triangle.rotation.

Как я делал с этим ползунком.

<slider  ng-model="triangle.rotation" floor="0" ceiling="359" step="5" precsion="1"></slider>

Но вы также можете использовать форум.

здесьмой плункер http://plnkr.co/edit/x0egXI

2 голосов
/ 22 сентября 2018

Никто не упоминал об использовании предварительно повернутых значков.В зависимости от вашего приложения, вы можете взять один значок и повернуть его на +10 градусов, +20 градусов ... +350 градусов и вместо того, чтобы вращать сам маркер, просто назначьте ему другой значок - один из 36, если разрешение 10 градусов хорошеедовольно.Это также очень мало для клиентских ресурсов.

В приведенном ниже примере я создал 36 иконок, каждая из которых повернута на 10 градусов.Их имена: icon0.png, icon10.png, icon20.png, ... icon340.png, icon350.png, icon360.png .0 и 360 - это один и тот же значок (например, символическая ссылка)

var rotation = 123 // degrees
var iconName = "icon" + (Math.round(rotation/10)*10).toString() + ".png"
var marker = new google.maps.Marker({
    icon: iconName
})
2 голосов
/ 27 августа 2017

Идея состоит в том, чтобы сначала нарисовать повернутое изображение маркера на скрытом холсте.

Скажем, у вас есть скрытый холст:

<canvas id="carCanvas" width="50" height="50" style="display:none"></canvas>

Теперь вы можете сделать это:

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);
    }
}

Выше мой оригинальный код. Я оставил его без изменений, чтобы вы могли увидеть другие мои оптимизации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...