Add zoom in and zoom out buttons for those without scale gestures

This commit is contained in:
Patrick Walton 2017-09-10 13:17:24 -07:00
parent ce855cc0ff
commit 65e3278e94
6 changed files with 93 additions and 12 deletions

View File

@ -13,6 +13,16 @@
<div class="fixed-bottom mb-3 d-flex justify-content-between align-items-end pf-pointer-events-none">
<div class="rounded py-1 px-3 ml-3" id="pf-fps-label">0 ms</div>
<div id="pf-toolbar">
<div class="btn-group" role="group" aria-label="Zoom">
<button id="pf-zoom-out-button" type="button"
class="btn btn-outline-secondary pf-toolbar-button">
{{octicon "dash"}}
</button>
<button id="pf-zoom-in-button" type="button"
class="btn btn-outline-secondary pf-toolbar-button">
{{octicon "plus"}}
</button>
</div>
<button id="pf-screenshot-button" type="button"
class="btn btn-outline-secondary pf-toolbar-button">
{{octicon "device-camera"}}

View File

@ -12,6 +12,16 @@
<div class="fixed-bottom mb-3 d-flex justify-content-between align-items-end pf-pointer-events-none">
<div class="rounded py-1 px-3 ml-3" id="pf-fps-label">0 ms</div>
<div id="pf-toolbar">
<div class="btn-group" role="group" aria-label="Zoom">
<button id="pf-zoom-out-button" type="button"
class="btn btn-outline-secondary pf-toolbar-button">
{{octicon "dash"}}
</button>
<button id="pf-zoom-in-button" type="button"
class="btn btn-outline-secondary pf-toolbar-button">
{{octicon "plus"}}
</button>
</div>
<button id="pf-screenshot-button" type="button"
class="btn btn-outline-secondary pf-toolbar-button">
{{octicon "device-camera"}}

View File

@ -83,6 +83,22 @@ export abstract class DemoAppController<View extends PathfinderDemoView> extends
}, false);
}
const zoomInButton = document.getElementById('pf-zoom-in-button') as HTMLButtonElement |
null;
if (zoomInButton != null) {
zoomInButton.addEventListener('click', () => {
this.view.then(view => view.zoomIn());
}, false);
}
const zoomOutButton = document.getElementById('pf-zoom-out-button') as HTMLButtonElement |
null;
if (zoomOutButton != null) {
zoomOutButton.addEventListener('click', () => {
this.view.then(view => view.zoomOut());
}, false);
}
this.filePickerElement = document.getElementById('pf-file-select') as
(HTMLInputElement | null);
if (this.filePickerElement != null) {

View File

@ -13,6 +13,9 @@ import {PathfinderView} from "./view";
const ORTHOGRAPHIC_ZOOM_SPEED: number = 1.0 / 100.0;
const ZOOM_IN_FACTOR: number = 1.2;
const ZOOM_OUT_FACTOR: number = 1.0 / ZOOM_IN_FACTOR;
const PERSPECTIVE_MOVEMENT_SPEED: number = 10.0;
const PERSPECTIVE_ROTATION_SPEED: number = 1.0 / 300.0;
@ -25,6 +28,9 @@ export abstract class Camera {
this.canvas = canvas;
}
abstract zoomIn(): void;
abstract zoomOut(): void;
protected canvas: HTMLCanvasElement;
}
@ -52,17 +58,9 @@ export class OrthographicCamera extends Camera {
mouseLocation[1] = canvasLocation.bottom - mouseLocation[1];
glmatrix.vec2.scale(mouseLocation, mouseLocation, window.devicePixelRatio);
const absoluteTranslation = glmatrix.vec2.create();
glmatrix.vec2.sub(absoluteTranslation, this.translation, mouseLocation);
glmatrix.vec2.scale(absoluteTranslation, absoluteTranslation, 1.0 / this.scale);
const scale = 1.0 - event.deltaY * window.devicePixelRatio * ORTHOGRAPHIC_ZOOM_SPEED;
this.scale *= 1.0 - event.deltaY * window.devicePixelRatio * ORTHOGRAPHIC_ZOOM_SPEED;
glmatrix.vec2.scale(absoluteTranslation, absoluteTranslation, this.scale);
glmatrix.vec2.add(this.translation, absoluteTranslation, mouseLocation);
if (this.onZoom != null)
this.onZoom();
this.zoom(scale, mouseLocation);
} else {
// Pan event.
const delta = glmatrix.vec2.fromValues(-event.deltaX, event.deltaY);
@ -74,6 +72,32 @@ export class OrthographicCamera extends Camera {
}
}
zoomIn(): void {
this.zoom(ZOOM_IN_FACTOR, this.centerPoint);
}
zoomOut(): void {
this.zoom(ZOOM_OUT_FACTOR, this.centerPoint);
}
private zoom(scale: number, point: glmatrix.vec2): void {
const absoluteTranslation = glmatrix.vec2.create();
glmatrix.vec2.sub(absoluteTranslation, this.translation, point);
glmatrix.vec2.scale(absoluteTranslation, absoluteTranslation, 1.0 / this.scale);
this.scale *= scale;
glmatrix.vec2.scale(absoluteTranslation, absoluteTranslation, this.scale);
glmatrix.vec2.add(this.translation, absoluteTranslation, point);
if (this.onZoom != null)
this.onZoom();
}
private get centerPoint(): glmatrix.vec2 {
return glmatrix.vec2.fromValues(this.canvas.width * 0.5, this.canvas.height * 0.5);
}
onPan: (() => void) | null;
onZoom: (() => void) | null;
@ -149,6 +173,14 @@ export class PerspectiveCamera extends Camera {
return matrix;
}
zoomIn(): void {
// TODO(pcwalton)
}
zoomOut(): void {
// TODO(pcwalton)
}
onChange: (() => void) | null;
translation: glmatrix.vec3;

View File

@ -293,8 +293,13 @@ class TextDemoView extends MonochromePathfinderView {
rect[0], rect[1],
rect[2], rect[1],
], glyphIndex * 8);
glyphIndices.set(Array.from(QUAD_ELEMENTS).map(index => index + 4 * glyphIndex),
glyphIndex * 6);
for (let glyphIndexIndex = 0;
glyphIndexIndex < QUAD_ELEMENTS.length;
glyphIndexIndex++) {
glyphIndices[glyphIndexIndex + glyphIndex * 6] =
QUAD_ELEMENTS[glyphIndexIndex] + 4 * glyphIndex;
}
}
this.glyphPositionsBuffer = unwrapNull(this.gl.createBuffer());

View File

@ -88,6 +88,14 @@ export abstract class PathfinderView {
this.dirty = false;
}
zoomIn(): void {
this.camera.zoomIn();
}
zoomOut(): void {
this.camera.zoomOut();
}
protected canvas: HTMLCanvasElement;
protected camera: Camera;