но, с другой стороны, когда я читал ваш ответ и дошел до того, что вы предлагаете HTML в источнике graphviz, то до меня дошло - я могу получить источник HTMLless graphviz, чем прямо перед передачей его в viz.js Я могу предварительно обработать его с помощью HTML, и когда изменения в SVG необходимо будет сохранить обратно в исходный файл Graphviz, они будут фактически сохранены в версии без HTML, полностью обходя версию HTML. Спасибо!

я сгенерировал SVG-график из точечного файла, используя viz.js.
Теперь легко выбрать его элементы, используя JavaScript, но я не вижу никакой связи с исходным точечным файлом. Я не вижу никакой объектной структуры в библиотеке viz.js, которая связывает сгенерированные элементы диаграммы svg с точечными исходными элементами, поэтому, если бы я выбрал элемент svg с помощью мыши, я бы знал, что этот элемент svg соответствует к точечному элементу, из которого он был сгенерирован. Есть ли способ получить такую ​​обратную связь? Мне это нужно, так что, если я отредактирую элемент в svg (визуально в браузере), я смогу отобразить редактирование обратно в файл точек и отразить изменение в источнике.

объяснениеИтак, вот пример возможного исходного кода GraphViz:
digraph DB {
rankdir=LR
node [shape=record]

person [
    label="
        Person table|
        <id> Person ID|
        <fn> First Name|
        <mn> Middle Name|
        <ln> Last Name
    "
]

address [
    label="
        Addresses table|
        <id> Address ID|
        <pid> Person ID|
        <index> ZIP Code|
        <street> Street Name|
        <house> House Number|
        <town> City/Town/Village Name|
        <state> State Name|
        <district> County/District Name|
        <country> Country Name
    "
]

phone [
    label="
        Phone Number table|
        <pid> Person ID|
        <cc> Country Code|
        <ac> Area Code|
        <n> Phone Number
    "
]
{phone:pid address:pid} -> person:id
}

Вот результат svg, сгенерированный библиотекой Viz.js (но мне все равно, если то же самое может быть сделано другой библиотекой, я буду использовать эту другую библиотеку):

<svg width="671pt" height="257pt" viewBox="0 0 671 257" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 253)">
<title>DB</title>
<polygon fill="#ffffff" stroke="transparent" points="-4,4 -4,-253 666.8861,-253 666.8861,4 -4,4"></polygon>
<!-- person -->
<g id="node1" class="node">
<title>person</title>
<polygon fill="none" stroke="#000000" points="277.8566,-62.5 277.8566,-186.5 371.2234,-186.5 371.2234,-62.5 277.8566,-62.5"></polygon>
<text text-anchor="middle" x="324.54" y="-169.9" font-family="Times,serif" font-size="14.00" fill="#000000">Person table</text>
<polyline fill="none" stroke="#000000" points="277.8566,-161.7 371.2234,-161.7 "></polyline>
<text text-anchor="middle" x="324.54" y="-145.1" font-family="Times,serif" font-size="14.00" fill="#000000">Person ID</text>
<polyline fill="none" stroke="#000000" points="277.8566,-136.9 371.2234,-136.9 "></polyline>
<text text-anchor="middle" x="324.54" y="-120.3" font-family="Times,serif" font-size="14.00" fill="#000000">First Name</text>
<polyline fill="none" stroke="#000000" points="277.8566,-112.1 371.2234,-112.1 "></polyline>
<text text-anchor="middle" x="324.54" y="-95.5" font-family="Times,serif" font-size="14.00" fill="#000000">Middle Name</text>
<polyline fill="none" stroke="#000000" points="277.8566,-87.3 371.2234,-87.3 "></polyline>
<text text-anchor="middle" x="324.54" y="-70.7" font-family="Times,serif" font-size="14.00" fill="#000000">Last Name</text>
</g>
<!-- address -->
<g id="node2" class="node">
<title>address</title>
<polygon fill="none" stroke="#000000" points="504.1939,-.5 504.1939,-248.5 662.8861,-248.5 662.8861,-.5 504.1939,-.5"></polygon>
<text text-anchor="middle" x="583.54" y="-231.9" font-family="Times,serif" font-size="14.00" fill="#000000">Addresses table</text>
<polyline fill="none" stroke="#000000" points="504.1939,-223.7 662.8861,-223.7 "></polyline>
<text text-anchor="middle" x="583.54" y="-207.1" font-family="Times,serif" font-size="14.00" fill="#000000">Address ID</text>
<polyline fill="none" stroke="#000000" points="504.1939,-198.9 662.8861,-198.9 "></polyline>
<text text-anchor="middle" x="583.54" y="-182.3" font-family="Times,serif" font-size="14.00" fill="#000000">Person ID</text>
<polyline fill="none" stroke="#000000" points="504.1939,-174.1 662.8861,-174.1 "></polyline>
<text text-anchor="middle" x="583.54" y="-157.5" font-family="Times,serif" font-size="14.00" fill="#000000">ZIP Code</text>
<polyline fill="none" stroke="#000000" points="504.1939,-149.3 662.8861,-149.3 "></polyline>
<text text-anchor="middle" x="583.54" y="-132.7" font-family="Times,serif" font-size="14.00" fill="#000000">Street Name</text>
<polyline fill="none" stroke="#000000" points="504.1939,-124.5 662.8861,-124.5 "></polyline>
<text text-anchor="middle" x="583.54" y="-107.9" font-family="Times,serif" font-size="14.00" fill="#000000">House Number</text>
<polyline fill="none" stroke="#000000" points="504.1939,-99.7 662.8861,-99.7 "></polyline>
<text text-anchor="middle" x="583.54" y="-83.1" font-family="Times,serif" font-size="14.00" fill="#000000">City/Town/Village Name</text>
<polyline fill="none" stroke="#000000" points="504.1939,-74.9 662.8861,-74.9 "></polyline>
<text text-anchor="middle" x="583.54" y="-58.3" font-family="Times,serif" font-size="14.00" fill="#000000">State Name</text>
<polyline fill="none" stroke="#000000" points="504.1939,-50.1 662.8861,-50.1 "></polyline>
<text text-anchor="middle" x="583.54" y="-33.5" font-family="Times,serif" font-size="14.00" fill="#000000">County/District Name</text>
<polyline fill="none" stroke="#000000" points="504.1939,-25.3 662.8861,-25.3 "></polyline>
<text text-anchor="middle" x="583.54" y="-8.7" font-family="Times,serif" font-size="14.00" fill="#000000">Country Name</text>
</g>
<!-- address&#45;&gt;person -->
<g id="edge1" class="edge">
<title>address-&gt;person:id</title>
<path fill="none" stroke="#000000" d="M503.9959,-133.8802C457.4691,-139.3669 403.6776,-145.7102 381.6916,-148.3029"></path>
<polygon fill="#000000" stroke="#000000" points="381.0613,-144.8529 371.54,-149.5 381.8811,-151.8047 381.0613,-144.8529"></polygon>
</g>
<!-- phone -->
<g id="node3" class="node">
<title>phone</title>
<polygon fill="none" stroke="#000000" points="0,-62.5 0,-186.5 131.08,-186.5 131.08,-62.5 0,-62.5"></polygon>
<text text-anchor="middle" x="65.54" y="-169.9" font-family="Times,serif" font-size="14.00" fill="#000000">Phone Number table</text>
<polyline fill="none" stroke="#000000" points="0,-161.7 131.08,-161.7 "></polyline>
<text text-anchor="middle" x="65.54" y="-145.1" font-family="Times,serif" font-size="14.00" fill="#000000">Person ID</text>
<polyline fill="none" stroke="#000000" points="0,-136.9 131.08,-136.9 "></polyline>
<text text-anchor="middle" x="65.54" y="-120.3" font-family="Times,serif" font-size="14.00" fill="#000000">Country Code</text>
<polyline fill="none" stroke="#000000" points="0,-112.1 131.08,-112.1 "></polyline>
<text text-anchor="middle" x="65.54" y="-95.5" font-family="Times,serif" font-size="14.00" fill="#000000">Area Code</text>
<polyline fill="none" stroke="#000000" points="0,-87.3 131.08,-87.3 "></polyline>
<text text-anchor="middle" x="65.54" y="-70.7" font-family="Times,serif" font-size="14.00" fill="#000000">Phone Number</text>
</g>
<!-- phone&#45;&gt;person -->
<g id="edge2" class="edge">
<title>phone-&gt;person:id</title>
<path fill="none" stroke="#000000" d="M131.1663,-132.2389C180.2951,-138.0324 243.0276,-145.4301 267.307,-148.2933"></path>
<polygon fill="#000000" stroke="#000000" points="267.1989,-151.8047 277.54,-149.5 268.0187,-144.8529 267.1989,-151.8047"></polygon>
</g>
</g>
</svg>

Допустим, я хочу отредактировать «Город / Название города / деревни» в исходном точечном файле не путем редактирования исходного текста, а путем визуального нажатия на соответствующее сгенерированное svg-представление этого точечного источника. Я могу написать немного JavaScript, который позволит мне, например, щелкнуть «Название города / населенного пункта / деревни» на графике svg, и блок станет активным. Затем я редактирую его на месте, как хочу. Проблема заключается в сохранении изменений обратно в источник. JavaScript должен соответствующим образом изменить источник точек, но проблема в том, что svg, созданный с помощью viz.js, не имеет никаких связей с источником. То есть, если вы посмотрите на источник сгенерированного svg, он не добавляет ни идентификаторов, ни чего-либо, что указывало бы на то, что из какого точечного элемента был сгенерирован конкретный элемент svg. Невозможно определить, какой элемент был отредактирован, чтобы передать отредактированное значение обратно правильному точечному элементу для изменения, которое будет сделано в источнике. Есть несколько способов, которые я могу придумать, чтобы решить мою проблему:

отредактируйте библиотеку viz.js, чтобы она помещала некоторые идентификаторы в сгенерированный svgтщательно проанализировать сгенерированный svg, чтобы логически идентифицировать правильный исходный элемент, к отредактированному элементу svg

, но все вышеперечисленное - слишком сложная работа, и ее выполнение может занять много времени, поэтому я спрашиваю, есть ли какая-то особенность в viz.js, которую я пропустил, которая позволила бы мне выполнить мою задачу, или, может быть, Есть какая-то другая библиотека, которую я мог бы использовать, которая может делать то, что мне нужно?

 magjac08 нояб. 2017 г., 12:46
Пожалуйста, укажите источник DOT и укажите, какому элементу вы хотите найти соответствие. Также перефразируйте вопрос, чтобы задать именно это. В противном случае он, вероятно, будет снова приостановлен
 igoryonya09 нояб. 2017 г., 09:32
маджак, я редактировал
 igoryonya10 нояб. 2017 г., 05:37
Спасибо, это залог успеха! Я буду играть с этим. Итак, мне нужно использовать D3 lib для этого. Когда они снимают блокировку, и вы продвигаете свой комментарий к ответу, я буду голосовать за него. Если вы хотите, я создам новый вопрос с тем же заголовком и содержанием, и удалю этот. Вы отправляете свой ответ там, и я отмечу это.
 magjac07 нояб. 2017 г., 20:43
Я думаю, что понимаю, что ОП хочет сделать, и я сделал именно это. Если «удержание» будет отменено, я дам ответ.
 igoryonya08 нояб. 2017 г., 07:48
magjac, может быть, я буду ждать полдня, и если они не поднимут статус «в ожидании», я могу создать еще один вопрос, и вы можете ответить там?

Ответы на вопрос(1)

Решение Вопроса

<title> Элемент может быть использован для ссылки на узлы и ребра. Для узлов заголовокnode_id"(не путать с атрибутом узлаЯ бы) а по краям это такnode_id edgeop node_id"Например,a -> b, Из вашего SVG-кода:

<g id="node1" class="node"> <title>person</title>

person может использоваться для обращения к исходной строке DOT:person [....

В общем случае ГрафвизЯ бы атрибут твой друг:

Я бы

Позволяет автору графика предоставить идентификатор для объектов графа, который должен быть включен в вывод. Применяются нормальные подстановки "\ N", "\ E", "\ G". Если он предоставлен, то поставщик должен сохранять его значения достаточно уникальными для его предполагаемого последующего использования. Обратите внимание, в частности, что «\ E» не предоставляет уникальный идентификатор для нескольких ребер. Если атрибут id не указан, то используется уникальный внутренний идентификатор. Однако это значение непредсказуемо для автора графика. Внешне предоставленный идентификатор не используется внутри.

Если график предоставляет атрибут id, он будет использоваться в качестве префикса для внутренних сгенерированных атрибутов. Различая их, пользователь может включить несколько карт изображений в один и тот же документ.

В вашем случае вы хотите ссылаться не только на узлы, но и на отдельные поляоснованные на записи узлы.

Хотя поля меток записи определены сfieldIdПохоже, они не предназначены для распространения на сгенерированный SVG:

Первая строка в fieldId назначает имя порта для поля и может быть объединена с именем узла, чтобы указать, где прикрепить ребро к узлу. (См. PortPos.)

К вам на помощь приходитHTML-подобные метки:

Форма, основанная на записях, была в значительной степени заменена и в значительной степени обобщена с помощью HTML-подобных меток. То есть вместо использования shape = record можно рассмотреть использование shape = none, margin = 0 и HTML-подобной метки.

С их помощью вы можете создать узел, который представляет собой таблицу со строками и столбцами, где выМожно использоватьЯ БЫ атрибут:

ID = "значение"

позволяет пользователю указать уникальный идентификатор для таблицы или ячейки. Смотрите атрибут id для получения дополнительной информации. Обратите внимание, что «значение» обрабатывается как escString аналогично атрибуту id.

К сожалению естьЖук в Графвизе (лучше описаноВот), который заставляет этот атрибут игнорироваться в выводе SVG. К счастью, естьобходной путь.

Ниже приведено решение, основанное наd3-Graphviz, который используетviz.js внутренне. Вам не нужно использовать d3-graphviz, хотя. Вы можете достичь того же самого с помощью viz.js напрямую.

Если вы сохраняете свой идентификатор достаточно уникальным, и у вас есть контроль над форматированием источника DOT, вы можете использовать простую замену шаблона, как в представленном решении.

Если у вас нет контроля над форматированием источника DOT, вам, вероятно, лучше передать информацию приложению, которое ее генерирует. Альтернативой, чтобы избежать написания полноценного синтаксического анализатора DOT, является нормализация источника DOT с помощью viz.js с использованием «точки» в качестве выходного формата и попытка его проанализировать.

<!DOCTYPE html>
<meta charset="utf-8">
<body>
<script src="//d3js.org/d3.v4.min.js"></script>
<script src="https://unpkg.com/[email protected]/viz.js"></script>
<script src="https://unpkg.com/[email protected]/build/d3-graphviz.js"></script>
<div id="graph" style="text-align: center;"></div>
<script>

var dotSrc = `
digraph DB {
graph [label="Click on a cell to convert to upper/lower case" labelloc="t", fontsize="20.0" tooltip=" "]
rankdir=LR
node [shape=plain]

person [

    // NOTE: The use of HREF is a workaround for '[Dot] ID="value" fails to produce id string in svg:svg output for html nodes'
    //       See https://gitlab.com/graphviz/graphviz/issues/207
    //       For the workaorund and more info, see http://ftp.graphviz.org/mantisbt/view.php?id=2197

    label=< <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4">
              <TR><TD>Person table</TD></TR>
              <TR><TD ID="p.id" PORT="id" HREF=" ">Person ID</TD></TR>
              <TR><TD ID="p.fn" PORT="fn" HREF=" ">First Name</TD></TR>
              <TR><TD ID="p.mn" PORT="mn" HREF=" ">Middle Name</TD></TR>
              <TR><TD ID="p.ln" PORT="ln" HREF=" ">Last Name</TD></TR>
            </TABLE> >
]

address [
    label=< <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4">
        <TR><TD>Addresses table</TD></TR>
        <TR><TD ID="a.id" PORT="id" HREF=" ">Address ID</TD></TR>
        <TR><TD ID="a.pid" PORT="pid" HREF=" ">Person ID</TD></TR>
        <TR><TD ID="a.index" PORT="index" HREF=" ">ZIP Code</TD></TR>
        <TR><TD ID="a.street" PORT="street" HREF=" ">Street Name</TD></TR>
        <TR><TD ID="a.house" PORT="house" HREF=" ">House Number</TD></TR>
        <TR><TD ID="a.town" PORT="town" HREF=" ">City/Town/Village Name</TD></TR>
        <TR><TD ID="a.state" PORT="state" HREF=" ">State Name</TD></TR>
        <TR><TD ID="a.district" PORT="district" HREF=" ">County/District Name</TD></TR>
        <TR><TD ID="a.country" PORT="country" HREF=" ">Country Name</TD></TR>
      </TABLE> >
]

phone [
    label=< <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4">
        <TR><TD>Phone Number table</TD></TR>
        <TR><TD ID="n.pid" PORT="pid" HREF=" ">Person ID</TD></TR>
        <TR><TD ID="n.cc" PORT="cc" HREF=" ">Country Code</TD></TR>
        <TR><TD ID="n.ac" PORT="ac" HREF=" ">Area Code</TD></TR>
        <TR><TD ID="n.n" PORT="n" HREF=" ">Phone Number</TD></TR>
      </TABLE> >
]
{phone:pid address:pid} -> person:id

}
`;

var graphviz = d3.select("#graph").graphviz();
var dotSrcLines;

function render(dotSrc) {
//    console.log('DOT source =', dotSrc);
    dotSrcLines = dotSrc.split('\n');

    transition1 = d3.transition()
        .delay(100)
        .duration(1000);

    graphviz
        .transition(transition1)
        .renderDot(dotSrc);

    transition1
      .transition()
        .duration(0)
        .on("end", function () {
            nodes = d3.selectAll('.node,.edge');
            nodes
              .selectAll("g")
                .on("click", fieldClickHandler)
              .selectAll("a")
                // Remove the workaround attributes to avoid consuming the click events
                .attr("href", null)
                .attr("title", null);
        });
}

function fieldClickHandler () {
    var node = d3.select(this);
    var text = node.selectAll('text').text();
    var id = node.attr('id');
    var class1 = node.attr('class');
    dotElement = id.replace(/^a_/, '');
    console.log('Element id="%s" class="%s" text="%s" dotElement="%s"', id, class1, text, dotElement);
    console.log('Finding and deleting references to %s "%s" from the DOT source', class1, dotElement);
    for (i = 0; i < dotSrcLines.length; i++) {
        if (dotSrcLines[i].indexOf(dotElement) >= 0) {
            ucText = text.toUpperCase();
            lcText = text.toLowerCase();
            if (text != ucText) {
                newText = ucText;
            } else {
                newText = lcText;
            }
            console.log('Converting "%s" to "%s" on line %d: %s', text, newText, i, dotSrcLines[i]);
            dotSrcLines[i] = dotSrcLines[i].replace(text, newText);
        }
    }
    dotSrc = dotSrcLines.join('\n');
    render(dotSrc);
}

render(dotSrc);

</script>

 igoryonya13 нояб. 2017 г., 07:05
но, с другой стороны, когда я читал ваш ответ и дошел до того, что вы предлагаете HTML в источнике graphviz, то до меня дошло - я могу получить источник HTMLless graphviz, чем прямо перед передачей его в viz.js Я могу предварительно обработать его с помощью HTML, и когда изменения в SVG необходимо будет сохранить обратно в исходный файл Graphviz, они будут фактически сохранены в версии без HTML, полностью обходя версию HTML. Спасибо!
 igoryonya13 нояб. 2017 г., 06:58
Спасибо за помощь. На самом деле, у меня была мысль, что если все не получится, мне придется использовать HTML в источнике GraphViz, но я хотел бы оставить его в качестве крайней меры, так как это будет беспощадно раздувать источник GraphViz и сделать его едва читаемый Я надеялся, что в реальном viz.js или d3.js или какой-либо другой js-библиотеке есть какая-то особенность, которая на самом деле генерирует svg с идентификаторами, которую можно использовать далее, чтобы связать сгенерированный граф с источником, или возможно, эти библиотеки создают объект, taht связывает исходный графвиз и сгенерированный svg вместе, о котором я не знал,

Ваш ответ на вопрос