在Google地图中已创建的SVG路径的中间添加图标 [英] Adding icon in the middle of created SVG path in Google Maps

查看:86
本文介绍了在Google地图中已创建的SVG路径的中间添加图标的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在Google Maps Javascript的路径中间创建带有箭头符号的弯曲路径

我正在尝试在Google地图中的两个坐标之间创建一条弯曲的路径,类似于kiwi.com中显示的折线(在可用航班上悬停一张卡片时).不幸的是,折线尚不支持此功能,当两个点彼此靠近时,该功能会使2条折线相互重叠.我什至尝试创建两条折线,一条使用测地线选项,而另一条没有,但是该线似乎仍然重叠在两个近点上.我从 geocodezip 的链接

I'm trying to create a curved path in between two coordinates in Google maps, similar to the polylines displayed in kiwi.com (when hovering a card in the available flights). Unfortunately Polylines do not support this feature yet which makes 2 polylines overlap each other when the two points are near each other. I even tried to create two polylines one using geodesic option while the other don't but the line seems to still overlap on two near points. I found a solution from geocodezip in this link curve svg path which uses svg path to draw the curved line instead of using polylines but failed to add an arrow in the middle of the created path. Is there a way to achieve a line with an arrow in the middle similar to kiwi.com using this approach? Here's my current code based on geocodezip's svg path:

var map;

var curvature = 0.175;
var invercurve = -0.175;


$(window).load(function() {
  init();
});


function init() {
  var Map = google.maps.Map,
    LatLng = google.maps.LatLng,
    LatLngBounds = google.maps.LatLngBounds,
    Marker = google.maps.Marker,
    Point = google.maps.Point;


  var pos1 = new LatLng(35.6730185, 139.4302008);
  var pos2 = new LatLng(34.678395, 135.4601306);

  var bounds = new LatLngBounds();
  bounds.extend(pos1);
  bounds.extend(pos2);

  map = new Map(document.getElementById('map-canvas'), {
    center: bounds.getCenter(),
    zoom: 6
  });
  map.fitBounds(bounds);

  var markerP1 = new Marker({
    position: pos1,
    map: map
  });
  var markerP2 = new Marker({
    position: pos2,
    map: map
  });





  var curveMarker, curveMarkerInv;

  function updateCurveMarker() {
    var pos1 = markerP1.getPosition(), // latlng
      pos2 = markerP2.getPosition(),
      projection = map.getProjection(),
      p1 = projection.fromLatLngToPoint(pos1), // xy
      p2 = projection.fromLatLngToPoint(pos2);


    var e = new Point(p2.x - p1.x, p2.y - p1.y), // endpoint (p2 relative to p1)
      m = new Point(e.x / 2, e.y / 2), // midpoint
      o = new Point(e.y, -e.x), // orthogonal
      c = new Point( // curve control point
        m.x + curvature * o.x,
        m.y + curvature * o.y);

    var f = new Point(p2.x - p1.x, p2.y - p1.y), // endpoint (p2 relative to p1)
      n = new Point(f.x / 2, f.y / 2), // midpoint
      p = new Point(f.y, -f.x), // orthogonal
      d = new Point( // curve control point
        n.x + invercurve * p.x,
        n.y + invercurve * p.y);
    console.log('F:' + p1.x * curvature / 2 + ' ' + p1.y * curvature / 2);


    var pathDef = 'M 0,0 ' +
      'q ' + c.x + ',' + c.y + ' ' + e.x + ',' + e.y;

    var pathDefInv = 'M 0,0 ' +
      'q ' + d.x + ',' + d.y + ' ' + f.x + ',' + f.y;

    var zoom = map.getZoom(),
      scale = 1 / (Math.pow(2, -zoom));

    var marker = new google.maps.Marker({
      position: new google.maps.LatLng,
      icon: {
        path: google.maps.SymbolPath.FORWARD_CLOSED_ARROW,
        scale: 10
      },
      //draggable: true,
      map: map
    });

    var symbol = {
      path: pathDef,
      scale: scale,
      strokeWeight: 2,
      strokeColor: '#f00',
      fillColor: 'none'
    };

    var symbolInv = {
      path: pathDefInv,
      scale: scale,
      strokeWeight: 2,
      strokeColor: '#f00',
      fillColor: 'none'
    };



    if (!curveMarker) {
      curveMarker = new Marker({
        position: pos1,
        clickable: false,
        icon: symbol,
        zIndex: 0, // behind the other markers
        map: map
      });
      curveMarkerInv = new Marker({
        position: pos1,
        clickable: false,
        icon: symbolInv,
        zIndex: 0, // behind the other markers
        map: map
      });

    } else {
      curveMarker.setOptions({
        position: pos1,
        icon: symbol,
      });
      curveMarkerInv.setOptions({
        position: pos1,
        icon: symbolInv,
      });
    }
  }

  google.maps.event.addListener(map, 'projection_changed', updateCurveMarker);
  google.maps.event.addListener(map, 'zoom_changed', updateCurveMarker);

  google.maps.event.addListener(markerP1, 'position_changed', updateCurveMarker);
  google.maps.event.addListener(markerP2, 'position_changed', updateCurveMarker);

  var lineLength = google.maps.geometry.spherical.computeDistanceBetween(markerP1.getPosition(), markerP2.getPosition());
  var lineHeading = google.maps.geometry.spherical.computeHeading(markerP1.getPosition(), markerP2.getPosition());


}

#map-canvas {
  height: 100%;
}
html,
body {
  height: 100%;
  margin: 0;
  padding: 0;
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="http://maps.google.com/maps/api/js?libraries=geometry&sensor=false"></script>

<div id="map-canvas"></div>

推荐答案

使用"SVG"标记,您将无法使用漂亮的

With the "SVG" markers, you can't use the nifty symbols on a polyline, you need to calculate the position and heading of the arrows, then add them to the map.

// point for FORWARD center arrow
var c2 = new Point(
  c.x + p1.x - curvature * o.x * 0.5,
  c.y + p1.y - curvature * o.y * 0.5
);
var aPt = projection.fromPointToLatLng(c2);
var aMkr = new google.maps.Marker({
  position: aPt,
  map: map,
  icon: {
    path: google.maps.SymbolPath.FORWARD_CLOSED_ARROW,
    rotation: lineHeading,
    scale: 2
  }
});
// point for BACKWARD center arrow
var d2 = new Point(
  d.x + p1.x - invercurve * p.x * 0.5,
  d.y + p1.y - invercurve * p.y * 0.5
);
var bPt = projection.fromPointToLatLng(d2);
var bMkr = new google.maps.Marker({
  position: bPt,
  map: map,
  icon: {
    path: google.maps.SymbolPath.BACKWARD_CLOSED_ARROW,
    rotation: lineHeading,
    scale: 2
  }
});

代码段:

var map;
var curvature = 0.175;
var invercurve = -0.175;

$(window).load(function() {
  init();
});

function init() {
  var Map = google.maps.Map,
    LatLng = google.maps.LatLng,
    LatLngBounds = google.maps.LatLngBounds,
    Marker = google.maps.Marker,
    Point = google.maps.Point;

  var pos1 = new LatLng(35.6730185, 139.4302008);
  var pos2 = new LatLng(34.678395, 135.4601306);

  var bounds = new LatLngBounds();
  bounds.extend(pos1);
  bounds.extend(pos2);

  map = new Map(document.getElementById('map-canvas'), {
    center: bounds.getCenter(),
    zoom: 6
  });
  google.maps.event.addListener(map, 'click', function(evt) {
    document.getElementById('status').innerHTML = evt.latLng.toUrlValue(6);
  });
  map.fitBounds(bounds);

  var markerP1 = new Marker({
    position: pos1,
    map: map
  });
  var markerP2 = new Marker({
    position: pos2,
    map: map
  });

  var curveMarker, curveMarkerInv;

  function updateCurveMarker() {
    var pos1 = markerP1.getPosition(), // latlng
      pos2 = markerP2.getPosition(),
      projection = map.getProjection(),
      p1 = projection.fromLatLngToPoint(pos1), // xy
      p2 = projection.fromLatLngToPoint(pos2);

    var e = new Point(p2.x - p1.x, p2.y - p1.y), // endpoint (p2 relative to p1)
      m = new Point(e.x / 2, e.y / 2), // midpoint
      mPt = projection.fromPointToLatLng(m);
    console.log(mPt.toUrlValue(6));

    var mMkr = new google.maps.Marker({
      position: mPt,
      map: map,
      icon: {
        path: google.maps.SymbolPath.FORWARD_CLOSED_ARROW,
        scale: 2
      }
    });
    o = new Point(e.y, -e.x), // orthogonal
      c = new Point( // curve control point
        m.x + curvature * o.x,
        m.y + curvature * o.y);
    var c2 = new Point(
      c.x + p1.x - curvature * o.x * 0.5,
      c.y + p1.y - curvature * o.y * 0.5
    );

    var aPt = projection.fromPointToLatLng(c2);
    console.log(aPt.toUrlValue(6));

    var aMkr = new google.maps.Marker({
      position: aPt,
      map: map,
      icon: {
        path: google.maps.SymbolPath.FORWARD_CLOSED_ARROW,
        rotation: lineHeading,
        scale: 2
      }
    });

    var f = new Point(p2.x - p1.x, p2.y - p1.y), // endpoint (p2 relative to p1)
      n = new Point(f.x / 2, f.y / 2), // midpoint
      p = new Point(f.y, -f.x), // orthogonal
      d = new Point( // curve control point
        n.x + invercurve * p.x,
        n.y + invercurve * p.y);
    var d2 = new Point(
      d.x + p1.x - invercurve * p.x * 0.5,
      d.y + p1.y - invercurve * p.y * 0.5
    );
    var bPt = projection.fromPointToLatLng(d2);
    console.log(aPt.toUrlValue(6));
    var bMkr = new google.maps.Marker({
      position: bPt,
      map: map,
      icon: {
        path: google.maps.SymbolPath.BACKWARD_CLOSED_ARROW,
        rotation: lineHeading,
        scale: 2
      }
    });
    console.log('F:' + p1.x * curvature / 2 + ' ' + p1.y * curvature / 2);

    var pathDef = 'M 0,0 ' +
      'q ' + c.x + ',' + c.y + ' ' + e.x + ',' + e.y;
    var pathDefInv = 'M 0,0 ' +
      'q ' + d.x + ',' + d.y + ' ' + f.x + ',' + f.y;

    var zoom = map.getZoom(),
      scale = 1 / (Math.pow(2, -zoom));

    var marker = new google.maps.Marker({
      position: new google.maps.LatLng,
      icon: {
        path: google.maps.SymbolPath.FORWARD_CLOSED_ARROW,
        scale: 10
      },
      //draggable: true,
      map: map
    });

    var symbol = {
      path: pathDef,
      scale: scale,
      strokeWeight: 2,
      strokeColor: '#f00',
      fillColor: 'none'
    };

    var symbolInv = {
      path: pathDefInv,
      scale: scale,
      strokeWeight: 2,
      strokeColor: '#f00',
      fillColor: 'none'
    };

    if (!curveMarker) {
      curveMarker = new Marker({
        position: pos1,
        clickable: false,
        icon: symbol,
        zIndex: 0, // behind the other markers
        map: map
      });
      curveMarkerInv = new Marker({
        position: pos1,
        clickable: false,
        icon: symbolInv,
        zIndex: 0, // behind the other markers
        map: map
      });

    } else {
      curveMarker.setOptions({
        position: pos1,
        icon: symbol,
      });
      curveMarkerInv.setOptions({
        position: pos1,
        icon: symbolInv,
      });
    }
  }

  google.maps.event.addListener(map, 'projection_changed', updateCurveMarker);
  google.maps.event.addListener(map, 'zoom_changed', updateCurveMarker);

  google.maps.event.addListener(markerP1, 'position_changed', updateCurveMarker);
  google.maps.event.addListener(markerP2, 'position_changed', updateCurveMarker);

  var lineLength = google.maps.geometry.spherical.computeDistanceBetween(markerP1.getPosition(), markerP2.getPosition());
  var lineHeading = google.maps.geometry.spherical.computeHeading(markerP1.getPosition(), markerP2.getPosition());


}

#map-canvas {
  height: 100%;
}
html,
body {
  height: 100%;
  margin: 0;
  padding: 0;
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="http://maps.google.com/maps/api/js?libraries=geometry&sensor=false"></script>
<div id="status"></div>
<div id="map-canvas"></div>

这篇关于在Google地图中已创建的SVG路径的中间添加图标的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆