Another trivial question. I am trying to draw a line between points, here, starting from lineData[0] to lineData[1], and so on. I am getting a very funny looking area rather than a line! Can you please help me.
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title> Icon </title>
<script type="text/javascript" src="lib/d3/d3.v3.js"></script>
</head>
<body>
<p id="drawing">
<script>
// data is not same as here, just to explain the requirement created it.
var lineData = [{"x": 55, "y": 65},
{"x": 63, "y": 57},
{"x": 157, "y": 57},
{"x": 165, "y": 65}];
var svg = d3.select("#drawing")
.append("svg")
.attr("height", 200)
.attr("width", 200)
.attr("transform", "translate(20, 20)");
var lineFunction = d3.svg.line()
.x(function (d) {
return d.x;
})
.y(function (d) {
return d.y;
})
.interpolate("linear");
svg.append("path")
.attr("d", lineFunction(lineData))
.style("stroke-width", 0.5)
.style("stroke", "rgb(6,120,155)")
.on("mouseover", function () {
d3.select(this)
.style("stroke", "orange");
})
.on("mouseout", function () {
d3.select(this)
.style("stroke", "rgb(6,120,155)");
});
</script>
</body>
</html>
Your issue is that you're drawing a <path>, and you haven't set the path's fill. By default it's black, so you're drawing an object instead. Try removing the fill after appending your <path>:
svg.append("path")
.attr("d", lineFunction(lineData))
.style("stroke-width", 0.5)
.style("stroke", "rgb(6,120,155)")
.style("fill", "none") // <------ add this line
and you get this:
Related
I'm having some difficulty getting d3 to render a geoAlbersUsa projection from topoJson data. I'm showing a blank screen, but no errors returned. The geoJson data seems to be coming through fine, but it's not rendering the path for some reason. Any help would be greatly appreciated!
Here's the relevant code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<script src="https://d3js.org/d3.v6.min.js"></script>
<script src="https://unpkg.com/topojson-client#3"></script>
</head>
<body>
<script>
const width = 1000;
const height = 600;
const projection = d3.geoAlbersUsa()
.translate([width / 2, height / 2])
.scale(800);
const path = d3.geoPath(projection);
const svg = d3.select("body")
.append("svg")
.attr("height", height)
.attr("width", width)
.style("display", "block")
.style("margin", "auto");
d3.json("https://d3js.org/us-10m.v1.json").then(data => {
svg.selectAll(".states")
.data(topojson.feature(data, data.objects.states).features)
.attr("d", path)
.style("fill", "none")
.attr("class", "states")
.style("stroke", "black")
.style("stroke-width", "2px")
});
</script>
</body>
</html>
You need to join with an element:
.data(topojson.feature(data, data.objects.states).features)
.join("path") // here
.attr("d", path)
.style("fill", "none")
.attr("class", "states")
.style("stroke", "black")
.style("stroke-width", "2px")
I'm new to D3 and getting the following error in my demo script -
FirstD3.jsp:31 Uncaught TypeError: Cannot read property 'linear' of undefined
My demo code is as follow
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<title>Linear Scales</title>
<style type="text/css">
</style>
</head>
<body>
<script type="text/javascript">
var dataset = [
[ 5, 20 ],
[ 460, 90 ],
[ 250, 50 ],
[ 100, 33 ],
[ 330, 95 ],
[ 410, 12 ],
[ 468, 44 ],
[ 25, 67 ],
[ 85, 21 ],
[ 220, 88 ]
];
var w = 500;
var h = 100;
var xScale = d3.scale.linear()
.domain([0, d3.max(dataset, function(d) { return d[0]; })])
.range([0, w]);
var yScale = d3.scale.linear()
.domain([0, d3.max(dataset, function(d) { return d[1]; })])
.range([0, h]);
var svg = d3.select("body")
.append("svg")
.attr("height", h)
.attr("width", w);
svg.selectAll("circle")
.data(dataset)
.enter()
.append("circle")
.attr("cx", function (d) {
return xScale(d[0]);
})
.attr("cy", function(d) {
return yScale(d[1]);
})
.attr("r", function (d) {
return Math.sqrt(h-(d[1]));
});
svg.selectAll("text")
.data(dataset)
.enter()
.append("text")
.text(function (d) {
return d[0]+","+d[1];
})
.attr("x", function (d) {
return xScale(d[0]);
})
.attr("y", function (d) {
return yScale(d[1]);
})
.attr("font-size", "11px")
.attr("fill", "red");
</script>
</body>
</html>
what is causing this error? and how to solve it
In D3 v4 it is no longer named d3.scale.linear(). Use d3.scaleLinear() instead.
Thanks for the answer, I've solved this error for the following code (I'm studing D3.js) :
var colorScale = d3.scale.linear().domain([0, 100]).range(["#add8e6", "blue"]);
With the following error (inside the web page) :
Uncaught TypeError: Cannot read property 'linear' of undefined at index.html:22
I'm starting with d3js and trying to make a graph on my own.
I'm trying to draw a curve between two points.
function CreateEdge(nodeId1,nodeId2,edgeLabel)
{
var curveData = [ { "x": 190, "y": 100}, { "x": 260, "y": 50} ];
var edge = d3.select("svg").append('g');
//diagonal function that can draw a curve goes in here
var curve = edge.append("path")
.attr("d", diagonal)
.attr("stroke", "#444")
.attr("stroke-width", 2)
.attr("fill", "none");
}
When i did my research i found some examples using diagonal function to draw curves. like this
Is there a way to use diagonal to draw a simple curve between two known points ? Or is there some alternative methods ?
You can do like this:
var curveData = [{ x: 190, y: 100 }, { x: 360, y: 150 }];
var edge = d3.select('svg').append('g');
var diagonal = d3.svg.diagonal()
.source(function (d) { return { x: d[0].y, y: d[0].x }; })
.target(function (d) { return { x: d[1].y, y: d[1].x }; })
.projection(function (d) { return [d.y, d.x]; });
d3.select('g')
.datum(curveData)
.append('path')
.attr('class', 'link')
.attr('d', diagonal)
.attr('stroke', '#444')
.attr('stroke-width', 2)
.attr('fill', 'none');
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.12/d3.js"></script>
</head>
<body>
<svg width=500 height=500></svg>
</body>
</html>
I have loaded an external graphic from an svg file and I want to experiment drawing on it but cannot figure out how. my simple d3 code is here:
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="http://mbostock.github.com/d3/d3.js"></script>
</head>
<body>
<script type="text/javascript">
d3.xml("brussels.svg", "image/svg+xml", function(xml) {
document.body.appendChild(xml.documentElement);
});
svg.append("circle")
.style("stroke", "gray")
.style("fill", "white")
.attr("r", 40)
.attr("cx", 50)
.attr("cy", 50)
.on("mouseover", function(){d3.select(this).style("fill", "aliceblue");})
.on("mouseout", function(){d3.select(this).style("fill", "white");});
</script>
</body>
</html>
I am sure it is something simple but I am not sure how to create the actual circle.
Thanks!
The function:
d3.xml("brussels.svg", "image/svg+xml", function(xml) {
document.body.appendChild(xml.documentElement);
});
executes asynchronously. Hence, the code following it is executed before the callback is executed. The second problem is that you need to define the svg variable before you can operate on it.
Something like the following should work:
d3.xml("brussels.svg", "image/svg+xml", function(xml) {
document.body.appendChild(xml.documentElement);
var svg = d3.select('svg');
svg.append("circle")
.style("stroke", "gray")
.style("fill", "white")
.attr("r", 40)
.attr("cx", 50)
.attr("cy", 50)
.on("mouseover", function(){d3.select(this).style("fill", "aliceblue");})
.on("mouseout", function(){d3.select(this).style("fill", "white");});
});
I'm trying to create a graduated symbol map and am struggling to find a way to make this happen. I can create pie charts and I can create a symbol map, but how to place pie charts at specific coordinates on a map?
I've successfully placed proportional symbols at the proper coordinates, but I can't figure out how to replace the symbols with pie charts. Every attempt leaves me with an empty map.
I've tried to merge Mike Bostock's Pie Multiples example with his Symbol Map example but have instead only managed to expose my lack of understanding of d3's data and event functions.
Index.html
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
<title>Graduated Symbol Map</title>
<script type="text/javascript" src="http://d3js.org/d3.v3.min.js"></script>
<script type="text/javascript" src="http://d3js.org/topojson.v1.min.js"></script>
<script type="text/javascript" src="http://d3js.org/queue.v1.min.js"></script>
<style type="text/css">
body {
text-align: center;
}
</style>
</head>
<body>
<script type="text/javascript">
var width = 400,
height = 500;
var radius = d3.scale.sqrt()
.domain([0, 5e5])
.range([0, 40]);
// Define map projection
var projection = d3.geo.transverseMercator()
.rotate([72.57, -44.20])
.translate([175,190])
.scale([12000]);
// Define path generator
var path = d3.geo.path()
.projection(projection);
// Create SVG Element
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
queue()
.defer(d3.json, "vermont.json")
.defer(d3.json, "fed.json")
.await(ready)
function ready(error, vt, centroid) {
svg.append("path")
.attr("class", "towns")
.datum(topojson.feature(vt, vt.objects.vt_towns))
.attr("d", path)
.style("stroke", "#ddd")
.style("stroke-width", "1px")
.style("fill", "#ccc");
svg.append("path")
.datum(topojson.feature(vt, vt.objects.lake))
.attr("d", path)
.style("stroke", "#89b6ef")
.style("stroke-width", "1px")
.style("fill", "#b6d2f5");
svg.selectAll(".symbol")
.data(centroid.features.sort(function(a,b) {
return b.properties.dollars - a.properties.dollars; }))
.enter().append("path")
.attr("class", "symbol")
.attr("d", path.pointRadius(function(d) {
return radius(d.properties.dollars); })
)
.style("fill", "#509e2f")
.style("stroke", "#ddd")
.style("fill-opacity", 0.7);
}
</script>
</body>
</html>
fed.json (there are 14 points, all with the same format)
'dollars' are the total dollars spent by the four organizations, the size of the pie chart should relate to this value.
{
"type": "Feature",
"id": "53",
"geometry": {
"type": "Point",
"coordinates": [-73.1349605, 43.0278745]
},
"properties": {
"name": "Bennington County",
"dollars": 79730,
"unit": "county",
"ECP": 49608,
"LIP": 3451,
"NAP": 0,
"SURE": 26671
}
},
vermont.json
Large file, map is not the issue.
References I've used
http://mbostock.github.io/protovis/ex/symbol.html
http://bl.ocks.org/mbostock/1305111
http://bl.ocks.org/mbostock/4342045
Here's my solution, using #LarsKotthoff's answer from this question to solve the projection issue.
I've scaled the pie charts in a rather hackish way.
index.html
Below is just the ready function. Everything else has remained unchanged.
function ready(error, vt, centroid) {
svg.append("path")
.attr("class", "towns")
.datum(topojson.feature(vt, vt.objects.vt_towns))
.attr("d", path)
.style("stroke", "#ddd")
.style("stroke-width", "1px")
.style("fill", "#ccc");
svg.append("path")
.datum(topojson.feature(vt, vt.objects.lake))
.attr("d", path)
.style("stroke", "#89b6ef")
.style("stroke-width", "1px")
.style("fill", "#b6d2f5");
var pieArray = [],
pieMeta = [];
function pieData() {
for (var i=0; i<centroid.features.length; i++) {
pieArray.push([
parseInt(centroid.features[i].properties.ECP),
parseInt(centroid.features[i].properties.LIP),
parseInt(centroid.features[i].properties.NAP),
parseInt(centroid.features[i].properties.SURE)
]);
pieMeta.push([
projection(centroid.features[i].geometry.coordinates),
radius(parseInt(centroid.features[i].properties.dollars))
]);
}
return [pieArray, pieMeta];
};
var svgSvg = d3.select("body").select("svg").selectAll("g")
.data(pieData()[0])
.enter().append("svg:svg")
.attr("width", width)
.attr("height", height)
.append("svg:g")
.style("opacity", 0.8)
.attr("property", function (d,i) {
return pieData()[1][i][1];
})
.attr("transform", function (d,i) {
var coordinates = pieData()[1][i][0];
return ("translate(" + (coordinates[0]) + "," +
(coordinates[1]) + ")");
});
svgSvg.selectAll("path")
.data(d3.layout.pie())
.enter().append("svg:path")
.attr("d", d3.svg.arc()
.innerRadius(0)
.outerRadius(function (d) {
var chartList = d3.select(this.parentNode).attr("property");
return chartList;
}))
.style("fill", function(d, i) { return color[i]; });
}