I'm having a problem while getting the xAxis done. I'm a newby using D3 and I just got lost by using the D3 Date method. Could anyone help me to figure it out the problem that is causing the undefined is not a function. I will really appreciate the help, here is my code:
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<link rel="stylesheet" type="text/css" href="styles/main.css"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
</head>
<body>
<h1>Hello worlds</h1>
<div id="wrapper"></div>
<script type="text/javascript" src="scripts/app.js"></script>
</body>
</html>
scripts.js
var height = 800,
width = 500,
padding = 50;
var vizz = d3.select('#wrapper')
.append('svg')
.attr('height', height + padding * 2)
.attr('width', width + padding * 2)
.append('g')
.attr('id', 'visual')
.attr('transform', 'translate(' + padding + ',' + padding + ')');
var yScale = d3.scale.linear().range([height, 0]);
var xScale = d3.time.scale().range([0, width]);
var parseTime = d3.time.format("%Y%m%D");
var xAxis = d3.svg.axis().scale(xScale).orient("botom").tricks(8);
var yAxis = d3.svg.axis().scale(yScale).orient("left").tricks(20);
d3.csv('data/climate_data.csv', function(data){
yDomain = d3.extent(data, function(element){
return parseInt(element.TMAX)
});
xDomain = d3.extent(data, function(element){
return parseTime.parse(element.DATE)
});
yScale.domain(yDomain);
xScale.domain(xDomain);
dots = vizz.selectAll('circle')
.data(data)
.enter()
.append('circle');
dots.attr('r', function (d){
return d.TMAX / 100; })
.attr('cx', function(d) {return Math.max(0 + padding, Math.random() * width - padding)})
.attr('cy', function(d) {
return yScale(d.TMAX);
});
});
data/climate_data.csv
STATION,STATION_NAME,ELEVATION,LATITUDE,LONGITUDE,DATE,PRCP,TMAX,TMIN,TOBS
GHCND:USC00356749,PORTLAND KGW TV OR US,48.5,45.51667,-122.68333,19730801,0,294,133,217
GHCND:USC00356749,PORTLAND KGW TV OR US,48.5,45.51667,-122.68333,19730802,0,300,128,217
GHCND:USC00356749,PORTLAND KGW TV OR US,48.5,45.51667,-122.68333,19730803,0,289,133,172
To give the scale a suggestion for the number of ticks, you can call the function scale.ticks(). See also https://github.com/mbostock/d3/wiki/SVG-Axes#ticks
Related
I'm brand new to D3.js, so my apologies in advance if I'm overlooking something obvious, but I cannot for the life of me figure out what's not working here...
I've been inching my way through Scott Murray's Interactive Data Visualization for the Web and I've hit a block at Chapter 7. My goal is to load some simple data from a csv document, parse the first column as Date data, and then display. The head of the csv looks like this...
Date, Amount
9/15/17, 26
11/9/17, 31
11/30/17, 23
12/21/17, 26
2/7/18, 23
I run the code below (which comes directly from the book!) and...none of that seems to be happening. When I enter "dataset" into the console, it only seems to include the final row:
{Date: "01/31/17", Amount: "23"}
Amount: "23"
Date: "01/31/17"
I'm perplexed since, again, the code itself comes from the book. I've been working through previous chapters just fine until now. And yes, I'm running a local server. Any idea what I'm doing wrong here? Thanks very much in advance!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>D3: Time scale</title>
<script type="text/javascript" src="../d3.js"></script>
<style type="text/css">
/* No style rules here yet */
</style>
</head>
<body>
<script type="text/javascript">
//Width and height
var w = 500;
var h = 300;
var padding = 40;
var dataset, xScale, yScale;
//For converting strings to Dates
var parseTime = d3.timeParse("%m/%d/%y");
//Function for converting CSV values from strings to Dates and numbers
var rowConverter = function(d) {
return {
Date: parseTime(d.Date),
Amount: parseInt(d.Amount)
};
}
//Load in the data
d3.csv("time_scale_data.csv", rowConverter, function(data) {
//Copy data into global dataset
dataset = data;
//Create scale functions
xScale = d3.scaleTime()
.domain([
d3.min(dataset, function(d) { return d.Date; }),
d3.max(dataset, function(d) { return d.Date; })
])
.range([padding, w - padding]);
yScale = d3.scaleLinear()
.domain([
d3.min(dataset, function(d) { return d.Amount; }),
d3.max(dataset, function(d) { return d.Amount; })
])
.range([h - padding, padding]);
//Create SVG element
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
//Generate date labels first, so they are in back
svg.selectAll("text")
.data(dataset)
.enter()
.append("text")
.text(function(d) {
return formatTime(d.Date);
})
.attr("x", function(d) {
return xScale(d.Date) + 4;
})
.attr("y", function(d) {
return yScale(d.Amount) + 4;
})
.attr("font-family", "sans-serif")
.attr("font-size", "11px")
.attr("fill", "#bbb");
//Generate circles last, so they appear in front
svg.selectAll("circle")
.data(dataset)
.enter()
.append("circle")
.attr("cx", function(d) {
return xScale(d.Date);
})
.attr("cy", function(d) {
return yScale(d.Amount);
})
.attr("r", 2);
});
</script>
</body>
</html>
Instead of :
d3.csv("time_scale_data.csv", rowConverter, function(data) {
--- your code ---
});
Try this :
d3.csv("time_scale_data.csv", rowConverter).then(data){
--- your code ---
});
I would like to minimize greenland and antartica on my D3 geojson map. How do I do this. I've tried scale and translate methods but they simply move the map around on the page not providing the minimized y coordinates.
image of map
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="d3.v3.js"></script>
<script src="topojson.min.js"></script>
<style>
</style>
<script type="text/javascript">
function draw(geo_data) {
"use strict";
var margin = 75,
width = 1920 - margin,
height = 1080 - margin;
var svg = d3.select("body")
.append("svg")
.attr("width", width + margin)
.attr("height", height + margin)
.append('g')
.attr('class', 'map');
var projection = d3.geo.mercator();
var path = d3.geo.path().projection(projection);
var map = svg.selectAll('path')
.data(geo_data.features)
.enter()
.append('path')
.attr('d', path)
.style('fill', 'rgb(9, 157, 217)')
.style('stroke', 'black')
.style('stroke-width', 0.5);
};
</script>
</head>
<body>
<script type="text/javascript">
/*
Use D3 to load the GeoJSON file
*/
//d3.json("world-topo-min.json", draw);
d3.json("world_countries.json", draw);
</script>
</body>
</html>
If you want to remove the areas for Greenland and Antarctica on the fly, you can simply filter your GeoJSON FeatureCollection, i.e. geo_data.features. In this array you will find features for both Greenland ("id": "GRL") as well as Antarctica ("id": "ATA"). Hence, you can make use of the array's .filter() method to get rid of these two features leaving the rest untouched:
var map = svg.selectAll('path')
.data(geo_data.features.filter(d => d.id !== "GRL" && d.id !== "ATA))
I want to use the data value from json file and use it in d3.js.
I would like to display the data in the json file by using a bar graph in 0 to 100% on the x axis, and convert it to a percentage and graph it.
I do not know how to change the data value to a percentage.
So there is no longer any progress in the code.
<%# page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>D3_percent_Bar</title>
<script src="http://d3js.org/d3.v4.js"></script>
<script src="//code.jquery.com/jquery.min.js"></script>
</head>
<body>
<svg id="bar1" width="250" height="250"></svg>
<script>
var margin={top:10,bottom:10,left:15,right:15},
w = 250 - margin.left - margin.right,
h = 250 - margin.top - margin.bottom;
var canvas = d3.select("#bar1")
.append("svg")
.attr("width",w+margin.left+margin.right)
.attr("height",h+margin.top+margin.bottom);
var formatter = d3.format(".0%");
var x = d3.scaleLinear()
.range([0,w]);
var xAxis = d3.axisBottom()
.scale(x)
.ticks(10,formatter);
var data = d3.json("data_F.json", function (error,data){
alert(data);
alert(error);
var max = Math.max.apply(Math, data);
var percents = (data / max)*100;
//var maxX = d3.max(data, function(d){return d.num2;});
//var minX = d3.min(data, function(d){return d.num1;});
//x.domain([0,maxX]);
canvas.append("g")
.attr("class","axis")
.attr("transform", "translate("+margin.left+","+50+")")
.call(xAxis);
var bar = canvas.selectAll("rect")
.data(data)
.attr("class","bar")
.enter()
.append("rect")
.attr("x",margin.left+40)
.attr("width", function(d){return d.num1;})
.attr("y",function(d,i){return i*50;})
.attr("height",40);
//.attr("height",barHeight-1)
//.attr("transform","translate(0,4)");
});
</script>
</body>
</html>
You don't need to "change the data value to a percentage". You can simply change the tick format:
.tickFormat(d => Math.round(d*100/d3.max(data)) + "%");
Have a look at the following demos. This is a regular bar chart:
var data = [20,45,245,134,267,111,54,333,23];
var w = 500, h = 200, padding = 20;
var svg = d3.select("body").append("svg")
.attr("width", w)
.attr("height", h);
var xScale = d3.scaleLinear()
.range([padding, (w - padding)])
.domain([0, d3.max(data)]);
var rects = svg.selectAll(".rects")
.data(data)
.enter()
.append("rect")
.attr("x", xScale(0))
.attr("y", (d,i) => i*20)
.attr("height", 14)
.attr("width", d => xScale(d) - padding)
.attr("fill", "teal");
var xAxis = d3.axisBottom(xScale);
var gX = svg.append("g")
.attr("transform", "translate(0," + (h - padding) + ")")
.call(xAxis);
<script src="https://d3js.org/d3.v4.min.js"></script>
Nothing new here, the ticks show the absolute values, the maximum being 333.
But here is the same code, without changing any data, only changing the tickFormat:
var data = [20,45,245,134,267,111,54,333,23];
var w = 500, h = 200, padding = 20;
var svg = d3.select("body").append("svg")
.attr("width", w)
.attr("height", h);
var xScale = d3.scaleLinear()
.range([padding, (w - padding)])
.domain([0, d3.max(data)]);
var rects = svg.selectAll(".rects")
.data(data)
.enter()
.append("rect")
.attr("x", xScale(0))
.attr("y", (d,i) => i*20)
.attr("height", 14)
.attr("width", d => xScale(d) - padding)
.attr("fill", "teal");
var xAxis = d3.axisBottom(xScale)
.tickFormat(d => Math.round(d*100/d3.max(data)) + "%");
var gX = svg.append("g")
.attr("transform", "translate(0," + (h - padding) + ")")
.call(xAxis);
<script src="https://d3js.org/d3.v4.min.js"></script>
Not sure if this is a plnkr issue or an issue with my code.. although the console is not showing any errors.
I am writting a little svg script and it does not render.
var w = 300;
var h = 100;
var padding = 2;
var dataset = [5, 10, 14, 20, 25];
var svg = d3.select("body").append("svg").attr("width", w).attr("height", h);
svg.selectAll('rect')
.data(dataset)
.enter()
.append('rect')
.attr('x', function(d, i) {
return i * (w/dataset.length);
})
.attr('y', function(d) {
return h - (d);
})
.attr("width", w/ dataset.length - padding)
.attr("height", function(d) {
return d;
});
Plnkr here:
http://plnkr.co/edit/X7KomlmOVS6C0zhNL19b
Run it inside a document.ready or wait till the window is loaded. http://plnkr.co/edit/TmFWndyCgLk7GYEng7XP
<!DOCTYPE html>
<html>
<head>
<script data-require="d3#*" data-semver="3.5.3" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="http://code.jquery.com/jquery-2.1.4.min.js"></script>
<script src="script.js"></script>
</head>
<body>
<h1>Hello Plunker!</h1>
</body>
</html>
and in the JS
$(document).ready(function(){
var w = 300;
var h = 100;
var padding = 2;
var dataset = [5, 10, 14, 20, 25];
var svg = d3.select("body").append("svg").attr("width", w).attr("height", h);
console.log('running the plnkr');
svg.selectAll('rect')
.data(dataset)
.enter()
.append('rect')
.attr('x', function(d, i) {
return i * (w/dataset.length);
})
.attr('y', function(d) {
return h - (d * 4);
})
.attr("width", w/ dataset.length - padding)
.attr("height", function(d) {
return d * 4;
});
});
I am a D3 newer and wrote a program to draw a pie ring.
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>pie ring</title>
</head>
<body>
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script type="text/javascript">
var dataset=[{name:A,value:5},{name:C,value:10},{name:F,value:13}];
var pie=d3.layout.pie(dataset);
var h=600;
var w=600;
var outerRadius=w/2;
var innerRadius=w/3;
var arc=d3.svg.arc()
.outerRadius(outerRadius)
.innerRadius(innerRadius);
var svg=d3.select("body")
.append("svg")
.attr("width",w)
.attr("height",h);
var color=d3.scale.category10();
var arcs=svg.selectAll("g.arc")
.data(pie(dataset))
.enter()
.append("g")
.attr("class","arc")
.attr("transform","translate("+outerRadius+","+outerRadius+")");//translate(a,b)
arcs.append("path")
.attr("fill",function(d,i){
return color(i);
})
.attr("d",arc);
arcs.append("text")
.attr("transform",function(d){
return "translate("+arc.centroid(d)+")";
})
.attr("text-anchor","middle")
.text(function(d){
return d.name + ":" + d.value;
});
</script>
</body>
</html>
But failed, I don't know that how to define data structure and don't know how to pie dataset. pie(dataset) or pie(function(d){return d.value} ); could you help me to correct it
the javascript console told me that A is not defined. This A is the value of the name of the dataset. I don't know if the only request is digital value or digital array for pie ring.
Few problems here. It's telling you A isn't defined because it's not. You're using plain text instead of a string, so it thinks A is a variable, not a label. Even if you resolved that, there would be some other issues with the structure.
Copied almost straight from the d3 pie chart example here, I put in your data and it works a charm.
Here's the code, but I also strongly recommend going over the tutorial so you can see how it's supposed to work.
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>pie ring</title>
</head>
<body>
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script type="text/javascript">
var w = 600;
var h = 600;
var outerRadius=w/2;
var innerRadius=w/3;
color = d3.scale.category20c();
data = [{"label":"A", "value":5},
{"label":"C", "value":10},
{"label":"F", "value":13}];
var vis = d3.select("body")
.append("svg:svg")
.data([data])
.attr("width", w)
.attr("height", h)
.append("svg:g")
.attr("transform", "translate(" + outerRadius + "," + outerRadius + ")")
var arc = d3.svg.arc()
.outerRadius(outerRadius)
.innerRadius(innerRadius);
var pie = d3.layout.pie()
.value(function(d) { return d.value; });
var arcs = vis.selectAll("g.slice")
.data(pie)
.enter()
.append("svg:g")
.attr("class", "slice");
arcs.append("svg:path")
.attr("fill", function(d, i) { return color(i); } )
.attr("d", arc);
arcs.append("svg:text")
.attr("transform", function(d) {
d.innerRadius = innerRadius;
d.outerRadius = outerRadius;
return "translate(" + arc.centroid(d) + ")";
})
.attr("text-anchor", "middle")
.text(function(d, i) { return data[i].label; });
</script>
</body>
</html>