Deadpool
Deadpool

Reputation: 8240

D3 - Multiple line chart, Second line circles not showing

I am making a comparison line chart plotting frequency & frequency2 against letters. Additionaly, I want circles to be made at nodes of both lines. However, I am getting circles in first set of line nodes. I am not getting circles for second line.

If I am commenting first set of code for circles, then I am able to see red circles in second line.

Please, help out so that I can see red circles in second line also, along with those in first line.

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", "frequency2":"18.03"},
                  {"letter": "B","frequency": "7.80", "frequency2":"15.03"},
                  {"letter": "C","frequency": "15.35","frequency2":"27.03"},
                  {"letter": "D","frequency": "22.70","frequency2":"12.03"},
                  {"letter": "E","frequency": "34.25", "frequency2":"21.03"},
                  {"letter": "F","frequency": "10.21","frequency2":"28.03"},
                  {"letter": "G","frequency": "7.68","frequency2":"09.03"},
            ];

                //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").attr("transform", "translate(" + margin.left + "," + margin.top + ")");

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

                x.domain(data.map(function(d) { return d.letter; }));
                y.domain([0, d3.max(data, function(d) { return +d.frequency; })]);

                //Final Plotting 

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

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


            /**************** First Path ******************/ 

                //the line function for path 
                var lineFunction = d3.line()
                    .x(function(d) {return x(d.letter); })
                    .y(function(d) { return y(d.frequency); })
                    .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")
                    .append("circle");


                g.selectAll('circle')
                  .data(data)
                  .enter().append('circle')
                  .attr('cx', function(d) {
                    return x(d.letter);
                  })
                  .attr('cy', function(d) {
                    return y(d.frequency);
                  })
                  .attr('r', 6)
                  .style("fill", "blue");

            /**************** Second Path *********************/ 

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

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

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


                g.selectAll('circle')
                  .data(data)
                  .enter().append('circle')
                  .attr('cx', function(d) {
                    return x(d.letter);
                  })
                  .attr('cy', function(d) {
                    return y(d.frequency2);
                  })
                  .attr('r', 6)
                  .style("fill", "red");

        });

    </script> 

</body> 

</html> 

RESULT:

enter image description here

I think I am making some silly mistake somewhere. Pl help.

Upvotes: 1

Views: 1341

Answers (1)

Gerardo Furtado
Gerardo Furtado

Reputation: 102194

You have two issues here:

First, when you do this for both groups of circles:

g.selectAll('circle')

Your second group is selecting existing elements, and the "enter" selection of this second group will be empty.

Try to use different selectors for each group, like this:

//for the first group
g.selectAll('.circles1')

//for the second group
g.selectAll('.circles2')

The second issue is that, for the second group of circles, you should use frequency2:

.attr('cy', function(d) {
    return y(d.frequency2);
})

This is a working demo:

var data = [
                  {"letter": "A","frequency": "5.01", "frequency2":"18.03"},
                  {"letter": "B","frequency": "7.80", "frequency2":"15.03"},
                  {"letter": "C","frequency": "15.35","frequency2":"27.03"},
                  {"letter": "D","frequency": "22.70","frequency2":"12.03"},
                  {"letter": "E","frequency": "34.25", "frequency2":"21.03"},
                  {"letter": "F","frequency": "10.21","frequency2":"28.03"},
                  {"letter": "G","frequency": "7.68","frequency2":"09.03"},
            ];

                //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", 500).attr("height", 300);

                //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").attr("transform", "translate(" + margin.left + "," + margin.top + ")");

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

                x.domain(data.map(function(d) { return d.letter; }));
                y.domain([0, d3.max(data, function(d) { return +d.frequency; })]);

                //Final Plotting 

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

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


            /**************** First Path ******************/ 

                //the line function for path 
                var lineFunction = d3.line()
                    .x(function(d) {return x(d.letter); })
                    .y(function(d) { return y(d.frequency); })
                    .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")
                    .append("circle");


                g.selectAll('.circles1')
                  .data(data)
                  .enter().append('circle')
                  .attr('cx', function(d) {
                    return x(d.letter);
                  })
                  .attr('cy', function(d) {
                    return y(d.frequency);
                  })
                  .attr('r', 6)
                  .style("fill", "blue");

            /**************** Second Path *********************/ 

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

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

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


                g.selectAll('.circles2')
                  .data(data)
                  .enter().append('circle')
                  .attr('cx', function(d) {
                    return x(d.letter);
                  })
                  .attr('cy', function(d) {
                    return y(d.frequency2);
                  })
                  .attr('r', 6)
                  .style("fill", "red");
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg></svg>

Upvotes: 3

Related Questions