Skip to content

Commit 506fc8b

Browse files
authored
Merge pull request #49 from EarthyScience/Plot-Axis-Scaler
Implement-sperate scaling of the axis'
2 parents 1c50b56 + 953e6dc commit 506fc8b

File tree

8 files changed

+156
-16
lines changed

8 files changed

+156
-16
lines changed

src/components/PlotObjects/FixedTicks.tsx

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ interface FixedTicksProps {
1818
fontSize?: number;
1919
showGrid?: boolean;
2020
gridOpacity?: number;
21-
height:number
21+
height:number,
22+
yScale:number,
23+
xScale:number,
2224
}
2325

2426
export function FixedTicks({
@@ -27,7 +29,9 @@ export function FixedTicks({
2729
fontSize = 18,
2830
showGrid = true,
2931
gridOpacity = 0.5,
30-
height
32+
height,
33+
yScale = 1,
34+
xScale=1,
3135
}: FixedTicksProps) {
3236
const { camera } = useThree()
3337
const [bounds, setBounds] = useState<ViewportBounds>({ left: 0, right: 0, top: 0, bottom: 0 })
@@ -143,7 +147,7 @@ export function FixedTicks({
143147
if (i === 0 || i === xTickCount-1) return null; // Skip edges
144148
const x = Math.round(bounds.left / stickyLines) * stickyLines +
145149
(Math.round(bounds.right / stickyLines) *stickyLines - Math.round(bounds.left / stickyLines) * stickyLines) * (i / (xTickCount-1))
146-
const normX = x/(initialBounds.right - initialBounds.left)+.5;
150+
const normX = x/xScale/(initialBounds.right - initialBounds.left)+.5;
147151
const y = vertY
148152
return (
149153
<>
@@ -201,7 +205,7 @@ export function FixedTicks({
201205
{Array.from({ length: yTickCount }, (_, i) => {
202206
if (i === 0 || i === yTickCount-1) return null; // Skip edges
203207
const y = (bounds.bottom + (bounds.top - bounds.bottom) * (i / (yTickCount-1)))
204-
const normY = (y/(bounds.top - bounds.bottom)/zoom)+.5
208+
const normY = (y/yScale/(bounds.top - bounds.bottom)/zoom)+.5
205209
const x = horX
206210
return (
207211
<>
@@ -246,7 +250,7 @@ export function FixedTicks({
246250
anchorY="middle"
247251
>
248252
{(yRange[0]+(normY*yDimSize)).toFixed(1)}
249-
{/* {normY.toFixed(1)} */}
253+
250254
</Text>
251255
)}
252256
</group>

src/components/PlotObjects/PlotArea/PlotArea.tsx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { parseLoc } from '@/utils/HelperFuncs'
33
import { PlotLine, FixedTicks } from '@/components/PlotObjects'
44
import { useContext, useEffect, useState } from 'react'
55
import { plotContext } from '@/components/Contexts'
6-
import { ResizeBar } from '@/components/UI'
6+
import { ResizeBar, YScaler,XScaler } from '@/components/UI'
77
import './PlotArea.css'
88

99
interface pointInfo{
@@ -53,6 +53,9 @@ export function PlotArea() {
5353
const [showPointInfo,setShowPointInfo] = useState<boolean>(false)
5454
const [height, setHeight] = useState<number>(Math.round(window.innerHeight-(window.innerHeight*0.15)-48))
5555

56+
const [yScale,setYScale] = useState<number>(1)
57+
const [xScale,setXScale] = useState<number>(1)
58+
5659
const pointSetters ={
5760
setPointID,
5861
setPointLoc,
@@ -73,13 +76,15 @@ export function PlotArea() {
7376
>
7477
<PointInfo pointID={pointID} pointLoc={pointLoc} showPointInfo={showPointInfo} />
7578
<ResizeBar height={height} setHeight={setHeight}/>
79+
<YScaler scale={yScale} setScale={setYScale} />
80+
<XScaler scale={xScale} setScale={setXScale} />
7681
<Canvas
7782
orthographic
7883
camera={{ position: [0, 0, 40] }}
7984
frameloop="demand"
8085
>
81-
<PlotLine height={height} pointSetters={pointSetters}/>
82-
<FixedTicks height={height}/>
86+
<PlotLine height={height} pointSetters={pointSetters} yScale={yScale} xScale={xScale}/>
87+
<FixedTicks height={height} yScale={yScale} xScale={xScale}/>
8388
</Canvas>
8489
{ //Only show coords when coords exist
8590
coords && coords.first.name !== 'Default' &&

src/components/PlotObjects/PlotLine.tsx

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@ interface PlotLineProps {
1313
pointColor?: string;
1414
interpolation?: 'linear' | 'curved';
1515
height:number,
16-
pointSetters:pointSetters
16+
pointSetters:pointSetters,
17+
yScale:number,
18+
xScale:number
1719
}
1820

1921
interface pointSetters{
@@ -104,10 +106,12 @@ export const PlotLine = ({
104106
lineWidth = 5,
105107
showPoints = true,
106108
pointSize = 5,
107-
pointColor = "white",
109+
pointColor = "#777777",
108110
interpolation = 'linear',
109111
height,
110-
pointSetters
112+
pointSetters,
113+
yScale,
114+
xScale
111115
}: PlotLineProps) => {
112116

113117
const {scaling, timeSeries} = useContext(plotContext)
@@ -129,11 +133,11 @@ export const PlotLine = ({
129133
if (!data || data.length === 0) return [[new THREE.Vector3(0,0,0)],[0]];
130134
const viewWidth = window.innerWidth;
131135
const viewHeight = (window.innerHeight-height-50); //The 50 here is the footer at the bottom
132-
const xCoords = linspace(-viewWidth/2,viewWidth/2,data.length)
136+
const xCoords = linspace(-viewWidth*xScale/2,viewWidth*xScale/2,data.length)
133137
const normed = data.map((i) => (i - minVal) / (maxVal - minVal));
134-
const points = normed.map((val,idx) => new THREE.Vector3(xCoords[idx], (val-.5)*viewHeight, 5));
138+
const points = normed.map((val,idx) => new THREE.Vector3(xCoords[idx], (val-.5)*viewHeight*yScale, 5));
135139
return [points,normed]
136-
}, [data, interpolation, height])
140+
}, [data, interpolation, height, yScale,xScale])
137141

138142
const geometry = useMemo(() => {
139143
if (!data || data.length === 0) return null;

src/components/UI/ResizeBar.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
position: fixed;
33
width: 100vw;
44
height: 10px;
5-
z-index: 11;
5+
z-index: 5;
66
cursor: n-resize;
77
background-color: transparent;
88
}

src/components/UI/Scalers.css

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
.yScaler{
2+
z-index: 5;
3+
position: absolute;
4+
right: 0%;
5+
height: 100%;
6+
background-color: transparent;
7+
width: 40px;
8+
cursor: n-resize;
9+
}
10+
11+
.xScaler{
12+
z-index:5;
13+
position: absolute;
14+
top: 10px;
15+
width: 100%;
16+
height: 20px;
17+
background-color: transparent;
18+
cursor: ew-resize;
19+
}

src/components/UI/XScaler.tsx

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import './Scalers.css'
2+
import { useEffect, useState, useRef } from 'react';
3+
4+
const XScaler = ({scale,setScale}:{scale:number,setScale:React.Dispatch<React.SetStateAction<number>>}) => {
5+
6+
const [isResizing, setIsResizing] = useState<boolean>(false);
7+
const initialPosition = useRef<number | null>(null)
8+
9+
// Start resizing on mousedown
10+
const handleMouseDown = (e: React.MouseEvent<HTMLDivElement>) => {
11+
e.preventDefault(); // Prevent text selection
12+
setIsResizing(true);
13+
initialPosition.current = e.clientY // Record starting height
14+
};
15+
16+
// Adjust height on mousemove
17+
const handleMouseMove = (e: MouseEvent) => {
18+
if (isResizing) {
19+
e.preventDefault();
20+
const sizeDelta = initialPosition.current ? (initialPosition.current - e.clientX)/1000 : 0
21+
setScale(Math.min(Math.max(scale+sizeDelta,0.1),2))
22+
}
23+
};
24+
25+
// Stop resizing on mouseup
26+
const handleMouseUp = () => {
27+
setIsResizing(false);
28+
};
29+
30+
// Add/remove document event listeners based on resizing state
31+
useEffect(() => {
32+
if (isResizing) {
33+
document.addEventListener('mousemove', handleMouseMove);
34+
document.addEventListener('mouseup', handleMouseUp);
35+
}
36+
return () => {
37+
document.removeEventListener('mousemove', handleMouseMove);
38+
document.removeEventListener('mouseup', handleMouseUp);
39+
};
40+
}, [isResizing]);
41+
42+
return (
43+
<div className='xScaler'
44+
onMouseDown={handleMouseDown}
45+
onMouseUp={handleMouseUp}
46+
/>
47+
48+
)
49+
}
50+
51+
export default XScaler

src/components/UI/YScaler.tsx

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import './Scalers.css'
2+
import { useEffect, useState, useRef } from 'react';
3+
4+
const YScaler = ({scale,setScale}:{scale:number,setScale:React.Dispatch<React.SetStateAction<number>>}) => {
5+
6+
const [isResizing, setIsResizing] = useState<boolean>(false);
7+
const initialPosition = useRef<number | null>(null)
8+
// Start resizing on mousedown
9+
const handleMouseDown = (e: React.MouseEvent<HTMLDivElement>) => {
10+
e.preventDefault(); // Prevent text selection
11+
setIsResizing(true);
12+
initialPosition.current = e.clientY // Record starting height
13+
};
14+
15+
// Adjust height on mousemove
16+
const handleMouseMove = (e: MouseEvent) => {
17+
if (isResizing) {
18+
e.preventDefault();
19+
const sizeDelta = initialPosition.current ? (initialPosition.current - e.clientY)/100 : 0
20+
setScale(Math.min(Math.max(scale+sizeDelta,0.1),10))
21+
}
22+
};
23+
24+
// Stop resizing on mouseup
25+
const handleMouseUp = () => {
26+
setIsResizing(false);
27+
};
28+
29+
// Add/remove document event listeners based on resizing state
30+
useEffect(() => {
31+
if (isResizing) {
32+
document.addEventListener('mousemove', handleMouseMove);
33+
document.addEventListener('mouseup', handleMouseUp);
34+
}
35+
return () => {
36+
document.removeEventListener('mousemove', handleMouseMove);
37+
document.removeEventListener('mouseup', handleMouseUp);
38+
};
39+
}, [isResizing]);
40+
41+
return (
42+
<div className='yScaler'
43+
onMouseDown={handleMouseDown}
44+
onMouseUp={handleMouseUp}
45+
46+
>
47+
48+
</div>
49+
)
50+
}
51+
52+
export default YScaler

src/components/UI/index.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,16 @@ import CanvasGeometry from "../CanvasGeometry";
44
import AboutButton from "./AboutButton";
55
import Metadata from "./MetaData";
66
import ResizeBar from "./ResizeBar";
7+
import YScaler from "./YScaler";
8+
import XScaler from "./XScaler";
9+
710
export {
811
Navbar,
912
Footer,
1013
CanvasGeometry,
1114
AboutButton,
1215
Metadata,
13-
ResizeBar
16+
ResizeBar,
17+
YScaler,
18+
XScaler
1419
};

0 commit comments

Comments
 (0)