Javascript: анимированные элементы интерфейса для табличных значений.Ошибка Gettting: Контейнер не существует - PullRequest
0 голосов
/ 11 декабря 2018

Я написал некоторый код как некое доказательство концепции, которую я собираюсь затем перенести в более крупный проект, когда он заработает.
Часть, над которой я работаю, будет таблицей, содержащей различные значения, некоторые из которыхкоторые должны быть преобразованы в маленькие диаграммы в ячейке таблицы.
Например, проценты должны быть преобразованы в радиальные кольцевые диаграммы, а значения миль и минут должны быть преобразованы в маленькие столбцы со значениями на них.

Я получаю

Uncaught Error: контейнер не существует

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

Проблема в том, что, насколько я могу судить (хотя я должен быть неверным), порядок моего кода должен ссылаться на div только после его создания, и я не могу понять, почему это не так,

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

Я использую внешнюю библиотеку progressbar.js .HTML / CSS / JS код выглядит следующим образом.Чтобы увидеть, каким должен быть конечный результат, можно найти более раннюю рабочую версию, которая использует очень небрежный обходной путь, чтобы заставить его работать: http://www.workstage.stephenirving.net.

В настоящее время я просто храню весь код в одном файле с javascript и css в заголовке html.Я попытался поместить часть JS в нижней части тела в HTML, но это тоже не сработало.

// Function initiates when DOM content is loaded and all the functions for charting is subsequently called
document.addEventListener("DOMContentLoaded", function() {
  const totalRads = 9,
    totalMinBars = 3,
    totalMileBars = 3;
  totalBars = totalMinBars + totalMileBars;
  let colValPairs = getColVals(totalRads, totalBars);
  setColChartWrappers(totalRads, totalBars);
  generateCharts(colValPairs, totalRads, totalMinBars, totalMileBars);
});

// Table value getter function
function getColVals(totalRads, totalBars) {
  'use strict';

  const totalCharts = totalRads + totalBars; // The combined total number of bars and radials

  let colVals = new Array(), // An array of all the numbers that will be converted into radials/bars
    cellIds = new Array(), // An array containing all the table cell IDS for cells containing numbers
    idValPairs = new Object();

  for (let i = 0; i < totalCharts; i++) {
    cellIds[i] = "col0num" + i;
    // Get the contents of table cells, this is the progress number
    colVals[i] = document.getElementById(cellIds[i]).innerHTML;
    idValPairs[cellIds[i]] = colVals[i];
  }
  return idValPairs;
}

// Setter function that replaces the numbers in the cells with the div containers for the graphs
function setColChartWrappers(totalRads, totalBars) {
  const chartColor = '#58b86b', // Move this line when done
    animTime = 1400, // The time it will take the radial to reach 100% completion, in milliseconds
    minsMax = 200; // The max value for minute bar charts

  let wrapperNames = new Array(), // Array for the names of all the wrapper cells for the radials
    cellIds = new Array(); // An array containing all the table cell IDS for cells containing numbers
  i = 0;

  for (let i = 0; i < (totalRads + totalBars); i++) {
    wrapperNames[i] = "chart_wrapper" + i;
    cellIds[i] = "col0num" + i;
    if (i < totalRads) {
      document.getElementById(cellIds[i]).innerHTML = '<div class="container"><div id="' + wrapperNames[i] +
        '" class="rad-wrapper"></div></div>';
    } else {
      document.getElementById(cellIds[i]).innerHTML = '<div class="container"><div id="' + wrapperNames[i] +
        '" class="bar-wrapper"></div></div>';
    }
  }
}

/*********************************************************************************
 * FUNC  :	createRadial
 * PURP  :	This function will create and return a small radial graph object.
 * INPUT :	* wrapperName - Name associated with the div wrapper where the radial will go. (chart_wrapperX)
 *			* radColor - The color the created radial will be
 *           * animTime - The amount of time it will take to reach 100% completion in ms
 * OUTPUT:	* rad - The returned radial graph object
 **********************************************************************************/
function createRadial(wrapperName, radColor, animTime) {

  const startColor = '#a0d6aa'; // Create the starting color for the radial (20% lighter than radColor)

  // Create a radial
  let rad = new ProgressBar.Circle(wrapperName, {
    color: radColor, // Set the font color of the number and % sign in the center of the radial
    strokeWidth: 9, // To prevent clipping, make the same as the max width it will animate to
    trailWidth: 9, // The width of the trail the radial will animate along
    trailColor: '#e2e2e2', // The color of the trail
    easing: 'easeInOut', // Animation easing function
    duration: animTime, // Sets the total time in milliseconds for the animation to reach 100%
    text: {
      autoStyleContainer: false
    },
    // Changes loading bar color & width as it progresses.
    // Keep in mind: The bar radial bar only reach the stated 'to' color and width when it reaches 100%
    from: { // Starting color and width
      color: startColor,
      width: 9
    },
    to: { // Ending color and width
      color: radColor,
      width: 9 // To prevent clipping, make width here the same as strokeWidth
    },

    // Animate the path of the radial and the text inside it
    step: function step(state, circle) {
      circle.path.setAttribute('stroke', state.color);
      circle.path.setAttribute('stroke-width', state.width);

      let value = Math.round(circle.value() * 100);
      circle.setText(value + '%');
    }
  });
  // Set the text style of above radial
  rad.text.style.fontFamily = '"Roboto", Arial, Helvetica, sans-serif;';
  rad.text.style.fontSize = '20px';
  rad.text.style.fontWeight = '700'; // Make the font weight bold
  return rad;
}

/*********************************************************************************
 * FUNC  :	createBar
 * PURP  :	This function will create and return a small bar graph object.
 * INPUT :	* wrapperName - Name associated with the div wrapper where the bar will go. (chart_wrapperX)
 *			* progressNum - The number that is in the cell being replaced with the bar
 *			* barColor - The color the created bar will be
 *          	* animTime - The amount of time it will take to reach 100% completion in ms
 *			* maxVal - The maximum value or range that the graph will rise to
 * OUTPUT:  	* bar - The returned bar graph object
 **********************************************************************************/
function createBar(wrapperName, progressNum, barColor, animTime, maxVal) {
  'use strict';

  const startColor = '#a0d6aa'; // Create the starting color for the bar (20% lighter than barColor)

  let progress, // Initialize variable for the progress the bar will animate to
    endText, // If maxVal = 50 endText is 'miles', otherwise it is 'mins'
    endColor = barColor; // Initialize variable for the color the bar will end up

  if (maxVal == 50) {
    endText = 'miles';
  } else {
    endText = 'mins';
  }

  if (progressNum > maxVal) {
    endColor = '#2b6537';
  } // Darken the ending color if the it goes higher than the maximum

  let bar = new ProgressBar.Line(wrapperName, {
    color: barColor, // Sets the color that the bar will be
    trailColor: '#e2e2e2', // The color of the trail
    easing: 'easeInOut', // Animation easing function
    duration: animTime, // Sets the total time in milliseconds for the animation to reach 100%
    svgStyle: {
      width: '98%',
      height: '98%'
    },
    text: {
      style: {
        left: '-38%', // Due to rotation, 'left' attribute is really 'bottom' attribute
        top: '40%' // Due to rotation, 'top' attribute is really 'left' attribute
      },
      autoStyleContainer: false
    },
    from: {
      color: startColor
    }, // Sets the starting color of the bar
    to: {
      color: endColor
    }, // Sets the final color of the bar if and when it reaches 100%

    // Animate the path of the bar and the text inside it
    step: function step(state, bar) {
      bar.path.setAttribute('stroke', state.color);
      let value = Math.round((bar.value() * maxVal) * 10) / 10;
      bar.setText(value + ' ' + endText);
    }
  });
  bar.text.style.color = '#fff'; // Set text color
  bar.text.style.whiteSpace = 'nowrap'; // Keep text from wrapping
  bar.text.style.position = 'absolute';
  bar.text.style.width = '100%';
  bar.text.style.fontfamily = '"Roboto", Arial, Helvetica, sans-serif'; // Text font
  bar.text.style.fontSize = '1em'; // Text font size
  bar.text.style.fontWeight = '700'; // Make the font weight bold
  bar.text.style.transform = 'rotate(90deg)'; // Rotate the text back so that it is not sideways.
  // Add shadow to text to make it easier to see on light bg
  bar.text.style.textShadow = '1px 1px 0px rgba(150, 150, 150, 0.6)';
  return bar;
}
// Function generate the chart elements in the table
function generateCharts(idValPairs, totalRads, totalMinBars, totalMileBars) {
  'use strict';
  const chartColor = '#58b86b', // Set the color the radial will be
    animTime = 1400, // The time it will take the radial to reach 100% completion, in milliseconds
    totalBars = totalMinBars + totalMileBars,
    totalCharts = totalRads + totalBars;

  let i = 0,
    wrapperNames = new Array(), // Array for the names of all the wrapper cells for the radials
    radObjects = new Array(),
    barOjects = new Array();
  for (const key of Object.keys(idValPairs)) {
    wrapperNames[i] = "chart_wrapper" + i;
    radObjects[i] = createRadial(wrapperNames[i], chartColor, animTime);
    if (i < totalMileBars) {
      barObjects[i] = createBar(wrapperNames[i], idValPairs[key], chartColor, animTime, 50);
    } else {
      barObjects[i] = createBar(wrapperNames[i], idValPairs[key], chartColor, animTime, minuteMax);
    }
    i++;
  }

  i = 0;
  for (const key of Object.keys(idValPairs)) {
    if (i < totalRads) {
      radObjects[i].animate((idValPairs[key] / 100));
    } else if (i < (totalRads + totalMileBars)) {
      barObjects[i].animate((idValPairs[key] / 50));
    } else {
      barObjects[i].animate((idValPairs[key] / 200));
    }
    i++;
  }
}
body {
  font-family: 'Roboto', Helvetica, sans-serif;
}

table {
  border: 2px solid black;
  float: left;
  display: inline;
}

th {
  border-bottom: 2px solid black;
}

td {
  border: 1px solid black;
  text-align: center;
  height: 100px;
  width: 120px;
  color: white;
}

.container {
  height: 100%;
  width: 100%;
  margin: 0 auto;
  display: flex;
  justify-content: center;
  align-items: center;
}

.rad-wrapper {
  margin: 0 auto;
  padding: 0;
  width: 5.8em;
  /* This is the size of the radial, make it equal to height */
  height: 5.8em;
  /* This is the size of the radial, make it equal to width */
  position: relative;
}

.bar-wrapper {
  width: 5.8em;
  /* This is the height of the bar (due to rotation transform) */
  height: 7em;
  /* This is the width of the bar */
  position: relative;
  margin: 0 auto;
  padding: 0;
  transform: rotate(-90deg);
  -webkit-transform: rotate(-90deg);
  -moz-transform: rotate(-90deg);
  -o-transform: rotate(-90deg);
  -ms-transform: rotate(-90deg);
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <title>RADIAL AND BAR TEST</title>
  <meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
  <link href="https://fonts.googleapis.com/css?family=Roboto:700" rel="stylesheet">
  <script src="https://raw.githubusercontent.com/kimmobrunfeldt/progressbar.js/master/dist/progressbar.min.js"></script>
</head>

<body>
  <table>
    <tr>
      <th colspan="3">EXAMPLE NUMBERS</th>
    </tr>
    <tr>
      <td id="col0num0">38</td>
      <td id="col0num1">52</td>
      <td id="col0num2">49</td>
    </tr>
    <tr>
      <td id="col0num3">56</td>
      <td id="col0num4">61</td>
      <td id="col0num5">30</td>
    </tr>
    <tr>
      <td id="col0num6">33</td>
      <td id="col0num7">29</td>
      <td id="col0num8">32</td>
    </tr>
    <tr>
      <!-- Bars begin -->
      <td id="col0num9">9.9</td>
      <td id="col0num10">8.5</td>
      <td id="col0num11">11.2</td>
    </tr>
    <tr>
      <!-- minute bar (Max 200) -->
      <td id="col0num12">106.9</td>
      <td id="col0num13">104.8</td>
      <td id="col0num14">83.5</td>
    </tr>
  </table>
</body>

</html>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...