UNPKG

3.42 kBPlain TextView Raw
1// Copyright 2019 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5import {Overlay} from './common.js';
6
7export type ScreenshotToolMessage = {
8 x: number,
9 y: number,
10 width: number,
11 height: number,
12};
13
14let anchor: {x: number, y: number}|null = null;
15let position: {x: number, y: number}|null = null;
16
17export class ScreenshotOverlay extends Overlay {
18 private zone!: HTMLElement;
19
20 constructor(window: Window, style: CSSStyleSheet[] = []) {
21 super(window, style);
22 this.onMouseDown = this.onMouseDown.bind(this);
23 this.onMouseUp = this.onMouseUp.bind(this);
24 this.onMouseMove = this.onMouseMove.bind(this);
25 this.onKeyDown = this.onKeyDown.bind(this);
26 }
27
28 install() {
29 const root = this.document.documentElement;
30 root.addEventListener('mousedown', this.onMouseDown, true);
31 root.addEventListener('mouseup', this.onMouseUp, true);
32 root.addEventListener('mousemove', this.onMouseMove, true);
33 root.addEventListener('keydown', this.onKeyDown, true);
34
35 const zone = this.document.createElement('div');
36 zone.id = 'zone';
37 this.document.body.append(zone);
38
39 this.zone = zone;
40
41 super.install();
42 }
43
44 uninstall() {
45 this.document.body.innerHTML = '';
46 const root = this.document.documentElement;
47 root.removeEventListener('mousedown', this.onMouseDown, true);
48 root.removeEventListener('mouseup', this.onMouseUp, true);
49 root.removeEventListener('mousemove', this.onMouseMove, true);
50 root.removeEventListener('keydown', this.onKeyDown, true);
51 super.uninstall();
52 }
53
54 onMouseDown(event: MouseEvent) {
55 anchor = {x: event.pageX, y: event.pageY};
56 position = anchor;
57 this.updateZone();
58 event.stopPropagation();
59 event.preventDefault();
60 }
61
62 onMouseUp(event: MouseEvent) {
63 if (anchor && position) {
64 const rect = currentRect();
65 if (rect.width >= 5 && rect.height >= 5) {
66 this.window.InspectorOverlayHost.send(rect);
67 }
68 }
69 cancel();
70 this.updateZone();
71 event.stopPropagation();
72 event.preventDefault();
73 }
74
75 onMouseMove(event: MouseEvent) {
76 if (anchor && event.buttons === 1) {
77 position = {x: event.pageX, y: event.pageY};
78 } else {
79 anchor = null;
80 }
81 this.updateZone();
82 event.stopPropagation();
83 event.preventDefault();
84 }
85
86 onKeyDown(event: KeyboardEvent) {
87 if (anchor && event.key === 'Escape') {
88 cancel();
89 this.updateZone();
90 event.stopPropagation();
91 event.preventDefault();
92 }
93 }
94
95 updateZone() {
96 const zone = this.zone;
97 if (!position || !anchor) {
98 zone.style.display = 'none';
99 return;
100 }
101 zone.style.display = 'block';
102 const rect = currentRect();
103 zone.style.left = rect.x + 'px';
104 zone.style.top = rect.y + 'px';
105 zone.style.width = rect.width + 'px';
106 zone.style.height = rect.height + 'px';
107 }
108}
109
110function currentRect() {
111 if (!anchor) {
112 throw new Error('Error calculating currentRect: no anchor was defined.');
113 }
114 if (!position) {
115 throw new Error('Error calculating currentRect: no position was defined.');
116 }
117 return {
118 x: Math.min(anchor.x, position.x),
119 y: Math.min(anchor.y, position.y),
120 width: Math.abs(anchor.x - position.x),
121 height: Math.abs(anchor.y - position.y),
122 };
123}
124
125function cancel() {
126 anchor = null;
127 position = null;
128}