D3 dynamically assign stroke-width on a line - javascript

I'm trying to achieve similar line effect to the one visible on those charts: https://www.informationisbeautifulawards.com/showcase/2873-a-night-under-the-stars
To build my visualization I use React + d3.
This is the code for my line:
var avgWeekday = d3.selectAll('.radial').append("path")
.datum(this.props.avgWeekday)
.attr("fill", "none")
.attr("stroke", "#2A41E5")
.attr("stroke-width", function(d) { return d.value; })
.attr("d", line);
The line is rendered properly but the stroke width is not assigned, what am I doing wrong here?
The data from this.props.avgWeekday looks like this:
However when I actually try to print it inside stroke-width function I get undefined.

Related

D3: How can I cause the stroke of an SVG path generated with D3 to be clipped to the interior of the same path?

I've got a choropleth map working with D3 on Observable. When the user mouses over a country, the border (path) is redrawn in red. I'd like to make this border extend on the interior of the path.
Here is the page: https://observablehq.com/d/33b758c361e919e8
This question is similar to Simple way to use existing object as a clipping path? with the difference that the clipping path needs to be set for each country individually. I'm just not sure how to handle that.
In an ideal world I would use the SVG Strokes extension to simply draw the stroke on the inside of the path, as discussed here: Can you control how an SVG's stroke-width is drawn?
I think I've essentially solved this problem by adding clipPath elements which refer to the previous paths (with the "use" tag).
svg
.append("g")
.attr("id", "map")
.selectAll("path")
.data(topojson.feature(world, world.objects.countries).features)
.join("path")
.attr("class", "country")
.attr("fill", d => color(value.get(d.properties.name)))
.attr("id", d => `${d.id}`)
.attr("d", path);
svg
.append("g")
.selectAll("clipPath")
.data(topojson.feature(world, world.objects.countries).features)
.join("clipPath")
.attr("id", d => `${d.id}_clip`)
.append("use")
.attr("xlink:href", d => new URL(`#${d.id}`, location))

Drawing line outside of axis in d3js line chart

I have been trying to create a dynamic line chart in d3.js, using the tutorial here. I have almost got it working, but there is a slight problem. When I choose a date interval using the viewport and redraw the chart, it draws the line outside of the axis too. See the left of the graphic below.
Normally, I draw the line as below:
var valueline = d3.svg.line()
.x(function (d) {
return xScale(d.timestamp);
})
.y(function (d) {
return yScale(d.value);
});
plotChart.append("path")
.attr("class", "line")
.attr("id", "lineGraphId")
.attr("d", valueline(data));
And my redraw chart function is as below:
function redrawChart() {
plotChart.select("#lineGraphId").remove();
plotChart.append("path")
.attr("class", "line")
.attr("id", "lineGraphId")
.attr("d", valueline(data));
plotChart.select('.x.axis').call(xAxis);
}
I could not find a solution for drawing outside of the axis. I could not host my code in jsfiddle because I needed to load a csv data, but you can see all source code here.
Apparently, I needed to add this line of code to redrawChart function:
.attr('clip-path', 'url(#plotAreaClip)')

D3 updating DOM, but nothing is showing

I am building a force-directed graph, and as far as I can tell, I have written the code correctly. The DOM looks exactly right after this code runs. And yet, nothing is displayed.
var type_node_list = typeNodes(data);
shuffle(type_node_list);
initializePosition(type_node_list);
var links = typeLinks(type_node_list);
var svg = d3.select('#root');
var link = svg
.append('g')
.attr('id', 'links')
.selectAll('line')
.data(links)
.enter()
.append('line')
.attr('class', 'link');
var type_nodes = svg
.append('g')
.attr('id', 'nodes')
.selectAll('.node')
.data(type_node_list)
.enter()
.append(createTypeNode);
function updateTypeNodeLocations() {
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;});
type_nodes
.attr('x', nodeX)
.attr('y', nodeY);
}
updateTypeNodeLocations();
/*
var position_the_types = d3.forceSimulation()
.nodes( type_node_list )
.force("charge",d3.forceManyBody().strength(-10))
;
position_the_types.on('tick',updateTypeNodeLocations());
*/
The simulation portion is commented out because I'm trying to get the first part working. When I uncomment it, it only calls the 'tick' event once, even though the processing is clearly not complete. And there is nothing in the JavaScript console to explain it.
See http://jsfiddle.net/jarrowwx/gof5knaj/36/ for the full code.
I had things working this morning, and something changed and now nothing I do seems to work. I checked the D3 github, and the last commit appears to have been 11 days ago, so it's not likely caused by a change to the library.
Has anybody experienced something like this before? Any pointers on what I'm doing wrong? Have I uncovered a D3 bug?
The problem lie in my function createTypeNode.
I created the image element via: document.createElement('image'). That doesn't work. To create an image via JavaScript, one must use Namespaces.
See: Programmatically creating an SVG image element with javascript

Colour links of a d3 network graph according to a data variable

I would like to colour different links of a network graph according to a value within a data vector (where each element of the vector corresponds to a particular link). I have tried something of the form:
var data = [1,1,1,2];
var link = svg.selectAll(".link")
.data(force.links())
.enter()
.append("line")
.attr("class", "link")
.attr("marker-end", "url(#end)")
.on("mouseover", linkmouseover)
.on("mouseout", linkmouseout);
link.data(force.links()).enter().append(".link")
.style("stroke", function(d,i){
return ( (data[i]==2) ?
"red" : "black" )
});
However, this does not seem to work. If it's important I also have an svg styling:
.link {
stroke: #ff0000;
opacity: 0.6;
stroke-width: 1.5px;
}
Does anyone know why this isn't working? I have the Plunker version here.
The way you are setting up your links looks quite odd. Especially the following line doesn't seem to make any sense:
link.data(force.links()).enter().append(".link")
The statement directly preceding this line successfully inserts the lines for the links handling the enter selection. On the suspicious line you are then binding the same data again to the links' selection. Because you did not specify any key function to access your data this will compute a join based on the data's index which will, because you handled this same data before, yield an empty enter selection. Therefore, the method setting style("stroke",...) will never execute the callback. Furthermore, the call to .append(".link") is wrong, because .link is not a valid SVG element which could be appended using this method.
You somehow seem to have messed up this part of your code by, maybe, some copy&paste action. If you get rid of the above mentioned line and delete the directly preceding semicolon your code will work as expected:
var link = svg.selectAll(".link")
.data(force.links())
.enter()
.append("line")
.attr("class", "link")
.attr("marker-end", "url(#end)")
.on("mouseover", linkmouseover)
.on("mouseout", linkmouseout)
.style("stroke", function(d,i){
return ( (data[i]==2) ? "red" : "black" );
});
Have a look at the updated code for a working example.

d3.js path dom element

I am creating a streamgraph, having used the example code from http://bl.ocks.org/mbostock/4060954 as a template.
I draw the streamgraph:
var svg = d3.select("#graph_area").append("svg")
.attr("width", width)
.attr("height", height)
....
svg.selectAll("path")
.data(layers)
.enter().append("path")
.attr("d", function (d) {return area(d.layer);})
Now it seems that I am not allowed to choose a different name from "path" for the DOM element here. If I do, then streamgraph no longer plots. Why is that?
Then I want to add a legend with bullets, but they don't plot. The elements show up in my web inspector (firebug), but their graphical representation is just not there. I figured it might be a similar problem with the DOM element name, but I don't actually know. Here is the code for my bullets:
//draw all the legend bullets and effects
svg.selectAll("bullets")
.data(layers)
.enter().append("bullets")
.attr("cx", 200)
.attr("cy", function(d, i) { return 20 + i*10; })
.style("fill", function(d) { return d.color; })
.attr("r", 5)
I briefly looked at API's for paths here and here, but I didn't find my answers there.
The element names you can use are defined in the SVG specification. This is a specific set (e.g. path, circle) -- using anything else will work in terms of appending the element to the DOM, but the browser won't know how to interpret and render it.
It's the same way in HTML -- there's a specific set of defined element names that browsers know how to render.

Categories

Resources