Deadpool
Deadpool

Reputation: 8240

D3 line graph getting error and not getting plotted

I am making a line graph for a set of data regarding letter vs frequency. I have made proper code for x and y axis, but while plotting line I am getting error and not able to plot the line-graph. Can someone help fix the issue?

SNIPPET:

<html>

<head>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.12/angular.min.js"></script> 
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script> 
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.3.0/d3.min.js"></script>

</head> 

<body ng-app="myApp" ng-controller="myCtrl"> 

    <svg></svg>

    <script>

        //module declaration 
        var app = angular.module('myApp',[]);

        //Controller declaration
        app.controller('myCtrl',function($scope){

            $scope.svgWidth = 800;//svg Width
            $scope.svgHeight = 500;//svg Height 

            //Data in proper format 
            var data = [
                  {"letter": "A","frequency": "5.01"},
                  {"letter": "B","frequency": "7.80"},
                  {"letter": "C","frequency": "15.35"},
                  {"letter": "D","frequency": "22.70"},
                  {"letter": "E","frequency": "34.25"},
                  {"letter": "F","frequency": "10.21"},
                  {"letter": "G","frequency": "7.68"},
            ];

                //removing prior svg elements ie clean up svg 
                d3.select('svg').selectAll("*").remove();

                //resetting svg height and width in current svg 
                d3.select("svg").attr("width", $scope.svgWidth).attr("height", $scope.svgHeight);

                //Setting up of our svg with proper calculations 
                var svg = d3.select("svg");
                var margin = {top: 20, right: 20, bottom: 30, left: 40};
                var width = svg.attr("width") - margin.left - margin.right;
                var height = svg.attr("height") - margin.top - margin.bottom;

                //Plotting our base area in svg in which chart will be shown 
                var g = svg.append("g");



                //shifting the canvas area from left and top 
                g.attr("transform", "translate(" + margin.left + "," + margin.top + ")");

                //X and Y scaling 
                var x = d3.scaleLinear().rangeRound([0, width]);
                var y = d3.scaleBand().rangeRound([height, 0]).padding(0.4);

                //Feeding data points on x and y axis 
                x.domain([0, d3.max(data, function(d) { return +d.frequency; })]);
                y.domain(data.map(function(d) { return d.letter; }));

                //Final Plotting 

                //for x axis 
                g.append("g")
                    .attr("transform", "translate(0," + height + ")")
                    .call(d3.axisBottom(x));

                //for y axis 
                g.append("g")
                    .call(d3.axisLeft(y))
                    .append("text")
                    .attr("transform", "rotate(-90)")
                    .attr("y", 6)
                    .attr("dy", "0.71em")
                    .attr("text-anchor", "end");


                //the line function for path 
                var lineFunction = d3.line()
                    .x(function(d) {return xScale(d.x); })
                    .y(function(d) { return yScale(d.y); })
                    .curve(d3.curveLinear);

                //defining the lines
                var path = g.append("path");

                //plotting lines
                path
                    .attr("d", lineFunction(data))
                    .attr("stroke", "blue")
                    .attr("stroke-width", 2)
                    .attr("fill", "none");

        });

    </script> 

</body> 

</html> 

ERROR:

enter image description here

NEW ERROR:

enter image description here

Upvotes: 1

Views: 455

Answers (2)

Harshal
Harshal

Reputation: 948

If you want to use xScale and yScale , you need to define these functions. Syntax is given below (ignore values):

Below code is for d3 version 3

me.xscale = d3.scale.linear()   // for horizontal distances if using for 2D 
        .domain([0, 500])
        .range([0, 700]); 

me.yscale = d3.scale.linear()   // for vertical distances if using for 2D
        .domain([0, 600])
        .range([0, 200]);

These functions are used to define mapping of a values in one range to values in other range.

e.g - Suppose you want draw a graph on your browser screen. And you want assume that width 500px on your browser screen should be counted as 500 on your graph. You need to define xScale as above . In this case , this function will map every value in domain (0-500) to unique value in range (0-700) and vice versa.

Upvotes: 1

Gerardo Furtado
Gerardo Furtado

Reputation: 102219

Look at the console: you don't have a xScale or a yScale.

So, the line generator should be:

var lineFunction = d3.line()
    .x(function(d) {return x(d.frequency); })
    .y(function(d) { return y(d.letter); })
    .curve(d3.curveLinear);

Besides that, frequency is a string, not a number. So, it's a good idea turning it into a number. Write this right after your data variable:

data.forEach(function(d){
    d.frequency = +d.frequency;
});

Note: it's a good practice defining your variable names properly, with descriptive names, like xScale, yAxis, chartLegend or formatNumber... Look at your line generator: you have two different x in a single line. If you don't take care, you'll mix them.

Upvotes: 3

Related Questions