如何在Google地图 V3 上旋转图像(标记图像)?
备注:有类似的问题,但所有的V2而不是V3(据我所知)。我需要它为V3。
答案 0 :(得分:16)
我解决这个问题的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/
答案 1 :(得分:11)
我发现了Google MAP V3的两个扩展程序:infobox.js和markerwithlabel.js 两者都可以将图像DOM元素作为内容处理,然后我可以通过jQuery image rotate plugin进行旋转。
旋转后无需再次设置标记图像即可正常工作。
编辑:如下问题/评论:
标签的扩展名是必需的,因为它可以处理其他DOM元素。所以我可以添加任意HTML作为标签,在我的特殊情况下我添加图像。然后我用旋转插件旋转这个图像(标签的孩子)。因此,为图像分配一个id,以便轻松访问它。实际上我只为图像使用一个标签,为描述性文本使用另一个标签。
编辑2:由于Stephan对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);
答案 2 :(得分:8)
我也很难找出旋转.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)'});
答案 3 :(得分:5)
如何在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#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);
就是这样。
我希望它可能会有所帮助。
答案 4 :(得分:4)
我已使用以下代码在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();
}
我希望有所帮助。
答案 5 :(得分:4)
你没有在你的问题中说明,但我假设你希望这个旋转相对于点a和点b之间的线,这将是它们的路径。为了制作可以旋转的google svg图标,您需要使用google符号类对象来定义标记符号的属性。这不使用完整的.svg文件,而只使用路径的d属性。请注意,Google符号类每个标记只能占用一个路径。
使用javascript(直接更新标记对象属性)或使用CSS(通过添加和删除类更新标记属性)创建标记后,可以设置颜色,笔触,宽度,不透明度等的其他属性
作为一个例子,下面将创建一个可以拖动的箭头标记,它将围绕地图上的点旋转,即使在标记移动后也是标记的纬度和长度。
HTML
<body id="document_body" onload="init();">
<div id="rotation_control">
Heading°<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图像,而是常规标记图像。
希望这有助于做出有关地图标记的决定。
答案 6 :(得分:3)
我能够很容易地解决这个问题,但使用指向使用svg路径语法的自定义符号的marker.icon.rotation选项。
$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,绑定ui控件以更改triangle.rotation是微不足道的。
就像我使用这个滑块一样。
<slider ng-model="triangle.rotation" floor="0" ceiling="359" step="5" precsion="1"></slider>
但你也可以使用论坛。
这是我的plunker http://plnkr.co/edit/x0egXI
答案 7 :(得分:3)
这是我实现旋转图像的方式,我认为叠加形式的标记和叠加位置到位,下面的代码将被添加。
不使用任何其他库,它会被旋转,您需要解决方法为叠加层添加点击事件和鼠标事件,与标记点击事件类似。
使用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>
答案 8 :(得分:2)
每次图像更改时,您都可以调用yourmarker.setIcon(canvas.toDataUrlOrSomeThig)。我在api参考中没有看到任何直接使用canvas元素的内容,除非你实现了自己的google.maps.OverlayView。
如果您只想要动画,可以使用gif,并添加优化的标记选项:false。
答案 9 :(得分:2)
最简单的方法是使用rotation property of google.maps.Symbol。只需在创建或更新标记时将其设置为图标的属性:
new google.maps.Marker({
position: map.getCenter(),
icon: {
path: google.maps.SymbolPath.FORWARD_CLOSED_ARROW,
scale: 7,
rotation: 193
},
map: map
});
答案 10 :(得分:2)
我们的想法是首先在隐藏的画布上绘制旋转的标记图像。
说,你有一个隐藏的画布:
<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);
}
}
以上是我的原始代码。我保持完好无损,以便您可以看到我的其他优化。
答案 11 :(得分:2)
没有人提到使用预旋转图标。根据您的应用程序,您可以选择一个图标并将其旋转+10度,+ 20度... +350度,而不是旋转标记本身,只需为其分配不同的图标-如果分辨率为10度,则可以分配36个图标足够。这对客户的资源也很轻。
在下面的示例中,我生成了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
})
答案 12 :(得分:1)
使用MarkerWithLabel Library,您可以通过以下方式实现:
var ico = document.createElement('img');
ico.src = 'ImageSource';
ico.setAttribute('style', 'transform:rotate('30deg);');
mapMarkers[0].labelContent = ico;
mapMarkers[0].label.draw();
答案 13 :(得分:0)
我找到了一种简单的方法来旋转google标记的png图像标记。创建一个覆盖google.maps.OverlayView的自定义标记,然后简单地使用css / inline样式旋转图像
export const createCustomMarker = ({ OverlayView = google.maps.OverlayView, ...args }) => {
class GoogleMarker extends OverlayView {
options: any = {};
div: any = null;
innerHtml: any = null;
constructor(options) {
super();
this.options = options;
this.setMap(options.map);
}
createDiv() {
const options = this.options;
this.div = document.createElement('div');
this.div.style.position = 'absolute';
this.setRotation(this.options.rotation);
if (options.icon) {
this.setInnerHtml(this.getInnerImageHtml(options));
}
}
getInnerImageHtml(options) {
const size = this.getSize(options);
const label = this.options.label;
const labelHtml = label ? `<span style="color:black;margin-left: -40px;width: 100px;text-align: center;display: block;font-weight:bold;">${label}</span>` : "";
return `<img style="height:${size.height}px;width:${size.width}px" id="${options.id || ''}" src="${options.icon}">${labelHtml}`;
}
addListeners() {
const self = this;
google.maps.event.addDomListener(this.div, 'click', event => {
google.maps.event.trigger(self, 'click');
});
this.div.onmouseenter = function () {
debugger
google.maps.event.trigger(self, 'onmouseenter');
}
this.div.onmouseover = function () {
google.maps.event.trigger(self, 'onmouseover');
}
this.div.onmouseleave = function () {
google.maps.event.trigger(self, 'onmouseleave');
}
this.div.onmouseout = function () {
google.maps.event.trigger(self, 'onmouseout');
}
}
appendDivToOverlay(appendDiv: any) {
const panes: google.maps.MapPanes = this.getPanes();
panes.floatPane.appendChild(appendDiv);
}
setRotation(degrees: number) {
if (this.div) {
this.div.style.transform = 'rotate(' + degrees + 'deg)';
}
this.options.rotation = degrees;
}
getRotation() {
return this.options.rotation;
}
setInnerHtml(html: string) {
this.innerHtml = html;
this.div.innerHTML = this.innerHtml;
}
private positionDiv(div: any, options: any) {
if (div != null) {
const point = this.getProjection().fromLatLngToDivPixel(options.latlng);
if (point) {
const size = this.getSize(options);
const anchor = options.anchor ? options.anchor : new google.maps.Point((size.width / 2), (size.height / 2))
const leftAnchor = anchor.x;
const topAnchor = anchor.y;
div.style.left = `${point.x - leftAnchor}px`;
div.style.top = `${point.y - topAnchor}px`;
}
}
}
private getSize(options) {
const size = options.size || { height: 52, width: 52 };
return size;
}
draw() {
if (!this.div) {
this.createDiv();
this.appendDivToOverlay(this.div);
this.addListeners();
}
this.positionDiv(this.div, this.options);
}
remove() {
if (this.div) {
this.div.parentNode.removeChild(this.div);
this.div = null;
}
}
setVisible(value: boolean) {
if (this.div) {
this.div.style["display"] = value ? "block" : "none";
}
}
getVisible() {
if (this.div) {
return this.div.style["display"] == "none";
}
return false;
}
setPosition(position) {
this.options.latlng = position;
this.infoOptions.latlng = position;
this.positionDiv(this.div, this.options);
}
getPosition() {
return this.options.latlng;
}
getDraggable() {
return false;
}
isHTML(html: string) {
return /<([A-Za-z][A-Za-z0-9]*)\b[^>]*>(.*?)<\/\1>/.test(html);
}
}
return new GoogleMarker(args)
}
创建此自定义标记后-通过以下方式初始化标记
import { createCarMarker } from "./marker.component"; // dynamic path to component
let marker = createCarMarker({
id: id, // will add id to the parent container div
latlng: new google.maps.LatLng(0, 0), // replace latitude-longitude with your values
map: this.map,
size: new google.maps.Size(52, 52), // replace the image size with your values
rotation: markerData.direction, // Provide values in degrees
icon: iconUrl, // Replace it with your image url
label: markerLabel // Provide marker label. Optional field
});
现在只需使用以下方法旋转标记即可
marker.setRotation(180); // You just need to call only this method every-time the degrees changes.
收听标记上的更改。
google.maps.event.addDomListener(marker, 'click', function (event) {
});
google.maps.event.addListener(marker, 'onmouseenter', function (event) {
});
google.maps.event.addListener(marker, 'onmouseleave', function (event) {
});
google.maps.event.addListener(marker, 'onmouseover', function (event) {
});
google.maps.event.addListener(marker, 'onmouseout', function (event) {
});
您可以根据需要自定义侦听器或在自定义标记类中添加新内容/更新。
答案 14 :(得分:0)
假设您仅在Google地图中使用该图像,则可以执行以下操作
bearing = 20
document.querySelectorAll('img[src="/images/imageName"]').forEach((node) => {
node.style['transform'] = `rotate(${bearing}deg)`
node.style['webkitTransform'] = `rotate(${bearing}deg)`
node.style['MozTransform'] = `rotate(${bearing}deg)`
node.style['msTransform'] = `rotate(${bearing}deg)`
node.style['OTransform'] = `rotate(${bearing}deg)`
})
这会到达dom树,并设置标记图标的变换以旋转所需的角度。图片imageName
应该朝北
不确定是否需要Webkit,Moz,ms和O版本,但是??♂️不会受伤
答案 15 :(得分:-1)
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",
});