D3 - Add background fill to rect - d3.js

Is it possible to add a background fill to a rect element? I am using rect elements to create a bar graph. Each rect element has a width and fill set. I want to fill the remaining width with a color.
See here: http://codepen.io/jesouhaite08/pen/fhvzA
Thanks!

For best flexibility I would use other rectangles to draw the background for your bars, check the forked example: http://codepen.io/anon/pen/JnlAE
// Bars
svg_fun.selectAll('rect.background')
.data(dataset)
.enter()
.append('rect')
.classed('background', true)
.attr('y', function(d, i) {return i * h_line; })
.attr('x', 0)
.attr('height', 20)
.attr('width', function(d) {return scale_x(max_x);} )
.attr('fill', 'red')
svg_fun.selectAll('rect.bar')
.data(dataset)
.enter()
.append('rect')
.classed('bar', true)
.attr('y', function(d, i) {return i * h_line; })
.attr('x', 0)
.attr('height', 20)
.attr('width', function(d) {return scale_x(d);} )
.attr('fill', 'teal')

Related

D3.js V5 tree in svg layout

I create three svg paint board in body element, and i want create a tree layout in first svg. But the tree layout always show at last one. I can't find some error in my codes. 3Q
result in html:
html result
my d3.js(v5) code shown below:
var svg = body.append('svg')
.attr('width', width)
.attr('height', height)
svg.append('rect')
.attr('width', '100%')
.attr('height', '100%')
.attr('fill', 'rgb(255, 100, 100)')
d3.json('map_tree.json').then(function(datas){
var root = d3.hierarchy(datas)
var tree = d3.tree()
.size([height, width-120])
.separation(function separation(a, b){
return a.parent == b.parent ? 1:2
})
tree(root)
svg.append('g')
.selectAll('circle')
.data(root.descendants())
.enter()
.append('circle')
.attr('r', 4)
.attr('transform', 'translate(50, 0)')
.attr('fill', 'white')
.attr('stroke', 'blue')
.attr('stroke-width', 1)
.attr('cx', function(d, i){
return d.y
})
.attr('cy', function(d, i){
return d.x
})
.attr('cx', function(d, i){
return d.y
})
.attr('cy', function(d, i){
return d.x
})
var svg = body.append('svg')
.attr('width', width)
.attr('height', height)
svg.append('rect')
.attr('width', '100%')
.attr('height', '100%')
.attr('fill', 'rgb(100, 255, 100)')
var svg = body.append('svg')
.attr('width', width)
.attr('height', height)
svg.append('rect')
.attr('width', '100%')
.attr('height', '100%')
.attr('fill', 'rgb(100, 100, 255)')
I hava found the reason. I created more than one d3.select('doby').append('svg') named svg, and the problem has gone when i named others with svg1、svg2

Transition height stacked bar chart

I have a codepen here - https://codepen.io/anon/pen/GybENz
I've created a simple stacked bar chart with a legend to filter the chart.
I'd like to animated the height of the bar from the bottom axis up.
Currently its animating from the left and down
let layersBar = layersBarArea.selectAll('.layer').data(stackedSeries)
.enter()
.append('g')
.attr('class', 'layer')
.style('fill', (d, i) => {
return colors[i];
});
layersBar.selectAll('rect')
.data((d) => {
return d
})
.enter()
.append('rect')
.attr('height', 100)
.transition()
.duration(400)
.attr('height', (d, i) => {
return y(d[0]) - y(d[1]);
})
.attr('y', 0)
.attr('y', (d) => {
return y(d[1]);
})
.attr('x', (d, i) => {
return x(d.data.date)
})
.attr('width', x.bandwidth());
}
Set the x position, the width, the y position (as the baseline) and the height (as zero) before the transition:
.attr('height', 0)
.attr("y", h - margin.bottom - margin.top)
.attr('x', (d, i) => {
return x(d.data.date)
})
.attr('width', x.bandwidth())
Here is the updated CodePen: https://codepen.io/anon/pen/ypdoMK?editors=0010
PS: It would be a good idea transitioning each rectangle individually. For instance, if the user clicked usedInf, you should transition only those rectangles... however, since you did this...
layersBarArea.selectAll('g.layer').remove();
... at the beginning of your drawChart function, which is a wrong approach, such suggestion will need a big refactor, out of the scope of this question/answer.

Adding background color to axis labels in D3 parallel coordinates

I'm working on a modified version of this D3 code for parallel coordinates. I would like to add a background color for the axis labels. I realize I cannot set a background color using CSS styles because this is SVG text, so I tried to append rectangles but to no avail. Here is what I wrote but it's not drawing anything:
d3.selectAll(".label")
.append("rect")
.attr("x", function(d){ return d3.select(this).node().getBBox().x - 5;})
.attr("y", function(d){ return d3.select(this).node().getBBox().y - 5;})
.attr("width", function(d){ return d3.select(this).node().getBBox().width;})
.attr("height", function(d) {return d3.select(this).node().getBBox().height;})
.style("stroke", "black")
.style("fill", "yellow");
What am I doing wrong?
EDIT:
based on comments, I appended to the parent g rather than the text label itself. Now the code looks like this:
// Add an axis and title.
var gsvg= g.append("svg:g")
.attr("class", "axis")
.attr("id", "gsvg")
.each(function(d) { d3.select(this).call(axis.scale(yscale[d])); })
.attr("transform", "translate(0,0)");
d3.selectAll("#gsvg")
.append("rect")
.attr("x", function(d){ return this.parentNode.getBBox().x - 5;})
.attr("y", function(d, i){ return i%2 === 0 ? this.parentNode.getBBox().y - 20: this.parentNode.getBBox().y - 35;})
.attr("width", function(d){ return this.parentNode.getBBox().width;})
.attr("height", function(d) {return 20;})
.style("stroke", "lightgrey")
.style("stroke-width", 2)
.style("fill", function(d){
return self.fcolorMap[d];
})
.style("opacity", 0.5);
gsvg.append("svg:text")
.style("text-anchor", "middle")
.attr("y", function(d,i) { return i%2 == 0 ? -14 : -30 } )
.attr("x",0)
.attr("class", "axis-label")
.text(function(d) {
var s = d.split("|");
return s[s.length-1]; });
The only problem is now I need to figure out how to get the bounding boxes of the labels rather than those of the axes.

Cannot get d3 svg tutorial to work in jsfiddle

I'm trying to follow a d3 tutorial and I've created a JSFiddle for the following code
var dataset = [1,2,3,4,5];
var sampleSVG = d3.select("#viz")
.append("svg")
.attr("width", 400)
.attr("height", 75);
sampleSVG.selectAll("circle")
.data(dataset)
.enter().append("circle")
.style("stroke", "gray")
.style("fill", "red")
.attr("height", 40)
.attr("width", 75)
.attr("x", function(d, i){return i*80})
.attr("y", 20);
However, I see the generated circles in the svg but I can't see them on the screen. Can anyone see what I'm missing?
Here is a FIDDLE:
var dataset = [1,2,3,4,5];
sampleSVG.selectAll("circle")
.data(dataset)
.enter().append("circle")
.style("stroke", "gray")
.style("fill", "red")
.attr("cx", function(d, i){return (i + 1 ) *60})
.attr("cy", 30)
.attr("r", 20);
I just focused on the main parts that needed change. You can study the differences. Basically, you had the wrong attributes for a circle (x and y, instead of cx and cy) and was missing the radius attribute. Finally, height and width are not circle attributes.

D3.js - can clipping paths be used with d3.svg.symbol?

I'm trying to draw multiple 'cross' symbols inside of a circle for use in a visualization. I'd like to draw the crosses in a 'g' tag and then apply a clipping path.
Is it possible to use clip paths with d3.svg.symbol ?
In the below example, the svg circle is masked correctly with the clip path; however the cross (the last part of the code) isn't.
Am I doing something wrong or is this not a feature?
var svg = d3.select("#maskingExample")
.append("svg:svg")
.attr("width", 500)
.attr("height", 200);
svg.append("svg:clipPath")
.attr("id", "clipper")
.append("svg:rect")
.style("stroke", "gray")
.style("fill", "black")
.attr("x", 50)
.attr("y", 25)
.attr("width", 300)
.attr("height", 45);
svg.append("g").append("svg:circle")
.style("stroke", "gray")
.style("fill", "blue")
.attr("cx", 175)
.attr("cy", 55)
.attr("r", 50)
.attr("clip-path", "url(#clipper)");
svg.append("g").append("path")
.attr("d", d3.svg.symbol()
.size( function(d) { return 3000; })
.type( function(d) { return d3.svg.symbolTypes[1]; }))
.attr("transform", "translate(150, 50)")
.attr("clip-path", "url(#clipper")
.style("fill", "black");
You're missing a close paren. Instead of
.attr("clip-path", "url(#clipper")
it should read
.attr("clip-path", "url(#clipper)")

Resources