Skip to content

Proces Week 3

Marco Fijan edited this page Jan 21, 2021 · 5 revisions

Maandag

Vandaag ging zelfstandig aan de slag met de data. Ik begon met het visualiseren van een kaart. Dit lukte me na een poosje, maar kwam achter verschillende problemen.

  • Ik kan tot nu toe geen api vinden met de kaart van Amsterdam
  • De kaart van Nederland die ik nu gebruik heeft de gemeentes erg versimpeld waardoor het gebied Amsterdam erg versimpelde hoeken heeft wanneer je daar op inzoemt
  • Ik heb nog geen makkelijke manier gevonden om echt een kaart te tonen met d3
  • Ik heb nog geen succes met het plotten van de json op een d3 kaart.

Ik besloot daarom om eerst maar aan de slag te gaan met het verkrijgen van de data die ik nodig heb om de datavisualisaties te maken. Ik ben vandaag begonnen met het verkrijgen van de data om de stackedbarchart te visualiseren. Hiervoor gebruik ik de link van Jordy Fronik die zelf de json deels heeft verbeterd en host (http://ringring.jorrr.nl/geojson-data-ringring.json).

Inmiddels heb ik de data kunnen verkrijgen. Ik heb de datums omgezet in tijdblokken en heb de duur van de fietsrit ook succesvol opgehaald en opgeslagen. Voordat ik deze data volledig klaarmaak voor een stackedbarchart, wacht ik eerst de feedback af van Ring Ring. Deze feedback krijgen we morgen.

const proxyURL = "https://cors-anywhere.herokuapp.com/";
const ringRingApi = "http://ringring.jorrr.nl/geojson-data-ringring.json";
let shortDuration = [];
let mediumDuration = [];
let longDuration = [];

function setupData() {
  const ringRingRawData = d3
    .json(proxyURL + ringRingApi)
    .then((ringRingFetchedData) => {
      console.log("done");
      const ringRingFeatures = ringRingFetchedData[0].features;
      console.log(ringRingFeatures);
      durationInMinutes(ringRingFeatures);
      const timeStamps = getTimeStamp(ringRingFeatures);
      console.log(timeStamps);
      createDiagram();
    });
}

function durationInMinutes(ringRingFeatures) {
  ringRingFeatures.forEach((feature) => {
    const duration = feature.properties.duration;
    if (duration <= 5) {
      shortDuration.push(feature);
    } else if (duration > 5 && duration <= 30) {
      mediumDuration.push(feature);
    } else {
      longDuration.push(feature);
    }
  });
}

function getTimeStamp(ringRingFeatures) {
  return ringRingFeatures.map((feature) => {
    const startTime = feature.properties.start;
    const startTimestamp = startTime.substr(11, 2);
    const startTimestampInteger = parseInt(startTimestamp, 10);
    console.log(startTimestampInteger);
    if (startTimestampInteger >= 00 && startTimestampInteger < 2) {
      return "00:00-02:00";
    } else if (startTimestampInteger >= 2 && startTimestampInteger < 6) {
      return "02:00-06:00";
    } else if (startTimestampInteger >= 6 && startTimestampInteger < 8) {
      return "06:00-08:00";
    } else if (startTimestampInteger >= 8 && startTimestampInteger < 10) {
      return "08:00-10:00";
    } else if (startTimestampInteger >= 10 && startTimestampInteger < 12) {
      return "10:00-12:00";
    } else if (startTimestampInteger >= 12 && startTimestampInteger < 14) {
      return "12:00-14:00";
    } else if (startTimestampInteger >= 14 && startTimestampInteger < 16) {
      return "14:00-16:00";
    } else if (startTimestampInteger >= 16 && startTimestampInteger < 18) {
      return "16:00-18:00";
    } else if (startTimestampInteger >= 18 && startTimestampInteger < 20) {
      return "18:00-20:00";
    } else if (startTimestampInteger >= 20 && startTimestampInteger < 22) {
      return "20:00-22:00";
    } else if (startTimestampInteger >= 22 && startTimestampInteger < 24) {
      return "22:00-24:00";
    }
  });
}

Dinsdag

We begonnen vandaag met een feedbackronde van de opdrachtgever. Hier bleek toch wel dat het concept dat Tugce had bedacht te lastig is om te maken voor mij als developer, wat ik ook al meerdere keren had gezegd. Ze had allerlei mooie afbeeldingen en straatnamen gebruikt. Deze zijn niet makkelijk te halen uit de dataset. Het concept moest hierdoor weer aangepast worden. We kozen ervoor om ons te focussen op locatie en tijd. We wilde een kaart weergeven waar de routes uit de dataset uitgestippeld worden. Daarnaast plaatsen we ook nog wat diagrammen die de data uit de dataset mooi weergeeft. Aangezien het ontwerpen van het concept even duurt, ben ik verder gegaan met puur de datavisualisatie in diagrammen.

Ik begon eerst door het dashboard op te delen in vlakken. Ik wil, net zoals in het concept, op alle pagina's 1 groot vlak en 1 sidebar hebben waar er dingen als filters en acties gedaan kunnen worden met de content van het grote vlak. Ik ben daarnaast verder gegaan met functies maken om een datavisualisatie te maken. Deze heb ik vervolgens nog geprobeerd om in een diagram weer te geven maar hier had ik niet genoeg tijd meer voor vandaag.

Woensdag

Vandaag had ik de stacked diagram werkend. Ik ben hier de hele dag mee bezig geweest. Ik had moeite met het plotten van de Xaxis. Dit kwam omdat ik vergeten was om de variable data mee te geven aan de functie setScales. Hierdoor had de x-as geen data. Verder zaten er nog wat slordige fouten in zoals het missen van een tijdsvak. Uiteindelijk had ik vandaag dit: afbeelding.png

Hiervoor heb ik deze code gebruikt:

function createDiagram(data) {
  g = svg
    .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

  // Define d3 variables
  stackedBars = stackGenerator(data);

  // Create Diagram
  setScales(data);
  setAxises();
  drawBar();
  // checkInput();
}

// Set the scales for the chart
function setScales(data) {
  colorScale = d3
    .scaleOrdinal()
    .domain(["shortDuration", "mediumDuration", "longDuration"])
    .range(["#F48A14", "#D22F30", "#054488"]);

  scaleY = d3
    .scaleLinear()
    .domain([
      d3.max(stackedBars, (layer) => d3.max(layer, (subLayer) => subLayer[1])),
      0,
    ])
    .range([0, innerHeight])
    .nice();

  scaleX = d3
    .scaleBand()
    .domain(data.map(valueX)) // Select all the provinces for the domain
    .range([0, innerWidth])
    .padding(0.2);
}

// Set the axisses for the chart
function setAxises() {
  const yAxis = d3.axisLeft(scaleY).tickSize(-innerWidth);

  const xAxis = d3.axisBottom(scaleX);

  const yAxisGroup = g.append("g").call(yAxis).attr("class", "yAxis");

  yAxisGroup.select(".domain").remove();

  yAxisGroup
    .append("text")
    .attr("y", -50)
    .attr("x", -(innerHeight / 2))
    .attr("transform", "rotate(-90)")
    .attr("class", "yAxisName")
    .text("Aantal fietsritten");

  const xAxisGroup = g
    .append("g")
    .call(xAxis)
    .attr("transform", "translate(0," + innerHeight + ")")
    .attr("class", "xAxis");

  xAxisGroup
    .selectAll("text")
    .attr("transform", "rotate(55)")
    .attr("text-anchor", "start");

  xAxisGroup.selectAll(".domain, .tick line").remove();

  xAxisGroup
    .append("text")
    .attr("y", 80)
    .attr("x", innerWidth / 2)
    .attr("class", "xAxisName")
    .text("Tijdsvak");

  g.append("text")
    .text("Aantal fietsritten per tijdsvlak")
    .attr("y", -20)
    .attr("x", innerWidth / 2)
    .attr("text-anchor", "middle")
    .attr("class", "title");
}

// Draw the rectangles
function drawBar() {
  g.selectAll(".layer")
    .data(stackedBars)
    .enter()
    .append("g")
    .attr("class", "layer")
    .attr("fill", (d) => colorScale(d.key))
    .selectAll("rect")
    .data((d) => d)
    .enter()
    .append("rect")
    .attr("x", (d) => scaleX(d.data.timeStamp))
    .attr("y", (d) => scaleY(d[1]))
    .attr("width", scaleX.bandwidth())
    .attr("height", 0) // set height 0 for the transition
    .transition()
    .duration(800)
    .attr("height", (d) => scaleY(d[0]) - scaleY(d[1]));
}

Donderdag

Nadag ik woensdag erg lang bezig was geweest met d3. Ben ik vandaag wat meer met de styling van de website aan de slag gegaan. Ik gaf de dashboardbuttons een style en begon met het maken van een inlogpagina. afbeelding.png

Vrijdag

Vandaag hadden we weer een coachingsgesprek. Hier kreeg ik als feedback dat de Suze de stackedbarchart legenda erg op filters vond lijken. Ik zelf vond dit niet het geval, maar ik ga later nog proberen om de legenda om te zetten in filters aangezien dat me wel interessant lijkt om de data zo te kunnen filteren. Verder ging ik vandaag nog verder met de inlogpagina en maakte deze ook responsive. afbeelding.png

Zondag

Zondag ging ik ook nog even aan de slag. Ik wilde vandaag een werkende map hebben om later de routes op uit te stippelen. Maandag heb ik afgesproken met de andere tech studenten die dit project volgen om uit te vogelen hoe we de route precies kunnen uitstippelen. Het is daarom handig als ik al een map klaar heb staan. Ik had al geprobeerd om dit met google maps te doen. Helaas vraagt google maps nu om een billing plan in te vullen als je zelf data wilt plotten. Hiervoor had je een creditcard nodig en die heb ik niet. Ik veranderde daarom de map van google maps naar mapbox op tip van Jordy Fronik. Al met al ging werkte mapbox erg makkelijk. Velen malen makkelijker dan google maps. Je kon gratis een account aanmaken op mapbox, en vervolgens kant en klare code copy-pasten om de map op je website te krijgen. In de code stond al mijn persoonlijke api_key. Alleen de zoom en positie vaststellen kostte wat tijd. Ik moest namelijk met de hand inzoomen en navigeren naar Amsterdam. Uiteindelijk kwam ik op deze waarden:

center: [4.89, 52.371], // starting position [lng, lat]
zoom: 12.8, // starting zoom

afbeelding.png

Clone this wiki locally