Week 3

Detailed description about my work during the third week

Notes from logbook

This week I continued working on the D3 application of our app, I was able to also display the data in a canvas instead of an svg. So if the possibility arises where the svg fails I now know how to implement a canvas. Still wasn't able to make the connecting links of the items and persons. I also was able to make the play/pause button for the automatic steps. Next up on the list is to make an step counter so people can see on which step you are. On thursday I worked some more on the wiki of this project. I wrote about the D3 library and the API Marcio made, after that we had a meeting with Yuri which was a brainstorm session about what visualisations we can use to properly display the data.

Logbook

Deep dive of this week's work

So because it is possible that an SVG can become too large to work with, and it will slow down your browser, I had a look at displaying the data in a canvas. The advantage of displaying the data in a canvas is that you will only create one HTML element instead of the possibility of having thousands of different lines and circles in the SVG group that would result in a different HTML element for each node and link.

The code for that looked like this

const width = window.innerWidth
const height = window.innerHeight
const margin = {width: (0.1 * width), height:(0.1 * height)}


d3.select('#graph')
  .append('canvas')
  .attr('width', width)
  .attr('height', height)

const canvas = d3.select('canvas')
const ctx = canvas.node().getContext('2d')

const detachedContainer = document.createElement('custom')
const dataContainer = d3.select(detachedContainer)

const xScale = d3.scaleLinear().range([0 + margin.width, width - margin.width])
const yScale = d3.scaleLinear().range([0 + margin.height, height - margin.height])

const update =  async (data) => {
  console.log(data)
  xScale.domain([d3.min(data.nodes, (d) => d.x), d3.max(data.nodes, (d) => d.x)])
  yScale.domain([d3.min(data.nodes, (d) => d.y), d3.max(data.nodes, (d) => d.y)])

  ctx.clearRect(0, 0, canvas.attr('width'), canvas.attr('height'))

  await data.nodes.forEach(drawNode)
  await data.links.forEach(drawLink)
}

const drawNode = async (d) => {
  const x = xScale(d.x)
  const y = yScale(d.y)
  const color = (label) => {
    if (label === 'person'){
      return '#348b90b0'
    } else {
      return '#dc143cbe'
    }
  }
  const r = (label) => {
    if (label === 'person'){
      return 15
    } else {
      return 5
    }
  }

  ctx.moveTo(x,y)
  ctx.beginPath()
  ctx.arc(x,y, r(d.label), 0, Math.PI*2)
  ctx.fillStyle = color(d.label)
  ctx.fill()
}

In the end, we didn't end up using it because all the research that happened between my teammates and me was with SVGs. Therefore, rewriting it all to be applicable in a canvas would take too much time. Because writing the function so that it draws the data in the canvas is different to making an SVG.

Last updated