diff --git a/client/src/components/Features/Features.tsx b/client/src/components/Features/Features.tsx
index 0e1d3c5c1..4643423b8 100644
--- a/client/src/components/Features/Features.tsx
+++ b/client/src/components/Features/Features.tsx
@@ -116,7 +116,7 @@ const Features = () => {
@@ -128,7 +128,7 @@ const Features = () => {
diff --git a/client/src/components/Footer/Footer.tsx b/client/src/components/Footer/Footer.tsx
index d0ffd9430..32e3854b8 100644
--- a/client/src/components/Footer/Footer.tsx
+++ b/client/src/components/Footer/Footer.tsx
@@ -34,7 +34,7 @@ const Footer = () => {
Information
-
+
GitHub Repository
@@ -61,25 +61,20 @@ const Footer = () => {
Social
-
- CSESoc Website
+
+ DevSoc Website
-
+
Facebook
-
-
- YouTube
-
-
- © {new Date().getFullYear()} — CSESoc UNSW
+ © {new Date().getFullYear()} — Software Development Society (DevSoc)
);
diff --git a/client/src/components/Visualiser/VisualiserCanvas.tsx b/client/src/components/Visualiser/VisualiserCanvas.tsx
index 110ce83ee..f7367023d 100644
--- a/client/src/components/Visualiser/VisualiserCanvas.tsx
+++ b/client/src/components/Visualiser/VisualiserCanvas.tsx
@@ -1,4 +1,4 @@
-import React, { useState } from 'react';
+import React, { PointerEvent, useEffect, useRef, useState } from 'react';
import { Box } from '@mui/material';
import { styled } from '@mui/material/styles';
@@ -19,6 +19,10 @@ const ZoomableSvg = styled('svg')(({ scale }) => ({
*/
const VisualiserCanvas: React.FC = () => {
const [scale, setScale] = useState(1);
+ const svgRef = useRef(null);
+ const [height, setHeight] = useState(1000);
+ const [width, setWidth] = useState(1000);
+
const ZOOM_SPEED = 0.05;
const MAX_SCALE = 2;
const MIN_SCALE = 0.5;
@@ -30,6 +34,65 @@ const VisualiserCanvas: React.FC = () => {
}
};
+ const [isPointerDown, setIsPointerDown] = useState(false);
+
+ const [pointerOrigin, setPointerOrigin] = useState({
+ x: 0,
+ y: 0,
+ });
+
+ const handlePointerDown = (event: PointerEvent) => {
+ setIsPointerDown(true);
+
+ setPointerOrigin({
+ x: event.clientX,
+ y: event.clientY,
+ });
+ };
+
+ const [viewBox, setViewBox] = useState({
+ x: 0,
+ y: 0,
+ });
+
+ const [newViewBox, setNewViewBox] = useState({
+ x: 0,
+ y: 0,
+ });
+
+ const handlePointerMove = (event: PointerEvent) => {
+ if (!isPointerDown) {
+ return;
+ }
+
+ event.preventDefault();
+
+ // Ensure x is between -width and width and y is between -height and height
+ setNewViewBox({
+ x: Math.min(width, Math.max(-width, viewBox.x - (event.clientX - pointerOrigin.x))),
+ y: Math.min(height, Math.max(-height, viewBox.y - (event.clientY - pointerOrigin.y))),
+ });
+ };
+
+ const handlePointerUp = () => {
+ setIsPointerDown(false);
+
+ setViewBox({
+ x: newViewBox.x,
+ y: newViewBox.y,
+ });
+ };
+
+ useEffect(() => {
+ setHeight(svgRef.current.clientHeight);
+ setWidth(svgRef.current.clientWidth);
+ setViewBox((prevViewBox) => ({
+ ...prevViewBox,
+ height,
+ width,
+ }));
+ }, []);
+
return (
{
margin="auto"
height="100vh"
width={window.screen.width}
+ onPointerDown={handlePointerDown}
+ onPointerUp={handlePointerUp}
+ onPointerMove={handlePointerMove}
+ onPointerLeave={handlePointerUp}
>
-
+
);
};