我的可视化使用节点之间的线来表示它们之间的关系。线越宽,两个节点的连接越多。在这种情况下,我想将一小部分线条设置为较暗的色调,以将更多信息附加到可视化。最接近线上“标记”的节点是主导节点。
是否有一些命令只能改变部分线的颜色?或者更容易创建一个宽度和角度与线条相同的矩形?
我附上了当前的可视化,我在其中创建了一些丑陋的小矩形来说明我正在尝试做什么。此外,附上了代码(虽然遗憾的是有点乱)。
<!DOCTYPE html>
<meta charset="utf-8">
<style>
.node circle {
stroke: white;
stroke-width: 2px;
opacity: 1.0;
}
line {
stroke-width: 3.5px;
stroke-opacity: 1.0;
}
</style>
<body>
<script src="http://d3js.org/d3.v3.js"></script>
<script>
data = {
nodes: [
{size: 200, fill: '#ffffff', line: '#8C8C8C', id: 'Me'},
{size: 30, fill: '#D2D2D2', line: '#ffffff', id: 'Bob'},
{size: 30, fill: '#D2D2D2', line: '#ffffff', id: 'Alice'},
{size: 30, fill: '#D2D2D2', line: '#ffffff', id: 'Tim Tim'},
{size: 30, fill: '#D2D2D2', line: '#ffffff', id: 'Mustafa'},
{size: 30, fill: '#D2D2D2', line: '#ffffff', id: 'Zeus'},
{size: 30, fill: '#D2D2D2', line: '#ffffff', id: 'McHammer'},
{size: 30, fill: '#D2D2D2', line: '#ffffff', id: 'Thoooor'},
{size: 30, fill: '#D2D2D2', line: '#ffffff', id: 'Le Viking'}
],
links: [
{source: 0,target: 1, calls: 20, texts:0},
{source: 0,target: 2, calls: 5, texts:0},
{source: 0,target: 3, calls: 8, texts:0},
{source: 0,target: 4, calls: 3, texts:0},
{source: 0,target: 5, calls: 2, texts:0},
{source: 0,target: 6, calls: 3, texts:0},
{source: 0,target: 7, calls: 5, texts:0},
{source: 0,target: 8, calls: 2, texts:0}
]
}
var total_interactions = data.links.reduce(function(result, currentObject) {
return result + currentObject.calls;
}, 0);
console.log(total_interactions);
var mouseOverFunction = function(d) {
var circle = d3.select(this);
circle
.transition(500)
.attr("r", function(){ return 1.4 * node_radius(d)});
}
var mouseOutFunction = function() {
var circle = d3.select(this);
circle
.transition(500)
.attr("r", node_radius);
}
function isConnected(a, b) {
return isConnectedAsTarget(a, b) || isConnectedAsSource(a, b) || a.index == b.index;
}
function isConnectedAsSource(a, b) {
return linkedByIndex[a.index + "," + b.index];
}
function isConnectedAsTarget(a, b) {
return linkedByIndex[b.index + "," + a.index];
}
function isEqual(a, b) {
return a.index == b.index;
}
var line_diff = 0
function tick() {
callLink
.attr("x1", function(d) { return d.source.x-line_diff; })
.attr("y1", function(d) { return d.source.y-line_diff; })
.attr("x2", function(d) { return d.target.x-line_diff; })
.attr("y2", function(d) { return d.target.y-line_diff; });
textLink
.attr("x1", function(d) { return d.source.x+line_diff; })
.attr("y1", function(d) { return d.source.y+line_diff; })
.attr("x2", function(d) { return d.target.x+line_diff; })
.attr("y2", function(d) { return d.target.y+line_diff; });
node
.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
}
function node_radius(d) { return Math.pow(40.0 * d.size, 1/3); }
var width = 1000;
var height = 500;
var nodes = data.nodes
var links = data.links
var force = d3.layout.force()
.nodes(nodes)
.links(links)
.charge(-3000) // -3000
.friction(0.6)
.gravity(0.6)
.size([width,height])
.start();
var linkedByIndex = {};
links.forEach(function(d) {
linkedByIndex[d.source.index + "," + d.target.index] = true;
});
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
var callLink = svg.selectAll(".call-line")
.data(links)
.enter().append("line");
var textLink = svg.selectAll(".text-line")
.data(links)
.enter().append("line");
var link = svg.selectAll("line");
var node = svg.selectAll(".node")
.data(nodes)
.enter().append("g")
.attr("class", "node")
.call(force.drag);
node
.append("circle")
.attr("r", node_radius)
.style("fill", function(d) {return d.fill; })
.style("stroke", function(d) {return d.line; })
.on("mouseover", mouseOverFunction)
.on("mouseout", mouseOutFunction);
svg
.append("marker")
.attr("id", "arrowhead")
.attr("refX", 6 + 7)
.attr("refY", 2)
.attr("markerWidth", 6)
.attr("markerHeight", 4)
.attr("orient", "auto")
.append("path")
.attr("d", "M 0,0 V 4 L6,2 Z");
// link
// .style("stroke-width", function stroke(d) {return d.calls/data.total_interactions*20; })
var line_width_factor = 40 // width for a line with all points
textLink
.style("stroke-width", function stroke(d) {return d.texts / total_interactions*line_width_factor; })
.style("stroke", "#70C05A")
callLink
.style("stroke-width", function stroke(d) {return d.calls / total_interactions*line_width_factor; })
.style("stroke", "#438DCA")
force
.on("tick",tick);
</script>
</body>
答案 0 :(得分:1)
事实上,你can't apply CSS gradients to SVG elements。你必须使用SVG渐变。
要沿图表中的链接创建SVG渐变,常规形式为:
defs.append("linearGradient")
.attr("id", gradient_id)
.attr("gradientUnits", "userSpaceOnUse")
.attr("x1", source.px)
.attr("y1", source.py)
.attr("x2", target.px)
.attr("y2", target.py)
.selectAll("stop")
.data([
{offset: "0%", color: "cyan"}, //color 1
{offset: "50%", color: "cyan"}, //start the gradient from haf distance
{offset: "100%", color: "darkBlue"} //to a darker color
])
.enter().append("stop")
.attr("offset", function(d) { return d.offset; })
.attr("stop-color", function(d) { return d.color; });
在您的情况下,source
和target
的排名随每个force.tick()
而变化。因此,您需要为每个tick
中的所有链接计算和应用渐变。将此行添加到tick
函数:
callLink.each(function(d){applyGradient(this, d)});
接下来,我们需要定义applyGradient(line, d)
函数:
function applyGradient(line, d){
var self = d3.select(line); //select the current link
// store the currently used gradient to delete it later.
var current_gradient = self.style("stroke")
current_gradient = current_gradient.substring(4, current_gradient.length-1);
// Generate a random id for the gradient calculated for this link
var new_gradient_id = "line-gradient" + getRandomInt();
// Determine the direction of the gradient. In your example, you need
// the darker hue to be near the bigger node.
var from = d.source.size < d.target.size? d.source: d.target;
var to = d.source.size < d.target.size? d.target: d.source;
// Add the gradient to the svg:defs
defs.append("linearGradient")
.attr("id", new_gradient_id)
.attr("gradientUnits", "userSpaceOnUse")
.attr("x1", from.px)
.attr("y1", from.py)
.attr("x2", to.px)
.attr("y2", to.py)
.selectAll("stop")
.data([
{offset: "0%", color: "cyan"},
{offset: "50%", color: "cyan"},
{offset: "100%", color: "darkBlue"}
])
.enter().append("stop")
.attr("offset", function(d) { return d.offset; })
.attr("stop-color", function(d) { return d.color; });
//apply the gradient
self.style("stroke", "url(#" + new_gradient_id + ")")
//Remove the old gradient from defs.
defs.select(current_gradient).remove();
}