Here is a part of code I got from some example:
svg = d3.select("body")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")").on("click", click)
;
And here is what I am trying to do based on some other example:
var rect = svg.append("rect")
.attr("x", 0)
.attr("y", 0)
.attr("height", height)
.attr("width", width)
.style("fill", '#000');
rect.on("click", click);
Click works, but I cannot known where th clickable zone is located, it is not covering my chart, but is somewhere in a corner of it. So I tried to give it a colour (black in this case), but still it stay invisible.
I have also tried
var rect = svg.append("rect")
.attr("x", margin.left)
.attr("y", margin.top)
.attr("height", height + margin.top + margin.bottom)
.attr("width", width + margin.left + margin.right)
.style("fill", '#000');
rect.on("click", click);
No better result.
Questions:
How can I give my rectangle a colour so that I can know where it is
on the page?
How can I have my rectangle match the whole SVG?
EDIT: I have just realised that "onclick" works because it is also attached to the "g" , but I am still interested in the answers.
You have given it a colour, #000 i.e. black.
The trouble is here
svg = d3.select("body")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")").on("click", click)
;
The svg variable is not the <svg> element, because of chaining it's the <g> element, which has a transform on it so the rect is transformed.
Related
I am currently trying to draw a map of the US with the counties-albers-10m.json file found on the topojson repo. I initially got a solid rectangle and, after changing fill to none, I am getting specks here and there. Going through stack, I found that the winding order may be wrong so I incorporated turf.js, but nothing is really changing. Here is the code:
var margin = {top: 0, left: 0, right: 0, bottom: 0},
height = 600 - margin.top - margin.bottom,
width = 1200 - margin.left - margin.right;
var svg = d3.select("#map")
.append("svg")
.attr("height", height + margin.top + margin.bottom)
.attr("width", width + margin.left + margin.right)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top +")");
d3.json("counties-albers-10m.json").then(function(data) {
console.log(data);
var projection = d3.geoAlbersUsa();
var path = d3.geoPath()
.projection(projection);
var counties = topojson.feature(data, data.objects.counties).features
console.log(counties)
counties.forEach(function(feature) {
feature.geometry = turf.rewind(feature.geometry, {reverse:true});
})
svg.selectAll(".county")
.data(counties)
.enter().append("path")
.attr("class", "county")
.attr("fill", "none")
.attr("stroke", "black")
.attr("d", path);
})
The dreaded black box
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'm new to D3. I want to display a sentence on screen, I have the words in an array, when i run the code all words are overlapping, I want them displayed in a natural way like normal text.
var margin = {top: 20, right: 20, bottom: 30, left: 20},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var svgContainer = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var cars=["this","is","a","normal","sentence"];
var text = svgContainer.selectAll("text")
.data(cars)
.enter()
.append("text");
//Add SVG Text Element Attributes
var textLabels = text
.text( function (d) { return d; })
.attr("font-family", "sans-serif")
.attr("font-size", "20px")
.attr("fill", "red");
One simple way is to use tspan elements within a single text element.
var margin = {top: 20, right: 20, bottom: 30, left: 20},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var svgContainer = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var text = svgContainer.append("text");
var cars=["this","is","a","normal","sentence"];
var text = text.selectAll("tspan")
.data(cars)
.enter()
.append("tspan");
//Add SVG Text Element Attributes
var textLabels = text
.text( function (d) { return d + ' '; })
.attr("font-family", "sans-serif")
.attr("font-size", "20px")
.attr("fill", "red");
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
I have this fiddle : http://jsfiddle.net/q0ubpmwj/5/
I have been trying to mess around with the clip path so the graph doesnt go outside the axis but i cant seem to get it to work.
Heres a bit of the clip path code i have used but it doesnt seem to work :/
var svg = viewer.append("svg").attr('id', 'viewerPins')
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var clip = viewer.append("defs").append("svg:clipPath")
.attr("id", "clip")
.append("svg:rect")
.attr("id", "clip-rect")
.attr("x", "0")
.attr("y", "0").attr("width", width)
.attr("height", height);
var chartBody = svg.append("g")
.attr("clip-path", "url(#clip)")
//.call(zoom)
;
You appending the defs outside of the svg:
viewer.append("defs").append("svg:clipPath")
should be
svg.append("defs").append("svg:clipPath")
I've created an inner dimension to cut off plotting in d3. Here is the code:
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
var nestedSVG = svg.append('svg')
.attr("width", innerWidth)
.attr("height", innerHeight)
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
This works fine in firefox. But I've learned that chrome does not support svg transforms like this (and it isn't working in chrome). Is there a workaround so that I can transform nestedSVG?
You can set x and y attributes on your nested SVG to create a translation of coordinates.
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
var nestedSVG = svg.append('svg')
.attr("width", innerWidth)
.attr("height", innerHeight)
.attr("x", margin.left)
.attr("y", margin.top);
For more complicated transforms, you would use a parent or child <g> element and transform that, as you mentioned in comments to your previous question.