Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
D
DV-HW4
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
almohanad.hafez
DV-HW4
Commits
b9cb1e08
Commit
b9cb1e08
authored
Jan 10, 2025
by
Almouhannad Hafez
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add scatter plot
parent
0a8a1501
Changes
5
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
443 additions
and
7 deletions
+443
-7
vancouver_trails.csv
data/vancouver_trails.csv
+189
-0
index.html
index.html
+8
-0
style.css
src/css/style.css
+82
-3
main.ts
src/ts/main.ts
+24
-4
scatter.ts
src/ts/scatter.ts
+140
-0
No files found.
data/vancouver_trails.csv
0 → 100644
View file @
b9cb1e08
This diff is collapsed.
Click to expand it.
index.html
View file @
b9cb1e08
...
...
@@ -8,6 +8,14 @@
</head>
<body>
<div
id=
"scatterplot-container"
>
<svg
id=
"scatterplot"
></svg>
<ul
class=
"legend"
id=
"scatterplot-legend"
>
<li><span
class=
"legend-e easy"
id=
"scatterplot-legend-easy"
></span>
Easy
</li>
<li><span
class=
"legend-e intermediate"
id=
"scatterplot-intermediate"
></span>
Intermediate
</li>
<li><span
class=
"legend-e difficult"
id=
"scatterplot-difficult"
></span>
Difficult
</li>
</ul>
</div>
<script
type=
"module"
src=
"/src/ts/main.ts"
></script>
</body>
...
...
src/css/style.css
View file @
b9cb1e08
...
...
@@ -5,8 +5,87 @@ body {
padding
:
0
;
box-sizing
:
border-box
;
overflow-x
:
hidden
;
background
:
#f7f7f7
;
}
h1
{
color
:
red
;
}
\ No newline at end of file
/* #region scatterplot*/
#scatterplot-container
{
padding
:
1em
;
}
#scatterplot-container
.source
{
font-size
:
10px
;
color
:
#888
;
}
#scatterplot-container
.source
a
{
color
:
#888
;
}
/* Axes */
#scatterplot-container
.axis
line
{
fill
:
none
;
stroke
:
#ddd
;
shape-rendering
:
crispEdges
;
}
#scatterplot-container
.axis
text
{
font-size
:
13px
;
fill
:
#6b6b6b
;
}
#scatterplot-container
.axis-title
{
font-size
:
13px
;
fill
:
#888
;
}
.y-axis
.tick
:first-child
line
{
stroke
:
#b1b1b1
;
}
#scatterplot-container
.y-axis
.tick
:first-child
text
{
display
:
none
;
}
#scatterplot-container
.x-axis
.tick
:first-child
line
{
display
:
none
;
}
#scatterplot-container
.axis
path
{
display
:
none
;
}
/* Legend */
#scatterplot-container
.legend
{
margin
:
20px
0
;
list-style
:
none
;
padding
:
0
;
}
#scatterplot-container
.legend
li
{
display
:
inline-block
;
margin
:
0
20px
0
0
;
}
#scatterplot-container
.legend-e
{
width
:
12px
;
height
:
12px
;
margin-right
:
3px
;
display
:
inline-block
;
}
#scatterplot-container
.legend-e.easy
{
background
:
#d3eecd
;
}
#scatterplot-container
.legend-e.intermediate
{
background
:
#7bc77e
;
}
#scatterplot-container
.legend-e.difficult
{
background
:
#2a8d46
;
}
/* #endregion */
\ No newline at end of file
src/ts/main.ts
View file @
b9cb1e08
import
'../css/style.css'
;
import
{
ChartConfiguration
}
from
'./chartConfiguration'
;
import
{
Scatterplot
}
from
'./scatter'
;
import
'/src/css/style.css'
;
import
*
as
d3
from
'd3'
;
d3
.
select
(
"body"
)
.
append
(
"h1"
)
.
text
(
"Hello world"
);
/**
* Load data from CSV file asynchronously and render scatter plot
*/
const
scatterplot
=
new
Scatterplot
(
new
ChartConfiguration
(
"#scatterplot"
));
d3
.
csv
(
'/data/vancouver_trails.csv'
)
.
then
(
data
=>
{
// Convert strings to numbers
data
.
forEach
((
d
:
any
)
=>
{
d
.
time
=
+
d
.
time
;
d
.
distance
=
+
d
.
distance
;
});
// Initialize chart
scatterplot
.
data
=
data
;
// Show chart
scatterplot
.
updateVis
();
})
.
catch
(
error
=>
console
.
error
(
error
));
setTimeout
(()
=>
{
scatterplot
.
data
=
[];
scatterplot
.
updateVis
();
},
1000
);
src/ts/scatter.ts
0 → 100644
View file @
b9cb1e08
import
*
as
d3
from
'd3'
;
import
{
Chart
}
from
"./chart"
;
import
{
ChartConfiguration
}
from
'./chartConfiguration'
;
export
class
Scatterplot
extends
Chart
{
private
colorScale
:
d3
.
ScaleOrdinal
<
string
,
unknown
,
never
>
;
private
xScale
:
d3
.
ScaleLinear
<
number
,
number
,
never
>
;
private
yScale
:
d3
.
ScaleLinear
<
number
,
number
,
never
>
;
private
xAxis
:
d3
.
Axis
<
d3
.
NumberValue
>
;
private
yAxis
:
d3
.
Axis
<
d3
.
NumberValue
>
;
private
xAxisG
:
any
;
private
yAxisG
:
any
;
private
colorValue
:
(
d
:
any
)
=>
any
;
private
xValue
:
(
d
:
any
)
=>
any
;
private
yValue
:
(
d
:
any
)
=>
any
;
private
idValue
:
(
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
:
25
,
right
:
20
,
bottom
:
20
,
left
:
35
};
}
protected
getDefaultContainerSize
():
{
width
:
number
;
height
:
number
;
}
{
return
{
width
:
600
,
height
:
400
};
}
protected
initVis
():
void
{
const
vis
=
this
;
vis
.
colorScale
=
d3
.
scaleOrdinal
()
.
range
([
'#d3eecd'
,
'#7bc77e'
,
'#2a8d46'
])
// light green to dark green
.
domain
([
'Easy'
,
'Intermediate'
,
'Difficult'
]);
vis
.
xScale
=
d3
.
scaleLinear
()
.
range
([
0
,
vis
.
width
]);
vis
.
yScale
=
d3
.
scaleLinear
()
.
range
([
vis
.
height
,
0
]);
// Initialize axes
vis
.
xAxis
=
d3
.
axisBottom
(
vis
.
xScale
)
.
ticks
(
6
)
.
tickSize
(
-
vis
.
height
-
10
)
.
tickPadding
(
10
)
.
tickFormat
(
d
=>
d
+
' km'
);
vis
.
yAxis
=
d3
.
axisLeft
(
vis
.
yScale
)
.
ticks
(
6
)
.
tickSize
(
-
vis
.
width
-
10
)
.
tickPadding
(
10
);
// Append empty x-axis group and move it to the bottom of the chart
vis
.
xAxisG
=
vis
.
chart
.
append
(
'g'
)
.
attr
(
'class'
,
'axis x-axis'
)
.
attr
(
'transform'
,
`translate(0,
${
vis
.
height
}
)`
);
// Append y-axis group
vis
.
yAxisG
=
vis
.
chart
.
append
(
'g'
)
.
attr
(
'class'
,
'axis y-axis'
);
// Append both axis titles
vis
.
chart
.
append
(
'text'
)
.
attr
(
'class'
,
'axis-title'
)
.
attr
(
'y'
,
vis
.
height
-
15
)
.
attr
(
'x'
,
vis
.
width
+
10
)
.
attr
(
'dy'
,
'.71em'
)
.
style
(
'text-anchor'
,
'end'
)
.
text
(
'Distance'
);
vis
.
svg
.
append
(
'text'
)
.
attr
(
'class'
,
'axis-title'
)
.
attr
(
'x'
,
0
)
.
attr
(
'y'
,
0
)
.
attr
(
'dy'
,
'.71em'
)
.
text
(
'Hours'
);
}
public
updateVis
():
void
{
let
vis
=
this
;
// Specificy accessor functions
vis
.
colorValue
=
d
=>
d
.
difficulty
;
vis
.
xValue
=
d
=>
d
.
time
;
vis
.
yValue
=
d
=>
d
.
distance
;
// Set the scale input domains
vis
.
xScale
.
domain
([
0
,
d3
.
max
(
vis
.
data
,
vis
.
xValue
)]);
vis
.
yScale
.
domain
([
0
,
d3
.
max
(
vis
.
data
,
vis
.
yValue
)]);
vis
.
renderVis
();
}
protected
renderVis
()
{
let
vis
=
this
;
vis
.
idValue
=
(
d
:
any
)
=>
d
.
trail
;
// Bind data to circles
const
circles
=
vis
.
chart
.
selectAll
(
'.point'
)
.
data
(
vis
.
data
,
(
d
:
any
)
=>
vis
.
idValue
(
d
));
// Enter phase
const
circlesEnter
=
circles
.
enter
()
.
append
(
'circle'
)
.
attr
(
'class'
,
'point'
)
.
attr
(
'r'
,
4
)
.
attr
(
'fill'
,
(
d
:
any
)
=>
vis
.
colorScale
(
vis
.
colorValue
(
d
)))
.
attr
(
'cy'
,
vis
.
yScale
(
0
))
// Start from y=0
.
attr
(
'cx'
,
(
d
:
any
)
=>
vis
.
xScale
(
vis
.
xValue
(
d
)));
circlesEnter
.
transition
()
.
duration
(
1000
)
.
attr
(
'cy'
,
(
d
:
any
)
=>
vis
.
yScale
(
vis
.
yValue
(
d
)));
// Animate to the final position
// Update phase
circlesEnter
.
merge
(
circles
)
.
transition
()
.
duration
(
1000
)
.
attr
(
'cy'
,
(
d
:
any
)
=>
vis
.
yScale
(
vis
.
yValue
(
d
)))
.
attr
(
'cx'
,
(
d
:
any
)
=>
vis
.
xScale
(
vis
.
xValue
(
d
)))
.
attr
(
'fill'
,
(
d
:
any
)
=>
vis
.
colorScale
(
vis
.
colorValue
(
d
)));
// Exit phase: remove circles that no longer have data
circles
.
exit
()
.
transition
()
.
duration
(
1000
)
.
attr
(
'r'
,
0
)
.
remove
();
// Update the axes/gridlines
vis
.
xAxisG
.
call
(
vis
.
xAxis
)
.
call
((
g
:
any
)
=>
g
.
select
(
'.domain'
).
remove
());
vis
.
yAxisG
.
call
(
vis
.
yAxis
)
.
call
((
g
:
any
)
=>
g
.
select
(
'.domain'
).
remove
());
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment