Custom Polar Chart with gridlines D3.js - javascript

I have to plot a custom polar chart in which the radius of the circles vary and the grid lines are created at 30 degrees separation.Below is my code which plots the circle. The problem is that I am not able to plot the gridlines on the svg. The gridlines takes values from the list grid and it has values in x1,y1,x2,y2 format. Any idea why is it not plotting the gridline?
The image shows that it is taking only a single value from the list and appending it in the variables x1,y1,x2,y2
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="http://mbostock.github.com/d3/d3.js"></script>
</head>
<body>
<div id="circles"></div>
<script type="text/javascript">
var circleRadii = [100,90,80,70,60,50,40,30,20];
var min_radii = d3.min(circleRadii);
var max_radii = d3.max(circleRadii);
var theta_range = d3.range(0,360,30);
document.write(theta_range);
//set the svg container size
width = 750;
height = 750;
grid = [395,375,392.32,385,385,392.32,375,395,365,392.32,357.68,385,355,375,357.68,365,365,357.68,375,355,385,357.68,392.32,365,395,375]
var svgContainer = d3.select("body").append("svg")
.attr("width",width)
.attr("height",height);
var circles = svgContainer.selectAll("circle")
.data(circleRadii)
.enter()
.append("circle")
var circleAttributes = circles
.attr("cx",width/2)
.attr("cy",height/2)
.attr("r", function (d) { return d; })
.style("stroke","gray")
.style("fill","white");
var gridlines = svgContainer.append("gridline")
.data(grid)
.enter().append("gridline")
.attr("x1",function(d){return d;})
.attr("y1",function(d){return d;})
.attr("x2",function(d){return d;})
.attr("y2",function(d){return d;})
.attr("stroke", "black")
.attr("stroke-width", 2);
console.log(gridlines);
</script>
</body>
</html>

Related

D3.js - How to create transitions with drop down control for donut chart?

I want to create a donut chart with d3.js that changes with drop down options.
<!DOCTYPE html>
<meta charset="utf-8">
<body>
<form id="form1">
<select id="thedropdown">
<option value ="data">Loesche</option>
<option value ="data1">Bayer</option>
</select>
</form>
<!-- Load d3.js -->
<script src="https://d3js.org/d3.v4.js"></script>
<!-- Create a div where the graph will take place -->
<div id="my_dataviz"></div>
This is the first part of my code I wrote. The drop down options are shown, but don't work.
<script>
// set the dimensions and margins of the graph
var width = 450
height = 450
margin = 40
var radius = Math.min(width, height) / 2 - margin
var svg = d3.select("#my_dataviz")
.append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
var data = {a: 785, b: 345, c: 98}
var data1 = {a: 116998, b: 39586, c: 90 }
var color = d3.scaleOrdinal()
.domain(data)
.range(["#003f5c", "#bc5090", "#ffa600"])
var pie = d3.pie()
.value(function(d) {return d.value; })
var data_ready = pie(d3.entries(data))
document.getElementById("form1").onchange = function() {
company = document.getElementById("thedropdown").value;
if(company == "data") {
data = [785, 345, 98];
draw();
}
if(company == "data1") {
mydata = [116998, 39586, 90];
draw();
}
}
svg
.selectAll('whatever')
.data(data_ready)
.enter()
.append('path')
.attr('d', d3.arc()
.innerRadius(100) // This is the size of the donut hole
.outerRadius(radius)
)
.attr('fill', function(d){ return(color(d.data.key)) })
.attr("stroke", "black")
.style("stroke-width", "2px")
.style("opacity", 0.7)
</script>
What is the best technique to to solve this problem? What have I done wrong by creating the drop down? I would like to use a drop down option selector because I have around 20 categories and I would look not good with a click button option.
Do you have a draw() function that your are not showing? Otherwise, this is a brief example on using a dropdown to change dots on a scatter plot (https://observablehq.com/#kickout/basic-scatterplot)
dropdown.on('change',function(d){
var selvalue = this.value
updateColor(selvalue)

How can I render a d3.arc with different colors for different percentage?

I am using d3.arc to render a radial component. The code is:
https://codepen.io/zhaoyi0113/pen/PEgYZX
The current code renders a arc with percentage and the colour is red. See below screenshot:
I want to set up the color for the different percentage. For example, show green from 0% to 20%, orange from 20% to 50%, red for 50% above. How can I make this change on the d3?
One more thing I need to mention that I want to show all related colors in the radial component.For example, the first 20% is green, it shows orange from 20% to 50% and red for 50% above.
What you are describing is just a conventional donut chart with custom coloring:
<!DOCTYPE html>
<html>
<head>
<script src="//d3js.org/d3.v4.min.js"></script>
</head>
<body>
<svg width="960" height="500"></svg>
<script>
var tau = 2 * Math.PI; // http://tauday.com/tau-manifesto
// An arc function with all values bound except the endAngle. So, to compute an
// SVG path string for a given angle, we pass an object with an endAngle
// property to the `arc` function, and it will return the corresponding string.
var arc = d3.arc()
.innerRadius(80)
.outerRadius(100)
.cornerRadius(20);
var svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height"),
g = svg.append("g").attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
// Add the background arc, from 0 to 100% (tau).
var background = g.append("path")
.datum({
endAngle: tau
})
.style("fill", "#ddd")
.attr("d", arc);
var data = [.2, .3, .51];
var c = d3.scaleThreshold()
.domain([.201, .501, 1])
.range(["green", "orange", "red"]);
var pie = d3.pie()
.sort(null)
.value(function(d) {
return d;
});
g.selectAll(".arc")
.data(pie(data))
.enter()
.append("path")
.attr("class", "arc")
.style("fill", function(d) {
return c(d.value);
})
.attr("d", arc);
</script>
</body>
</html>

Cannot get JS chart to work / draw

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.)

How to append SVG to the page using D3

So I have a .js file that contains a simple SVG that creates a square. Code below:
function load(){
var xmlns = "http://www.w3.org/2000/svg";
var foo = document.getElementById("printSquare");
var bar = document.createElementNS(xmlns, "svg");
var svgSquare = d3.select("div.output svg")
s.appendChild(svgSquare)
foo.appendChild(bar);
var square = svg.select("rect")
square.attr("width", 200)
square.attr("height", 200)
}
window.onload = load;
I want to append this square to an html file so I can open it in a browser and see the square. My HTML code as of right now:
<html>
<head>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script type="text/javascript" src="drawSquare.js"></script>
</head>
<body>
<div id="printSquare"></div>
</body>
</html>
Check out this fiddle - https://jsfiddle.net/s8capLx3/2/
If you want to just create a square and nothing else, there are 2 ways to go about it...
Use d3 symbols or 2. Use a rect (like you tried)
var data = [0];
var svg = d3.select('#printSquare').append('svg').attr('width',400).attr('height',200);
//symbols approach
svg.selectAll('.symbol')
.data(data)
.enter()
.append('path')
.attr('transform',function(d,i) { return 'translate('+(i*20+20 )+','+30+')';})
.attr('d', d3.symbol().type( function(d,i) { return d 3.symbols[3];}).size("200"));
//rect approach
svg.append("rect")
.attr("x", "200")
.attr("y", "10")
.attr("width", "75")
.attr("height", "75")
.attr("fill", "black");

User input to Project on JSON map

I have the following D3.js project that is available here:
http://bl.ocks.org/diggetybo/raw/e75dcb649ae3b26e2312a63434fc970c/
The latitude and longitude inputs are below the map.
It's supposed to take user input numbers of latitude and longitude and "project" svg circles at the given coordinate. The issue is I'm either getting ____ is not a function error or dev tools throws no errors at all, but the circles are never projected.
It's a short file, can someone explain why it's not working the way I thought?
Your update function doesn't make any sense.
It accepts two inputs, but you only ever call it with one.
.selectAll("circle").enter() is not valid d3 syntax.
You need to call projection with both the latitude and longitude, you pass 0 which will result in it returning null since it's outside of the projection.
After you fix all this, you'll still be off because you've moved your paths by your margin and would have been better off putting them in a g moved by the margins.
All that said, a simple rewrite would be:
var lat = d3.select("#latValue").on("input", function() {
update();
}).node();
var long = d3.select("#lonValue").on("input", function() {
update();
}).node();
function update() {
// lat/long to pixel
var coors = projection([long.value, lat.value]);
// if outside projection don't add circle
if (coors === null) return;
// add circle
container
.append("circle")
.attr("cx", coors[0])
.attr("cy", coors[1])
.attr("r", Math.sqrt(5) * 4)
.style("fill", "black")
.style("opacity", 0.85);
}
Running code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<script src="http://d3js.org/d3.v3.min.js"></script>
<style type="text/css">
/* On mouse hover, lighten state color */
path:hover {
fill-opacity: .7;
}
</style>
</head>
<body>
<script type="text/javascript">
//Width and height of map
var width = 960;
var height = 500;
var margins = { left: 0, top: 100, right: 0, bottom: 0 };
// D3 Projection
var projection = d3.geo.albersUsa()
.translate([width/2, height/2]) // translate to center of screen
.scale([1000]); // scale things down so see entire US
// Define path generator
var path = d3.geo.path() // path generator that will convert GeoJSON to SVG paths
.projection(projection); // tell path generator to use albersUsa projection
// Define linear scale for output
var color = d3.scale.linear()
.range(["#c3e2ff","#15198e"]);
//Create SVG element and append map to the SVG
var svg = d3.select("body")
.append("svg")
.attr("width", width)
.attr("height", height+margins.top);
svg.append('text')
.text('Coordinate Query')
.attr('font-size','24px')
.attr('transform', 'translate(' + 30 + ',' +70 + ')')
.attr('font-family','Calibri');
svg.append('text')
.text('Data as of 12/2016')
.attr('font-size','12px')
.attr('transform', 'translate(' + 35 + ',' +100 + ')')
.attr('font-family','Calibri');
// Load in my states data!
color.domain([0,100]); // setting the range of the input data
// Load GeoJSON data and merge with states data
d3.json("https://jsonblob.com/api/573228c3-d068-11e6-b16a-b501dc8d2b08", function(json) {
//var coordinates = d3.mouse(this);
// Bind the data to the SVG and create one path per GeoJSON feature
var container = svg.append("g")
.attr('transform', 'translate(' + margins.left + ',' + margins.top + ')');
container.selectAll("path")
.data(json.features)
.enter()
.append("path")
.attr("d", path)
.style("stroke", "#fff")
.style("stroke-linejoin","round")
.style("stroke-width", "1.5")
.style("fill", 'steelblue');
// Modified Legend Code from Mike Bostock: http://bl.ocks.org/mbostock/3888852
var lat = d3.select("#latValue").on("input", function() {
update();
}).node();
var long = d3.select("#lonValue").on("input", function() {
update();
}).node();
function update() {
// lat/long to pixel
var coors = projection([long.value, lat.value]);
// if outside projection don't add circle
if (coors === null) return;
// add circle
container
.append("circle")
.attr("cx", coors[0])
.attr("cy", coors[1])
.attr("r", Math.sqrt(5) * 4)
.style("fill", "black")
.style("opacity", 0.85);
}
});
</script>
<p>
<label for="latValue"
style="display: inline-block;width:240px;text-align:right;font-size:18px;font-family:Play">
Lattitude:<span id="latValue-value"></span>
</label>
<input type="number"min="-360"max="360"step="1"value="0" id="latValue">
<label for="lonValue"
style="display: inline-block;width:240px;text-align:right;font-size:18px;font-family:Play">
Longitude:<span id="lonValue-value"></span>
</label>
<input type="number"min="-360"max="360"step="1"value="0" id="lonValue">
</p>
</body>
</html>

Categories

Resources