使用谷歌地图折线绘制贝塞尔曲线

时间:2015-04-22 22:49:23

标签: javascript google-maps google-maps-api-3

我试图通过在折线中使用SVG路径在Google地图中绘制贝塞尔曲线。起初我使用的标记与Curved line between two near points in google maps类似,后者给出了我之后的结果。但是,由于无法在地图下拖动地图,我无法使用此方法。

所以我切换到折线而不是标记。现在,当我缩小时,我得到了相同的好结果,但是当我放大曲线变为"裁剪"。

以下是代码:

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

我用代码http://jsfiddle.net/s7djLzyd/3/

制作了一个jsfiddle

有人知道缩放时裁剪折线的原因,以及是否有解决方法?

由于

1 个答案:

答案 0 :(得分:2)

从这个相关问题:Google Maps API: Bézier curve polyline wrap

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

example 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;
  }
};
&#13;
html,
body,
#map {
  height: 100%;
  margin: 0px;
  padding: 0px
}
&#13;
<script src="https://maps.googleapis.com/maps/api/js?v=3&libraries=geometry"></script>
<div id="map" style="float:left;width:100%;height:100%;"></div>
&#13;
&#13;
&#13;