使用Google地图的折线编码绘制贝塞尔曲线。

3
我正在尝试使用SVG路径在Polyline中绘制谷歌地图中的贝塞尔曲线。起初,我使用了一个标记而不是Curved line between two near points in google maps中类似的方法,这给出了我想要的结果。然而,由于不可能在标记下拖动地图,所以我不能使用这种方法。

因此,我改用Polyline代替标记。现在当我缩小地图时,我得到相同的好结果,但是当我放大时,曲线变得“裁剪”了。

以下是代码:

function initialize() {
    var mapOptions = {
        mapTypeId: google.maps.MapTypeId.ROADMAP
    };

    var map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);

    var coord1 = new google.maps.LatLng(49.165876, -123.152446);
    var coord2 = new google.maps.LatLng(25.786328, -80.193694);
    var bounds = new google.maps.LatLngBounds();
    bounds.extend(coord1);
    bounds.extend(coord2);
    map.fitBounds(bounds);

    pLineOpt = {
        path: [coord1, coord2],
        strokeWeight: 4,
        strokeOpacity: 0,
        map: map,
    }

    pLine = new google.maps.Polyline(pLineOpt);

    var markers = [
        new google.maps.Marker({
            position: coord1,
            map: map
        }),
        new google.maps.Marker({
            position: coord2,
            map: map
        })
    ];

    google.maps.event.addListener(map, 'zoom_changed', function () {
        //points
        var p1 = map.getProjection().fromLatLngToPoint(coord1);
        var p2 = map.getProjection().fromLatLngToPoint(coord2);
        //distance between points
        var d = new google.maps.Point(p2.x - p1.x, p2.y - p1.y);
        var lengthSqr = d.x * d.x + d.y * d.y;
        //middle point
        var m = new google.maps.Point(d.x / 2, d.y / 2);
        //slope of perpendicular line
        var perpK = -d.x / d.y;
        //distance to control point
        var ratioDistanceControlLengthSqr = 9;
        var controlDSqr = lengthSqr / ratioDistanceControlLengthSqr;
        var p3dX = Math.sqrt(controlDSqr / (Math.pow(perpK, 2) + 1));
        var p3dY = perpK * p3dX;
        //control point
        var p3 = new google.maps.Point(m.x - p3dX, m.y - p3dY);
        //curve path
        var path = "M 0 0 q " + p3.x + " " + p3.y + " " + d.x + " " + d.y;
        //calc scale                
        var zoom = map.getZoom();
        var scale = 1 / (Math.pow(2, -zoom));

        var icon = {
            path: path,
            scale: scale,
            strokeWeight: 3,
            strokeOpacity: 1,
        };

        pLineOpt.icons = [{
            fixedRotation: true,
            icon: icon,
            offset: '0'
        }];
        pLine.setOptions(pLineOpt);
    });
}

google.maps.event.addDomListener(window, 'load', initialize);

我已经用这段代码创建了一个jsfiddle: http://jsfiddle.net/s7djLzyd/3/

有人知道为什么在缩放时折线会被裁剪,是否有解决方法?

谢谢


你的折线在瓦片边界处被裁剪了。我经常看到这种情况,不确定为什么会发生在你的特定情况中,但可能是API瓦片渲染折线的一个bug。对于奇怪的问题,我总是建议首先尝试API的发布和冻结版本,但在这种情况下没有帮助 - geocodezip
2个回答

2

您需要修复您的折线选项:

pLineOpt = {
    path: [coord1, coord2],
    geodesic: true,
    strokeColor: '#000',
    strokeOpacity: 1.0,
    strokeWeight: 4
}

请尝试以下代码片段:也许这正是您想要的... :)

function initialize() {
    var mapOptions = {
        mapTypeId: google.maps.MapTypeId.ROADMAP
    };

    var map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);

    var coord1 = new google.maps.LatLng(49.165876, -123.152446);
    var coord2 = new google.maps.LatLng(25.786328, -80.193694);
    var bounds = new google.maps.LatLngBounds();
    bounds.extend(coord1);
    bounds.extend(coord2);
    map.fitBounds(bounds);

    pLineOpt = {
        path: [coord1, coord2],
        geodesic: true,
        strokeColor: '#000',
        strokeOpacity: 1.0,
        strokeWeight: 4
    }

    pLine = new google.maps.Polyline(pLineOpt);

    var markers = [
    new google.maps.Marker({
        position: coord1,
        map: map
    }),
    new google.maps.Marker({
        position: coord2,
        map: map
    })];

    pLine.setMap(map);

    google.maps.event.addListener(map, 'zoom_changed', function () {

    });
}

google.maps.event.addDomListener(window, 'load', initialize);
html, body, #map-canvas {
    height: 100%;
    width: 100%;
    margin: 0px;
    padding: 0px
}
<script src="https://maps.googleapis.com/maps/api/js?sensor=false&libraries=geometry,places&ext=.js"></script>

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


2

根据这个相关问题:Google Maps API:Bézier曲线折线包装

var curvedLine = new GmapsCubicBezier(
      49.165876, -123.152446, 
      33.811192,-115.032444, 
      30.820807,-123.749998, 
      25.786328, -80.193694, 
      0.01, map);

示例fiddle

生成地图截屏

代码片段:

var map;
var origLoc = new google.maps.LatLng(45, -85);

function initialize() {
  var mapOptions = {
    center: new google.maps.LatLng(33.811192, -115.032444),
    zoom: 3
  };
  map = new google.maps.Map(document.getElementById("map"), mapOptions);

  var coord1 = new google.maps.LatLng(49.165876, -123.152446);
  var coord2 = new google.maps.LatLng(25.786328, -80.193694);
  var marker1 = new google.maps.Marker({
    position: coord1,
    title: "marker 1",
    map: map
  });
  var marker2 = new google.maps.Marker({
    position: coord2,
    title: "marker 2",
    map: map
  });


  var curvedLine = new GmapsCubicBezier(
    49.165876, -123.152446,
    33.811192, -115.032444,
    30.820807, -123.749998,
    25.786328, -80.193694,
    0.01, map);
}
google.maps.event.addDomListener(window, 'load', initialize);

var GmapsCubicBezier = function(lat1, long1, lat2, long2, lat3, long3, lat4, long4, resolution, map) {

  var points = [];

  for (it = 0; it <= 1; it += resolution) {
    points.push(this.getBezier({
      x: lat1,
      y: long1
    }, {
      x: lat2,
      y: long2
    }, {
      x: lat3,
      y: long3
    }, {
      x: lat4,
      y: long4
    }, it));
  }

  for (var i = 0; i < points.length - 1; i++) {
    var Line = new google.maps.Polyline({
      path: [new google.maps.LatLng(points[i].x, points[i].y), new google.maps.LatLng(points[i + 1].x, points[i + 1].y, false)],
      geodesic: true,
      strokeOpacity: 1,
      strokeColor: 'black',
      /* icons: [{
          icon: {
              path: 'M 0,-2 0,2',
              strokeColor: 'violet',
              strokeOpacity: 1,
              strokeWeight: 4
          },
          repeat: '36px'
      }, {
          icon: {
              path: 'M -1,-2 -1,2',
              strokeColor: 'black',
              strokeOpacity: 1,
              strokeWeight: 2
          },
          repeat: '36px'
      }] */
    });
    Line.setMap(map);
  }
  // connect end of line to first point
  var Line = new google.maps.Polyline({
      path: [new google.maps.LatLng(lat1,long1),new google.maps.LatLng(points[points.length-1].x, points[points.length-1].y)],
      geodesic: true,
      strokeOpacity: 1,
      strokeColor: 'black',
      /* icons: [{
          icon: {
              path: 'M 0,-2 0,2',
              strokeColor: 'violet',
              strokeOpacity: 1,
              strokeWeight: 4
          },
          repeat: '36px'
      }, {
          icon: {
              path: 'M -1,-2 -1,2',
              strokeColor: 'black',
              strokeOpacity: 1,
              strokeWeight: 2
          },
          repeat: '36px'
      }] */
    });
    Line.setMap(map);
  
  return Line;
};


GmapsCubicBezier.prototype = {

  B1: function(t) {
    return t * t * t;
  },
  B2: function(t) {
    return 3 * t * t * (1 - t);
  },
  B3: function(t) {
    return 3 * t * (1 - t) * (1 - t);
  },
  B4: function(t) {
    return (1 - t) * (1 - t) * (1 - t);
  },
  getBezier: function(C1, C2, C3, C4, percent) {
    var pos = {};
    pos.x = C1.x * this.B1(percent) + C2.x * this.B2(percent) + C3.x * this.B3(percent) + C4.x * this.B4(percent);
    pos.y = C1.y * this.B1(percent) + C2.y * this.B2(percent) + C3.y * this.B3(percent) + C4.y * this.B4(percent);
    return pos;
  }
};
html,
body,
#map {
  height: 100%;
  margin: 0px;
  padding: 0px
}
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&libraries=geometry"></script>
<div id="map" style="float:left;width:100%;height:100%;"></div>


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接