aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlonkaars <loek@pipeframe.xyz>2021-07-27 17:08:33 +0200
committerlonkaars <loek@pipeframe.xyz>2021-07-27 17:08:33 +0200
commit1d71bf0c49693c9a896a653d9755e612ead8f6e4 (patch)
tree5c449e73462bf553083d1b1ab0a739b5993c8d37
parentbccd4a7e46d0c9470822e8bd4334abc92b5bf85f (diff)
better menu bar physics
-rw-r--r--components/controls.tsx95
1 files changed, 53 insertions, 42 deletions
diff --git a/components/controls.tsx b/components/controls.tsx
index b7df330..d544c6b 100644
--- a/components/controls.tsx
+++ b/components/controls.tsx
@@ -18,29 +18,35 @@ export function MenuBarControls({ next, previous, menu }: controlsPropsType) {
var canvasRef = useRef(null);
var options = {
- margin: 100, // screen margin
- friction: 0.0, // friction
- edgeForce: 1.0, // force outside margin (inwards to edges)
- centerForce: 0.6, // force inside margin (outwards to edges)
- maxForce: 50, // limit force to not go over this value
+ margin: 24, // screen margin
+ friction: 0.2, // friction
+ edgeForce: 0.4, // force outside margin (inwards to edges)
+ centerForce: 0.4, // force inside margin (outwards to edges)
+ maxForce: 10, // limit force to not go over this value
doneTolerance: 0.5, // if movement per frame goes below this value the animation is considered done
+ releaseSlopeAverageCount: 3,
};
+ var positionHistory: [number, number][] = [];
+ var slopeAverage: [number, number][] = [];
+
useEffect(() => {
var canvas = canvasRef.current as HTMLCanvasElement;
var ctx = canvas.getContext('2d');
- function line([x1, y1]: [number, number], [x2, y2]: [number, number]) {
- ctx.beginPath();
- ctx.moveTo(x1, y1);
- ctx.lineTo(x2, y2);
- ctx.stroke();
- }
+ var physicsObject = {
+ velocity: [0, 0],
+ position: [0, 0],
+ };
var mouseX = 0;
var mouseY = 0;
+ var mouseDown = false;
function draw() {
+ positionHistory.push([mouseX, mouseY]);
+ if (positionHistory.length >= options.releaseSlopeAverageCount + 1) positionHistory.shift();
+
var box = {
outer: {
x: 0,
@@ -86,57 +92,61 @@ export function MenuBarControls({ next, previous, menu }: controlsPropsType) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.lineWidth = 2;
- ctx.strokeStyle = '#ff00ff';
-
- var center = findCenter(mouseX, mouseY);
- var mouse = [mouseX, mouseY];
- // line(center, mouse as [ number, number ]);
+ var center = findCenter(physicsObject.position[0], physicsObject.position[1]);
+ var position = physicsObject.position;
- var slope = (mouse[1] - center[1]) / (mouse[0] - center[0]);
+ var slope = (position[1] - center[1]) / (position[0] - center[0]);
if (Math.abs(slope) < 1) {
- var right = mouse[0] > center[0];
+ var right = position[0] > center[0];
if (right) {
var x = box.inner.x + box.inner.width;
- var y = (x - mouseX) * slope + mouseY;
+ var y = (x - position[0]) * slope + position[1];
} else {
var x = box.inner.x;
- var y = (mouseX - x) * -slope + mouseY;
+ var y = (position[0] - x) * -slope + position[1];
}
} else {
- var slope = (mouse[0] - center[0]) / (mouse[1] - center[1]);
- var bottom = mouse[1] > center[1];
+ var slope = (position[0] - center[0]) / (position[1] - center[1]);
+ var bottom = position[1] > center[1];
if (bottom) {
var y = box.inner.y + box.inner.height;
- var x = (y - mouseY) * slope + mouseX;
+ var x = (y - position[1]) * slope + position[0];
} else {
var y = box.inner.y;
- var x = (mouseY - y) * -slope + mouseX;
+ var x = (position[1] - y) * -slope + position[0];
}
}
- var offset = [mouse[0] - x, mouse[1] - y];
- var outside = mouse[0] < box.inner.x
- || mouse[0] > box.inner.x + box.inner.width
- || mouse[1] < box.inner.y
- || mouse[1] > box.inner.y + box.inner.height;
+ var offset = [position[0] - x, position[1] - y];
+ var outside = position[0] < box.inner.x
+ || position[0] > box.inner.x + box.inner.width
+ || position[1] < box.inner.y
+ || position[1] > box.inner.y + box.inner.height;
offset = offset.map(o => o * options[outside ? 'edgeForce' : 'centerForce']);
var distance = Math.sqrt(offset[0] ** 2 + offset[1] ** 2);
offset = offset.map(o => o * -Math.min(1, options.maxForce / distance));
- ctx.strokeStyle = '#ff0000';
- line([mouseX + offset[0], mouseY + offset[1]], [mouseX, mouseY]);
+ if (mouseDown) {
+ physicsObject.position = [mouseX, mouseY];
+ for (let i = 1; i < positionHistory.length; i++) {
+ slopeAverage[i - 1] = [
+ positionHistory[i][0] - positionHistory[i - 1][0],
+ positionHistory[i][1] - positionHistory[i - 1][1],
+ ];
+ }
+ physicsObject.velocity[0] = slopeAverage.reduce((a, b) => a + b[0], 0) / slopeAverage.length;
+ physicsObject.velocity[1] = slopeAverage.reduce((a, b) => a + b[1], 0) / slopeAverage.length;
+ } else {
+ physicsObject.velocity[0] += offset[0];
+ physicsObject.velocity[1] += offset[1];
+ }
- ctx.strokeStyle = '#00ffff';
+ ctx.fillStyle = '#ff00ff';
+ ctx.fillRect(physicsObject.position[0], physicsObject.position[1], 10, 10);
- line([box.inner.x, box.inner.y], [box.inner.x + box.inner.width, box.inner.y]);
- line([box.inner.x + box.inner.width, box.inner.y + box.inner.height], [
- box.inner.x + box.inner.width,
- box.inner.y,
- ]);
- line([box.inner.x, box.inner.y + box.inner.height], [
- box.inner.x + box.inner.width,
- box.inner.y + box.inner.height,
- ]);
- line([box.inner.x, box.inner.y], [box.inner.x, box.inner.y + box.inner.height]);
+ physicsObject.position[0] += physicsObject.velocity[0];
+ physicsObject.position[1] += physicsObject.velocity[1];
+ physicsObject.velocity[0] *= 1 - options.friction;
+ physicsObject.velocity[1] *= 1 - options.friction;
requestAnimationFrame(draw);
}
@@ -151,6 +161,7 @@ export function MenuBarControls({ next, previous, menu }: controlsPropsType) {
canvas.addEventListener('mousemove', e => {
mouseX = e.clientX;
mouseY = e.clientY;
+ mouseDown = (e.buttons & (1 << 0)) > 0;
});
}, []);
return <div className='fullscreenControls posabs a0'>