{"id":29583569,"url":"https://github.com/cr2007/f20dv-lab1","last_synced_at":"2025-07-19T23:14:10.772Z","repository":{"id":305131795,"uuid":"743973718","full_name":"cr2007/F20DV-Lab1","owner":"cr2007","description":"Lab 1 - Introduction to D3","archived":false,"fork":false,"pushed_at":"2025-07-18T10:11:46.000Z","size":148,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-07-18T14:15:54.361Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://cr2007.github.io/F20DV-Lab1/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cr2007.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2024-01-16T11:30:28.000Z","updated_at":"2025-07-18T10:11:50.000Z","dependencies_parsed_at":"2025-07-18T14:17:45.406Z","dependency_job_id":"dc966b58-74bc-4c42-8c29-6fd4e1b932d9","html_url":"https://github.com/cr2007/F20DV-Lab1","commit_stats":null,"previous_names":["cr2007/f20dv-lab1"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/cr2007/F20DV-Lab1","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cr2007%2FF20DV-Lab1","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cr2007%2FF20DV-Lab1/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cr2007%2FF20DV-Lab1/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cr2007%2FF20DV-Lab1/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cr2007","download_url":"https://codeload.github.com/cr2007/F20DV-Lab1/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cr2007%2FF20DV-Lab1/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266039240,"owners_count":23867854,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-07-19T23:14:07.420Z","updated_at":"2025-07-19T23:14:10.764Z","avatar_url":"https://github.com/cr2007.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n# F20DV Lab 1\n\n\u003ctable\u003e\n\t\u003ctr\u003e\n\t\t\u003ctd\u003e\u003cb\u003eLab 1\u003c/b\u003e\u003c/td\u003e\n\t\t\u003ctd\u003e\u003cb\u003e\u003ca href=\"https://cr2007.github.io/F20DV-Lab2\"\u003eLab 2 →\u003c/a\u003e\u003c/b\u003e\u003c/td\u003e\n\t\u003c/tr\u003e\n\u003c/table\u003e\n\n[![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/cr2007/F20DV-Lab1)\n\n\u003cdiv align=\"center\"\u003e\n\t\u003ctable\u003e\n\t\t\u003ctr\u003e\n\t\t\t\u003ctd\u003e\u003cb\u003e\u003ca href=\"lab1_tutorial1.html\"\u003eTutorial 1\u003c/a\u003e\u003c/b\u003e\u003c/td\u003e\n\t\t\t\u003ctd\u003e\u003cb\u003e\u003ca href=\"lab1_tutorial2.html\"\u003eTutorial 2\u003c/a\u003e\u003c/b\u003e\u003c/td\u003e\n\t\t\t\u003ctd\u003e\u003cb\u003e\u003ca href=\"lab1_tutorial3.html\"\u003eTutorial 3\u003c/a\u003e\u003c/b\u003e\u003c/td\u003e\n\t\t\t\u003ctd\u003e\u003cb\u003e\u003ca href=\"lab1_tutorial4.html\"\u003eTutorial 4\u003c/a\u003e\u003c/b\u003e\u003c/td\u003e\n\t\t\u003c/tr\u003e\n\t\u003c/table\u003e\n\u003c/div\u003e\n\n\n## Introduction to D3\n\n- **Name:** Chandrashekhar Ramaprasad ([cr2007](mailto:cr2007@hw.ac.uk))\n- **Course:** Data Visualization and Analytics ([**F20DV**](https://curriculum.hw.ac.uk/coursedetails/F20DV?termcode=202324))\n\n---\n\n#### Progress\n![66%](https://progress-bar.dev/66)\n\n- [X] [Project Setup](#exercise-project-setup)\n- [X] [Let's Make a Bar Chart](#exercise-lets-make-a-bar-chart)\n- [X] [Scalable Charts](#exercise-scalable-charts)\n- [X] [Let's Make a Scatter Plot](#exercise-lets-make-a-scatter-plot)\n- [ ] Let's Make a Donut Chart\n- [ ] Let's Make a Line Chart\n\n---\n\n## Tutorial 1: Web Languages\n\n#### Exercise: Project Setup\n\n[Lab 1 - Tutorial 1](https://cr2007.github.io/F20DV-Lab1/lab1_tutorial1.html)\n\nSuccessfully created a GitHub repository and added the starter files:\n- HTML file\n- CSS file (within a `styles` directory)\n- JavaScript file (within a `scripts` directory)\n\n\n\u003cdiv align=\"center\"\u003e\n\t\u003ca href=\"https://github.com/cr2007/F20DV-Lab1\"\u003e\u003cb\u003eRepository Link\u003c/b\u003e\u003c/a\u003e |\n\t\u003ca href=\"https://cr2007.github.io/F20DV-Lab1\"\u003e\u003cb\u003eDeployed Website Link\u003c/b\u003e\u003c/a\u003e\n\u003c/div\u003e\n\n\n---\n\u003cdiv align=\"right\"\u003e\n\t\u003ca href=\"#progress\"\u003eBack To Top ↥\u003c/a\u003e\n\u003c/div\u003e\n\n## Tutorial 2: D3 Selections\n\n#### Exercise: Let's Make a Bar Chart\n\n[Lab 1 - Tutorial 2](https://cr2007.github.io/F20DV-Lab1/lab1_tutorial2.html)\n\n\u003e Inspect the bar associated with the city Ottawa, is there any problems with it? What could be the reason?\n\nThere is a problem with the bar associated with the city Ottawa. The bar is not visible because the height of the bar.\u003cbr\u003e\nThe height for the SVG is set to **500px** and the height of the bar is set to **700px**.\u003cbr\u003e\nThis results in the bar being cut off at the top of the SVG.\n\n### Code\n\n\u003clink rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css\"\u003e\n\u003cscript src=\"https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js\"\u003e\u003c/script\u003e\n\n\u003cscript\u003ehljs.highlightAll();\u003c/script\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ccode\u003emain.js\u003c/code\u003e\u003c/summary\u003e\n\u003cpre\u003e\u003ccode class=\"language-javascript\"\u003e'use strict';\n\nimport BarChart from './barChart.js';\n\nconsole.log(`d3.version: ${d3.version}`);\n\nlet cities = [\n    {city: 'Edinburgh', pop: 506000, area: 119, alt: 47},\n    {city: 'Dubai', pop: 3604000, area: 1610, alt: 5},\n    {city: 'Putrajaya', pop: 109000, area: 49, alt: 38},\n    {city: 'Qingdao', pop: 10071000, area: 11228, alt: 25},\n    {city: 'Lagos', pop: 8048000, area: 1171, alt: 41},\n    {city: 'Ottawa', pop: 1017000, area: 2790, alt: 70},\n]\n\nlet bar1 = new BarChart('div#bar1', 800, 500);\n\n// This line transforms the cities dataset in the generic format\n// that BarChart expects: [[k,v], ...]\n// we will explain it further in the next lab\n\nlet citiesElevation = cities.map(d =\u003e [d.city, d.alt]);\n\nbar1.render(citiesElevation);\n\u003c/code\u003e\u003c/pre\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ccode\u003ebarChart.js\u003c/code\u003e\u003c/summary\u003e\n\u003cpre\u003e\u003ccode class=\"language-javascript\"\u003eexport default class BarChart {\n    // Attributes (you can make those private too)\n    width; height;    // size\n    svg; chart; bars; // selections\n    data;             // internal data\n\n    // Constructor\n    constructor(container, width, height) {\n        this.width = width;\n        this.height = height;\n\n        this.svg = d3.select(container).append('svg')\n            .classed('barchart', true)\n            .attr('width', width).attr('height', height);\n        this.chart = this.svg.append('g');\n        this.bars = this.chart.selectAll('rect.bar');\n    }\n\n    // Private methods\n    // data is in the format [[key, value], ...]\n    #updateBars() {\n        this.bars = this.bars\n            .data(this.data, d =\u003e d[0])\n            .join('rect')\n            .classed('bar', true)\n            .attr('x', (d, i) =\u003e i*40+5)\n            .attr('y', d =\u003e this.height - d[1]*10)\n            .attr('width', 40)\n            .attr('height', d =\u003e d[1]*10);\n    }\n\n    // Public API\n\n    // The dataset parameter needs to be in a generic format,\n    // so that it works for all future data\n    // here we assume a [[k, v], ...] format for efficiency\n    render(dataset) {\n        this.data = dataset;\n        this.#updateBars();\n        return this; // to allow chaining\n    }\n}\n\u003c/code\u003e\u003c/pre\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ccode\u003ebarchart.css\u003c/code\u003e\u003c/summary\u003e\n\u003cpre\u003e\u003ccode class=\"language-css\"\u003esvg.barchart {\n    fill: #3F94D3;\n    stroke: #003C71;\n    stroke-width: 2px;\n}\n\u003c/code\u003e\u003c/pre\u003e\n\u003c/details\u003e\n\n---\n\u003cdiv align=\"right\"\u003e\n\t\u003ca href=\"#progress\"\u003eBack To Top ↥\u003c/a\u003e\n\u003c/div\u003e\n\n## Tutorial 3: D3 Scales and Axes\n\n[Lab 1 - Tutorial 3](https://cr2007.github.io/F20DV-Lab1/lab1_tutorial3.html)\n\n#### Exercise: Scalable Charts\n\nIncludes extra attribute for margins in the Bar Chart constructor.\n\n#### Exercise: Let's Make a Scatter Plot\n\nCreates a Scatter Plot that plots the population against the area.\n\nRepurposes the code used in Bubble Charts and Bar Charts to include Scalability and Axes too.\n\n### Code\n\u003cdetails\u003e\n\u003csummary\u003e\u003ccode\u003emain.js\u003c/code\u003e\u003c/summary\u003e\n\u003cpre\u003e\u003ccode class=\"language-javascript\"\u003e\"use strict\";\n\nimport BarChart from \"./barChart_Tut3.js\";\nimport BubbleChart from \"./bubbleChart.js\";\nimport ScatterPlot from \"./scatterPlot.js\";\n\n// ...\n\n/***** Bubble Chart *****/\nlet bubble1 = new BubbleChart(\"div#bubble1\", 600, 400, [10, 40, 45, 20]);\nlet citiesArea = cities.map((d) =\u003e [d.city, d.alt]);\nbubble1.render(citiesArea);\n\n\n/***** Scatter Plot *****/\nlet scatter1 = new ScatterPlot(\"div#scatter1\", 600, 400, [10, 50, 45, 20]);\nlet citiesPop = cities.map((d) =\u003e [d.pop, d.area]);\nscatter1.render(citiesPop);\n\u003c/code\u003e\u003c/pre\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ccode\u003escatterPlot.js\u003c/code\u003e\u003c/summary\u003e\n\u003cpre\u003e\u003ccode class=\"language-javascript\"\u003eexport default class ScatterPlot {\n    // Attributes (you can make those private too)\n    width; height; margin; // Size\n    svg; plot; scatters;   // Selections\n    axisX; axisY;          // Axes\n    labelX; labelY;        // Labels\n    scaleX; scaleY;        // Scales\n    data;                  // Internal Data\n\n    // Constructor\n    constructor(container, width, height, margin) {\n        this.width = width;\n        this.height = height;\n        this.margin = margin;\n\n        this.svg = d3.select(container).append(\"svg\")\n            .classed(\"scatterplot\", true)\n            .attr(\"width\", width).attr(\"height\", height);\n\n        this.plot = this.svg.append(\"g\").attr(\"transform\", `translate(${this.margin[2]}, ${this.margin[0]})`);\n        this.scatters = this.plot.selectAll(\"circle.scatter\");\n\n        // Axes\n        this.axisX = this.svg.append(\"g\")\n            .attr(\"transform\", `translate(${this.margin[2]}, ${this.height - this.margin[1]})`);\n        this.axisY = this.svg.append(\"g\").attr(\"transform\", `translate(${this.margin[2]}, ${this.margin[0]})`);\n\n        // Labels\n        this.labelX = this.svg.append(\"text\")\n            .attr(\"transform\", `translate(${this.width / 2}, ${this.height})`)\n            .style(\"text-anchor\", \"middle\").attr(\"dy\", -5);\n\n        this.labelY = this.svg.append(\"text\")\n    }\n\n    #updateScales() {\n        let plotWidth = this.width - this.margin[2] - this.margin[3],\n            plotHeight = this.height - this.margin[0] - this.margin[1];\n\n        let rangeX = [0, plotWidth],\n            rangeY = [plotHeight, 0];\n\n        let domainX = this.data.map((d) =\u003e d[0]),\n            domainY = [0, d3.max(this.data, (d) =\u003e d[1])];\n\n        this.scaleX = d3.scaleBand(domainX, rangeX).padding(0.2);\n        this.scaleY = d3.scaleLinear(domainY, rangeY).nice();\n    }\n\n    #updateAxes() {\n        let axisGenX = d3.axisBottom(this.scaleX),\n            axisGenY = d3.axisLeft(this.scaleY);\n\n        this.axisX.call(axisGenX);\n        this.axisY.call(axisGenY);\n    }\n\n    // Private methods\n    // data is in the format [[key, value], ...]\n    #updateScatter() {\n        this.scatters = this.scatters\n            .data(this.data, (d) =\u003e d[0])\n            .join(\"circle\")\n            .classed(\"scatter\", true)\n            .attr(\"cx\", (d) =\u003e this.scaleX(d[0]) + this.scaleX.bandwidth() / 2)\n            .attr(\"cy\", (d) =\u003e this.height - this.margin[1] - this.scaleY(d[1]))\n            .attr(\"r\", 8);\n    }\n\n    // Public API\n\n    // The dataset parameter needs to be in a generic format,\n    // so that it works for all future data\n    // here we assume a [[k, v], ...] format for efficiency\n    render(dataset) {\n        this.data = dataset;\n        this.#updateScales();\n        this.#updateScatter();\n        this.#updateAxes();\n        return this; // to allow chaining\n    }\n\n    setLabels(labelX = \"categories\", labelY = \"values\") {\n        this.labelX.text(labelX);\n        this.labelY.text(labelY);\n        return this; // to allow chaining\n    }\n}\n\u003c/code\u003e\u003c/pre\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ccode\u003escatterplot.css\u003c/code\u003e\u003c/summary\u003e\n\u003cpre\u003e\u003ccode class=\"language-css\"\u003esvg.scatterplot {\n    fill: #3F94D3;\n    stroke: #003C71;\n    stroke-width: 2px;\n    border: 1px solid #121212;\n}\n\ntext {\n    font-family: sans-serif;\n    font-size: 12px;\n    fill: #121212;\n    stroke: none;\n}\n\u003c/code\u003e\u003c/pre\u003e\n\u003c/details\u003e\n\n---\n\u003cdiv align=\"right\"\u003e\n\t\u003ca href=\"#progress\"\u003eBack To Top ↥\u003c/a\u003e\n\u003c/div\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcr2007%2Ff20dv-lab1","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcr2007%2Ff20dv-lab1","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcr2007%2Ff20dv-lab1/lists"}