关于javascript:附加到svg的圈数不正确

Incorrect number of circles appended to svg

目标

  • 我试图用EDCOX1×0的一个数组来迭代数组中的项目,并使用jQuery的EDCOX1×1方法来添加一系列的圆,它们代表这个特定的玩家在其职业生涯中的运行,在一个棒球场的四个SVG上,以便创建一个命中的喷洒图表。

Codepen:

https://codepen.io/onlyandrown/project/editor/dkaevw

问题

四个SVG没有附加正确的圈数,我希望这是48个红点(职业生涯本垒打)和22个红点(上赛季)。

我试过什么

  • 在第18-21行:在for循环中,我尝试使用jquery根据每个SVG的类(.layer_1.layer_2等)来确定每个SVG的目标,但似乎在四个SVG上划分了点的总数,而不是在一张图表上显示全部48个点(职业生涯本垒打)或全部22个点(赛季本垒打)。
  • 在第24-31行:我试图用一个if语句来显示data[i].game_year,以便从2017年的这个赛季获得本垒打,但是显示的圆点不是从去年开始的。
  • 还尝试将类转换为ID,并使用eachforEach分别尝试针对父SVG。

脚本语言

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
$(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();
    }
});

JSON数据示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[
  {
   "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"
  },


你的方法有点错误。

首先,您不需要为每个圆创建SVG。只需在SVG中添加圆即可。对于每个棒球场图像,循环浏览数据,如果是正确的年份,则添加一个圆圈。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
    $.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();
      });
    });
  }

此处更新了代码笔


在javascript中使用类名layer_1,在HTML中使用大写的layer_1。因为jquery选择器区分大小写,所以这可能是主要问题。