Using D3 for painting grid cells multiple times?

Viewed 101

I have a tsv file with 100000+ lines and 3 columns: time(ascending, nanoseconds);object;color. In this file each object appears multiple times with different color and time. And i have a grid, where each cell represents one of the objects (about 500+) and their actual color.

Here is the Code:

<!DOCTYPE html>
<html>

  <head>
    <meta charset="utf-8">
    <style type="text/css">
      svg {
        width: 90%;
        height: 400px;
      }

    </style>
  </head>

  <body>
    <div id="vis">
      <button id="play-button" onclick="runMain()" style="margin-left: 2em; margin-top:2em;">Play </button>
      <label for="inputDelay">delay:</label>
      <input type="text" id="inputDelay" placeholder="20" value="20">
    </div>
    <svg></svg>
  </body>
  <script src="https://d3js.org/d3.v4.min.js"></script>
  <script src="https://d3js.org/d3-timer.v1.min.js"></script>
  <link type="text/css" href="style.css" rel="stylesheet" />
  <script type="text/javascript">
    let nodeColors2 = ["#33b5e5", "#cc0000", "#669900", "#b4e56b", "#ffbb33", "#f540ff", "#aa18ff", "#16ffa9", "gray"]

    var playButton = d3.select("#play-button");
    createSVG();

    function createSVG(numParam) {
      var svg = d3.select("svg");

      var row = svg.selectAll(".row")
        .data(createGrid(numParam))
        .enter().append("g")
        .attr("class", "row");

      var column = row.selectAll(".square")
        .data(function(d) {
          return d;
        })
        .enter().append("rect")
        .attr("class", "square")
        .attr("id", function(d) {
          return "rect" + d.id
        })
        .attr("x", function(d) {
          return d.x;
        })
        .attr("y", function(d) {
          return d.y;
        })
        .attr("width", function(d) {
          return d.width;
        })
        .attr("height", function(d) {
          return d.height;
        })
        .style("fill", "#fff")
        .style("stroke", "#222");
    }

    /**prescan dataSet for further computation **/
    function fileScanning() {
      return new Promise(function(resolve, reject) {
        let parameterList = [];
        setTimeout(() => reject(new Error("setTimeoutError")), 1000);
        d3.tsv('testFile.tsv', function(data) {
          data.forEach(function(d) {
            if (!parameterList.includes(d.param)) {
              parameterList.push(d.param);
            }
          });
          resolve(parameterList.sort((a, b) => a - b));
        });
      });

    }

    /** create grid: cells get a squareID for parameters **/
    function createGrid(numParam = 600) {

      var num_columns = 50;
      var num_rows = Math.ceil(numParam / num_columns);
      var data = new Array();
      var xpos = 10; //starting xpos and ypos at 10 so the stroke will show when we make the grid below
      var ypos = 10;
      var width = 20;
      var height = 20;
      var squareID = 0;

      // iterate for rows
      for (var row = 0; row < num_rows; row++) {
        data.push(new Array());

        // iterate for cells/columns inside rows
        for (var column = 0; column < num_columns; column++) {
          data[row].push({
            x: xpos,
            y: ypos,
            width: width,
            height: height,
            id: "" + squareID
          });
          // each cell gets an ID for further linking to parameters
          squareID++;
          // increment the x position. I.e. move it over by 50 (width variable)
          xpos += width;
        }
        // reset the x position after a row is complete
        xpos = 10;
        // increment the y position for the next row. Move it down 50 (height variable)
        ypos += height;
      }
      return data;

    }

    async function runMain() {

      let delay = document.getElementById('inputDelay').value;
      d3.select("svg").selectAll(".row").remove();
      let parameterList = await fileScanning();
      createSVG(parameterList.length);

      /** run through dataSet and change nodecolors line for line**/
      d3.tsv('testFile.tsv', function(data) {
        for (let i = 0; i < data.length; i++) {
          setTimeout(() => {
            document.querySelector("#rect" + parameterList.indexOf(data[i].param)).setAttribute("style", "fill:" + nodeColors2[data[i].target] + "; stroke: black;");
          }, i * delay);
        }
      });
    }

  </script>

</html>

The dataset looks like this where object=param and color=target:

time    param   target
5396736 0   0
21620736    307000  5
36134400    430000  7
38073600    369000  6
39064064    246000  4
39318784    123000  2
48853504    62000   1
58494720    1000    0
65408512    185000  3
87599616    431000  7
87736832    247000  4
90412544    308000  5
91149568    370000  6
96732416    63000   1
96962816    124000  2
116216064   2000    0
117147392   186000  3

i want to start the visualisation (like youtube: variable speed, slider, possible to play/pause, back and forth) and while time is running it should always check the time in the file if an object needs to be updated. so, e.g. beeing at 45 seconds and all objects should represent their latest color update until that time.

As a newbie in general but especially in D3 i am wondering if D3 is a good choice and if so how my approach should look like or if i shouldn't use D3 with these requirements at all? I didn't figure out to fully understand update,enter and exit, yet but it feels like it should be the answer. If so i have no clue how the approach for "rewinding" should look like, since it shouldn't delete an object but repaint it with its latest color before the chosen time.

Here is the latest working example on plunker with a very small dataset for better understanding. It is supposed to look like this (missing the whole slider functionality like in youtube). But it is not supposed to use setTimeout for the moments of painting. I want to use "real time" from the tsv file.

As best fit got these sources: slider, grid. With slider i am having trouble to change the Date approach into my nanoseconds. Do you have some help if D3 will work and how to approach all of this since i am a bit lost?

PS: First question for me: Any suggestion for a better title of this question? I am happy to edit my question to make it more comfortable for everyone.

0 Answers
Related