2017-01-09 2 views
1

Я хочу показать несколько кривых линий на основе данных JSON, которые я извлекаю из базы данных, которые являются координатами x, y, каждая строка представляет собой отдельный массив из нескольких объекты, содержащие координаты, чтобы сделать полный путь.Нарисуйте кривую между перетаскиваемыми точками с контрольными точками для настройки кривой SVG и d3.js

Все точки должны перетаскиваться, и между каждыми двумя точками должна быть контрольная точка для настройки кривой каждой линии.

До сих пор с помощью Интернета у меня есть набор точек, которые можно перетаскивать, но контрольные точки для кривой являются лишь одной из координат и не создаются динамически, возможно, позиция контрольной точки должна быть разработана и подается в массив до выхода, но я не уверен, что это способ сделать это. (Надежда, что имеет смысл)

См JSFiddle

var point_positions = []; 
var json_data_muliple_lines = [[{"id": "82","x": "100","y": "50"}, {"id": "83","x": "25","y": "110"}, {"id": "97","x": "90","y": "150"}, {"id": "98","x": "150","y": "224"}, {"id": "99","x": "250","y": "150"}, {"id": "100","x": "300","y": "200"}, {"id": "100","x": "320","y": "230"}],[{"id": "1","x": "120","y": "60"}, {"id": "2","x": "30","y": "150"}, {"id": "3","x": "120","y": "170"}, {"id": "4","x": "180","y": "260"}, {"id": "5","x": "300","y": "250"}]]; 
var json_data = [{"line_pi_id": "82","x": "100","y": "50"}, {"line_pi_id": "83","x": "25","y": "110"}, {"line_pi_id": "97","x": "90","y": "150"}, {"line_pi_id": "98","x": "150","y": "224"}, {"line_pi_id": "99","x": "250","y": "150"}, {"line_pi_id": "100","x": "300","y": "200"}, {"line_pi_id": "100","x": "320","y": "230"}]; 

$.each(json_data, function(i, item) { 
    line_response = json_data[i]; 
    var line_pi_id = line_response.line_pi_id; 
    var li_x = parseInt(line_response.x); 
    var li_y = parseInt(line_response.y); 

    point_positions.push({ 
     x: li_x, 
     y: li_y 
    }) 
}) 
var svg = d3.select('#curves').append('svg') 
    .attr({ 
     width: 1000, 
     height: 1000 
    }); 
var handleRadius = 8; 

function curves_init(point_positions) { 
    var curves = [{ 
     type: 'Q', 
     points: point_positions 
    }]; 
    console.log("curves", curves); 
    var controlLineLayer = svg.append('g').attr('class', 'control-line-layer'); 
    var mainLayer = svg.append('g').attr('class', 'main-layer'); 
    var handleTextLayer = svg.append('g').attr('class', 'handle-text-layer'); 
    var handleLayer = svg.append('g').attr('class', 'handle-layer'); 

    var drag = d3.behavior.drag() 
     .origin(function(d) { 
      return d; 
     }) 
     .on('drag', dragmove); 

    function dragmove(d) { 
     d.x = d3.event.x; 
     d.y = d3.event.y; 
     d3.select(this).attr({ 
      cx: d.x, 
      cy: d.y 
     }); 
     d.pathElem.attr('d', pathData); 
     if (d.controlLineElem) { 
      d.controlLineElem.attr('d', controlLinePath); 
     } 
     handleTextLayer.selectAll('text.handle-text.path' + d.pathID + '.p' + (d.handleID + 1)) 
      .attr({ 
       x: d.x, 
       y: d.y 
      }).text(handleText(d, d.handleID)); 
    } 
    show_curves(controlLineLayer, mainLayer, handleTextLayer, handleLayer, curves, drag); 
} 

function pathData(d) { 
    var p = d.points; 
    curve = [ 
     'M', p[0].x, ' ', p[0].y, 
     'Q', p[1].x, ' ', p[1].y, 
     ' ', p[2].x, ' ', p[2].y, 
     ' ', p[3].x, ' ', p[3].y, 
     ' ', p[4].x, ' ', p[4].y, 
     ' ', p[5].x, ' ', p[5].y, 
     ' ', p[6].x, ' ', p[6].y 
    ].join(''); 

    console.log("curve", curve); 
    return curve; 
} 

function controlLinePath(d) { 
    var values = []; 
    d.points.forEach(function(p) { 
     values.push(p.x); 
     values.push(p.y); 
    }); 
    return 'M' + values.join(' '); 
} 

function handleText(d, i) { 
    return 'p' + (i + 1) + ': ' + d.x + '/' + d.y; 
} 

function show_curves(controlLineLayer, mainLayer, handleTextLayer, handleLayer, curves, drag) { 
    mainLayer.selectAll('path.curves').data(curves) 
     .enter().append('path') 
     .attr({ 
      'class': function(d, i) { 
       return 'curves path' + i; 
      }, 
      d: pathData 
     }) 
     .each(function(d, i) { 
      var pathElem = d3.select(this), 
       controlLineElem, 
       handleTextElem; 
      if (d.type !== 'L') { 
       controlLineElem = controlLineLayer.selectAll('path.control-line.path' + i) 
        .data([d]).enter().append('path') 
        .attr({ 
         'class': 'control-line path' + i, 
         d: controlLinePath(d) 
        }); 
      } 
      handleTextElem = handleTextLayer.selectAll('text.handle-text.path' + i) 
       .data(d.points).enter().append('text') 
       .attr({ 
        'class': function(handleD, handleI) { 
         return 'handle-text path' + i + ' p' + (handleI + 1); 
        }, 
        x: function(d) { 
         return d.x 
        }, 
        y: function(d) { 
         return d.y 
        }, 
        dx: 10, 
        dy: 0 
       }) 
       .text(handleText); 
      handleLayer.selectAll('circle.handle.path' + i) 
       .data(d.points).enter().append('circle') 
       .attr({ 
        'class': 'handle path' + i, 
        cx: function(d) { 
         return d.x 
        }, 
        cy: function(d) { 
         return d.y 
        }, 
        r: handleRadius 
       }) 
       .each(function(d, handleI) { 
        d.pathID = i; 
        d.handleID = handleI; 
        d.pathElem = pathElem; 
        d.controlLineElem = controlLineElem; 
       }) 
       .call(drag); 
     }); 
} 
curves_init(point_positions); 

Так мне нужна ваша помощь, чтобы выяснить, как создать контрольную точку между каждыми 2 координат, и если мне нужно изменить вывод JSON для построения координаты точки управления и как адаптировать этот код для нескольких путей, поскольку он работает только, если функция pathData() установлена ​​вручную в соответствии с выходом JSON.

Любая помощь приветствуется!

ответ

0

Чтобы преобразовать прямую линию в эквивалентную кривую безье, просто вставьте контрольные точки в положение 1/3 и 2/3 между начальной и конечной точками.

<svg width="500" height="500"> 
 
    
 
    <path d="M 100 100 
 
      C 200 200 300 300 400 400" 
 
     fill="none" stroke="blue" stroke-width="10"/> 
 
    
 
</svg>

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

  • Нет связанных вопросов^_^