【问题标题】:Adding icon in the middle of created SVG path in Google Maps在 Google 地图中创建的 SVG 路径中间添加图标
【发布时间】:2016-11-23 04:52:07
【问题描述】:

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

我正在尝试在 Google 地图中的两个坐标之间创建一条曲线路径,类似于 kiwi.com 中显示的折线(将卡片悬停在可用航班中时)。不幸的是,折线还不支持此功能,当两个点彼此靠近时,这会使 2 条折线相互重叠。我什至尝试使用测地线选项创建两条折线,而另一条则没有,但这条线似乎仍然在两个近点上重叠。我在此链接curve svg path 中找到了 geocodezip 的解决方案,它使用 svg 路径而不是使用折线来绘制曲线,但未能在创建的路径中间添加箭头。有没有办法使用这种方法实现类似于 kiwi.com 的中间带箭头的线?这是我当前基于 geocodezip 的 svg 路径的代码

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>

【问题讨论】:

  • 你想放在行中间的“箭头”是什么?

标签: javascript google-maps


【解决方案1】:

使用“SVG”标记,你不能使用漂亮的symbols on a polyline,你需要计算箭头的位置和方向,然后将它们添加到地图中。

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

代码 sn-p:

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>

【讨论】:

    猜你喜欢
    • 2018-05-13
    • 2021-11-24
    • 1970-01-01
    • 1970-01-01
    • 2019-10-09
    • 1970-01-01
    • 2017-04-22
    • 2018-01-28
    • 2021-04-03
    相关资源
    最近更新 更多