-
Notifications
You must be signed in to change notification settings - Fork 107
Open
Labels
bugsomething isn't workingsomething isn't workingui-uxsubpar user interface or user experiencesubpar user interface or user experience
Description
If you move the focus point with the arrow keys, pressing right/down individually will keep the focus point on-screen, but if you press both at once, it can escape the view.
The relevant code is:
Lines 2156 to 2253 in 1203391
| if (this.in_mode(UIMode.Default)) { | |
| // Reveal the focus point if it wasn't already visible. | |
| if (!this.focus_point.class_list.contains("focused")) { | |
| this.focus_point.class_list.remove("revealed", "pending", "active"); | |
| this.focus_point.class_list.add("focused"); | |
| this.toolbar.update(this); | |
| // We first reposition to the correct location, then add the delta after adding | |
| // the `smooth` class (directly below), so that it animates to the new position. | |
| this.reposition_focus_point(this.focus_position); | |
| delay(() => { | |
| this.focus_point.class_list.add("smooth"); | |
| this.reposition_focus_point(this.focus_position.add(position_delta)); | |
| }); | |
| } else { | |
| this.reposition_focus_point(this.focus_position.add(position_delta)); | |
| } | |
| this.update_focus_tooltip(); | |
| // Reposition the view if the focus point is not complete in-view. | |
| const offset = this.offset_from_position(this.focus_position); | |
| const width = this.cell_size(this.cell_width, this.focus_position.x); | |
| const height = this.cell_size(this.cell_height, this.focus_position.y); | |
| const view = new Dimensions( | |
| document.body.offsetWidth / 2 ** this.scale, | |
| document.body.offsetHeight / 2 ** this.scale, | |
| ).sub(Dimensions.diag(CONSTANTS.VIEW_PADDING * 2)); | |
| const pan = Offset.zero(); | |
| // We only adjust in the direction of movement, to avoid issues with edge cases, | |
| // e.g. where the height of the screen is too small, which can cause panning | |
| // vertically back and forth with each key press. | |
| if (position_delta.x !== 0) { | |
| // Left. | |
| pan.x += Math.min(offset.x - (this.view.x - view.width / 2), 0); | |
| // Right. | |
| pan.x += Math.max(offset.x + width - (this.view.x + view.width / 2), 0); | |
| } | |
| if (position_delta.y !== 0) { | |
| // Top. | |
| pan.y += Math.min(offset.y - (this.view.y - view.height / 2), 0); | |
| // Bottom. | |
| pan.y += Math.max(offset.y + height - (this.view.y + view.height / 2), 0); | |
| } | |
| const start = performance.now(); | |
| const view_origin = new Offset(this.view.x, this.view.y); | |
| // We want to transition the view smoothly. We can animate the offset with CSS, but | |
| // the grid is drawn using a <canvas> and so must be updated manually. | |
| const partial_pan = () => { | |
| requestAnimationFrame(() => { | |
| // The panning animation lasts for 0.1 seconds. | |
| const x | |
| = Math.max(Math.min((performance.now() - start) / (1000 * 0.1), 1), 0); | |
| // The definition of the `ease` transition duration in CSS, which is the | |
| // default transition and the one we use. | |
| const ease = new CubicBezier( | |
| Point.zero(), | |
| new Point(0.25, 0.1), | |
| new Point(0.25, 1.0), | |
| Point.diag(1), | |
| ); | |
| // Do a binary search to find the value of `t` corresponding to the x | |
| // co-ordinate `x`. The value of `p.y` thereat is the distance through the | |
| // animation. | |
| let p; | |
| let [min, max] = [ease.point(0), ease.point(1)]; | |
| if (x === 0) { | |
| p = min; | |
| } else if (x === 1) { | |
| p = max; | |
| } else if (x > 0 && x < 1) { | |
| const EPSILON = 0.01; | |
| const BAIL_OUT = 128; | |
| let i = 0; | |
| while (true) { | |
| p = ease.point((max.t + min.t) / 2); | |
| if (p.x === x || max.t - min.t <= EPSILON || ++i >= BAIL_OUT) { | |
| break; | |
| } | |
| if (x > p.x) { | |
| min = p; | |
| } | |
| if (x < p.x) { | |
| max = p; | |
| } | |
| } | |
| } | |
| this.pan_to(view_origin.add(pan.mul(p.y))); | |
| if (x < 1) { | |
| partial_pan(); | |
| } | |
| }) | |
| }; | |
| partial_pan(); | |
| } |
Metadata
Metadata
Assignees
Labels
bugsomething isn't workingsomething isn't workingui-uxsubpar user interface or user experiencesubpar user interface or user experience