Множественные радиолокационные карты MDB не отображаются - PullRequest
2 голосов
/ 19 марта 2020

Я использую диаграммы MDB, в частности, диаграммы радара: https://mdbootstrap.com/docs/jquery/javascript/charts/

HTML

<!-- MDB core JavaScript -->
<script type="text/javascript" src="../static/js/mdb.min.js"></script>

<div id='canvas_div'></div>

JavaScript

const ids_list = [0,1,2,3,4,5];
var canvas_div = document.getElementById('canvas_div');
for (var i=0; i<ids_list.length; i++){
    canvas_div.innerHTML += "<canvas id='"+ids_list[i]+"'></canvas>";
    generate_chart(ids_list[i], foo_list1, foo_list2);
}

function generate_chart(chartID,foo_list1,foo_list2){
    var ctxR = document.getElementById(chartID).getContext('2d');
        var myRadarChart = new Chart(ctxR, {
          type: 'radar',
          data: {
            labels: Object.keys(foo_list1),
            datasets: [
              {
                label: "Your FOO LIST1",
                data: Object.values(foo_list1),
                backgroundColor: ['rgba(105, 0, 132, .2)',],
                borderColor: ['rgba(200, 99, 132, .7)',],
                borderWidth: 2
              },{
                label: "Your FOO LIST2",
                data: Object.values(foo_list2),
                backgroundColor: ['rgba(0, 250, 220, .2)',],
                borderColor: ['rgba(0, 213, 132, .7)',],
                borderWidth: 1
              }
            ]
          },
          options: {responsive: false}
        });
}

Теперь я ожидаю получить график для каждого значения моего ids_list . Вместо этого я получаю только последний график. Возможно ли, что я не могу отображать более 1 графика на страницу с диаграммами MDB? Или я что-то упустил?

Мой код работает нормально, если я хочу отобразить только один график.

Воспроизводимый пример:

ссылка на GitHub Repo

Скачать Мой пример с Google drive

ОБНОВЛЕНИЕ BOUNTY: Это на самом деле то, что я пытаюсь сделать:

enter image description here

Как вы видите в инспекторе, ко второму сгенерированному холсту прикреплена диаграмма, а к первому нет. Ниже приведена функция generate_chart, как и в моем приложении:

//radar
      function generate_chart(chartID,last_scores,best_scores){
        var ctxR = document.getElementById(chartID).getContext('2d');
        console.log(ctxR);
        var myRadarChart = new Chart(ctxR, {
          type: 'radar',
          data: {
            labels: Object.keys(last_scores),
            datasets: [
              {
                label: "Your Last Score",
                data: Object.values(last_scores),
                backgroundColor: ['rgba(105, 0, 132, .2)',],
                borderColor: ['rgba(200, 99, 132, .7)',],
                borderWidth: 2
              },{
                label: "Your Best Score",
                data: Object.values(best_scores),
                backgroundColor: ['rgba(0, 250, 220, .2)',],
                borderColor: ['rgba(0, 213, 132, .7)',],
                borderWidth: 1
              }
            ]
          },
          options: {responsive: false}
        });
        console.log(myRadarChart);
      }

, какой журнал консоли возвращает следующее:

--------------------------------------
CanvasRenderingContext2D

canvas: <canvas id="viRE6FIudKYBbuREGRU14GXLepI3" style="display: block;" height="150">
fillStyle: "rgba(0, 0, 0, 0.1)"
​filter: "none"
​font: "10px \"Helvetica Neue\", \"Helvetica\", \"Arial\", sans-serif"
​globalAlpha: 1
​globalCompositeOperation: "source-over"
​imageSmoothingEnabled: true
​lineCap: "butt"
​lineDashOffset: 0
​lineJoin: "miter"
​lineWidth: 1
​miterLimit: 10
​mozCurrentTransform: Array(6) [ 1, 0, 0, … ]
​mozCurrentTransformInverse: Array(6) [ 1, -0, -0, … ]
​mozImageSmoothingEnabled: true
​mozTextStyle: "10px \"Helvetica Neue\", \"Helvetica\", \"Arial\", sans-serif"
​shadowBlur: 0
​shadowColor: "rgba(0, 0, 0, 0)"
​shadowOffsetX: 0
​shadowOffsetY: 0
​strokeStyle: "rgba(0, 0, 0, 0.1)"
​textAlign: "center"
​textBaseline: "top"
​<prototype>: CanvasRenderingContext2DPrototype { drawImage: drawImage(), beginPath: beginPath(), fill: fill(), … }
read_article.html:625:17
{…}

--------------------------------------
​
"$plugins": Object { descriptors: (3) […], id: 4 }
​
_bufferedRender: false
​_listeners: Object { mousemove: n(), mouseout: n(), click: n()
, … }
​animating: false
​aspectRatio: 2
​boxes: Array(3) [ {…}, {…}, {…} ]
​canvas: <canvas id="viRE6FIudKYBbuREGRU14GXLepI3" style="display: block;" height="150">
​chart: Object { id: 0, width: 300, height: 150, … }
​chartArea: Object { left: 0, top: 32, right: 300, … }
​config: Object { type: "radar", data: {…}, options: {…} }
​controller: Object { id: 0, width: 300, height: 150, … }
​ctx: CanvasRenderingContext2D { mozTextStyle: "10px \"Helvetica Neue\", \"Helvetica\", \"Arial\", sans-serif", mozImageSmoothingEnabled: true, globalAlpha: 1, … }
​currentDevicePixelRatio: 1
​data: 
​height: 150
​id: 0
​lastActive: Array []
​legend: Object { doughnutMode: false, fullWidth: true, position: "top", … }
​options: Object { responsive: false, responsiveAnimationDuration: 0, maintainAspectRatio: true, … }
​scale: Object { id: "scale", type: "radialLinear", hidden: false, … }
​scales: Object { scale: {…} }
​titleBlock: Object { fullWidth: true, position: "top", weight: 2000, … }
​tooltip: Object { _chart: {…}, _chartInstance: {…}, _data: {…}, … }
​width: 300
​<get data()>: function get()​
<set data()>: function set(t)​
<prototype>: Object { construct: construct(e, n), initialize: initialize(), clear: clear()
, … }
read_article.html:648:17

--------------------------------------

CanvasRenderingContext2D
​canvas: <canvas id="Eb31hrWcNgZh1FdGiBxVaz3FOnt1" style="display: block;" height="150">
​fillStyle: "rgba(0, 0, 0, 0.1)"
​filter: "none"
​font: "10px \"Helvetica Neue\", \"Helvetica\", \"Arial\", sans-serif"
​globalAlpha: 1
​globalCompositeOperation: "source-over"
​imageSmoothingEnabled: true
​lineCap: "butt"
​lineDashOffset: 0
​lineJoin: "miter"
​lineWidth: 1
​miterLimit: 10
​mozCurrentTransform: Array(6) [ 1, 0, 0, … ]
​mozCurrentTransformInverse: Array(6) [ 1, -0, -0, … ]
​mozImageSmoothingEnabled: true
​mozTextStyle: "10px \"Helvetica Neue\", \"Helvetica\", \"Arial\", sans-serif"
​shadowBlur: 0
​shadowColor: "rgba(0, 0, 0, 0)"
​shadowOffsetX: 0
​shadowOffsetY: 0
​strokeStyle: "rgba(0, 0, 0, 0.1)"
​textAlign: "center"
​textBaseline: "top"
​<prototype>: CanvasRenderingContext2DPrototype { drawImage: drawImage(), beginPath: beginPath(), fill: fill(), … }
read_article.html:625:17
{…}

--------------------------------------
​
"$plugins": Object { descriptors: (3) […], id: 4 }
​
_bufferedRender: false
​_listeners: Object { mousemove: n(), mouseout: n(), click: n()
, … }
​animating: false
​aspectRatio: 2
​boxes: Array(3) [ {…}, {…}, {…} ]
​canvas: <canvas id="Eb31hrWcNgZh1FdGiBxVaz3FOnt1" style="display: block;" height="150">​
chart: Object { id: 1, width: 300, height: 150, … }
​chartArea: Object { left: 0, top: 32, right: 300, … }
​config: Object { type: "radar", data: {…}, options: {…} }
​controller: Object { id: 1, width: 300, height: 150, … }
​ctx: CanvasRenderingContext2D { mozTextStyle: "10px \"Helvetica Neue\", \"Helvetica\", \"Arial\", sans-serif", mozImageSmoothingEnabled: true, globalAlpha: 1, … }
​currentDevicePixelRatio: 1
​data: 
​height: 150
​id: 1
​lastActive: Array []
​legend: Object { doughnutMode: false, fullWidth: true, position: "top", … }
​options: Object { responsive: false, responsiveAnimationDuration: 0, maintainAspectRatio: true, … }
​scale: Object { id: "scale", type: "radialLinear", hidden: false, … }
​scales: Object { scale: {…} }
​titleBlock: Object { fullWidth: true, position: "top", weight: 2000, … }
​tooltip: Object { _chart: {…}, _chartInstance: {…}, _data: {…}, … }
​width: 300
​<get data()>: function get()​
<set data()>: function set(t)​
<prototype>: Object { construct: construct(e, n), initialize: initialize(), clear: clear(), … }

Я также добавляю сюда для l oop, в котором я вызываю функция generate_chart:

function populate_leaderboard(authorID,submissions,profiles){
        var leaderboard_div = document.getElementById('leaderboard_feed');
        leaderboard_div.innerHTML = '';
        scores_dict = {};
        last_submissions = {};
        best_submissions = {};
        for (var i=0; i<submissions.length; i++){
          sub_user = submissions[i];
          for (var k=0; k<Object.keys(sub_user).length; k++){
            sub = sub_user[Object.keys(sub_user)[k]];
            if (scores_dict[sub['author']]){
              if (scores_dict[sub['author']] < sub['weighted_score']){
                scores_dict[sub['author']] = sub['weighted_score'];
                best_submissions[sub['author']] = sub['scores'];
              }
            } else {
              scores_dict[sub['author']] = sub['weighted_score'];
              best_submissions[sub['author']] = sub['scores'];
            }
            last_submissions[sub['author']] = sub['scores'];
          }
        }

        const lead_array = Object.entries(scores_dict).sort(([,a], [,b]) => b-a).map(([p]) => p);

        let medals = {
          1 : 'Gold Medal',
          2 : 'Silver Medal',
          3 : 'Bronze Medal'
        }

        for (var i=0; i<lead_array.length; i++){
          var medal = '';
          var u = lead_array[i];
          var position = i+1;
          if (i>0 && scores_dict[u] == scores_dict[lead_array[i-1]]) {
            position = position-1;
          }
          medal = medals[position]
          var temp_feed = '';
          temp_feed += "<div class='horiz_line'></div><div class='row centered'>"
          temp_feed += "<div class='col'><img class='profile_picture_leaderboard nomargin' src='"+profiles[u]['profile']['img']+"' alt='profile_picture'>";
          temp_feed += "<p class='nomargin'>"+profiles[u]['profile']['name']+" "+profiles[u]['profile']['surname']+"</p></div><div class='col' align='center'>";
          temp_feed += "<canvas id='"+u+"'></canvas></div><div class='col'>";
          temp_feed += "<p>"+position+" of "+lead_array.length+" on the <strong>Public</strong> Leaderboard</p>";
          temp_feed += "<h3>"+medal+"</h3><div class='progress'>";

          var delta = lead_array.length - (position-1);
          if (delta == 0){
            delta += 0.1;
          }
          var progress = Math.round((delta / lead_array.length) * 100);
          temp_feed += "<div class='progress-bar' role='progressbar' style='width:"+progress+"%' aria-valuenow='"+progress+"' aria-valuemin='0' aria-valuemax='100'></div></div>";
          if (UID == authorID || UID == u){
            temp_feed += "<button style='font-size:70%; margin-top:10px;'>Download Submission <i class='fas fa-cloud-download-alt'></i></button>";
          }
          temp_feed += "</div></div>";
          leaderboard_div.innerHTML += temp_feed;
          generate_chart(u,last_submissions[u],best_submissions[u]);
        }

      }

1 Ответ

1 голос
/ 22 марта 2020

здесь, с каждым l oop, вы перезаписываете содержимое canvas_div
таким образом, что в конце l oop существует только один холст.

canvas_div.innerHTML = "<canvas id='"+ids_list[i]+"'></canvas>";

Вы должны добавить новый холст с каждым l oop.

canvas_div.innerHTML += "<canvas id='"+ids_list[i]+"'></canvas>";

РЕДАКТИРОВАТЬ

вместо добавления html в виде строки, здесь ...

canvas_div.innerHTML += "<canvas id='"+ids_list[i]+"'></canvas>";

create элемент canvas с использованием -> document.createElement

var canvas = canvas_div.appendChild(document.createElement('canvas'));
canvas.id = chartID;

см. следующий рабочий фрагмент ...

<!doctype html>
<html lang="en">
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
    <link href="https://fonts.googleapis.com/css?family=Lato:300,300i,400,400i,700,700i,900&display=swap" rel="stylesheet">
    <link href="https://fonts.googleapis.com/css?family=Noto+Serif:400,400i,700,700i&display=swap" rel="stylesheet">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">


    <script src="https://kit.fontawesome.com/c346c28ff4.js" crossorigin="anonymous"></script>

    <!-- Optional JavaScript -->
    <!-- jQuery first, then Popper.js, then Bootstrap JS -->
    <!-- AJAX -->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
    <!-- MDB core JavaScript -->
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mdbootstrap/4.14.1/js/mdb.min.js"></script>

  </head>

  <body>


    <div id='canvas_div'></div>

    <script>

      const foo_list1 = [1,2,3,4,5];
      const foo_list2 = [5,4,3,2,1];

      const ids_list = [0,1,2,3,4,5];
      var canvas_div = document.getElementById('canvas_div');
      for (var i=0; i<ids_list.length; i++){
          generate_chart(ids_list[i], foo_list1, foo_list2);
      }

      function generate_chart(chartID,foo_list1,foo_list2){
          var canvas = canvas_div.appendChild(document.createElement('canvas'));
          canvas.id = chartID;
          var ctxR = canvas.getContext('2d');
          var myRadarChart = new Chart(ctxR, {
            type: 'radar',
            data: {
              labels: Object.keys(foo_list1),
              datasets: [
                {
                  label: "Your FOO LIST1",
                  data: Object.values(foo_list1),
                  backgroundColor: ['rgba(105, 0, 132, .2)',],
                  borderColor: ['rgba(200, 99, 132, .7)',],
                  borderWidth: 2
                },{
                  label: "Your FOO LIST2",
                  data: Object.values(foo_list2),
                  backgroundColor: ['rgba(0, 250, 220, .2)',],
                  borderColor: ['rgba(0, 213, 132, .7)',],
                  borderWidth: 1
                }
              ]
            },
            options: {responsive: false}
          });
      }

    </script>

  </body>
</html>

РЕДАКТИРОВАТЬ 2

, следуя подходу из первого решения, попробуйте следующее ...

в функции populate_leaderboard,
удалите элемент canvas из temp_feed и добавьте id к родителю <div>.
, см. Следующий фрагмент ..

    for (var i=0; i<lead_array.length; i++){
      var medal = '';
      var u = lead_array[i];
      var position = i+1;
      if (i>0 && scores_dict[u] == scores_dict[lead_array[i-1]]) {
        position = position-1;
      }
      medal = medals[position]
      var temp_feed = '';
      temp_feed += "<div class='horiz_line'></div><div class='row centered'>"
      temp_feed += "<div class='col'><img class='profile_picture_leaderboard nomargin' src='"+profiles[u]['profile']['img']+"' alt='profile_picture'>";

      // remove canvas, add id
      temp_feed += "<p class='nomargin'>"+profiles[u]['profile']['name']+" "+profiles[u]['profile']['surname']+"</p></div><div class='col' align='center' id='"+u+"'>";
      temp_feed += "</div><div class='col'>";
      temp_feed += "<p>"+position+" of "+lead_array.length+" on the <strong>Public</strong> Leaderboard</p>";
      temp_feed += "<h3>"+medal+"</h3><div class='progress'>";

      var delta = lead_array.length - (position-1);
      if (delta == 0){
        delta += 0.1;
      }
      var progress = Math.round((delta / lead_array.length) * 100);
      temp_feed += "<div class='progress-bar' role='progressbar' style='width:"+progress+"%' aria-valuenow='"+progress+"' aria-valuemin='0' aria-valuemax='100'></div></div>";
      if (UID == authorID || UID == u){
        temp_feed += "<button style='font-size:70%; margin-top:10px;'>Download Submission <i class='fas fa-cloud-download-alt'></i></button>";
      }
      temp_feed += "</div></div>";
      leaderboard_div.innerHTML += temp_feed;
      generate_chart(u,last_submissions[u],best_submissions[u]);
    }

  }

затем в функции generate_chart,
используйте подход, аналогичный предыдущему решению.
см. следующий фрагмент ...

  function generate_chart(chartID,last_scores,best_scores){
    var canvas_div = document.getElementById(chartID);
    var canvas = canvas_div.appendChild(document.createElement('canvas'));
    var ctxR = canvas.getContext('2d');
    var myRadarChart = new Chart(ctxR, {
      type: 'radar',
      data: {
        labels: Object.keys(last_scores),
        datasets: [
          {
            label: "Your Last Score",
            data: Object.values(last_scores),
            backgroundColor: ['rgba(105, 0, 132, .2)',],
            borderColor: ['rgba(200, 99, 132, .7)',],
            borderWidth: 2
          },{
            label: "Your Best Score",
            data: Object.values(best_scores),
            backgroundColor: ['rgba(0, 250, 220, .2)',],
            borderColor: ['rgba(0, 213, 132, .7)',],
            borderWidth: 1
          }
        ]
      },
      options: {responsive: false}
    });
  }

EDIT 3

другой подход заключается в том, чтобы сначала загрузить весь контент,
, а затем, go назад и добавить диаграммы.

см. Следующий рабочий фрагмент,
все содержимое добавляется перед попыткой рисовать диаграммы.
имя класса используется для поиска элементов canvas ...

<!doctype html>
<html lang="en">
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
    <link href="https://fonts.googleapis.com/css?family=Lato:300,300i,400,400i,700,700i,900&display=swap" rel="stylesheet">
    <link href="https://fonts.googleapis.com/css?family=Noto+Serif:400,400i,700,700i&display=swap" rel="stylesheet">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">


    <script src="https://kit.fontawesome.com/c346c28ff4.js" crossorigin="anonymous"></script>

    <!-- Optional JavaScript -->
    <!-- jQuery first, then Popper.js, then Bootstrap JS -->
    <!-- AJAX -->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
    <!-- MDB core JavaScript -->
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mdbootstrap/4.14.1/js/mdb.min.js"></script>

  </head>

  <body>


    <div id='canvas_div'></div>

    <script>

      const foo_list1 = [1,2,3,4,5];
      const foo_list2 = [5,4,3,2,1];
      const ids_list = [0,1,2,3,4,5];
      var canvas_div = document.getElementById('canvas_div');

      for (var i=0; i<ids_list.length; i++){
        canvas_div.innerHTML += "<canvas class='chart' id='"+ids_list[i]+"'></canvas>";
      }

      var charts = document.getElementsByClassName('chart');
      Array.prototype.forEach.call(charts, function(canvas) {
        var ctxR = canvas.getContext('2d');
        var myRadarChart = new Chart(ctxR, {
          type: 'radar',
          data: {
            labels: Object.keys(foo_list1),
            datasets: [
              {
                label: "Your FOO LIST1",
                data: Object.values(foo_list1),
                backgroundColor: ['rgba(105, 0, 132, .2)',],
                borderColor: ['rgba(200, 99, 132, .7)',],
                borderWidth: 2
              },{
                label: "Your FOO LIST2",
                data: Object.values(foo_list2),
                backgroundColor: ['rgba(0, 250, 220, .2)',],
                borderColor: ['rgba(0, 213, 132, .7)',],
                borderWidth: 1
              }
            ]
          },
          options: {responsive: false}
        });
      });

    </script>

  </body>
</html>
...