简体   繁体   中英

d3.js: Ordinal scale

I am drawing line chart but unable to figure out the scale for x-axies I am using ordinal scale because i am showing categories on x-axis here is the code for scaling. please let me know what i am doing wrong here.

var xScale = d3.scale.ordinal()
       .domain(xExtents)
       .range([padding, w - padding * 2]);

here is the sample code sorry for putting all javascript and HTML at one place.

 <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <script type="text/javascript" src="http://mbostock.github.com/d3/d3.js"></script> <style type="text/css"> .axis path, .axis line { fill: none; stroke: black; shape-rendering: crispEdges; } .axis text { font-family: sans-serif; font-size: 11px; } .y1 { fill: white; stroke: orange; stroke-width: 1.5px; } .y2 { fill: white; stroke: red; stroke-width: 1.5px; } .y3 { fill: white; stroke: steelblue; stroke-width: 1.5px; } .line { fill: none; stroke-width: 1.5px; } div.tooltip { position: absolute; text-align: center; width: 50px; height: 10px; padding: 5px; font: 10px sans-serif; background: whiteSmoke; border: solid 1px #aaa; pointer-events: none; box-shadow: 2px 2px 1px #888; } .legend { padding: 5px; font: 10px sans-serif; background: yellow; box-shadow: 2px 2px 1px #888; } .title { font: 13px sans-serif; } </style> </head> <body> <script type="text/javascript"> //Width and height var w = 500; var h = 300; var padding = 50; var dataset = [ [ {x: "USA", y: 0}, {x: "UK", y: 0}, {x: "BRAZIL", y: 2}, {x: "KORIA", y: 0}, {x: "JAPAN", y: 0}, {x: "CHINA", y: 0} ], [ {x: "USA", y: 3}, {x: "UK", y: 4}, {x: "BRAZIL", y: 1}, {x: "KORIA", y: 3}, {x: "JAPAN", y: 1}, {x: "CHINA", y: 2} ], [ {x: "USA", y: 2}, {x: "UK", y: 0}, {x: "BRAZIL", y: 2}, {x: "KORIA", y: 3}, {x: "JAPAN", y: 4}, {x: "CHINA", y: 1} ] ]; var color_hash = { 0 : ["apple", "green"], 1 : ["mango", "orange"], 2 : ["cherry", "red"] } // Define axis ranges & scales var yExtents = d3.extent(d3.merge(dataset), function (d) { return dy; }); var xExtents = d3.extent(d3.merge(dataset), function (d) { return dx; }); var xScale = d3.scale.ordinal() .domain(xExtents) .range([padding, w - padding * 2]); var yScale = d3.scale.linear() .domain([0, yExtents[1]]) .range([h - padding, padding]); // Create SVG element var svg = d3.select("body") .append("svg") .attr("width", w) .attr("height", h); // Define lines var line = d3.svg.line() .x(function(d) { return x(dx); }) .y(function(d) { return y(d.y1, d.y2, d.y3); }); var pathContainers = svg.selectAll('g.line') .data(dataset); pathContainers.enter().append('g') .attr('class', 'line') .attr("style", function(d) { return "stroke: " + color_hash[dataset.indexOf(d)][1]; }); pathContainers.selectAll('path') .data(function (d) { return [d]; }) // continues the data from the pathContainer .enter().append('path') .attr('d', d3.svg.line() .x(function (d) { return xScale(dx); }) .y(function (d) { return yScale(dy); }) ); // add circles pathContainers.selectAll('circle') .data(function (d) { return d; }) .enter().append('circle') .attr('cx', function (d) { return xScale(dx); }) .attr('cy', function (d) { return yScale(dy); }) .attr('r', 3); //Define X axis var xAxis = d3.svg.axis() .scale(xScale) .orient("bottom") .ticks(5); //Define Y axis var yAxis = d3.svg.axis() .scale(yScale) .orient("left") .ticks(5); //Add X axis svg.append("g") .attr("class", "axis") .attr("transform", "translate(0," + (h - padding) + ")") .call(xAxis); //Add Y axis svg.append("g") .attr("class", "axis") .attr("transform", "translate(" + padding + ",0)") .call(yAxis); // Add title svg.append("svg:text") .attr("class", "title") .attr("x", 20) .attr("y", 20) .text("Fruit Sold Per Hour"); // add legend var legend = svg.append("g") .attr("class", "legend") .attr("x", w - 65) .attr("y", 25) .attr("height", 100) .attr("width", 100); legend.selectAll('g').data(dataset) .enter() .append('g') .each(function(d, i) { var g = d3.select(this); g.append("rect") .attr("x", w - 65) .attr("y", i*25) .attr("width", 10) .attr("height", 10) .style("fill", color_hash[String(i)][1]); g.append("text") .attr("x", w - 50) .attr("y", i * 25 + 8) .attr("height",30) .attr("width",100) .style("fill", color_hash[String(i)][1]) .text(color_hash[String(i)][0]); }); </script> </body> </html> 

If you want to show different categories on x axis (in your case, there are five countries with corresponding data), the x scale setting should be using rangeBands or rangeRoundBands for ordinal data. (see ordinal.rangeBands and ordinal.rangeRoundBands in official api documents).

var xScale = d3.scale.ordinal()
   .domain(xExtents)
   .rangeRoundBands([padding, w - padding * 2], 0.1);

range is often used with linear type of data. Hope this helps.

First Problem:

Use this https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js

Instead of this http://mbostock.github.com/d3/d3.js

Second Problem:

d3.extent(d3.merge(dataset), function (d) { return d.x; }

will return ["BRAZIL", "USA"]

You need all the unique countries.

var countries = d3.merge(dataset).map(function(d){return d.x});
countries = d3.set(countries).values();//unique countries


var xScale = d3.scale.ordinal()
       .domain(countries)
       .rangeBands([padding, w - padding * 2], 1);

this will return ["USA", "UK", "BRAZIL", "KORIA", "JAPAN", "CHINA"]

Last Problem:

var xScale = d3.scale.ordinal()
       .domain(countries)
       .rangeBands([padding, w - padding * 2], 1);//with ordinals we give range bands

Working code here

Hope this helps!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM