Alejandro
Alejandro

Reputation: 2326

D3.js -- Ordinal scale (version 3 to version 4)

I am taking an Udemy's course on D3.js.

Unfortunately because of the new version D3.js came out, there aren't any up-to-date tutorials on their new syntax so I am glancing at their API's wiki.

That being said, I've been stuck on how to translate this code (version 3). I am learning ordinal scale

var data = [
    {key: "Glazed",     value: 132},
    {key: "Jelly",      value: 71},
    {key: "Holes",      value: 337},
    {key: "Sprinkles",  value: 93},
    {key: "Crumb",      value: 78},
    {key: "Chocolate",  value: 43},
    {key: "Coconut",    value: 20},
    {key: "Cream",      value: 16},
    {key: "Cruller",    value: 30},
    {key: "Éclair",     value: 8},
    {key: "Fritter",    value: 17},
    {key: "Bearclaw",   value: 21}
];
var w = 800;
var h = 450;
var margin = {
    top: 20,
    bottom: 20,
    left: 20,
    right: 20
};
var width = w - margin.left - margin.right;
var height = h - margin.top - margin.bottom;
var x = d3.scale.linear()
        .domain([0, d3.max(data, function(d){
            return d.value;
        })])
        .range([0, width]);
var y = d3.scale.ordinal()
        .domain(data.map(function(entry){
            return entry.key;
        }))
        .rangeBands([0, height]);
var svg = d3.select("body").append("svg")
            .attr("id", "chart")
            .attr("width", w)
            .attr("height", h);
var chart = svg.append("g")
            .classed("display", true)
            .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
function plot(params){
    this.selectAll(".bar")
        .data(params.data)
        .enter()
            .append("rect")
            .classed("bar", true)
            .attr("x", 0)
            .attr("y", function(d,i){
                return y(d.key);
            })
            .attr("height", function(d,i){
                return y.rangeBand()-1;
            })
            .attr("width", function(d){
                return x(d.value);
            });
    this.selectAll(".bar-label")
        .data(params.data)
        .enter()
            .append("text")
            .classed("bar-label", true)
            .attr("x", function(d){
                return x(d.value);
            })
            .attr("dx", -4)
            .attr("y", function(d,i){
                return y(d.key);
            })
            .attr("dy", function(d,i){
                return y.rangeBand()/1.5+2;
            })
            .text(function(d){
                return d.value;
            })
}
plot.call(chart, {data: data});

to version 4.

Looking at their API Wiki, it seems that get rid rangeBand function CHANGES.MD

I've tried my best translating but I can't figure it out what it's wrong:

var data = [
    {key: "Glazed",     value: 132},
    {key: "Jelly",      value: 71},
    {key: "Holes",      value: 337},
    {key: "Sprinkles",  value: 93},
    {key: "Crumb",      value: 78},
    {key: "Chocolate",  value: 43},
    {key: "Coconut",    value: 20},
    {key: "Cream",      value: 16},
    {key: "Cruller",    value: 30},
    {key: "Éclair",     value: 8},
    {key: "Fritter",    value: 17},
    {key: "Bearclaw",   value: 21}
];
var w = 800;
var h = 450;
var margin = {
    top: 20,
    bottom: 20,
    left: 20,
    right: 20
};
var width = w - margin.left - margin.right;
var height = h - margin.top - margin.bottom;
var x = d3.scaleLinear()
        .domain([0, d3.max(data, function(d){
            return d.value;
        })])
        .range([0, width]);
var y = d3.scaleOrdinal()
        .domain(data.map(function(entry){
            return entry.key;
        }))
        .range([0, height]);

var svg = d3.select("body").append("svg")
            .attr("id", "chart")
            .attr("width", w)
            .attr("height", h);
var chart = svg.append("g")
            .classed("display", true)
            .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
function plot(params){
    this.selectAll(".bar")
        .data(params.data)
        .enter()
            .append("rect")
            .classed("bar", true)
            .attr("x", 0)
            .attr("y", function(d,i){
                return y(d.key);
            })
            .attr("height", function(d,i){
                return y.range(1)-1;
            })
            .attr("width", function(d){
                return x(d.value);
            });
    this.selectAll(".bar-label")
        .data(params.data)
        .enter()
            .append("text")
            .classed("bar-label", true)
            .attr("x", function(d){
                return x(d.value);
            })
            .attr("dx", -4)
            .attr("y", function(d,i){
                return y(d.key);
            })
            .attr("dy", function(d,i){
                return y.range(1)/1.5+2;
            })
            .text(function(d){
                return d.value;
            })
}
plot.call(chart, {data: data});

Working Version 3

Not Working Version 4

Upvotes: 15

Views: 24742

Answers (2)

msapkal
msapkal

Reputation: 8346

Below is the working code.

scale.oridnal is not supported in v4, hence scaleBand is used.

var data = [
    {key: "Glazed",     value: 132},
    {key: "Jelly",      value: 71},
    {key: "Holes",      value: 337},
    {key: "Sprinkles",  value: 93},
    {key: "Crumb",      value: 78},
    {key: "Chocolate",  value: 43},
    {key: "Coconut",    value: 20},
    {key: "Cream",      value: 16},
    {key: "Cruller",    value: 30},
    {key: "Éclair",     value: 8},
    {key: "Fritter",    value: 17},
    {key: "Bearclaw",   value: 21}
];
var w = 800;
var h = 450;
var margin = {
    top: 20,
    bottom: 20,
    left: 20,
    right: 20
};
var width = w - margin.left - margin.right;
var height = h - margin.top - margin.bottom;
var x = d3.scaleLinear()
        .domain([0, d3.max(data, function(d){
            return d.value;
        })])
        .range([0, width]);
/*var y = d3.scale.ordinal()
        .domain(data.map(function(entry){
            return entry.key;
        }))
        .rangeBands([0, height]);*/
var y = d3.scaleBand()
        .domain(data.map(function(entry){
            return entry.key;
        }))
    .rangeRound([0, height])
    .padding(0.1);      

var svg = d3.select("body").append("svg")
            .attr("id", "chart")
            .attr("width", w)
            .attr("height", h);
var chart = svg.append("g")
            .classed("display", true)
            .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
function plot(params){
    this.selectAll(".bar")
        .data(params.data)
        .enter()
            .append("rect")
            .classed("bar", true)
            .attr("x", 0)
            .attr("y", function(d,i){
                return y(d.key);
            })
            .attr("height", function(d,i){
                return y.bandwidth()-1;
            })
            .attr("width", function(d){
                return x(d.value);
            });
    this.selectAll(".bar-label")
        .data(params.data)
        .enter()
            .append("text")
            .classed("bar-label", true)
            .attr("x", function(d){
                return x(d.value);
            })
            .attr("dx", -4)
            .attr("y", function(d,i){
                return y(d.key);
            })
            .attr("dy", function(d,i){
                return y.bandwidth()/1.5+2;
            })
            .text(function(d){
                return d.value;
            })
}
plot.call(chart, {data: data});

Upvotes: 23

Aravind Cheekkallur
Aravind Cheekkallur

Reputation: 3195

Please have a look on d3.scaleBand(). d3.v4 ordinal scale implementation is available in d3.scaleBand().

var data = [
    {key: "Glazed",     value: 132},
    {key: "Jelly",      value: 71},
    {key: "Holes",      value: 337},
    {key: "Sprinkles",  value: 93},
    {key: "Crumb",      value: 78},
    {key: "Chocolate",  value: 43},
    {key: "Coconut",    value: 20},
    {key: "Cream",      value: 16},
    {key: "Cruller",    value: 30},
    {key: "Éclair",     value: 8},
    {key: "Fritter",    value: 17},
    {key: "Bearclaw",   value: 21}
];
var w = 500;
var h = 300;
var margin = {
    top: 20,
    bottom: 20,
    left: 20,
    right: 20
};
var width = w - margin.left - margin.right;
var height = h - margin.top - margin.bottom;
var x = d3.scaleLinear()
        .domain([0, d3.max(data, function(d){
            return d.value;
        })])
        .range([0, width]);
var y = d3.scaleBand()
        .domain(data.map(function(entry){
            return entry.key;
        }))
        .range([height, 0])
		.padding(0.1);

var svg = d3.select("body").append("svg")
            .attr("id", "chart")
            .attr("width", w)
            .attr("height", h);
var chart = svg.append("g")
            .classed("display", true)
            .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
function plot(params){
    this.selectAll(".bar")
        .data(params.data)
        .enter()
            .append("rect")
            .classed("bar", true)
            // .attr("x", function(d) { 
				// return x(d.value); })
            .attr("y", function(d,i){
                return y(d.key);
            })
            .attr("height", y.bandwidth())
            .attr("width", function(d){
                return x(d.value);
            });

}
plot.call(chart, {data: data});
.bar { fill: steelblue; }
<script src="https://d3js.org/d3.v4.min.js"></script>

Upvotes: 4

Related Questions