I am fairly new to D3 and javascript. Very useful library, though. But I am having trouble to make my stacked bar chart (I got the code from D3js.org website) responsive. Actually, I have problems making all kinds of D3 charts responsive when I start from scratch .
I tried using viewbox attribute and also preserveAspectRatio, but I am probably doing it wrong.
Here is my entire code: http://codepen.io/voltdatalab/pen/avMoMx
var svg = d3.select("graph").append("svg")
.attr("width", "100%")
.attr('preserveAspectRatio','xMinYMid')
.attr('viewBox','0 100% '+Math.min(width,height)+' '+Math.min(width,height))
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
Could someone give me a hand with this?
You need to set the viewbox attribute first. Try this:
var svg = d3.select("#chart").append("svg")
.attr("viewBox", "0 0 " + (width) + " " + (height))
.attr("preserveAspectRatio", "xMinYMin");
For this to work, you have to change your html:
<div id="chart"></div>
Related
I'm trying to set an initial zoom on my network. It works fine, but as soon as I try to manually zoom on the graph, the visualisation jumps to it's natural zoom settings. Reading answers on Stack and the official documentation of d3, the following code looks right to me, but it doesn't solve the issue.
What am I doing wrong?
Many thanks for your help!
const svg = d3.select('div#network')
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.call(d3.zoom().on("zoom", function () {
svg.attr("transform", d3.event.transform)
}),d3.zoomIdentity.scale(.2))
.append("g")
.attr("transform", `translate(${margin.left},${margin.top})`)
.attr("transform","scale(.2)")
Solved! I was almost right! You need to make a second "call" instead of giving this transform as a parameter of the first one.
const svg = d3.select('div#reseau')
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.call(d3.zoom().on("zoom", function () {
svg.attr("transform", d3.event.transform)
}))
.call(d3.zoom().transform,d3.zoomIdentity.scale(.2))
.append("g")
.attr("transform", `translate(${margin.left},${margin.top})`)
.attr("transform","scale(.2)")
I use this code to create a bullet chart with d3. Now I want to create a bullet chart in an Angular component.
I'm new to d3 so i tried to convert the code to typescript.
Here is my code. I know there are mistakes in the code. Could you help me to make it working?
this.svg = d3.select('body').selectAll('svg')
.enter().append('svg')
.attr('class', 'bullet')
.attr('width', 100 + this.margin.left + this.margin.right)
.attr('height', 300 + this.margin.top + this.margin.bottom);
this.g = this.svg.append('g')
.attr('transform', 'translate(' + this.margin.left + ',' + this.margin.top + ')')
;
This is the svg init function. I should create a svg element in the dom, but it doesn't.
In the example .attr('class', 'bullet') does the work. But this will not work in angular.
Any ideas?
Remove the .selectAll('svg').enter(). Enter only works after a .data() join. Have a look at Mike Bostock's Thinking with Joins.
I'm trying to implement box plots as part of a data visualization interface that uses d3 and AngularJS. I'm working with this box plot package: https://bl.ocks.org/mbostock/4061502.
However, I can't figure out which part of the sample code controls the positioning of the box plots. In the example, the five box plots are arranged sequentially. When I try to generate my plots, they all appear on top of each other.
Here is the code that I'm using to generate the box plots:
boxplots = svg.selectAll("svg")
.data(boxPlotData)
.enter().append("svg")
.attr("class", "box")
.attr("width", boxWidth + margin.left + margin.right)
.attr("height", boxHeight + margin.bottom + margin.top)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.call(chart);
Here's the code for how my svg canvas is created. This is done in an angular directive:
template:"<svg width='825' height='600'></svg>",
link: function($scope, elem){
var d3 = $window.d3;
var rawSvg=elem.find('svg'); // this is the svg created in the template
var width = rawSvg[0].attributes[0].value;
var height = rawSvg[0].attributes[1].value;
var svg = d3.select(rawSvg[0]);
Edit: not perfect yet but getting there:
What you need is an ordinal scale to position the svg-elements for the boxes within the parent svg. Assuming width represents the width of your parent svg element and data is an array of your data elements, you can use this to create the scale:
const x = d3.scaleBand()
.range( [0, width] )
.domain( data.map( (el,i) => i ) );
Within the svg creation you can now use
boxplots = svg.selectAll("svg")
.data(boxPlotData)
.enter().append("svg")
.attr( "x", (d,i) => x(i) ) // this is added
.attr("class", "box")
.attr("width", boxWidth + margin.left + margin.right)
.attr("height", boxHeight + margin.bottom + margin.top)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.call(chart);
PS: This assumes you use v4 of d3js. The syntax in v3 for the scale is different.
PPS: I currently can not test the code, but it should work like described.
I'm modifying the following code for a stacked bar chart by Mike Bostock from http://bl.ocks.org/yuuniverse4444/8325617 in order to learn d3.
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right+legend_width)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
I find that this code only renders just inside the closing body tag. I've tried moving the placement of the script in the page and changing d3.select("body") to d3.select("#chart_name").
Unless I use the term body the chart won't appear at all. Any ideas? Thanks.
Place your Javascript file at the bottom of your DOM structure.
Otherwise, D3 won't be able to make the selection.
Something like:
</body>
<script src="myscripts.js"></script>
I'm creating a diagram with D3 and JSON which is based on this:
http://bl.ocks.org/mbostock/4063550
I'm completely new to this...and I just can't seem to figure out how to move the position of the tree to the right or left of the page. Seems simple enough?
Reason I'm asking is because some of my text are cut out on the left side of screen.
Any help appreciated!
The easiest way to do this is to adjust the transform parameter of the top-level g element. In the example, it is created like this.
var svg = d3.select("body").append("svg")
.attr("width", diameter)
.attr("height", diameter - 150)
.append("g")
.attr("transform", "translate(" + diameter / 2 + "," + diameter / 2 + ")");
To move everything to the right, you would need to add something to the x translation, e.g.
var svg = d3.select("body").append("svg")
.attr("width", diameter)
.attr("height", diameter - 150)
.append("g")
.attr("transform", "translate(" + (diameter / 2 + 10) + "," + diameter / 2 + ")");