-
Notifications
You must be signed in to change notification settings - Fork 350
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add keyboard controls to angle graphs (#1472)
This PR makes it so angle graph questions can be solved with only a keyboard - no mouse required! There are several tricky constraints to this problem: - Every distinct state of the graph needs to be reachable using only the keyboard. - In order for the movement to feel natural, pressing an arrow key should always move the point in the corresponding direction: up, down, left, or right. - However, the points need to snap, not to a grid, but to angle measures (in degrees). - The side points of the angle should not be allowed to get too close to the vertex - if they overlap the vertex there's no way to drag them away again. - The points shouldn't be able to move outside the graph bounds - It should never be possible for an edge point to get "stuck" or blocked in its movement by the edge of the graph, or by the angle vertex. I believe this PR solves for all these constraints. To make it work, I had to do a few slightly weird things: - I constrained the movement of the vertex so no part of the angle-measure arc can go outside the graph bounds. This ensures that all the control points of the angle can always be placed onscreen, and prevents the side points from getting stuck on the edges of the graph. - I reworked the interface of `useDraggable`, renaming `constrain` to `constrainKeyboardMovement`. Movement constraints for dragging are now implemented entirely in the reducer. (They were almost all in the reducer before; circles were the only graph type that still depended on the constrain function for dragging.) - I also introduced a new type of `useDraggable` constraint, where the destination points for the up, left, right, and down arrows are listed explicitly. I think this ultimately makes the code clearer. It's also more efficient (since useDraggable does not have to do a bunch of repeated trig calculations to search for valid destination points). Issue: https://khanacademy.atlassian.net/browse/LEMS-2134 ## Test plan: View `/?path=/story/perseus-widgets-interactive-graph--angle-with-mafs` in Storybook. Try to break the graph. Author: benchristel Reviewers: benchristel, SonicScrewdriver, mark-fitzgerald, Myranae, nicolecomputer, nishasy Required Reviewers: Approved By: SonicScrewdriver Checks: ✅ codecov/project, ✅ codecov/patch, ✅ Upload Coverage (ubuntu-latest, 20.x), ✅ Publish npm snapshot (ubuntu-latest, 20.x), ✅ Lint, Typecheck, Format, and Test (ubuntu-latest, 20.x), ✅ Cypress (ubuntu-latest, 20.x), ✅ Jest Coverage (ubuntu-latest, 20.x), ✅ Check builds for changes in size (ubuntu-latest, 20.x), ✅ Check for .changeset entries for all changed files (ubuntu-latest, 20.x), ✅ Publish Storybook to Chromatic (ubuntu-latest, 20.x), ✅ gerald Pull Request URL: #1472
- Loading branch information
1 parent
b8a342c
commit 4c2ace5
Showing
21 changed files
with
505 additions
and
129 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@khanacademy/perseus": minor | ||
--- | ||
|
||
Add keyboard controls to Mafs angle graphs |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
69 changes: 69 additions & 0 deletions
69
packages/perseus/src/widgets/interactive-graphs/graphs/angle.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
import {getAngleSideConstraint} from "./angle"; | ||
|
||
import type {vec} from "mafs"; | ||
|
||
function closeTo(x: number) { | ||
return expect.closeTo(x, 6); | ||
} | ||
|
||
describe("getAngleSideConstraint", () => { | ||
it("prevents vertical movement given a vertical side of an angle", () => { | ||
const side: vec.Vector2 = [0, 5]; | ||
const vertex: vec.Vector2 = [0, 0]; | ||
const snapDegrees = 45; | ||
|
||
const constraint = getAngleSideConstraint(side, vertex, snapDegrees); | ||
|
||
expect(constraint).toEqual({ | ||
up: side, | ||
down: side, | ||
left: [closeTo(-5), 5], | ||
right: [closeTo(5), 5], | ||
}); | ||
}); | ||
|
||
it("prevents horizontal movement given a horizontal side of an angle", () => { | ||
const side: vec.Vector2 = [5, 0]; | ||
const vertex: vec.Vector2 = [0, 0]; | ||
const snapDegrees = 45; | ||
|
||
const constraint = getAngleSideConstraint(side, vertex, snapDegrees); | ||
|
||
expect(constraint).toEqual({ | ||
up: [5, closeTo(5)], | ||
down: [5, closeTo(-5)], | ||
left: side, | ||
right: side, | ||
}); | ||
}); | ||
|
||
it("assigns the correct points to 'left' and 'right' when the side is pointing down", () => { | ||
const side: vec.Vector2 = [0, -5]; | ||
const vertex: vec.Vector2 = [0, 0]; | ||
const snapDegrees = 45; | ||
|
||
const constraint = getAngleSideConstraint(side, vertex, snapDegrees); | ||
|
||
expect(constraint).toEqual({ | ||
up: side, | ||
down: side, | ||
left: [closeTo(-5), -5], | ||
right: [closeTo(5), -5], | ||
}); | ||
}); | ||
|
||
it("assigns the correct points to 'up' and 'down' when the side is pointing left", () => { | ||
const side: vec.Vector2 = [-5, 0]; | ||
const vertex: vec.Vector2 = [0, 0]; | ||
const snapDegrees = 45; | ||
|
||
const constraint = getAngleSideConstraint(side, vertex, snapDegrees); | ||
|
||
expect(constraint).toEqual({ | ||
up: [-5, closeTo(5)], | ||
down: [-5, closeTo(-5)], | ||
left: side, | ||
right: side, | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.