2016-01-18 5 views
0

Я следил за Mike Bostock's tutorial для рендеринга элементов svg с D3 поверх карты листов, но в дополнение к функциональности в его примере я бы хотел, чтобы пользователи были способный переместить D3-визуализированные элементы на карту, перетащив их. То есть, я хочу, чтобы пользователи могли географически перемещать объекты в SVG-элементе, созданным D3, в панели наложения листов, перетаскивая эти элементы и сохраняя обновленные географические места размещения, когда пользователь перетаскивает или масштабирует карту листов.Как включить перетаскивание для элементов D3, наложенных на карту листовки

С помощью очень хрупкого редактирования html в событиях перетаскивания D3 мне удалось это сделать (see jsFiddle - перетащить синие круги, чтобы подтвердить функциональность), но я надеюсь найти лучший метод. Какие-либо предложения? Вот то, что я до сих пор:

var svg, g, map, collection, transform, path, json, d_string; 
json = get_json(); 
setup_map(); 

function setup_map(){ 
    map = L.map('map').fitBounds([[-3.82,-73.24],[-3.69,-73.35]]); 
    L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',{ 
     maxZoom: 18, 
     attribution: 'OpenStreetMap, D3' 
    }).addTo(map); 
    map.on("viewreset", reset); 
    setup_d3(); 
} 

function setup_d3(){ 
    svg = d3.select(map.getPanes().overlayPane).append("svg"); 
    g = svg.append("g").attr("class", "leaflet-zoom-hide"); 

    drag = d3.behavior.drag() 
    .origin(function(d) { return d; }) 
    .on("dragstart", dragstarted) 
    .on("drag", dragged) 
    .on("dragend", dragended); 

    transform = d3.geo.transform({point: projectPoint}); 
    path = d3.geo.path().projection(transform); 

    g.selectAll("path") 
    .data(json.features) 
    .enter().append("path"); 

    g.selectAll("path") 
    .attr('fill','blue') 
    .attr("r", 10) 
    .style("cursor", "pointer") 
    .call(drag); 
    reset(); 
} 

function reset() { 
    var buffer_space = 200; //so point markers are fully drawn, and to give you space to move markers around 
    bounds = path.bounds(json); 
    var topLeft = bounds[0], bottomRight = bounds[1]; 
    topLeft[0] -= buffer_space; 
    topLeft[1] -= buffer_space; 
    bottomRight[0] += buffer_space; 
    bottomRight[1] += buffer_space; 

    svg.attr("width", bottomRight[0] - topLeft[0]) 
     .attr("height", bottomRight[1] - topLeft[1]) 
     .style("left", topLeft[0] + "px") 
     .style("top", topLeft[1] + "px"); 

    g.attr("transform", "translate(" + -topLeft[0] + "," + -topLeft[1] + ")"); 
    g.selectAll("path").attr("d", path); 
} 

function projectPoint(x, y) { 
    var point = map.latLngToLayerPoint(new L.LatLng(y, x)); 
    this.stream.point(point.x, point.y); 
} 

function dragstarted(d) { 
    d3.event.sourceEvent.stopPropagation(); 
    d3.select(this).classed("dragging", true); 
    d_string = d3.select(this).attr("d"); 
    d_string = d_string.substring(d_string.indexOf("m")); 
} 

function dragged(d) { 
    var offset = get_leaflet_offset(); 
    var size = d3.select(this).attr("r")/2; 
    var pt = [d3.event.sourceEvent.clientX - size - offset[0], d3.event.sourceEvent.clientY - size - offset[1]]; 
    var hackpath = "M" + pt[0] + "," + pt[1] + d_string; 
    d3.select(this).attr("d", hackpath); 
} 

function dragended(d) { 
    var offset = get_leaflet_offset(); 
    var size = d3.select(this).attr("r")/2; 
    var pt = layer_to_LL(d3.event.sourceEvent.clientX - size - offset[0], d3.event.sourceEvent.clientY - size - offset[1]); 
    d.geometry.coordinates = [pt.lng, pt.lat]; 
    d3.select(this).classed("dragging", false); 
    reset(); 
} 

function get_leaflet_offset(){ 
    var trfm = $(".leaflet-map-pane").css('transform'); 
    trfm = trfm.split(", "); 
    return [parseInt(trfm[4]), parseInt(trfm[5])]; 
} 

function layer_to_LL(x,y){return map.layerPointToLatLng(new L.Point(x,y));} 

function projectPoint(x, y) { 
    var point = map.latLngToLayerPoint(new L.LatLng(y, x)); 
    this.stream.point(point.x, point.y); 
} 

function projectSinglePoint(x, y) { 
    var point = map.latLngToLayerPoint(new L.LatLng(y, x)); 
    console.log(point); 
    return point; 
} 

function get_json(){ 
    return { 
    "type": "FeatureCollection", 
    "crs": { 
     "type": "name", 
     "properties": {"name": "urn:ogc:def:crs:EPSG::4269"} 
    }, 
    "features": [{ 
     "type": "Feature", 
     "properties": {"id": "pt0"}, 
     "geometry": { 
      "type": "Point", 
      "coordinates": [-73.25, -3.72] 
     } 
    }, { 
     "type": "Feature", 
     "properties": {"id": "pt1"}, 
     "geometry": { 
      "type": "Point", 
      "coordinates": [-73.37, -3.82] 
     } 
    }, { 
     "type": "Feature", 
     "properties": {"id": "pt2"}, 
     "geometry": { 
      "type": "Point", 
      "coordinates": [-73.32, -3.67] 
     } 
    }] 
    } 
} 

Спасибо, Крис

ответ

0

На мой взгляд, я бы использовал опцию листовку по умолчанию, чтобы сделать markers и установить его в качестве draggable

Что-то вроде этого:

json.features.forEach(function(d) { 
    var marker = L.marker(new L.LatLng(d.geometry.coordinates[1], d.geometry.coordinates[0]), { 
     draggable: true 
    }); 
    marker.addTo(map); 
    }) 

Это облегчит вам выполнение логики перетаскивания на D3, вы можете увидеть, сколько кода было уменьшено :)

Рабочего код here

документация Маркер here

Надеется, что это помогает!

+0

Спасибо Кирилл. Это не отвечает на вопрос, но это очень полезная альтернатива! – iamchriskelley

Смежные вопросы