Моя проблема в том, что, хотя я установил fixed : true
для моих узлов, исправлена только первая (загруженная из json-файла). Новые (созданные пользователем) не фиксированы, даже если с помощью инструмента разработчика браузера мы можем увидеть атрибут fixed="true"
. Что-то не хватает в функции redraw()
? Должен ли я использовать tick()
? Я борюсь с этой проблемой в течение недели, и я понятия не имею.d3js Почему мои фиксированные узлы движутся?
Вот мой весь код (где начальный узел действительно исправлен), но я также предлагаю jsfiddle (где и исходный узел тоже не фиксирован).
// Plan
var width = 960,
height = 500;
// Orange selected element
var selected_node = null,
selected_link = null;
// Element we clicked on it
var mouseclick_node = null,
mouseclick_link = null;
// To detect click or double click.
var clickedOnce = false,
timer;
// Useful function to compute the size of an element.
d3.selection.prototype.size = function() {
var n = 0;
this.each(function() { ++n; });
return n;
};
var svg = d3.select("body")
.append("svg")
.attr("width", width)
.attr("height", height)
.attr("pointer-events", "all");
var visual = svg
.append('svg:g')
.append('svg:g')
.on("mousemove", mousemove)
.on("click", click);
// ajoute une balise rect nested dans g, ave préfix svg
visual.append('svg:rect')
.attr('width', width)
.attr('height', height)
.attr('fill', 'white');
var force = d3.layout.force()
.size([width, height])
.charge(-400)
.on("tick", tick);
// Future link
var drag_line = visual.append("line")
.attr("class", "drag_line")
.attr("x1", 0)
.attr("y1", 0)
.attr("x2", 0)
.attr("y2", 0);
// get layout properties
var nodes = force.nodes(),
links = force.links();
var node = visual.selectAll(".node"),
link = visual.selectAll(".link");
// Allows the drag actions
var drag = force.drag();
// Read the json file and creates the links and the nodes
d3.json("graph_empty.json", function(error, graph) {
if (error) console.log("error: " + error);
nodes = graph.nodes;
links = graph.links;
// To redraw after loading nodes and links
redraw();
});
// Add properties to links and nodes
function tick() {
link.attr("x1", function (d) {
return d.source.x;
})
.attr("y1", function (d) {
return d.source.y;
})
.attr("x2", function (d) {
return d.target.x;
})
.attr("y2", function (d) {
return d.target.y;
});
node.attr("cx", function (d) {
return d.x;
})
.attr("cy", function (d) {
return d.y;
});
}
function mousemove() {
var point = d3.mouse(this), p = {x: point[0], y: point[1]};
if (selected_node) {
drag_line
.attr("x1", selected_node.x)
.attr("y1", selected_node.y)
.attr("x2", p.x)
.attr("y2", p.y);
}
}
function click() {
var point = d3.mouse(this), p = {x: point[0], y: point[1]};
// if already clicked once
if (clickedOnce) {
run_on_double_click();
}
// otherwise
else {
timer = setTimeout(function() {
run_on_simple_click(point);
}, 150);
clickedOnce = true;
}
}
function run_on_simple_click(p) {
console.log("[run_on_simple_click]");
clickedOnce = false;
if (!mouseclick_node && selected_node) {
// add a new node
point = {x: p[0], y: p[1]};
nodes.push(point);
// add link to mousedown node
links.push({source: selected_node, target: point});
// select the new node
selected_node = point;
selected_link = null;
// update the drag line
drag_line
.attr("x1", selected_node.x)
.attr("y1", selected_node.y)
.attr("x2", p.x)
.attr("y2", p.y);
redraw();
}
}
function run_on_double_click() {
clickedOnce = false;
clearTimeout(timer);
console.log("[run_on_double_click]");
}
function resetMouseVars() {
console.log("[resetMouseVars]");
mouseclick_node = null;
mouseclick_link = null;
}
function redraw() {
console.log("[redraw start]");
force
.nodes(nodes)
.links(links)
link = link.data(links);
link.enter().append("line")
.attr("class", "link")
.on("click", function(d) {
// double click:
if (clickedOnce_On) {
clickedOnce_On = false;
clearTimeout(timer);
mouseclick_link = d;
if (!selected_link)
selected_link = mouseclick_link;
else if (mouseclick_link == selected_link)
selected_link = null;
else if (mouseclick_link == selected_link) {
selected_link = null;
selected_link = mouseclick_link;
}
selected_node = null;
resetMouseVars();
redraw();
}
// single click:
else {
timer = setTimeout(function() {
// to do... create a new node between !
}, 250);
clickedOnce_On = true;
}
});
link.exit().remove();
link.classed("link_selected", function(d) {
return d === selected_link;
});
node = node.data(nodes);
var clickedOnce_On = false;
node.enter().append("circle")
.attr("class", "node")
.attr("r", 6)
.attr("fixed", true)
.call(drag)
.on("click", function(d) {
mouseclick_node = d;
// double click:
if (clickedOnce_On) {
clickedOnce_On = false;
clearTimeout(timer);
if (!selected_node)
selected_node = mouseclick_node;
else if (mouseclick_node == selected_node)
selected_node = null;
else if (mouseclick_node == selected_node) {
selected_node = null;
selected_node = mouseclick_node;
}
selected_link = null;
resetMouseVars();
redraw();
}
// single click:
else {
timer = setTimeout(function() {
// close the surface if
if ((selected_node) && (mouseclick_node) && (selected_node != mouseclick_node)) {
console.log("mouseclick_node: "+ mouseclick_node);
// Here: count the number of links for each node
// and find the node with only one link.
// If this node == mouseclick_node,
// we add a new link between it and the selected_node.
resetMouseVars();
redraw();
}
}, 250);
clickedOnce_On = true;
}
});
node.exit().transition()
.attr("r", 0)
.remove();
node.classed("node_selected", function(d) {
return d === selected_node;
});
force
.start()
.tick();
console.log("[redraw end]");
}
Благодарим вас за любые предложения/комментарии/решения!