Home Incorrect number of circles appended to svg
Reply: 2

Incorrect number of circles appended to svg

Andrew Nguyen
1#
Andrew Nguyen Published in 2018-01-10 23:35:32Z

Objective

  • I'm trying to iterate over items in an array using a for loop and use jQuery's .append() method to add a series of circles, which represent this particular player's home runs over their career, atop four svgs of a baseball stadium, in order to create a spray chart of hits.

Codepen:

https://codepen.io/onlyandrewn/project/editor/DkaEvW

Problem

The correct number of circles are not being appended to the four svgs, which I expect to be 48 red dots (career home runs) and 22 red dots (this past season).

What I've tried

  • On lines 18-21: Within the for loop, I've tried using jQuery to target each of the individual svgs based on their classes (.layer_1, .layer_2 etc.), but it appears that the total number of dots are being divided over the four svgs, instead of having all 48 dots (career home runs) or all 22 (season home runs) show up on one chart
  • On lines 24-31: I tried to show just data[i].game_year using an if-statement in order to get the home runs from this past 2017 season, but the dots that were being displayed were not from this past year.
  • Also tried, switching the classes to ids and using each and forEach to try to target the parent svgs individually.

scripts.js

$(function(){

    // Make a GET request with an AJAX call to fetch data from the json file, which contains stats on Marcell Ozuna's career homeruns from MLB Statcast via BaseballSavant.com

    // Documentation: http://api.jquery.com/jquery.ajax/
    // Example GET request: https://stackoverflow.com/questions/9269265/ajax-jquery-simple-get-request

    $.ajax({
        url: 'ozuna.json',
        method: 'GET',
        dataType: "json",
    }).then(function(data){

        for (i = 0; i < data.length; i++) {

            // On each of the SVG's of the baseball stadiums, use a for loop to iterate over each of the 48 items in the array. Then, append a circle with a class of `homerun` to the div.

            $(".layer_1").append("<svg><circle class='homerun'></svg>");
            $(".layer_2").append("<svg><circle class='homerun'></svg>");
            $(".layer_3").append("<svg><circle class='homerun'></svg>");
            $(".layer_4").append("<svg><circle class='homerun'></svg>");

            // Marcell Ozuna hit a total of 22 homeruns last season
            // if (data[i].game_year === 2017) {
            //  // console.log(data[i].game_year);
            //  // $(".layer_2").append("<svg><circle class='homerun'></svg>");
            //  // $(".layer_3").append("<svg><circle class='homerun'></svg>");
            // } else {
            //  // $(".layer_1").append("<svg><circle class='homerun'></svg>");
            //  // $(".layer_4").append("<svg><circle class='homerun'></svg>");
            // }

            // This refers to each of the circles. Each of the circles contains the following attributes. The user sees a small red dot with a black border.
            $(".homerun").each(function(index){
                $(this).attr({
                    cx: data[index].hc_x,
                    cy: data[index].hc_y, 
                    r: 4.71,
                    fill: "#a82254",
                    stroke: "#000",
                    "stroke-width": 1, 
                })

                $(this).hover(function(){
                    changeText(data, index);
                    showSidebar();
                })
            });
        }
    });

    // When you hover over one of the circles, change the text in the sidebar. It takes two parameters, the data from the AJAX call and the index of the object in the array.
    function changeText(data, index) {
        $(".sidebar__date").html(data[index].game_date);
        $(".team--home").html(data[index].home_team);
        $(".team--away").html(data[index].away_team);
        $(".sidebar__tb").html(data[index].inning_topbot);
        $(".sidebar__inning").html(data[index].inning);
        $(".sidebar__description").html(data[index].des_long);
        $(".sidebar__pitch").html(data[index].pitch_type);
        $(".value--balls").html(data[index].balls);
        $(".value--strikes").html(data[index].strikes);
        $(".value--outs").html(data[index].outs_when_up);
    }

    // Show the game details. By default, the sidebar is empty and a user will see only the attribution until they hover over the first red dot.
    function showSidebar() {
        $(".sidebar").show();
    }
});

Example of json data

[
  {
    "pitch_type": "four-seam fastball",
    "release_speed": 92.4,
    "game_date": "March 31, 2014",
    "game_year": 2014,
    "des_long": "In the bottom of the 3rd, Marcell Ozuna homers off a 92.4 mph four-seam fastball to left field. A. J. Ellis scores. Christian Yelich scores. Giancarlo Stanton scores.",
    "des_short": "Marcell Ozuna homers on a line drive to left field.",
    "home_team": "MIA",
    "away_team": "COL",
    "balls": 3,
    "strikes": 1,
    "outs_when_up": 0,
    "inning_topbot": "bottom",
    "inning": "3rd",
    "hc_x": 19.08,
    "hc_y": 85.34,
    "hit_distance_sc": "null"
  },
bigless
2#
bigless Reply to 2018-01-11 00:22:01Z

You are using classname layer_1 in javascript and capitalized Layer_1 in html. Since jQuery selectors are case sensitive, this could be the main issue.

Paul LeBeau
3#
Paul LeBeau Reply to 2018-01-15 04:21:02Z

Your approach is a bit wrong.

Firstly you don't need to create an SVG for every circle. Just add circles to the SVGs. For each ballpark image, loop through the data, add a circle if it's the right year.

    $.ajax({
        url: 'ozuna.json',
        method: 'GET',
        dataType: "json",
    }).then(function(data){

    // Marlins Park
    addHomeRuns(data, '.layer_1', 'all');
    addHomeRuns(data, '.layer_2', 2017);
    // Busch
    addHomeRuns(data, '.layer_3', 'all');
    addHomeRuns(data, '.layer_4', 2017);

    });


  // On each of the SVG's of the baseball stadiums, use a for loop to iterate over each of the 48 items in the array. Then, append a circle with a class of `homerun` to the div.
  function addHomeRuns(data, layerClass, year)
  {
    var svg = $(layerClass).get(0);

    $.each(data, function(i, obj) {

      var showHomer = year === 'all' || obj.game_year === year;
      if (showHomer)
      {
        var circle = document.createElementNS(svg.namespaceURI, 'circle');
        circle.setAttribute('cx', obj.hc_x);
        circle.setAttribute('cy', obj.hc_y);
        circle.setAttribute('r', 4.71);
        circle.setAttribute('fill', "#a82254");
        circle.setAttribute('stroke', "#000");
        circle.setAttribute('stroke-width', 1);
        svg.appendChild(circle);
      }

      $(circle).hover(function() {
        changeText(obj);
        showSidebar();
      });
    });
  }

Updated Codepen here

You need to login account before you can post.

About| Privacy statement| Terms of Service| Advertising| Contact us| Help| Sitemap|
Processed in 0.279734 second(s) , Gzip On .

© 2016 Powered by mzan.com design MATCHINFO