I am new in D3.js and can't fix a seemingly small problem. The thing is I don't realy understand what's wrong with "my" code. The error that I get on the console tells me: "SyntaxError: expected expression, got '<' ", which doesn't make any sense for me. May be some of you can help me with this. Here it is:
var xyr = [
{x:1,y:1,r:1},
{x:2,y:2,r:2},
{x:3,y:3,r:3}
];
var body = d3.select("body");
var svg = body.append("svg").attr("width",250).attr("height",250);
var scaleX = d3.scaleLinear().range([0,250]);
var scaleY = d3.scaleLinear().range([0,250]);
function render(data){
//Data Binding
var circles = svg.selectAll("circle").data(data);
scaleX.domain(d3.extent(data,function(d){ return d.x; }));
scaleY.domain(d3.extent(data,function(d){ return d.y; }));
//Debugging (working correct --> 125)
circles
//Enter
.enter().apend("circle").attr("r",5)
//Update
.merge(circles)
.attr("cx", function (d){ return scaleX; })
.attr("cy", function (d){ return scaleY; });
//Exit
circles.exit().remove();
};
//Invoking the funktion with var xyr
render(xyr);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
</body>
</html>
First remove the <script> and </script> tags, those are throwing the errors. Second, you link v3 when your code is v4/5 (I used v4 in my snippet). Third you had some spelling mistakes that threw some errors. Lastly (and the biggest issue with d3 rendering), is with this:
.merge(circles)
.attr("cx", function (d){ return scaleX; })
.attr("cy", function (d){ return scaleY; });
which was missing the link to the data, which was updated to
.merge(circles)
.attr("cx", function (d){ return scaleX(d.x); })
.attr("cy", function (d){ return scaleY(d.y); });
var xyr = [{
x: 1,
y: 1,
r: 1
},
{
x: 2,
y: 2,
r: 2
},
{
x: 3,
y: 3,
r: 3
}
];
var body = d3.select("body");
var svg = body.append("svg").attr("width", 250).attr("height", 250);
var scaleX = d3.scaleLinear().range([0, 250]);
var scaleY = d3.scaleLinear().range([0, 250]);
function render(data) {
//Data Binding
var circles = svg.selectAll("circle").data(data);
scaleX.domain(d3.extent(data, function(d) {
return d.x;
}));
scaleY.domain(d3.extent(data, function(d) {
return d.y;
}));
//Debugging (working correct --> 125)
circles
//Enter
.enter().append("circle").attr("r", 5)
//Update
.merge(circles)
.attr("cx", function(d) {
return scaleX(d.x);
})
.attr("cy", function(d) {
return scaleY(d.y);
});
//Exit
circles.exit().remove();
};
//Invoking the funktion with var xyr
render(xyr);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.min.js"></script>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
</body>
</html>
Related
The following SIMPLE :) code gives following error. Please help me what mistake I am making to ZOOM on onClick on the Circle ?
Similarly I will be very thankful if someone can give some idea that if i want to zoom to 3rd Circle DIRECTLY without clicking on it; what should I do ?
ERROR: Uncaught TypeError: Cannot read property 'apply' of undefined
at qr.call (d3.min.js:2)
at SVGCircleElement.clicked (index.html:52)
at SVGCircleElement.<anonymous> (d3.min.js:2)
And here is the code.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1,maximum-scale=1" />
<title>Zoom & Pan</title>
<link rel="stylesheet" type="text/css" href="styles.css" />
<script type="text/javascript" src="d3.min.js"></script>
<style type="text/css">
</style>
</head>
<body>
<script type="text/javascript">
var width = 600, height = 350;
var data = [
{ "r": 10, "cx": 100, "cy": 150 },
{ "r": 30, "cx": 200, "cy": 150 },
{ "r": 15, "cx": 300, "cy": 150 }
];
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.call(
d3.zoom()
.scaleExtent([1, 7])
.on("zoom", zoom)
);
const g = svg.append("g");
g.selectAll("circle")
.data(data)
.enter()
.append("circle")
//.attr("fill", function (d) { return d.color; })
.attr("fill", (d, i) => d3.interpolateRainbow(i / 3))
.on("click", clicked)
.attr("r", function (d) { return d.r; })
.attr("cx", function (d) { return d.cx; })
.attr("cy", function (d) { return d.cy; });
function clicked(d,i,nodes) {
console.log(nodes);
svg.transition().duration(750).call(
zoom.transform,
d3.zoomIdentity.translate(width / 2, height / 2).scale(40).translate(-d.cx, -d.cy),
d3.mouse(svg.node())
);
}
function zoom() {
g.attr("transform", d3.event.transform);
}
</script>
</body>
</html>
The issue is that zoom.transform is not a thing. You have created a function called zoom, if that is important then you'll need to create another variable called something else, e.g. zoomer, probably in window scope, like width and height:
var zoomer = d3.zoom();
Then in your click handler change zoom.transform to zoomer.transform:
function clicked(d,i,nodes) {
console.log(nodes);
svg.transition().duration(750).call(
zoomer.transform, //change here
d3.zoomIdentity.translate(width / 2, height / 2).scale(40).translate(-d.cx, -d.cy),
d3.mouse(svg.node())
);
}
If you don't need the zoom function, then delete that and create the zoom variable like the zoomer one above and don't change the click handler.
I want to flip the line so that the higher value goes up and the lower value goes down. I tried to use scale(1,-1) but it doesn't output anything. Please see my code below
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<div class="paths"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js"></script>
<script>
var canvas = d3.select(".paths").append("svg")
.attr("width", 500)
.attr("height", 500);
var data = [
{x:10, y:200},
{x:30, y:170},
{x:50, y:70},
{x:70, y:140},
{x:90, y:150},
{x:110, y:120},
{x:130, y:150},
{x:150, y:140},
{x:170, y:110}
];
var group = canvas.append('g')
.attr("transform", "scale(1,1)");
var line = d3.svg.line()
.x(function(d){ return d.x })
.y(function(d){ return d.y });
group.selectAll("path")
.data([data])
.enter()
.append("path")
.attr("d", line)
.attr("fill", "none")
.attr("stroke", "red")
.attr("stroke-width", 2);
</script>
</body>
</html>
https://jsbin.com/dayoxon/7/edit?html,output
You have to use a scale, which by the way will fix another problem you have: your data values should not be (or normally will not be) SVG coordinates.
This is a basic example of a linear scale:
var scale = d3.scale.linear()
.domain([0, 200])
.range([height,0]);
Here, the domain goes from 0 to 200, which is the maximum in your data. Then, those values will be mapped to:
.range([height, 0])
Where height is the height of the SVG.
Finally, use the scale in the line generator:
var line = d3.svg.line()
.x(function(d){ return d.x })
.y(function(d){ return scale(d.y) });
Here is your code with that scale:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<div class="paths"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js"></script>
<script>
var canvas = d3.select(".paths").append("svg")
.attr("width", 500)
.attr("height", 300);
var data = [
{x:10, y:200},
{x:30, y:170},
{x:50, y:70},
{x:70, y:140},
{x:90, y:150},
{x:110, y:120},
{x:130, y:150},
{x:150, y:140},
{x:170, y:110}
];
var group = canvas.append('g');
var scale = d3.scale.linear()
.domain([0, 200])
.range([300,0]);
var line = d3.svg.line()
.x(function(d){ return d.x })
.y(function(d){ return scale(d.y) });
group.selectAll("path")
.data([data])
.enter()
.append("path")
.attr("d", line)
.attr("fill", "none")
.attr("stroke", "red")
.attr("stroke-width", 2);
</script>
</body>
</html>
I am trying to get load data from iris.CSV and plot it in the web page.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>D3 Example</title>
<script src="https://d3js.org/d3.v3.js"></script>
</script>
</head>
<body>
<script>
var svg = d3.select("body").append("svg")
.attr("width", 250)
.attr("height", 250);
var xScale = d3.scale.linear().range([0, 250]);
var yScale = d3.scale.linear().range([0, 250]);
function render(data) {
xScale.domain(d3.extent(data, function(d) {
return d.sepal_length;
}));
yScale.domain(d3.extent(data, function(d) {
return d.petal_length;
}));
var circles = svg.selectAll("circle").data(data);
circles.enter().append("circle").attr("r", 10);
circles
.attr("cx", function(d) {
return xScale(d.sepal_length);
})
.attr("cy", function(d) {
return yScale(d.petal_length);
});
circles.exit().remove();
}
function type(d) {
d.sepal_length = +d.sepal_length;
d.sepal_width = +d.sepal_width;
d.petal_length = +d.petal_length;
d.petal_width = +d.petal_width;
return d;
}
d3.csv("iris.csv", type, render);
</script>
</body>
</html>
But I am getting an error in it.
Error: Uncaught TypeError: Cannot read property 'linear' of undefined
I even changed linear for scaleLinear for d3.v4., which is also showing the error.
Seems to work for me (I didn't have the CSV file so I just used some fake data):
var svg = d3.select("body").append("svg")
.attr("width", 250)
.attr("height", 250);
var xScale = d3.scale.linear().range([10, 240]);
var yScale = d3.scale.linear().range([10, 240]);
function render(data) {
xScale.domain(d3.extent(data, function(d) {
return d.sepal_length;
}));
yScale.domain(d3.extent(data, function(d) {
return d.petal_length;
}));
var circles = svg.selectAll("circle").data(data);
circles.enter().append("circle").attr("r", 10);
circles
.attr("cx", function(d) {
return xScale(d.sepal_length);
})
.attr("cy", function(d) {
return yScale(d.petal_length);
});
circles.exit().remove();
}
function type(d) {
d.sepal_length = +d.sepal_length;
d.sepal_width = +d.sepal_width;
d.petal_length = +d.petal_length;
d.petal_width = +d.petal_width;
return d;
}
render([{
sepal_length: 10,
petal_length: 20,
},
{
sepal_length: 15,
petal_length: 18,
}
])
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
I have found this gem while browsing this site : http://jsfiddle.net/MX7JC/9/ but I am not able to build a valid HTML who can run the script.
index.html
<!DOCTYPE html>
<html lang="en">
<script src="d3.v2.js"></script>
<link rel="stylesheet" type="text/css" href="d3portfolio.css" />
<head>
<div id="objectives">
Agg
Bal
Mod
Inc
</div>
<div id="d3portfolio"></div>
<script src="d3portfolio.js"></script>
</head>
</html>
Everything else is copy/paste from jsfiddle.
I use aptana studio but even if I upload it to altervista it doesnt work. I only see the "agg" donut chart.
I have 3 other files on my workspace : d3.v2.js, d3portfolio.js and d3portfolio.css
What I am missing ? I try to learn coding on my spare time by trial and errors.
Many thanks
The script in the page also makes use of jQuery for the click handler so you need to include that also.
Also use body to put your page content not the head
<!DOCTYPE html>
<html lang="en">
<head>
<script src="http://code.jquery.com/jquery-1.11.2.js"></script>
<script src="http://d3js.org/d3.v2.js"></script>
<link rel="stylesheet" type="text/css" href="d3portfolio.css" />
</head>
<body>
<div id="objectives">
Agg
Bal
Mod
Inc
</div>
<div id="d3portfolio"></div>
<script src="d3portfolio.js"></script>
</body>
</html>
var agg = {
label: 'Aggressive',
pct: [30, 10, 6, 30, 14, 10]
},
bal = {
label: 'Balanced',
pct: [24, 7, 2, 18, 13, 36]
},
mod = {
label: 'Moderate',
pct: [12, 4, 2, 10, 11, 61]
},
inc = {
label: 'Income',
pct: [0, 0, 0, 0, 0, 100]
},
data = agg;
var labels = ['LCAP', 'MCAP', 'SCAP', 'Intl', 'Alt', 'Fixed'];
var w = 320, // width and height, natch
h = 320,
r = Math.min(w, h) / 2, // arc radius
dur = 750, // duration, in milliseconds
color = d3.scale.category10(),
donut = d3.layout.pie().sort(null),
arc = d3.svg.arc().innerRadius(r - 70).outerRadius(r - 20);
// ---------------------------------------------------------------------
var svg = d3.select("#d3portfolio").append("svg:svg")
.attr("width", w).attr("height", h);
var arc_grp = svg.append("svg:g")
.attr("class", "arcGrp")
.attr("transform", "translate(" + (w / 2) + "," + (h / 2) + ")");
var label_group = svg.append("svg:g")
.attr("class", "lblGroup")
.attr("transform", "translate(" + (w / 2) + "," + (h / 2) + ")");
// GROUP FOR CENTER TEXT
var center_group = svg.append("svg:g")
.attr("class", "ctrGroup")
.attr("transform", "translate(" + (w / 2) + "," + (h / 2) + ")");
// CENTER LABEL
var pieLabel = center_group.append("svg:text")
.attr("dy", ".35em").attr("class", "chartLabel")
.attr("text-anchor", "middle")
.text(data.label);
// DRAW ARC PATHS
var arcs = arc_grp.selectAll("path")
.data(donut(data.pct));
arcs.enter().append("svg:path")
.attr("stroke", "white")
.attr("stroke-width", 0.5)
.attr("fill", function(d, i) {
return color(i);
})
.attr("d", arc)
.each(function(d) {
this._current = d
});
// DRAW SLICE LABELS
var sliceLabel = label_group.selectAll("text")
.data(donut(data.pct));
sliceLabel.enter().append("svg:text")
.attr("class", "arcLabel")
.attr("transform", function(d) {
return "translate(" + arc.centroid(d) + ")";
})
.attr("text-anchor", "middle")
.text(function(d, i) {
return labels[i];
});
// --------- "PAY NO ATTENTION TO THE MAN BEHIND THE CURTAIN" ---------
// Store the currently-displayed angles in this._current.
// Then, interpolate from this._current to the new angles.
function arcTween(a) {
var i = d3.interpolate(this._current, a);
this._current = i(0);
return function(t) {
return arc(i(t));
};
}
// update chart
function updateChart(model) {
data = eval(model); // which model?
arcs.data(donut(data.pct)); // recompute angles, rebind data
arcs.transition().ease("elastic").duration(dur).attrTween("d", arcTween);
sliceLabel.data(donut(data.pct));
sliceLabel.transition().ease("elastic").duration(dur)
.attr("transform", function(d) {
return "translate(" + arc.centroid(d) + ")";
})
.style("fill-opacity", function(d) {
return d.value == 0 ? 1e-6 : 1;
});
pieLabel.text(data.label);
}
// click handler
$("#objectives a").click(function() {
updateChart(this.href.slice(this.href.indexOf('#') + 1));
});
#d3portfolio {
width: 320px;
height: 320px;
}
.chartLabel {
font: 16px sans-serif;
fill: #666;
}
.arcLabel {
font: 10px sans-serif;
fill: #fff;
}
<script src="http://code.jquery.com/jquery-1.11.2.js"></script>
<script src="http://d3js.org/d3.v2.js"></script>
<div id="objectives">
Agg
Bal
Mod
Inc
</div>
<div id="d3portfolio"></div>
First thing you need to do is include the jquery library in your html. Secondly check you head section. You have put the content in it. That is not allowed in html. Move it to the body section.
<!DOCTYPE html>
<html lang="en">
<head>
<script src="http://code.jquery.com/jquery-1.11.2.js"></script>
//Your other scripts and stylesheets
</head>
<body>
//Your content.
//You include scripts at the bottom if you like.
</body>
</html>
I am trying to create a D3.js packed circle diagram.
When I embed the data in the HTML file, it works fine. When I put the data in an external file, I get nothing (blank DOM, no console msgs).
If you uncomment the var data declaration and comment out the d3.json (and the corresponding closing parentheses) it works fine.
I can see the "2013 Inf-2.json" file in the browser and it appears well formed (it passes jsonlint validation). It includes everything from the first "{" through/including the last "}". Much as the embedded example.
I'm running this through httpd (:80) on OSX Mavericks and trying to render the chart in Chrome or Safari.
<!DOCTYPE html>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<html lang="en">
<head>
<meta charset="utf-8">
<title></title>
<script type="text/javascript" src="./d3.v3.min.js"></script>
</head>
<body>
<div id="chart2"></div>
<script type="text/javascript">
var w = 640, h = 480;
/*
var data ={
"name" : "root",
"children" : [
{
"name":"URIN TRACT INFECTION NOS",
"size":12196
},
{
"name":"ACUTE PHARYNGITIS",
"size":6679
},
{
"name":"PNEUMONIA ORGANISM NOS",
"size":6452
},
{
"name":"BRONCHITIS NOS",
"size":2636
},
{
"name":"CELLULITIS OF LEG",
"size":2348
},
{
"name":"OBSTR CHRONIC BRONCHITIS W (ACUTE) EXACERBATION",
"size":2203
}
]
}
*/
var data = d3.json("2013 Inf-2.json", function(error, root) {
var canvas = d3.select("#chart2")
.append("svg:svg")
.attr("width", w)
.attr("height", h);
var nodes = d3.layout.pack()
.value(function(d) { return d.size; })
.size([w, h])
.nodes(data);
// Get rid of root node
nodes.shift();
canvas.selectAll("circles")
.data(nodes)
.enter().append("svg:circle")
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; })
.attr("r", function(d) { return d.r; })
.attr("fill", "green")
.attr("stroke", "grey");
});
</script>
</html>
You should change line
var data = d3.json("2013 Inf-2.json", function(error, root) {
to
var data = d3.json("2013 Inf-2.json", function(error, data) {
So you just have to replace "root" with "data"