Commit 6c16b023 authored by Almouhannad Hafez's avatar Almouhannad Hafez

Add AreaChart

parent 0843bcc2
date,close
2015-09-28,1951.359985
2015-10-05,2014.890015
2015-10-12,2033.109985
2015-10-19,2075.149902
2015-10-26,2079.360107
2015-11-02,2099.199951
2015-11-09,2023.040039
2015-11-16,2089.169922
2015-11-23,2090.110107
2015-11-30,2091.689941
2015-12-07,2012.369995
2015-12-14,2005.550049
2015-12-21,2060.98999
2015-12-28,2043.939941
2016-01-04,1922.030029
2016-01-11,1880.329956
2016-01-18,1906.900024
2016-01-25,1940.23999
2016-02-01,1880.050049
2016-02-08,1864.780029
2016-02-15,1917.780029
2016-02-22,1948.050049
2016-02-29,1999.98999
2016-03-07,2022.189941
2016-03-14,2049.580078
2016-03-21,2035.939941
2016-03-28,2072.780029
2016-04-04,2047.599976
2016-04-11,2080.72998
2016-04-18,2091.580078
2016-04-25,2065.300049
2016-05-02,2057.139893
2016-05-09,2046.609985
2016-05-16,2052.320068
2016-05-23,2099.060059
2016-05-30,2099.129883
2016-06-06,2096.070068
2016-06-13,2071.219971
2016-06-20,2037.410034
2016-06-27,2102.949951
2016-07-04,2129.899902
2016-07-11,2161.73999
2016-07-18,2175.030029
2016-07-25,2173.600098
2016-08-01,2182.870117
2016-08-08,2184.050049
2016-08-15,2183.870117
2016-08-22,2169.040039
2016-08-29,2179.97998
2016-09-05,2127.810059
2016-09-12,2139.159912
2016-09-19,2164.689941
2016-09-26,2168.27002
2016-10-03,2153.73999
2016-10-10,2132.97998
2016-10-17,2141.159912
2016-10-24,2126.409912
2016-10-31,2085.179932
2016-11-07,2164.449951
2016-11-14,2181.899902
2016-11-21,2213.350098
2016-11-28,2191.949951
2016-12-05,2259.530029
2016-12-12,2258.070068
2016-12-19,2263.790039
2016-12-26,2238.830078
2017-01-02,2276.97998
2017-01-09,2274.639893
2017-01-16,2271.310059
2017-01-23,2294.689941
2017-01-30,2297.419922
2017-02-06,2316.100098
2017-02-13,2351.159912
2017-02-20,2367.340088
2017-02-27,2383.120117
2017-03-06,2372.600098
2017-03-13,2378.25
2017-03-20,2343.97998
2017-03-27,2362.719971
2017-04-03,2355.540039
2017-04-10,2328.949951
2017-04-17,2348.689941
2017-04-24,2384.199951
2017-05-01,2399.290039
2017-05-08,2390.899902
2017-05-15,2381.72998
2017-05-22,2415.820068
2017-05-29,2439.070068
2017-06-05,2431.77002
2017-06-12,2433.149902
2017-06-19,2438.300049
2017-06-26,2423.409912
2017-07-03,2425.179932
2017-07-10,2459.27002
2017-07-17,2472.540039
2017-07-24,2472.100098
2017-07-31,2476.830078
2017-08-07,2441.320068
2017-08-14,2425.550049
2017-08-21,2443.050049
2017-08-28,2476.550049
2017-09-04,2461.429932
2017-09-11,2500.22998
2017-09-18,2502.219971
2017-09-25,2519.360107
2017-10-02,2549.330078
2017-10-09,2553.169922
2017-10-16,2575.209961
2017-10-23,2581.070068
2017-10-30,2587.840088
2017-11-06,2582.300049
2017-11-13,2578.850098
2017-11-20,2602.419922
2017-11-27,2642.219971
2017-12-04,2651.5
2017-12-11,2675.810059
2017-12-18,2683.340088
2017-12-25,2673.610107
2018-01-01,2743.149902
2018-01-08,2786.23999
2018-01-15,2810.300049
2018-01-22,2872.870117
2018-01-29,2762.129883
2018-02-05,2619.550049
2018-02-12,2732.219971
2018-02-19,2747.300049
2018-02-26,2691.25
2018-03-05,2786.570068
2018-03-12,2752.01001
2018-03-19,2588.26001
2018-03-26,2640.870117
2018-04-02,2604.469971
2018-04-09,2656.300049
2018-04-16,2670.139893
2018-04-23,2669.909912
2018-04-30,2663.419922
2018-05-07,2727.719971
2018-05-14,2712.969971
2018-05-21,2721.330078
2018-05-28,2734.620117
2018-06-04,2779.030029
2018-06-11,2779.659912
2018-06-18,2754.879883
2018-06-25,2718.370117
2018-07-02,2759.820068
2018-07-09,2801.310059
2018-07-16,2801.830078
2018-07-23,2818.820068
2018-07-30,2840.350098
2018-08-06,2833.280029
2018-08-13,2850.129883
2018-08-20,2874.689941
2018-08-27,2901.52002
2018-09-03,2871.679932
2018-09-10,2904.97998
2018-09-17,2929.669922
2018-09-24,2913.97998
2018-10-01,2885.570068
2018-10-08,2767.129883
2018-10-15,2767.780029
2018-10-22,2658.689941
2018-10-29,2723.060059
2018-11-05,2781.01001
2018-11-12,2736.27002
2018-11-19,2632.560059
2018-11-26,2760.169922
2018-12-03,2633.080078
2018-12-10,2599.949951
2018-12-17,2416.620117
2018-12-24,2485.73999
2018-12-31,2531.939941
2019-01-07,2596.26001
2019-01-14,2670.709961
2019-01-21,2664.76001
2019-01-28,2706.530029
2019-02-04,2707.879883
2019-02-11,2775.600098
2019-02-18,2792.669922
2019-02-25,2803.689941
2019-03-04,2743.070068
2019-03-11,2822.47998
2019-03-18,2800.709961
2019-03-25,2834.399902
2019-04-01,2892.73999
2019-04-08,2907.409912
2019-04-15,2905.030029
2019-04-22,2939.879883
2019-04-29,2945.639893
2019-05-06,2881.399902
2019-05-13,2859.530029
2019-05-20,2826.060059
2019-05-27,2752.060059
2019-06-03,2873.340088
2019-06-10,2886.97998
2019-06-17,2950.459961
2019-06-24,2941.76001
2019-07-01,2990.409912
2019-07-08,3013.77002
2019-07-15,2976.610107
2019-07-22,3025.860107
2019-07-29,2932.050049
2019-08-05,2918.649902
2019-08-12,2888.679932
2019-08-19,2847.110107
2019-08-26,2926.459961
2019-09-02,2978.709961
2019-09-09,3007.389893
2019-09-16,2992.070068
2019-09-23,2961.790039
2019-09-30,2952.01001
2019-10-07,2970.27002
2019-10-14,2986.199951
2019-10-21,3022.550049
2019-10-28,3066.909912
2019-11-04,3093.080078
2019-11-11,3120.459961
2019-11-18,3110.290039
2019-11-25,3140.97998
2019-12-02,3145.909912
2019-12-09,3168.800049
2019-12-16,3221.219971
2019-12-23,3240.02002
2019-12-30,3234.850098
2020-01-06,3265.350098
2020-01-13,3329.620117
2020-01-20,3295.469971
2020-01-27,3225.52002
2020-02-03,3327.709961
2020-02-10,3380.159912
2020-02-17,3337.75
2020-02-24,2954.219971
2020-03-02,2972.370117
2020-03-09,2711.02002
2020-03-16,2304.919922
2020-03-23,2541.469971
2020-03-30,2488.649902
2020-04-06,2789.820068
2020-04-13,2874.560059
2020-04-20,2836.73999
2020-04-27,2830.709961
2020-05-04,2929.800049
2020-05-11,2863.699951
2020-05-18,2955.449951
2020-05-25,3044.310059
2020-06-01,3193.929932
2020-06-08,3041.310059
2020-06-15,3097.73999
2020-06-22,3009.050049
2020-06-29,3130.01001
2020-07-06,3185.040039
2020-07-13,3224.72998
2020-07-20,3215.629883
2020-07-27,3271.120117
2020-08-03,3351.280029
2020-08-10,3372.850098
2020-08-17,3397.159912
2020-08-24,3508.01001
2020-08-31,3426.959961
2020-09-07,3340.969971
2020-09-14,3319.469971
2020-09-21,3298.459961
2020-09-28,3363
\ No newline at end of file
......@@ -8,7 +8,8 @@
</head>
<body>
<div id="scatterplot-container">
<div id="scatterplot-container" style="display: none;">
<div id="scatterplot-tooltip">fdsfds</div>
<svg id="scatterplot"></svg>
<ul class="legend" id="scatterplot-legend">
......@@ -18,6 +19,15 @@
<li id="scatterplot-legend-Difficult"><span class="legend-e difficult"></span> Difficult</li>
</ul>
</div>
<div id="area-chart-container">
<div class="heading">
<p class="title">S&P 500 Index</p>
<span class="select-text">Start year</span><input type="number" min="2015" max="2020" value="2015"
id="area-chart-year-input">
</div>
<svg id="area-chart"></svg>
</div>
<script type="module" src="/src/ts/main.ts"></script>
</body>
......
......@@ -113,4 +113,32 @@ body {
color: gray;
}
/* #endregion */
/* #region Area chart */
#area-chart-container .area {
fill: #e9eff5;
}
#area-chart-container .line {
fill: none;
stroke: #537591;
stroke-width: 2.5px;
}
#area-chart-container .title {
font-weight: 900;
font-size: 40px;
}
#area-chart-container .select-text {
font-weight: 900;
margin-right: 0.5em;
}
#area-chart-container .heading {
margin-left: 3em;
}
/* #endregion */
\ No newline at end of file
import * as d3 from 'd3';
import { Chart } from "./chart";
import { ChartConfiguration } from "./chartConfiguration";
export class AreaChart extends Chart {
xScale: any;
yScale: any;
xAxis: any;
yAxis: any;
xAxisGroup: any;
yAxisGroup: any;
lineGenerator: d3.Line<[number, number]>;
areaGenerator: d3.Area<[number, number]>;
xValue: (d: any) => any;
yValue: (d: any) => any;
constructor(_config: ChartConfiguration, _data?: any[]) {
super(_config, _data);
this.initVis();
}
protected getDefaultMargins(): { top: number; right: number; bottom: number; left: number; } {
return {
top: 20,
right: 30,
bottom: 30,
left: 50
};
}
protected getDefaultContainerSize(): { width: number; height: number; } {
return {
width: 800,
height: 500
};
}
protected initVis(): void {
const vis = this;
// Initialize scales (output range only)
// Input domain will be updated in updateVis method
// Set up scales
vis.xScale = d3.scaleTime()
.range([0, vis.width]);
vis.yScale = d3.scaleLinear()
.nice()
// Reverse for ordering
.range([vis.height, 0]);
// Initialize axes
vis.xAxis = d3.axisBottom(vis.xScale);
vis.yAxis = d3.axisLeft(vis.yScale);
// Append empty x-axis group and move it to the bottom of the chart
vis.xAxisGroup = vis.chart.append("g")
.attr("transform", "translate(0," + vis.height + ")")
.call(vis.xAxis);
// Append y-axis group
vis.yAxisGroup = vis.chart.append("g")
.call(vis.yAxis);
// Define line generator
vis.lineGenerator = d3.line()
.x((d: any) => vis.xScale(d.date))
.y((d: any) => vis.yScale(d.close));
// Define area generator
vis.areaGenerator = d3.area()
.x((d: any) => vis.xScale(d.date))
.y0(vis.height)
.y1((d: any) => vis.yScale(d.close));
}
protected renderVis(): void {
const vis = this;
// Bind data to area paths
const areaSelection = vis.chart.selectAll(".area")
.data([vis.data]); // Wrap data in an array for a single area
// Enter selection for area
areaSelection.enter()
.append("path")
.attr("class", "area")
.attr("d", vis.areaGenerator)
.transition()
.duration(1000)
.attr("opacity", 1);
// Update selection for area
areaSelection
.transition()
.duration(1000)
.attr("d", vis.areaGenerator);
// Exit selection for area
areaSelection.exit()
.transition()
.duration(1000)
.attr("opacity", 0)
.remove();
// Bind data to line paths
const lineSelection = vis.chart.selectAll(".line")
.data([vis.data]);
// Enter selection for line
lineSelection.enter()
.append("path")
.attr("class", "line")
.attr("d", vis.lineGenerator)
.transition()
.duration(1000)
.attr("opacity", 1);
// Update selection for line
lineSelection
.transition()
.duration(1000)
.attr("d", vis.lineGenerator);
// Exit selection for line
lineSelection.exit()
.transition()
.duration(1000)
.attr("opacity", 0)
.remove();
// Update the axes/gridlines
vis.xAxisGroup
.transition()
.duration(1000)
.call(vis.xAxis);
vis.yAxisGroup
.transition()
.duration(1000)
.call(vis.yAxis);
}
public updateVis(): void {
const vis = this;
// Specificy accessor functions
vis.xValue = (d: any) => d.date;
vis.yValue = (d: any) => d.close;
// Set the scale input domains
vis.xScale.domain(d3.extent(vis.data, vis.xValue));
vis.yScale.domain(d3.extent(vis.data, vis.yValue));
vis.renderVis();
}
}
\ No newline at end of file
import { AreaChart } from './areaChart';
import { ChartConfiguration } from './chartConfiguration';
import { Scatterplot } from './scatter';
import '/src/css/style.css';
import * as d3 from 'd3';
const selectedDifficulties: string[] = [];
let data: any[] = [];
const scatterplot = new Scatterplot(new ChartConfiguration("#scatterplot"));
function handleLevelSelectionEvent(element: any, difficulty: string) {
const index = selectedDifficulties.indexOf(difficulty);
if (index > -1) {
// Difficulty is in the array, remove it
selectedDifficulties.splice(index, 1);
d3.select(element).style("opacity", 1);
} else {
// Difficulty is not in the array, add it
selectedDifficulties.push(difficulty);
d3.select(element).style("opacity", 0.5);
}
const filteredData = data.filter(item => !selectedDifficulties.includes(item.difficulty));
scatterplot.data = filteredData;
scatterplot.updateVis();
}
const difficulties = ["Easy", "Intermediate", "Difficult"]
// Add click event listeners for each difficulty level
for (const level of difficulties) {
const id = `#scatterplot-legend-${level}`
d3.select(id)
.on("click", function () {
handleLevelSelectionEvent(this, level);
});
}
// const selectedDifficulties: string[] = [];
// let data: any[] = [];
// const scatterplot = new Scatterplot(new ChartConfiguration("#scatterplot"));
// function handleLevelSelectionEvent(element: any, difficulty: string) {
// const index = selectedDifficulties.indexOf(difficulty);
// if (index > -1) {
// // Difficulty is in the array, remove it
// selectedDifficulties.splice(index, 1);
// d3.select(element).style("opacity", 1);
// } else {
// // Difficulty is not in the array, add it
// selectedDifficulties.push(difficulty);
// d3.select(element).style("opacity", 0.5);
// }
// const filteredData = data.filter(item => !selectedDifficulties.includes(item.difficulty));
// scatterplot.data = filteredData;
// scatterplot.updateVis();
// }
// const difficulties = ["Easy", "Intermediate", "Difficult"]
// // Add click event listeners for each difficulty level
// for (const level of difficulties) {
// const id = `#scatterplot-legend-${level}`
// d3.select(id)
// .on("click", function () {
// handleLevelSelectionEvent(this, level);
// });
// }
// /**
// * Load data from CSV file asynchronously and render scatter plot
// */
// d3.csv('/data/vancouver_trails.csv')
// .then(inputData => {
// // Convert strings to numbers
// inputData.forEach((d: any) => {
// d.time = +d.time;
// d.distance = +d.distance;
// });
// data = inputData;
// // Initialize chart
// scatterplot.data = inputData;
// // Show chart
// scatterplot.updateVis();
// })
// .catch(error => console.error(error));
/**
* Load data from CSV file asynchronously and render scatter plot
*/
d3.csv('/data/vancouver_trails.csv')
const areaChart = new AreaChart(new ChartConfiguration("#area-chart"));
d3.csv('/data/sp_500_index.csv')
.then(inputData => {
// Convert strings to numbers
const dateParser = d3.timeParse("%Y-%m-%d");
inputData.forEach((d: any) => {
d.time = +d.time;
d.distance = +d.distance;
d.date = dateParser(d.date);
d.close = +d.close;
});
data = inputData;
// Initialize chart
scatterplot.data = inputData;
// Show chart
scatterplot.updateVis();
areaChart.data = inputData;
areaChart.updateVis();
})
.catch(error => console.error(error));
setTimeout(() => {
const dateParser = d3.timeParse("%Y-%m-%d");
let t: any = { date: '2025-10-29', close: 0 };
t.date = dateParser(t.date);
t.close = +t.close;
areaChart.data.push(t);
areaChart.updateVis();
}, 1000);
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment