13

Googleマップを作成し、その上にポリラインを描画しました。次に、ポリインの開始にマーカーを追加しました(ポリラインの開始座標と同じ座標)。

私ができるようにしたいのは、マーカーをつかんでドラッグすることですが、ポリラインに沿ってのみドラッグでき、離れたり横にドラッグしたりできないように、マーカーをポリラインに「固定」します。

ドラッグ可能なマーカーをGMV3のパスに限定することは可能ですか?そうでない場合、これがどのように行われるかを誰かが考えることができますか?ユーザーがマーカーをドロップしたときに、マーカーをパス上の最も近いポイントにスナップする可能性がありますが、よりスムーズな「パスに沿ったドラッグ」効果が必要です。

ArcGisの提案もあります。これは理論上の問題であるため、コードを提供していません。

さらに説明する必要がある場合はお知らせください。

前もって感謝します

4

2 に答える 2

13

さて、私はこれを解決することができました。それは正確にはエレガントではなく、改善できると確信していますが、私が思いついた一般的な概念は次のとおりです。

GPXファイルからlatlngポイントの配列を作成しましたが、ログポイントは20秒ごとにしか記録されません。これは私の目的には十分な粒度ではないので、gpxによってログに記録されたポイントの各ペアの間に約10ポイント(直線上)でポイントの配列をパディングしました。

$.each(array_of_points_to_pad, function(key, pt) {
    var current_point = pt;//The current point
    var next_point = array_of_points_to_pad[key + 1];//The point immediately after the current point

    //Check that we're not on the last point 
    if (typeof next_point !== 'undefined') {
        //Get a 10th of the difference in latitude between current and next points
        var lat_incr = (next_point.lat() - current_point.lat()) / 10;

        //Get a 10th of the difference in longitude between current and next points
        var lng_incr = (next_point.lng() - current_point.lng()) / 10;

        //Add the current point to a new padded_points array
        padded_points.push(current_point);

        //Now add 10 additional points at lat_incr & lng_incr intervals between current and next points (in the new padded_points array)
        for (var i = 1; i <= 10; i++) {
            var new_pt = new google.maps.LatLng(current_point.lat() + (i * lat_incr), current_point.lng() + (i * lng_incr));
            padded_points.push(new_pt);
        }
    }
});

より洗練されたポイントの配列ができたので、これを使用してポリラインをプロットします。追加のポイントはすべて、既存のポイント間の直線的な「カラスのように」線上にあるため、パディングされたポリラインは、パディングなしで描画されたポリラインと同じように見えます。

var line = new google.maps.Polyline({
    path: polyline_path_points_padded,
    strokeColor: '#ff0000',
    strokeOpacity: 1.0,
    strokeWeight: 2
});
line.setMap(map);

次に、行の先頭にドラッグ可能なマーカーを追加します。

var latLng = new google.maps.LatLng(startlat,startlng);
var marker = new google.maps.Marker({
  position: latLng,
  map: map,
  draggable:true
});

あとは、このマーカーのドラッグイベントとドラッグエンドイベントを制御するだけです。

google.maps.event.addDomListener(marker,'dragend',function(e){
    marker.setPosition(find_closest_point_on_path(e.latLng,padded_points));
});

google.maps.event.addDomListener(marker,'drag',function(e){
    marker.setPosition(find_closest_point_on_path(e.latLng,padded_points));
});

ここでは、ドラッグ中およびマーカーがドロップされたときに、マーカーのlatLngを関数find_closest_point_on_path()に送信するだけです。検索するパスとして、パディングされたポイントの配列を送信します。

関数は次のようになります。

function find_closest_point_on_path(marker_pt,path_pts){
    distances = new Array();
    distance_keys = new Array();
    $.each(path_pts,function(key, path_pt){
        var R = 6371; // km
        var dLat = (path_pt.lat()-marker_pt.lat()).toRad();
        var dLon = (path_pt.lng()-marker_pt.lng()).toRad();
        var lat1 = marker_pt.lat().toRad();
        var lat2 = path_pt.lat().toRad();

        var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
                Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(lat1) * Math.cos(lat2); 
        var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); 
        var d = R * c;
        //Store the key of the point on the path that matches this distance
        distance_keys[d] = key; 

    });
            //Return the latLng pt on the path for the second closest point 
    return path_pts[distance_keys[_.min(distances)]+1];
}

この関数が(ラジアン度からラジアン関数の助けを借りて)行うことは、マーカーの位置とライン上のすべてのポイントとの間の距離を見つけることです。次に、マーカーに最も近いポイントを見つけて、そのポイントの次に近いポイントの座標を返します。このように、マーカーをドラッグまたはドロップすると、(1つの場所にとどまるのではなく)次のポイントに「スナップ」します。

以下のJSフィドルの作業:

http://jsfiddle.net/Z5GwW/4/

クロスブラウザテストは行っていません。Chromeの最新バージョンで動作します。

于 2012-05-23T01:38:34.880 に答える