Задача с подключенным графом с использованием JSfiddle

#javascript #web #jsfiddle

#javascript #веб #jsfiddle

Вопрос:

Я хочу разработать тестовое задание, в котором пользователь должен попытаться соединить символы по порядку. Например, подключите (1) к (2), затем (2) к (3).

Я использовал JSfiddle и создал круги. Каждый раз, когда я обновляю его, расположение кругов меняется, как я могу создавать круги в определенном порядке?

 (function() {

var width = 900,
    height = 650;

var radius = 30; /* radius of circles */
var numCircles = 10; /* number of circles - you must update link source/target values to match changes in the number of circles */

var d3color = d3.interpolateRgb("#BAE4B3", "#006D2C"); /* color range for flow lines */

//A LIST OF LINKS BETWEEN CIRCLES
var links = [
    {
    source: 0,
    target: 5,
    strength: Math.round(Math.random() * 10)},
{
    source: 0,
    target: 2,
    strength: Math.round(Math.random() * 10)},
{
    source: 1,
    target: 3,
    strength: Math.round(Math.random() * 10)},
{
    source: 2,
    target: 4,
    strength: Math.round(Math.random() * 10)},
{
    source: 3,
    target: 5,
    strength: Math.round(Math.random() * 10)},
{
    source: 5,
    target: 0,
    strength: Math.round(Math.random() * 10)},
{
    source: 2,
    target: 0,
    strength: Math.round(Math.random() * 10)},
{
    source: 3,
    target: 1,
    strength: Math.round(Math.random() * 10)}
];

function createDefs(defs) {
    var dropShadowFilter = defs.append('svg:filter').attr('id', 'dropShadow');
    dropShadowFilter.append('svg:feGaussianBlur').attr('in', 'SourceAlpha').attr('stdDeviation', 1);
    dropShadowFilter.append('svg:feOffset').attr('dx', 0).attr('dy', 1).attr('result', 'offsetblur');
    var feMerge = dropShadowFilter.append('svg:feMerge');
    feMerge.append('svg:feMergeNode');
    feMerge.append('svg:feMergeNode').attr('in', "SourceGraphic");
}

var drag = d3.behavior.drag().origin(Object).on("drag", function() {
    dragmove(this);
});

//RANDOMLY GENERATE COORDINATES FOR CIRCLES
var circles = d3.range(numCircles).map(function(i, d) {
    return [Math.round(50   (i / numCircles) * (width - 50)), Math.round(30   Math.random() * (height - 80))];
});

//GLOBAL STRENGTH SCALE
var strength_scale = d3.scale.linear().range([2, 10]) /* thickness range for flow lines */
.domain([0, d3.max(links, function(d) {
    return d.strength;
})]);

var color_scale = d3.scale.linear().range([0, 1]).domain([0, d3.max(links, function(d) {
    return d.strength;
})]);

var svg = d3.select("body").append("svg").attr("width", width).attr("height", height);

var g_lines = svg.append("g").attr("class", "lines");
var g_circles = svg.append("g").attr("class", "circles");
var g_midpoints = svg.append("g").attr("class", "midpoints");

//SHADOW DEFINITION
createDefs(svg.append('svg:defs'));

$.each(circles, function(i, d) {
    g_circles.append("circle").attr('filter', 'url(#dropShadow)').attr("class", "circle").attr("id", "circle"   i).attr("r", radius).attr("cx", d[0]).attr("cy", d[1]).call(drag);
});

g_lines.selectAll(".link_line").data(links).enter().append("path").attr("class", "link_line").attr("fill", function(d) {
    return d3color(color_scale(d.strength));
}).attr("id", function(i, d) {
    return "link_line"   d;
}).attr("d", function(d) {
    return drawCurve(d);
});

function dragmove(dragged) {
    var x = d3.select(dragged).attr("cx");
    var y = d3.select(dragged).attr("cy");
    d3.select(dragged).attr("cx", Math.max(radius, Math.min(width - radius,  x   d3.event.dx))).attr("cy", Math.max(radius, Math.min(height - radius,  y   d3.event.dy)));
    $.each(links, function(i, link) {
        if (link.source == dragged.id.match(/d /)[0] || link.target == dragged.id.match(/d /)[0]) {
            d3.select('#link_line'   i).attr("d", function(d) {
                return drawCurve(d);
            });
        }
    });
}

function drawCurve(d) {
    var slope = Math.atan2(( d3.select('#circle'   d.target).attr("cy") - d3.select('#circle'   d.source).attr("cy")), ( d3.select('#circle'   d.target).attr("cx") - d3.select('#circle'   d.source).attr("cx")));
    var slopePlus90 = Math.atan2(( d3.select('#circle'   d.target).attr("cy") - d3.select('#circle'   d.source).attr("cy")), ( d3.select('#circle'   d.target).attr("cx") - d3.select('#circle'   d.source).attr("cx")))   (Math.PI / 2);

    var sourceX =  d3.select('#circle'   d.source).attr("cx");
    var sourceY =  d3.select('#circle'   d.source).attr("cy");
    var targetX =  d3.select('#circle'   d.target).attr("cx");
    var targetY =  d3.select('#circle'   d.target).attr("cy");

    var arrowOffset = 20;
    var points = [];
    points.push([sourceX   radius * Math.cos(slope) - strength_scale(d.strength) * Math.cos(slopePlus90), sourceY   radius * Math.sin(slope) - strength_scale(d.strength) * Math.sin(slopePlus90)]);
    points.push([sourceX   radius * Math.cos(slope), sourceY   radius * Math.sin(slope)]);
    points.push([targetX - radius * Math.cos(slope), targetY - radius * Math.sin(slope)]);
    points.push([targetX - (radius   arrowOffset) * Math.cos(slope) - strength_scale(d.strength   (arrowOffset / 2)) * Math.cos(slopePlus90), targetY - (radius   arrowOffset) * Math.sin(slope) - strength_scale(d.strength   (arrowOffset / 2)) * Math.sin(slopePlus90)]);
    points.push([targetX - (radius   arrowOffset) * Math.cos(slope) - strength_scale(d.strength) * Math.cos(slopePlus90), targetY - (radius   arrowOffset) * Math.sin(slope) - strength_scale(d.strength) * Math.sin(slopePlus90)]);
    return d3LineLinear(points)   "Z";
}
})();
  

Комментарии:

1. Юнг хороший

2. Привет @tofi, теперь, когда вы обновили свой вопрос, пожалуйста, также обновите свои теги, поскольку, похоже, мы говорим о проблеме JavaScript (то есть, не python или java) больше 🙂

Ответ №1:

JUNG — хороший вариант для визуализации, а также имеет довольно хороший набор доступных графовых алгоритмов, включая несколько различных механизмов для создания случайных графиков, перепрограммирования и т. Д. Я также обнаружил, что ее, как правило, довольно легко расширить и адаптировать там, где это необходимо.

Или JGraphT, простой, но мощный API:

 UndirectedGraph<String, DefaultEdge> g =
    new SimpleGraph<String, DefaultEdge>(DefaultEdge.class);

String v1 = "v1";
String v2 = "v2";
String v3 = "v3";
String v4 = "v4";

// add the vertices
g.addVertex(v1);
g.addVertex(v2);
g.addVertex(v3);
g.addVertex(v4);

// add edges to create a circuit
g.addEdge(v1, v2);
g.addEdge(v2, v3);
g.addEdge(v3, v4);
g.addEdge(v4, v1);