i have the code below and wonder, why the textpath isn't displayed? Can anyone help?
var areas = svg.append("g").selectAll("path")
.data(chord.groups)
.enter().append("path")
.style("fill", function(d) { return fill(d.index); })
.style("stroke", function(d) { return fill(d.index); })
.attr("class", "bar")
.attr("id", function(d, i) { return "group" + i; })
.attr("d", d3.svg.arc().innerRadius(innerRadius).outerRadius(outerRadius))
.on("mouseover", fade(.1))
.on("mouseout", fade(1));
svg.selectAll(".bar").append("text")
.style("font-size", "10px")
.attr("fill", "black")
.append("textPath")
.attr("x", 8)
.attr("dy", ".35em")
.style("fill", "#ff00ff")
.attr("xlink:href", function(d, i) { return "#group" + i; })
.text("Textexample");
Thank you very much!
Benjamin
Related
I want to write relations between 2 nodes on the links that connect them. This is my code, I do not know why he did not work. Can you help me ?
Thanks a lot.
PS: Sorry for my english.
d3.json("links.json", function(json) {
force
.nodes(json.nodes)
.links(json.links)
.start();
var link = svg.selectAll(".link")
.data(json.links)
.enter()
.append("line")
.attr("class", "link")
.style("stroke-width", function(d) { return Math.sqrt(d.weight); })
.style("stroke", function(d) { return color(d.group); });
link.append("path")
.attr("fill", "none")
.attr("stroke", "#333S")
.attr("stroke-width", "1.5px");
link.append("text")
.attr("font-family", "Arial, Helvetica, sans-serif")
.attr("fill", "Black")
.style("font", "normal 12px Arial")
.attr("transform", function(d) {
return "translate(" +
((d.source.x + d.target.y)/2) + "," +
((d.source.x + d.target.y)/2) + ")";
})
.attr("dy", ".35em")
.attr("text-anchor", "middle")
.text(function(d) {
console.log(d.relation);
return d.relation;
});
});
This is a links.json example :
{
"nodes":[{"name":"Gaillard Ruzé","group":0},{"name":"Guillaume Budé,Gulielmus Budaeus","group":1}],
"links":[{"source":0,"target":1,"weight":1,"group":15,"relation":"est dédicataire de"}]
}
Using d3.js v3, I've made this bubble chart:
d3.json(JSON_URL, function(data) {
data = JSON.parse(data)
var nodes = pack.nodes(data);
var node = canvas.selectAll(".node")
.data(nodes)
.enter()
.append("g")
.attr("class", "node")
.attr("transform", function (d) { return "translate(" + d.x + ","+ d.y + ")" ;});
node.append("circle")
.attr("r", function(d) {return d.r; })
.attr("fill", function (d, i) {return d.children ? "#fff" : color(i)})
.attr("opacity", 0.25)
.attr("stroke-width", "2");
node.append("text")
.text(function(d) {return d.children ? "" : d.name ;})
.attr("text-anchor", "middle")
.attr("class", "nodetext")
.attr("data-classname", function(d) {return d.className;})
.attr("style", function(d) {return "font-size:" + d.r/4;})
.on("click", function(d) { window.open("https://twitter.com/hashtag/" + d.name.trim() + "\?src=hash"); })
.on("mouseover", function(d) {
d3.select(this).attr("r", 10).style("fill", "#2f4cff");
d3.select(this).style("cursor", "pointer");
})
.on("mouseout", function(d) {
d3.select(this).attr("r", 5.5).style("fill", "#000");
});
//problem here
node.append("text")
.text(function(d) {return d.children ? "" : d.value ;})
.attr("text-anchor", "middle")
.attr("class", "nodevalue")
.attr("data-classname", function(d) {return d.className;})
.attr("style", function(d) {return "font-size:" + d.r/4;});
}) ;
It's all well, expect the fact that the texts for d.value overlap the texts of d.name, while I want them to come under the d.name. The result should be something like this:
I tried to tweak the nodevalue class but it did not affect the positioning of texts.
How can I acheive this?
You can use the y attribute to position vertically your text. Your code is a bit hard to test because we don't have access to your json, so blindly the code for the text part would be :
node.append("text")
.text(function(d) {return d.children ? "" : d.name ;})
.attr("text-anchor", "middle")
.attr("class", "nodetext")
.attr("data-classname", function(d) {return d.className;})
.attr("style", function(d) {return "font-size:" + d.r/4;})
.on("click", function(d) { window.open("https://twitter.com/hashtag/" + d.name.trim() + "\?src=hash"); })
.on("mouseover", function(d) {
d3.select(this).attr("r", 10).style("fill", "#2f4cff");
d3.select(this).style("cursor", "pointer");
})
.on("mouseout", function(d) {
d3.select(this).attr("r", 5.5).style("fill", "#000");
});
node.append("text")
.text(function(d) {return d.children ? "" : d.value ;})
.attr("text-anchor", "middle")
.attr("class", "nodevalue")
.attr("y", 15) // adding y attribute to offset vertically your text
.attr("data-classname", function(d) {return d.className;})
.attr("style", function(d) {return "font-size:" + d.r/4;});
I suspect I'm barking up the wrong tree - although I've got no errors in the console to help me out.
I've got this block of code:
var path = svg.data([json]).selectAll("path")
.data(partition.nodes)
.enter()
.append("path")
.attr("display", function(d) {
return d.depth ? null : "none";
})
.attr("d", arc)
.style("stroke", "#fff")
.style("fill", function(d) {
return color((d.children ? d : d.parent).name);
})
.attr("fill-rule", "evenodd")
.style("opacity", 1)
.each(stash);
//>>this section functions ok
path.append("title")
.text(function(d) {
return d.name + ": " + d.amount;
});
//>>this section throws no errors but "foo" does not appear
path.append("text")
.text(function(d) {
return "foo";
})
.style("stroke", "#3b5998")
.style("fill", "#3b5998");
The code snippet beginning path.append("title")... works ok but the final snippet beginning path.append("text")... adds the text foo to the html but it is not visible on the webpage - why is it not visible and how do I add labels?
This is part of this visual:
http://plnkr.co/edit/q9ODd5?p=preview
text cannot be nested with a path. You'll need to add it to the svg instead. Additionally, you'll want to position the text in some way:
svg.append("text")
.text(function(d) {
return "foo";
})
.attr("x", function(){ return 0 })
.attr("y", function(){ return 0 })
.style("stroke", "#3b5998")
.style("fill", "#3b5998");
The working code ended as the following:
var path = svg.data([json]).selectAll(".theArc")
.data(partition.nodes)
.enter()
.append("path")
.attr("class", "theArc") //<<<<<<<<<<new
.attr("id", function(d,i) { return "theArc_"+i; }) //Give each slice a unique ID //<<<<<<<<<<new jq
.attr("display", function(d) {
return d.depth ? null : "none";
})
.attr("d", arc)
.style("stroke", "#fff")
.style("fill", function(d) {
return color((d.children ? d : d.parent).name);
})
.attr("fill-rule", "evenodd")
.style("opacity", 1)
.each(stash);
path
.append("title") //mouseover title showing the figures
.text(function(d) {
return d.name + ": " + d.amount;
});
svg.data([json]).selectAll(".theTxts")
.data(partition.nodes)
.enter()
.append("text")
.attr("class", "theTxts")
.attr("dx", 10) //Move the text from the start angle of the arc
.attr("dy", 18) //Move the text down
.append("textPath")
.attr("xlink:href", function(d, i) {
return "#theArc_" + i;
})
.text(function(d) {
return d.name;
})
.style("stroke", "#3b5998")
.style("fill", "#3b5998");
I've been trying to adapt this design into a dynamic pie chart.
Everything has gone reasonably well aside from getting the text to reposition on update.
In the example below, I am first removing the text label and then redrawing, I don't think this is the best way to do it, I was trying to approach it with the code that is commented out just underneath but have been unsuccessful.
Plunk
Offending code;
function updatePath() {
g = svg.datum(donutData).selectAll(".arc")
.data(pie)
g.select("path")
.transition()
.duration(750)
.attrTween("d", arcTween) // redraw the arcs
svg.selectAll(".donutText").remove()
pieTextLabel()
}
// Attempt 1 Below
/*
svg.selectAll(".donutText")
.style("opacity", 0)
.attr("dy", 18)
.append("textPath")
.attr("startOffset", "50%")
.style("text-anchor", "middle")
.attr("xlink:href", function(d, i) {
return "#donutArc" + i;
})
.text(function(d) {
return d.value;
})
.transition()
.duration(1000)
.style("opacity", 1);
*/
function pieTextLabel() {
var selectText = svg.selectAll(".donutText")
.data(donutData)
selectText
.enter().append("text")
.attr("class", "donutText")
.attr("dy", 18)
.append("textPath")
.attr("startOffset", "50%")
.style("text-anchor", "middle")
.attr("xlink:href", function(d, i) {
return "#donutArc" + i;
})
.text(function(d) {
return d.value;
});
selectText.exit().remove()
}
function drawPie() {
var g = svg.selectAll(".donutArcSlices")
.data(pie(donutData))
.enter().append("g")
.attr("class", "arc");
var path = g.append("path")
.attr("d", arc)
.style("fill", function(d) {
return color(d.data.label);
})
.each(function(d, i) {
this._current = d;
var firstArcSection = /(^.+?)L/;
var newArc = firstArcSection.exec(d3.select(this).attr("d"))[1];
newArc = newArc.replace(/,/g, " ");
svg.append("path")
.attr("class", "hiddenDonutArcs")
.attr("id", "donutArc" + i)
.attr("d", newArc)
.style("fill", "none");
})
}
Having trouble cracking this - any help/advice is much appreciated!
Thanks
It's because you didn't update the path
First delete the old path
svg.selectAll("path").remove()
Then recreate it
var path = g.append("path")
.attr("d", arc)
.style("fill", function(d) {
return color(d.data.label);
})
.each(function(d, i) {
this._current = d;
var firstArcSection = /(^.+?)L/;
var newArc = firstArcSection.exec(d3.select(this).attr("d"))[1];
newArc = newArc.replace(/,/g, " ");
svg.append("path")
.attr("class", "hiddenDonutArcs")
.attr("id", "donutArc" + i)
.attr("d", newArc)
.style("fill", "none");
})
see http://plnkr.co/edit/WTuX38GCgIFLFfc1QPVv?p=preview
I've been working on a sunburst visualization example provided by the following link http://bl.ocks.org/mbostock/4063423. I want the label to display the name of the partition in question that has been moused over. Right now whenever I mouseover a partition it shows "flare" in the middle only. Is there a way for me to access the names of the children?
d3.json("flare.json", function(error, root) {
var path = svg.datum(root).selectAll("path")
.data(partition.nodes) //access the nodes
.enter()
.append("path")
.attr("display", function(d) { return d.depth ? null : 'none';}) //hide inner ring
.attr("d", arc)//used whenever I come across a path
.style("stroke", "#fff")
.style("fill", function(d) { return color((d.children ? d : d.parent).name);})
.style("fill-rule", "evenodd")
.each(stash)
.on("mouseover", mouseover)
.on("mouseout", mouseout);
var label = svg.append("text")
.attr("id", "tooltip")
.attr("x", 10)
.attr("y", 50)
.attr("text-anchor", "middle")
.attr("font-family", "sans-serif")
.attr("font-size", "11px")
.attr("font-weight", "bold")
.attr("fill", "black")
.style("opacity", 0)
.text(function(d) { return d.name; });
function mouseover(d) {
d3.select(this)
.transition()
.duration(100)
.style("opacity", 0.3);
label.style("opacity", .9);
console.log('mouseover', mouseover);
};
function mouseout(d) {
d3.select(this)
.transition()
.duration(100)
.style("opacity", 1);
label.style("opacity", 0);
console.log('mouseout', mouseout);
};
This problem is solved by first of all appending text elements to a g element and not svg element. Second you want to create a text element outside the mousehandler with a specific id then call it using that Id within the event handler like so.
d3.json("flare.json", function(error, root) {
var g = svg.selectAll("g")
.data(partition.nodes(root))
.enter().append("g");
var path =
g.append("path")
.attr("display", function(d) { return d.depth ? null : 'none';}) //hide inner ring
.attr("d", arc)//used whenever I come across a path
.attr("id", "part")
.style("stroke", "#fff")
.style("fill", function(d) { return color((d.children ? d : d.parent).name);})
.style("fill-rule", "evenodd")
.each(stash)
.on("mouseover", mouseover)
.on("mouseout", mouseout);
var text = g.selectAll("text")
.data(partition.nodes(root))
.enter()
.append("text")
.attr("id", "tip")
.attr("x", 10)
.attr("y", 50)
.attr("font-size", "11px")
.style("opacity", 0);
function mouseover(d) {
d3.select(this)
.transition()
.duration(1000)
.ease('elastic')
.style("opacity", 0.3);
//label.style("opacity", .9);
d3.select("#tip").text(d.name).style("opacity", 0.9);
console.log('mouseover', mouseover);
};
function mouseout(d) {
d3.select(this)
.transition()
.duration(100)
.style("opacity", 1);
d3.select("#tip").text(d.name).style("opacity", 0);
console.log('mouseout', mouseout);
};