Cannot get JS chart to work / draw - javascript

I have been trying to get the path element to draw a line between 2 points on the chart, but unable to. I am using json to grab the data, but it does not put anything on the graph other than the numbers and the dates. What am I missing here?
I also tried to use artificial numbers in my dates / rates array to see if it would draw something, but it hasn't. I'm just not sure how to get it to use the json data to draw a line or a point on the graph.
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.0/d3.min.js"></script>
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title></title>
<!-- <script src="charting.js"> </script> -->
<script src="https://d3js.org/d3.v4.min.js"> </script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
</head>
<body>
<div class="mypanel"></div>
<script>
function showChart()
{
d3.json("http://api.fixer.io/2017-01-03", function (jsonData) {
var width = 800;
var heigth = 500;
var margin = 100;
var chartWidth = width - margin*2;
var chartHeigth = heigth - margin*2;
var rates = ['1', '2000'];
var dates = ['2017-01-03', '2017-02-03'];
var yScale = d3.scaleLinear()
.domain([d3.min(rates), d3.max(rates)])
.range([chartHeigth, 0]);
var xScale = d3.scaleBand()
.domain(dates)
.range([0, chartWidth]);
var yAxis = d3.axisLeft(yScale);
var xAxis = d3.axisBottom(xScale);
var canvas = d3.select("body")
.append("svg")
.attr("width", width)
.attr("height", heigth);
var chartGroup = canvas.append("g")
.attr("transform", "translate(" + margin + ", " + margin + ")");
var line = d3.line()
.x(function (d) { return xScale(d.date) })
.y(function (d) { return yScale(d.rate) });
chartGroup.append("path")
.attr("d", line(jsonData))
.attr("fill", "none")
.attr("stroke", "red")
.attr("stroke-width", "3px")
.attr("transform", "translate(" + (100) / 2 + ", 0)");
chartGroup.append("g")
.call(yAxis);
chartGroup.append("g")
.attr("transform", "translate(0, "+chartHeigth+")")
.call(xAxis);
});
}
// for (var property in jsonData.rates) {
// if (jsonData.rates.hasOwnProperty(property)) {
// rates.push(jsonData.rates[property]);
// }
// }
</script>
<script> showChart(); </script>
</body>
</html>

There are two problems to start with. The JSON request is not https, so it's being denied. Once you have that fixed, the CORS headers from api.fixer.io isn't allowing cross-domain use. (I'm not sure that's all of what's going on, but it's a start.)

Related

How to zoom my stream-graph with using D3V6?

Update:
The zooming stream graph question is resolved. Thank you, Andrew! But the zooming of the streamgraph doesn't align with the zooming of the X and Y axis.
Thisis the picture showing how it looks like now2
the original post is here:
I am new to StackOverflow and the javascript community. I am trying to zoom a streamgraph I did use javascript and D3 and I followed this tutorial: https://www.d3-graph-gallery.com/graph/interactivity_zoom.html#axisZoom.
My code can be viewed here: https://github.com/Feisnowflakes/zoomtest222/tree/main/streamgraph-test
However, currently, I can zoom X aXis and Y aXis, but not my stream graph is zoomable. I didn't see any errors in my console, so I am stuck now. Can anyone like to look at my codes and help me figure out why my streamgraph cannot be zoomed?
Thank you so much!
(function () {
// first, load the dataset from a CSV file
d3.csv("https://raw.githubusercontent.com/Feisnowflakes/zoomtest222/main/streamgraph-test/Los_Angeles_International_Airport_-_Passenger_Traffic_By_Terminal.csv")
.then(data => {
// log csv in browser console
console.log(data);
var advanceVisData = {};
var airport = new Set();
data.forEach(d => {
airport.add(d['Terminal']);
var period = new Date(d['ReportPeriod']);
if (period in advanceVisData) {
if (d['Terminal'] in advanceVisData[period]) {
advanceVisData[period][d['Terminal']] += Number(d['Passenger_Count']);
}
else {
advanceVisData[period][d['Terminal']] = Number(d['Passenger_Count']);
}
}
else {
advanceVisData[period] = {};
advanceVisData[period][d['Terminal']] = Number(d['Passenger_Count']);
}
});
console.log(airport);
console.log(advanceVisData);
// reformat the advanceVisData for d3.stack()
var formattedData = [];
Object.keys(advanceVisData).forEach(d => {
var item = {};
item['year'] = d;
airport.forEach(terminal => {
if (terminal in advanceVisData[d]) {
item[terminal] = advanceVisData[d][terminal];
} else {
item[terminal] = 0;
}
});
formattedData.push(item);
});
console.log(formattedData);
/*********************************
* Visualization codes start here
* ********************************/
var width = 1200;
var height = 400;
var margin = { left: 60, right: 20, top: 20, bottom: 60 };
//set the dimensions and margins of the graph
// append the svg object to the body of the page
var svg = d3.select('#container')
.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 + ")");
// List of groups = header of the csv files
var keys = Array.from(airport);
//stack the data?
var stackedData = d3.stack()
//.offset(d3.stackOffsetSilhouette)
.keys(keys)
(formattedData);
console.log(stackedData);
var max_val = 0;
var min_val = 0;
stackedData.forEach(terminal => {
terminal.forEach(year => {
if (year[0] < min_val) min_val = year[0];
if (year[1] < min_val) min_val = year[1];
if (year[0] > max_val) max_val = year[0];
if (year[1] > max_val) max_val = year[1];
})
});
//console.log(max_val, min_val);
// Add X axis
var x = d3.scaleTime()
.domain(d3.extent(formattedData, function (d) {
return new Date(d.year);
}))
.range([0, width]);
var xAxis = svg.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x).ticks(20));
// Add Y axis
var y = d3.scaleLinear()
.domain([min_val, max_val])
.range([height, 0]);
var yAxis = svg.append("g")
.call(d3.axisLeft(y));
// color palette
var color = d3.scaleOrdinal()
.domain(keys)
.range(['#e41a1c', '#377eb8', '#4daf4a', '#984ea3', '#ff7f00', '#f781bf', "#87sbf", "#ff981bf","#d6a3b6", '#b3afb0', '#ddd8c2']);
// create a tooltip
var Tooltip = svg
.append("text")
.attr("x", 0)
.attr("y", 0)
.style("opacity", 0)
.style("font-size", 17)
// Show the areas
var stream = svg.append("g")
stream
.selectAll(".myStreamArea")
.data(stackedData)
.enter()
.append("path")
.attr("class", "myStreamArea")
.style("fill", function (d) {
return color(d.key);
})
.style("opacity", 1)
.attr("d", d3.area()
.x(function (d) {
return x(new Date(d.data.year));
})
.y0(function (d) {
return y(d[0]);
})
.y1(function (d) {
return y(d[1]);
})
);
// Set the zoom and Pan features: how much you can zoom, on which part, and what to do when there is a zoom
var zoom = d3.zoom()
.scaleExtent([.5, 20]) // This control how much you can unzoom (x0.5) and zoom (x20)
.extent([[0, 0], [width, height]])
.on("zoom", updateChart);
// This add an invisible rect on top of the chart area. This rect can recover pointer events: necessary to understand when the user zoom
svg.append("rect")
.attr("width", width)
.attr("height", height)
.style("fill", "none")
.style("pointer-events", "all")
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')
.call(zoom);
// now the user can zoom and it will trigger the function called updateChart
// A function that updates the chart when the user zoom and thus new boundaries are available
function updateChart() {
// recover the new scale
var transform = d3.zoomTransform(this);
var newX = transform.rescaleX(x);
var newY = transform.rescaleY(y);
// var newX = d3.event.transform.rescaleX(x);
// var newY = d3.event.transform.rescaleY(y);
// update axes with these new boundaries
xAxis.call(d3.axisBottom(newX))
yAxis.call(d3.axisLeft(newY))
stream
.selectAll(".myStreamArea")
.attr("d", d3.area()
.x(function (d) {
return newX(new Date(d.data.year));
})
.y0(function (d) {
return newY(d[0]);
})
.y1(function (d) {
return newY(d[1]);
}));
}
})
})();
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Zoomable streamgraph</title>
<script src="https://d3js.org/d3.v6.min.js"></script>
<style>
#tooltip {
min-width: 100px;
min-height: 50px;
background-color: white;
}
</style>
</head>
<body>
<div id="container"> <div id="tooltip"></div></div>
<script src="main.js"></script>
</body>
</html>

d3.js bar graph is not showing bars

I read previously answered questions but had no luck.
I am plotting a bar graph of elements on array using d3.js but the bars are not shown as they should be.
This is the script I am trying:
var data = [1, 2, 3, 4, 5];
var svg = d3.select("svg");
var margin = 100,
width = svg.attr("width") - margin,
height = svg.attr("height") - margin;
var Xscale = d3.scaleBand()
.domain([0, data.length])
.range([0, width])
.padding(0.2);
var Yscale = d3.scaleLinear()
.domain([0, d3.max(data)])
.range([height, 0]);
var g = svg.append("g")
.attr("transform", "translate(" + 100 + "," + 100 + ")");
g.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(Xscale).tickFormat(function(d) {
return d;
}).ticks(10));
// .append("text")
// .attr("x", 6)
// .attr("text-anchor", "end")
// .text("index");
g.append("g")
.call(d3.axisLeft(Yscale).tickFormat(function(d) {
return d;
}).ticks(10))
.append("text")
.attr("y", 6)
.attr("dy", "0.71em")
.attr("text-anchor", "end")
.text("value");
g.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", "bar")
.attr("x", function(d, i) {
return 0;
})
.attr("y", function(d, i) {
return 0;
})
.attr("width", Xscale.bandwidth())
.attr("height", function(d, i) {
return 0;
});
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Bar chart with D3.js</title>
<link href="https://fonts.googleapis.com/css?family=Open+Sans" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="styles/da.css">
<script src="https://d3js.org/d3.v5.min.js"></script>
<!-- <script src="js/da.js"></script> -->
</head>
<body>
<div id='layout'>
<h2>Bar chart example</h2>
<div class='container'>
<svg class="chart" height="500" width="1000" />
</div>
</div>
<p>Why this is not working?? </p>
</body>
</html>
I do feel that the problem is in last few lines, fetching x, y, width and height. I can't understand what values to return, I tried various, but didn't get the graph. So, I have just put return 0 there.
What should be the values? And how to decide it?
Thank you for help. :)
Your scaleBand().domain() has to be an array for the Xscale. In my solution I choose to have the indexes of the values as the array. You could map your data (usually an array of objects) to other values of the objects in an array.
Additionally there were several other issues with the scaling in terms of height and width of the actual bars and their positioning. Keep in mind that the SVG origin is the top left corner and everything is with respect to that.
I have updated the code below which makes necessary changes to produce a bar graph. Please go through it and let me know if there is anything that you do not understand.
var data = [1, 2, 3, 4, 5];
var svg = d3.select("svg");
var margin = 100,
width = svg.attr("width") - margin,
height = svg.attr("height") - margin;
var Xscale = d3.scaleBand()
.domain(data.map((e,i) => i)) //returns array [0,1,2,3,4] for the index of the values
.range([0, width])
.padding(0.2);
var dmax = d3.max(data) //calculates the max value of the data
var Yscale = d3.scaleLinear()
.domain([0, dmax])
.range([height, 0]);
var g = svg.append("g")
.attr("transform", "translate(" + 50 + "," + 50 + ")");
var x = g.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(Xscale).tickFormat(function(d) {
return d;
}).ticks(10))
.append("text")
.attr("x", 6)
.attr("text-anchor", "end")
.text("index");
var y = g.append("g")
.call(d3.axisLeft(Yscale).tickFormat(function(d) {
return d;
}).ticks(10))
.append("text")
.attr("y", 6)
.attr("dy", "0.71em")
.attr("text-anchor", "end")
.text("value");
g.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", "bar")
.attr("x", function(d, i){ return Xscale(i)}) //move the bar to the x position where it should appear
.attr("y", function(d, i) { return Yscale(d); }) //move the bar from the top down to the level of the value.
.attr("width", Xscale.bandwidth() ) //the width of the bar is the width between the points on the x-axis
.attr("height", function(d, i) {
return Yscale(dmax-d);
}); // the height of the points is calculated based on the scale and the difference between this point and the max value of the data.
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Bar chart with D3.js</title>
<link href="https://fonts.googleapis.com/css?family=Open+Sans" rel="stylesheet">
<script src="https://d3js.org/d3.v5.min.js"></script>
</head>
<body>
<div id='layout'>
<h2>Bar chart example</h2>
<div class='container'>
<svg class="chart" height="500" width="1000" />
</div>
</div>
<p>Why this is not working?? </p>
</body>
</html>
I recommand you to read this article. It explain very well how to use bar charts.
https://blog.risingstack.com/d3-js-tutorial-bar-charts-with-javascript/
I used your code and did a simple example. https://codepen.io/mp-9007/pen/jJpEWY
The main issues are because of the return values of x, y and height;
You have to provide the x and y position in the graph area. Drawing the bar chart is like drawing on a Cartesian plane, you must provide the coordinate of where to start the bar, the width of the bar and the height of it. The origin of the plan is at the top left of the image.
.attr("x", function(d, i) { //d = input data, i = index of it
return Xscale(d); //The scaling function returns the coordinate for a given domain value.
})
.attr("y", function(d, i) { //d = input data, i = index of it
return Yscale(d); //The scaling function returns the coordinate for a given domain value.
})
.attr("width", Xscale.bandwidth())
.attr("height", function(d, i) { //d = input data, i = index of it
return height - Yscale(d); //The computed y coordinate has to be subtracted from the height of the chart to get the correct representation of the value as a column.
});
Also, the domain for the x-axis can be think as categories. In your code, you were providing only two category: 0 and data.length . Provinding the array solved this issue.
var Xscale = d3.scaleBand().domain(data)

Data points and ticks in the scaleBand axis are not aligned

My data points and the values in the scaleBand y axis are not aligned. I am not able to align them properly, when I read the documentation, saw that by default the alignment is 0.5 and that's why my data points are plotted between the two points in the axis. But I tried to override the alignment my giving the alignment as 0, but there seems to be no change.
The following is my code.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<title>D3 v4 - linechart</title>
<style>
#graph {
width: 900px;
height: 500px;
}
.tick line {
stroke-dasharray: 2 2 ;
stroke: #ccc;
}
.y path{
fill: none;
stroke: none;
}
</style>
</head>
<body>
<div id="graph"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.1.1/d3.min.js"></script>
<script>
!(function(){
"use strict"
var width,height
var chartWidth, chartHeight
var margin
var svg = d3.select("#graph").append("svg")
var axisLayer = svg.append("g").classed("axisLayer", true)
var chartLayer = svg.append("g").classed("chartLayer", true)
var xScale = d3.scaleLinear()
var yScale = d3.scaleBand()
var align = 0
//d3.tsv("data1.tsv", cast, main)
d3.json("http://localhost/d32.json",cast)
//データの方変換
function cast(data) {
console.log("got it");
data.forEach(function(data) {
console.log(data.Letter);
data.Letter = data.Letter;
data.Freq = +data.Freq;
});
main(data);
}
function main(data) {
console.log("in main");
setSize(data)
drawAxis()
drawChart(data)
}
function setSize(data) {
width = document.querySelector("#graph").clientWidth
height = document.querySelector("#graph").clientHeight
margin = {top:40, left:100, bottom:40, right:0 }
chartWidth = width - (margin.left+margin.right+8)
chartHeight = height - (margin.top+margin.bottom)
svg.attr("width", width).attr("height", height)
axisLayer.attr("width", width).attr("height", height)
chartLayer
.attr("width", chartWidth)
.attr("height", chartHeight)
.attr("transform", "translate("+[margin.left, margin.top]+")")
xScale.domain([0, d3.max(data, function(d) { return d.Freq; })]).range([0,chartWidth])
yScale.domain(data.map(function(d) { return d.Letter; })).range([chartHeight, 0]).align(1)
}
function drawChart(data) {
console.log("in drawChart");
var t = d3.transition()
.duration(8000)
.ease(d3.easeLinear)
.on("start", function(d){ console.log("transiton start") })
.on("end", function(d){ console.log("transiton end") })
var lineGen = d3.line()
.x(function(d) { return xScale(d.Freq) })
.y(function(d) { return yScale(d.Letter) })
.curve(d3.curveStepAfter)
var line = chartLayer.selectAll(".line")
.data([data])
line.enter().append("path").classed("line", true)
.merge(line)
.attr("d", lineGen)
.attr("fill", "none")
.attr("stroke", "blue")
.attr("stroke-width","2px")
.attr("stroke-dasharray", function(d){ return this.getTotalLength() })
.attr("stroke-dashoffset", function(d){ return this.getTotalLength() })
chartLayer.selectAll(".line").transition(t)
.attr("stroke-dashoffset", 0)
chartLayer.selectAll("circle").classed("circle",true)
.data(data)
.enter().append("circle")
.attr("class", "circle")
.attr("fill","none")
.attr("stroke","black")
.attr("cx", function(d) { return xScale(d.Freq); })
.attr("cy", function(d) { return yScale(d.Letter); })
.attr("r", 4);
chartLayer.selectAll(".logo").transition(t)
.attr("stroke-dashoffset", 0)
}
function drawAxis(){
var yAxis = d3.axisLeft(yScale)
.tickSizeInner(-chartWidth)
axisLayer.append("g")
.attr("transform", "translate("+[margin.left, margin.top]+")")
.attr("class", "axis y")
.call(yAxis);
var xAxis = d3.axisBottom(xScale)
axisLayer.append("g")
.attr("class", "axis x")
.attr("transform", "translate("+[margin.left, chartHeight+margin.top]+")")
.call(xAxis);
}
}());
</script>
</body>
</html>
The output is shown here:
The band scale is the wrong tool in this situation. The main reason is that a band scale has an associated bandwidth.
You can tweak the paddingInner and paddingOuter values of the band scale to give you the expected result. However, the easiest solution is using a point scale instead. Point scales:
...are a variant of band scales with the bandwidth fixed to zero. (emphasis mine)
So, it should be:
var yScale = d3.scalePoint()

Using a conditional statement to draw polylines in d3.js

Currently drawing have a piechart made in d3, and want to add a set of polylines to each arc that will extrude out of each arc at a certain angle depending on where the arc lies.
<!doctype HTML>
<html>
<head>
<title>Page Title</title>
<meta charset="UTF-8">
<script type="text/javascript" src="js/d3.min.js"></script>
<link rel="stylesheet" type="text/css" href="css/style.css">
</head>
<body>
<script type="text/javascript">
//=========================================================================================================================================
// initializing variables
var data = []; // empty array to hold the objects imported from the JSON file
var oRadius = 300; //var holding value for the outer radius of the arc
var iRadius = 80; //var holding the value for the inner radius of the arc
var cRadius = 3; //var holding the value for the corner radius of the arc
var colors = d3.scale.category20b();//built in D3 function to color pieces of data
var width = 1400; //setting the width of the svg
var height = 1000; //setting the height of the svg
var dRadius = 5; //setting the radius for the dots
var sColor = "white"; // color for the stroke of the arcs
var dStrokeColor = "#666";
var dFillColor = "#ccc"
var lineMaker = d3.svg.line().x(function(d) { return d.x; }).y(function(d) { return d.y; }).interpolate("linear");
var myArcMaker= d3.svg.arc().outerRadius(oRadius).innerRadius(iRadius).cornerRadius(cRadius); //var that creates the arc
var bigArcMaker= d3.svg.arc().outerRadius(400).innerRadius(oRadius).cornerRadius(cRadius);
var mySvg = d3.select('body')
.append('svg')
.attr('width', width)
.attr("height", height) //selecting the body and appending an, then svg setting the height and width properties for the svg
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")")// centers the pie chart in the center of the svg
mySvg.append("g")
.attr("class", "slices");
mySvg.append("g")
.attr("class", "dots");
mySvg.append("g")
.attr("class", "lines");
mySvg.append("g")
.attr("class", "polyLines");
var myPie = d3.layout.pie()
.sort(null)
.startAngle(2*(Math.PI))
.endAngle(((Math.PI))/360)
.padAngle(-1.5*(2*(Math.PI))/360).value(function(d){return d.value}); //setting the values for that start angle, end angle and pad angle for the arcs and takes in the the values from the objects in the data array
//======================================================================================================================================================
d3.json("data.json", function (json) // importing the json file
{
data = json; // setting the empty data array equal to the values of the objects in the json file
visual(); // this function holds all the d3 code to create the arc
})
//======================================================================================================================================================
function visual() // this function prevents the code that creates the arc from running before the objects from the json file are added into the empty data array
{
// console.log(data); // checking to see if the objects are loaded into the data ray using the console in chrome
var slice = mySvg.select(".slices")
.selectAll("path.slice")
.data(myPie(data)) //
.enter()
.append("path")
.attr("class", "slice")
.attr("d", function(d) {
return myArcMaker(d)
})
.attr("fill", function(d, i) {
return colors(i);
}) //using the d3 color brewer to color each arc
.attr("stroke", "white") //giving each arc a stroke of white
var dots = mySvg.select("g.dots")
.selectAll("cirlces")
.data(myPie(data))
.enter()
.append("circle")
.attr("class", "g.dots")
.attr("transform", function(d)
{
return "translate(" + myArcMaker.centroid(d) + ")";
})
.attr("r", dRadius)
.attr("fill", dFillColor)
.attr("stroke", sColor)
//
var lines = mySvg.select(".lines")
.selectAll("path.lines")
.data(myPie(data)) //
.enter()
.append("path")
.attr("class", "lines")
.attr("d", function(d) {
return bigArcMaker(d)
}).attr("fill", "none")
.attr("stroke", "white")
var outerDots = mySvg.select("g.dots")
.selectAll("cirlces")
.data(myPie(data))
.enter()
.append("circle")
.attr("class", "g.dots")
.attr("transform", function(d)
{
return "translate(" + bigArcMaker.centroid(d) + ")";
})
.attr("r", dRadius)
.attr("fill", dFillColor)
.attr("stroke", sColor)
// var x1 = myArcMaker.centroid(d)[0];
// var y1 = myArcMaker.centroid(d)[1];
// var x2 = bigArcMaker.centroid(d)[0];
// var y2 = bigArcMaker.centroid(d)[1];
// var x3 = function(d){if(x2<0){return bigArcMaker.centroid(d)[0]-160}}
// var lineData = [{'x': x1},
// ]
var polyLines = mySvg.select(".polyLines")
.selectAll("polylines")
.data(data)
.enter()
.append("polyline")
.attr("class", "polyLines")
.attr("points", function(d)
{
return
myArcMaker.centroid(d)[0] + ',' + myArcMaker.centroid(d)[1] + ','
+ bigArcMaker.centroid(d)[0] + ',' + bigArcMaker.centroid(d)[1] + ','+
(bigArcMaker.centroid(d)[0] < 0 )
? (bigArcMaker.centroid(d)[0] - 160) : (bigArcMaker.centroid(d)[0] + 160) + ',' +
bigArcMaker.centroid(d)[1]
})
.attr("fill", "#ccc")
.attr("stroke", sColor)
}
</script>
</body>
</html>
I have the polylines being appending to my svg when I use the inspect element in chrome but they arent showing up, they have no points. This leads me to believe its something to do with my conditional statement, is there something I'm not seeing? I'm new to d3 and javascript so its possible I just wrote the entire conditional statement wrong.
Couple things.
1.) You forgot to "pie" your data in the data-binding when you generate your polylines.
2.) Your conditional is getting lost somewhere because of the string concatenation. I would suggest you re-write that into something readable like:
.attr("points", function(d) {
var p = "";
p += myArcMaker.centroid(d)[0] + ',' + myArcMaker.centroid(d)[1] + ',' + bigArcMaker.centroid(d)[0] + ',' + bigArcMaker.centroid(d)[1] + ',';
p += bigArcMaker.centroid(d)[0] < 0 ? bigArcMaker.centroid(d)[0] - 160 : bigArcMaker.centroid(d)[0] + 160;
p += ',' + bigArcMaker.centroid(d)[1];
return p;
})
Working code:
<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
<meta charset="UTF-8" />
<script data-require="d3#3.5.3" data-semver="3.5.3" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js"></script>
</head>
<body>
<script type="text/javascript">
//=========================================================================================================================================
// initializing variables
var data = []; // empty array to hold the objects imported from the JSON file
var oRadius = 300; //var holding value for the outer radius of the arc
var iRadius = 80; //var holding the value for the inner radius of the arc
var cRadius = 3; //var holding the value for the corner radius of the arc
var colors = d3.scale.category20b(); //built in D3 function to color pieces of data
var width = 1400; //setting the width of the svg
var height = 1000; //setting the height of the svg
var dRadius = 5; //setting the radius for the dots
var sColor = "white"; // color for the stroke of the arcs
var dStrokeColor = "#666";
var dFillColor = "#ccc"
var lineMaker = d3.svg.line().x(function(d) {
return d.x;
}).y(function(d) {
return d.y;
}).interpolate("linear");
var myArcMaker = d3.svg.arc().outerRadius(oRadius).innerRadius(iRadius).cornerRadius(cRadius); //var that creates the arc
var bigArcMaker = d3.svg.arc().outerRadius(400).innerRadius(oRadius).cornerRadius(cRadius);
var mySvg = d3.select('body')
.append('svg')
.attr('width', width)
.attr("height", height) //selecting the body and appending an, then svg setting the height and width properties for the svg
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")") // centers the pie chart in the center of the svg
mySvg.append("g")
.attr("class", "slices");
mySvg.append("g")
.attr("class", "dots");
mySvg.append("g")
.attr("class", "lines");
mySvg.append("g")
.attr("class", "polyLines");
var myPie = d3.layout.pie()
.sort(null)
.startAngle(2 * (Math.PI))
.endAngle(((Math.PI)) / 360)
.padAngle(-1.5 * (2 * (Math.PI)) / 360).value(function(d) {
return d.value
}); //setting the values for that start angle, end angle and pad angle for the arcs and takes in the the values from the objects in the data array
data= [{
value: 10
},{
value: 20
},{
value: 30
}];
visual();
//======================================================================================================================================================
function visual() // this function prevents the code that creates the arc from running before the objects from the json file are added into the empty data array
{
var slice = mySvg.select(".slices")
.selectAll("path.slice")
.data(myPie(data)) //
.enter()
.append("path")
.attr("class", "slice")
.attr("d", function(d) {
return myArcMaker(d)
})
.attr("fill", function(d, i) {
return colors(i);
}) //using the d3 color brewer to color each arc
.attr("stroke", "white") //giving each arc a stroke of white
var dots = mySvg.select("g.dots")
.selectAll("cirlces")
.data(myPie(data))
.enter()
.append("circle")
.attr("class", "g.dots")
.attr("transform", function(d) {
return "translate(" + myArcMaker.centroid(d) + ")";
})
.attr("r", dRadius)
.attr("fill", dFillColor)
.attr("stroke", sColor)
//
var lines = mySvg.select(".lines")
.selectAll("path.lines")
.data(myPie(data)) //
.enter()
.append("path")
.attr("class", "lines")
.attr("d", function(d) {
return bigArcMaker(d)
}).attr("fill", "none")
.attr("stroke", "white")
var outerDots = mySvg.select("g.dots")
.selectAll("cirlces")
.data(myPie(data))
.enter()
.append("circle")
.attr("class", "g.dots")
.attr("transform", function(d) {
return "translate(" + bigArcMaker.centroid(d) + ")";
})
.attr("r", dRadius)
.attr("fill", dFillColor)
.attr("stroke", sColor)
var polyLines = mySvg.select(".polyLines")
.selectAll("polylines")
.data(myPie(data))
.enter()
.append("polyline")
.attr("class", "polyLines")
.attr("points", function(d) {
var p = "";
p += myArcMaker.centroid(d)[0] + ',' + myArcMaker.centroid(d)[1] + ',' + bigArcMaker.centroid(d)[0] + ',' + bigArcMaker.centroid(d)[1] + ',';
p += bigArcMaker.centroid(d)[0] < 0 ? bigArcMaker.centroid(d)[0] - 160 : bigArcMaker.centroid(d)[0] + 160;
p += ',' + bigArcMaker.centroid(d)[1];
return p;
})
.attr("fill", "#ccc")
.attr("stroke", sColor)
}
</script>
</body>
</html>

D3 Horizontal stacked bar chart axis cut off

Hope someone can help, I have a slight problem in that the horizontal axis label 100 gets cut off the end of the stacked horizontal barchart. I can't seem to figure out what is wrong in the code. Thanks in advance for your help. Please see code below.
<!DOCTYPE html>
-->
<html>
<head>
<title>Horizontal stacked bar</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<script type="text/javascript" src="d3/d3.js"> </script>
<style>
.axis{
font-size: 14px;
}
#h{
}
</style>
</head>
<body>
<script>
var margin = {
top: 12,
left: 15,
right: 15,
bottom: 14
};
var w = 500 - margin.left - margin.right;
var h = 300 - margin.top - margin.bottom;
var dataset = [
[
{x:0,y:20}
],
[
{x:0,y:30}
],
[
{x:0,y:50}
]
];
//Set up stack method
var stack = d3.layout.stack();
//Data, stacked
stack(dataset);
//Set up scales
var xScale = d3.scale.linear()
.domain([0,d3.max(dataset, function(d) {return d3.max(d, function(d)
{return d.y0 + d.y;}); }) ])
// note use of margin + right to get axis to scale width
.range([0, w + margin.right]);
var yScale = d3.scale.ordinal()
.domain(d3.range(dataset[0].length))
.rangeRoundBands([0,w ], 0.05);
//Easy colors accessible via a 10-step ordinal scale
var colors = d3.scale.category10();
//or make your own colour palet
var color = d3.scale.ordinal()
.range(["#1459D9", "#148DD9", "#87ceeb", "#daa520"]);
// good site for colour codes http://www.colorpicker.com/113EF2
//Create SVG element
var svg = d3.select("body")
.append("svg")
.attr("width", w + margin.left + margin.right)
.attr("height", h + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
;
// Add a group for each row of data
var groups = svg.selectAll("g")
.data(dataset)
.enter()
.append("g")
.style("fill", function(d,i){return color(i);})
;
// Add a rect for each data value
var rects = groups.selectAll("rect")
.data(function(d) { return d; })
.enter()
.append("rect")
.attr("x", function(d) {return xScale(d.y0) ;}) //+99 will move axis right
.attr("y", 180)
.attr("height", 90)
.attr("width", yScale.rangeBand());
//Add an axis
var xAxis = d3.svg.axis()
.scale(xScale);
svg.append("g")
.call(xAxis)
;
</script>
</body>
</html>
You are really better off using the xScale for both dimensions, x and y. After all, your y is really a width. Here is what I mean:
...
//Set up scales
var xScale = d3.scale.linear()
.domain([0, d3.max(dataset, function (d) {
return d3.max(d, function (d) {
return d.y0 + d.y;
});
})])
.range([0, w]); // no need to tamper with margins since w already accounts for that
...
// Add a rect for each data value
var rects = groups.selectAll("rect")
.data(function (d) {return d;})
.enter()
.append("rect")
.attr("x", function (d) {
return xScale(d.y0); // use x scale
})
.attr("y", 50)
.attr("height", 50)
.attr("width", function (d) {
return xScale(d.y); // use x scale
})
...
And here is the updated FIDDLE. You can go ahead and make changes to the right margin value and any of your data y values (I placed comments in the code to that effect) and you can see that this solution scales well.

Categories

Resources