• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (C) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16import {Graph} from "./Graph.js";
17import {Rect} from "./Rect.js";
18import {ns2s, TimerShaftElement} from "../TimerShaftElement.js";
19import {ColorUtils} from "../base/ColorUtils.js";
20import {CpuStruct} from "../../../bean/CpuStruct.js";
21
22const markPadding = 5;
23
24export class Mark extends Graph {
25    name: string | undefined
26    inspectionFrame: Rect
27    private _isHover: boolean = false
28
29    constructor(canvas: HTMLCanvasElement | undefined | null, name: string, c: CanvasRenderingContext2D, frame: Rect) {
30        super(canvas, c, frame);
31        this.name = name;
32        this.inspectionFrame = new Rect(frame.x - markPadding, frame.y, frame.width + markPadding * 2, frame.height)
33    }
34
35    get isHover(): boolean {
36        return this._isHover;
37    }
38
39    set isHover(value: boolean) {
40        this._isHover = value;
41        if (value) {
42            document.body.style.cursor = 'ew-resize'
43        } else {
44            document.body.style.cursor = 'default'
45        }
46    }
47
48    draw(): void {
49        this.c.beginPath();
50        this.c.lineWidth = 7
51        this.c.strokeStyle = '#999999'
52        this.c.moveTo(this.frame.x, this.frame.y);
53        this.c.lineTo(this.frame.x, this.frame.y + this.frame.height / 3)
54        this.c.stroke();
55        this.c.lineWidth = 1
56        this.c.strokeStyle = '#999999'
57        this.c.moveTo(this.frame.x, this.frame.y);
58        this.c.lineTo(this.frame.x, this.frame.y + this.frame.height)
59        this.c.stroke();
60        this.c.closePath();
61    }
62}
63
64export interface TimeRange {
65    slicesTime: {
66        color: string | null | undefined;
67        startTime: number | null | undefined;
68        endTime: number | null | undefined;
69    };
70    scale: number;
71    totalNS: number
72    startX: number
73    endX: number
74    startNS: number
75    endNS: number
76    xs: Array<number>
77    refresh: boolean
78    xsTxt: Array<string>
79}
80
81export class RangeRuler extends Graph {
82    public rangeRect: Rect
83    public markA: Mark
84    public markB: Mark
85    public range: TimeRange;
86    private pressedKeys: Array<string> = [];
87    mouseDownOffsetX = 0
88    mouseDownMovingMarkX = 0
89    movingMark: Mark | undefined | null;
90    isMouseDown: boolean = false;
91    isMovingRange: boolean = false;
92    isNewRange: boolean = false;
93    markAX: number = 0;
94    markBX: number = 0;
95    isPress: boolean = false
96    pressFrameIdW: number = -1
97    pressFrameIdS: number = -1
98    pressFrameIdA: number = -1
99    pressFrameIdD: number = -1
100    upFrameIdW: number = -1
101    upFrameIdS: number = -1
102    upFrameIdA: number = -1
103    upFrameIdD: number = -1
104    currentDuration: number = 0
105    cacheInterval: { interval: number, value: number, flag: boolean } = {
106        interval: 200,
107        value: 0,
108        flag: false
109    }
110    centerXPercentage: number = 0;
111    animaStartTime: number | undefined
112    p: number = 1000;
113    private readonly notifyHandler: (r: TimeRange) => void;
114    private scale: number = 0;
115    private delayTimer: any = null
116    //缩放级别
117    private scales: Array<number> = [50, 100, 200, 500, 1_000, 2_000, 5_000, 10_000, 20_000, 50_000, 100_000, 200_000, 500_000,
118        1_000_000, 2_000_000, 5_000_000, 10_000_000, 20_000_000, 50_000_000, 100_000_000, 200_000_000, 500_000_000,
119        1_000_000_000, 2_000_000_000, 5_000_000_000, 10_000_000_000, 20_000_000_000, 50_000_000_000,
120        100_000_000_000, 200_000_000_000, 500_000_000_000];
121    private _cpuUsage: Array<{ cpu: number, ro: number, rate: number }> = []
122
123    constructor(timerShaftEL: TimerShaftElement, frame: Rect, range: TimeRange, notifyHandler: (r: TimeRange) => void) {
124        super(timerShaftEL.canvas, timerShaftEL.ctx!, frame)
125        this.range = range;
126        this.notifyHandler = notifyHandler;
127        this.markA = new Mark(timerShaftEL.canvas, 'A', timerShaftEL.ctx!, new Rect(range.startX, frame.y, 1, frame.height))
128        this.markB = new Mark(timerShaftEL.canvas, 'B', timerShaftEL.ctx!, new Rect(range.endX, frame.y, 1, frame.height))
129        this.rangeRect = new Rect(range.startX, frame.y, range.endX - range.startX, frame.height)
130    }
131
132    set cpuUsage(value: Array<{ cpu: number, ro: number, rate: number }>) {
133        this._cpuUsage = value
134        this.draw();
135    }
136
137    drawCpuUsage() {
138        let maxNum = Math.round(this._cpuUsage.length / 100)
139        let miniHeight = Math.round(this.frame.height / CpuStruct.cpuCount);//每格高度
140        let miniWidth = Math.ceil(this.frame.width / 100);//每格宽度
141        for (let i = 0; i < this._cpuUsage.length; i++) {
142            let it = this._cpuUsage[i]
143            this.c.fillStyle = ColorUtils.MD_PALETTE[it.cpu]
144            this.c.globalAlpha = it.rate
145            this.c.fillRect(this.frame.x + miniWidth * it.ro, this.frame.y + it.cpu * miniHeight, miniWidth, miniHeight)
146        }
147    }
148
149    draw(discardNotify: boolean = false): void {
150        this.c.clearRect(this.frame.x - markPadding, this.frame.y, this.frame.width + markPadding * 2, this.frame.height)
151        this.c.beginPath();
152        if (this._cpuUsage.length > 0) {
153            this.drawCpuUsage()
154            this.c.globalAlpha = 0;
155        } else {
156            this.c.globalAlpha = 1;
157        }
158        //绘制选中区域
159        this.c.fillStyle = window.getComputedStyle(this.canvas!, null).getPropertyValue("background-color");//"#ffffff"
160        this.rangeRect.x = this.markA.frame.x < this.markB.frame.x ? this.markA.frame.x : this.markB.frame.x
161        this.rangeRect.width = Math.abs(this.markB.frame.x - this.markA.frame.x)
162        this.c.fillRect(this.rangeRect.x, this.rangeRect.y, this.rangeRect.width, this.rangeRect.height)
163        this.c.globalAlpha = 1;
164        this.c.globalAlpha = .5;
165        this.c.fillStyle = "#999999"
166        this.c.fillRect(this.frame.x, this.frame.y, this.rangeRect.x, this.rangeRect.height)
167        this.c.fillRect(this.rangeRect.x + this.rangeRect.width, this.frame.y, this.frame.width - this.rangeRect.width, this.rangeRect.height)
168        this.c.globalAlpha = 1;
169        this.c.closePath();
170        this.markA.draw();
171        this.markB.draw();
172        if (this.notifyHandler) {
173            this.range.startX = this.rangeRect.x
174            this.range.endX = this.rangeRect.x + this.rangeRect.width
175            this.range.startNS = this.range.startX * this.range.totalNS / (this.canvas?.clientWidth || 0)
176            this.range.endNS = this.range.endX * this.range.totalNS / (this.canvas?.clientWidth || 0)
177            let l20 = (this.range.endNS - this.range.startNS) / 20;
178            let min = 0;
179            let max = 0;
180            let weight = 0;
181            for (let index = 0; index < this.scales.length; index++) {
182                if (this.scales[index] > l20) {
183                    if (index > 0) {
184                        min = this.scales[index - 1];
185                    } else {
186                        min = 0;
187                    }
188                    max = this.scales[index];
189                    weight = (l20 - min) * 1.0 / (max - min);
190                    if (weight > 0.243) {
191                        this.scale = max;
192                    } else {
193                        this.scale = min;
194                    }
195                    break;
196                }
197            }
198            if (this.scale == 0) {
199                this.scale = this.scales[0];
200            }
201            let tmpNs = 0;
202            let yu = this.range.startNS % this.scale;
203            let realW = (this.scale * this.frame.width) / (this.range.endNS - this.range.startNS);
204            let startX = 0;
205            if (this.range.xs) {
206                this.range.xs.length = 0
207            } else {
208                this.range.xs = []
209            }
210            if (this.range.xsTxt) {
211                this.range.xsTxt.length = 0
212            } else {
213                this.range.xsTxt = []
214            }
215            this.range.scale = this.scale;
216            if (yu != 0) {
217                let firstNodeWidth = ((this.scale - yu) / this.scale * realW);
218                startX += firstNodeWidth;
219                tmpNs += yu;
220                this.range.xs.push(startX)
221                this.range.xsTxt.push(ns2s(tmpNs))
222            }
223            while (tmpNs < this.range.endNS - this.range.startNS) {
224                startX += realW;
225                tmpNs += this.scale;
226                this.range.xs.push(startX)
227                this.range.xsTxt.push(ns2s(tmpNs))
228            }
229
230            if (!discardNotify) {
231                this.notifyHandler(this.range)
232            }
233        }
234    }
235
236    mouseDown(ev: MouseEvent) {
237        let x = ev.offsetX - (this.canvas?.offsetLeft || 0)
238        let y = ev.offsetY - (this.canvas?.offsetTop || 0)
239        this.isMouseDown = true;
240        this.mouseDownOffsetX = x;
241        if (this.markA.isHover) {
242            this.movingMark = this.markA;
243            this.mouseDownMovingMarkX = this.movingMark.frame.x || 0
244        } else if (this.markB.isHover) {
245            this.movingMark = this.markB;
246            this.mouseDownMovingMarkX = this.movingMark.frame.x || 0
247        } else {
248            this.movingMark = null;
249        }
250        if (this.rangeRect.containsWithPadding(x, y, 5, 0)) {
251            this.isMovingRange = true;
252            this.markAX = this.markA.frame.x;
253            this.markBX = this.markB.frame.x;
254            document.body.style.cursor = "move"
255        } else if (this.frame.containsWithMargin(x, y, 20, 0, 0, 0) && !this.rangeRect.containsWithMargin(x, y, 0, markPadding, 0, markPadding)) {
256            this.isNewRange = true;
257        }
258    }
259
260    mouseUp(ev: MouseEvent) {
261        this.isMouseDown = false;
262        this.isMovingRange = false;
263        this.isNewRange = false;
264        this.movingMark = null;
265    }
266
267    mouseMove(ev: MouseEvent) {
268        this.range.refresh = false;
269        let x = ev.offsetX - (this.canvas?.offsetLeft || 0);
270        let y = ev.offsetY - (this.canvas?.offsetTop || 0)
271        this.centerXPercentage = x / (this.canvas?.clientWidth || 0)
272        if (this.centerXPercentage <= 0) {
273            this.centerXPercentage = 0
274        } else if (this.centerXPercentage >= 1) {
275            this.centerXPercentage = 1
276        }
277        let maxX = this.canvas?.clientWidth || 0
278        if (this.markA.inspectionFrame.contains(x, y)) {
279            this.markA.isHover = true
280        } else if (this.markB.inspectionFrame.contains(x, y)) {
281            this.markB.isHover = true;
282        } else {
283            this.markA.isHover = false;
284            this.markB.isHover = false;
285        }
286        if (this.movingMark) {
287            let result = x - this.mouseDownOffsetX + this.mouseDownMovingMarkX;
288            if (result >= 0 && result <= maxX) {
289                this.movingMark.frame.x = result
290            } else if (result < 0) {
291                this.movingMark.frame.x = 0
292            } else {
293                this.movingMark.frame.x = maxX
294            }
295            this.movingMark.inspectionFrame.x = this.movingMark.frame.x - markPadding
296            this.recordMovingS()
297            requestAnimationFrame(() => {
298                this.draw()
299                this.range.refresh = false;
300                this.delayDraw()
301            });
302        } else if (this.rangeRect.containsWithPadding(x, y, markPadding, 0)) {
303            document.body.style.cursor = "move"
304        } else if (this.frame.containsWithMargin(x, y, 20, 0, 0, 0) && !this.rangeRect.containsWithMargin(x, y, 0, markPadding, 0, markPadding)) {
305            document.body.style.cursor = "crosshair";
306        }
307        if (this.isMovingRange && this.isMouseDown) {
308            let result = x - this.mouseDownOffsetX;
309            let mA = result + this.markAX
310            let mB = result + this.markBX
311            if (mA >= 0 && mA <= maxX) {
312                this.markA.frame.x = mA
313            } else if (mA < 0) {
314                this.markA.frame.x = 0
315            } else {
316                this.markA.frame.x = maxX
317            }
318            this.markA.inspectionFrame.x = this.markA.frame.x - markPadding
319            if (mB >= 0 && mB <= maxX) {
320                this.markB.frame.x = mB;
321            } else if (mB < 0) {
322                this.markB.frame.x = 0
323            } else {
324                this.markB.frame.x = maxX
325            }
326            this.markB.inspectionFrame.x = this.markB.frame.x - markPadding
327            this.recordMovingS()
328            requestAnimationFrame(() => {
329                this.draw()
330                this.range.refresh = false;
331                this.delayDraw()
332            });
333        } else if (this.isNewRange) {
334            this.markA.frame.x = this.mouseDownOffsetX;
335            this.markA.inspectionFrame.x = this.mouseDownOffsetX - markPadding;
336            if (x >= 0 && x <= maxX) {
337                this.markB.frame.x = x;
338            } else if (x < 0) {
339                this.markB.frame.x = 0;
340            } else {
341                this.markB.frame.x = maxX;
342            }
343            this.markB.inspectionFrame.x = this.markB.frame.x - markPadding;
344            this.recordMovingS()
345            requestAnimationFrame(() => {
346                this.draw()
347                this.range.refresh = false;
348                this.delayDraw()
349            });
350        }
351    }
352
353    recordMovingS() {
354        if (this.animaStartTime == undefined) {
355            let dat = new Date();
356            dat.setTime(dat.getTime() - 400);
357            this.animaStartTime = dat.getTime();
358        }
359        this.currentDuration = (new Date().getTime() - this.animaStartTime);
360        if (Math.trunc(this.currentDuration / this.cacheInterval.interval) != this.cacheInterval.value) {
361            this.cacheInterval.flag = true;
362            this.cacheInterval.value = Math.trunc(this.currentDuration / this.cacheInterval.interval)
363        } else {
364            this.cacheInterval.flag = false;
365        }
366        this.range.refresh = this.cacheInterval.flag;
367    }
368
369    delayDraw() {
370        if (this.delayTimer) {
371            clearTimeout(this.delayTimer)
372        }
373        this.delayTimer = setTimeout(() => {
374            this.range.refresh = true;
375            this.draw()
376            this.range.refresh = false;
377            this.animaStartTime = undefined
378        }, this.cacheInterval.interval + 50)
379    }
380
381    mouseOut(ev: MouseEvent) {
382        this.movingMark = null;
383    }
384
385    fillX() {
386        if (this.range.startNS < 0) this.range.startNS = 0;
387        if (this.range.endNS < 0) this.range.endNS = 0;
388        if (this.range.endNS > this.range.totalNS) this.range.endNS = this.range.totalNS;
389        if (this.range.startNS > this.range.totalNS) this.range.startNS = this.range.totalNS;
390        this.range.startX = this.range.startNS * (this.canvas?.clientWidth || 0) / this.range.totalNS
391        this.range.endX = this.range.endNS * (this.canvas?.clientWidth || 0) / this.range.totalNS
392        this.markA.frame.x = this.range.startX
393        this.markA.inspectionFrame.x = this.markA.frame.x - markPadding
394        this.markB.frame.x = this.range.endX
395        this.markB.inspectionFrame.x = this.markB.frame.x - markPadding
396    }
397
398    setRangeNS(startNS: number, endNS: number) {
399        this.range.startNS = startNS
400        this.range.endNS = endNS
401        this.fillX()
402        this.draw();
403    }
404
405    getRange(): TimeRange {
406        return this.range;
407    }
408
409    cancelPressFrame() {
410        if (this.pressFrameIdA != -1) cancelAnimationFrame(this.pressFrameIdA);
411        if (this.pressFrameIdD != -1) cancelAnimationFrame(this.pressFrameIdD);
412        if (this.pressFrameIdW != -1) cancelAnimationFrame(this.pressFrameIdW);
413        if (this.pressFrameIdS != -1) cancelAnimationFrame(this.pressFrameIdS);
414    }
415
416    cancelUpFrame() {
417        if (this.upFrameIdA != -1) cancelAnimationFrame(this.upFrameIdA);
418        if (this.upFrameIdD != -1) cancelAnimationFrame(this.upFrameIdD);
419        if (this.upFrameIdW != -1) cancelAnimationFrame(this.upFrameIdW);
420        if (this.upFrameIdS != -1) cancelAnimationFrame(this.upFrameIdS);
421    }
422
423
424    keyPress(ev: KeyboardEvent) {
425        if (this.animaStartTime == undefined ||
426            (this.pressedKeys.length > 0 && this.pressedKeys[this.pressedKeys.length - 1] != ev.key.toLocaleLowerCase())
427        ) {
428            let dat = new Date();
429            dat.setTime(dat.getTime() - 400);
430            this.animaStartTime = dat.getTime();
431        }
432        this.currentDuration = (new Date().getTime() - this.animaStartTime);
433        if (Math.trunc(this.currentDuration / this.cacheInterval.interval) != this.cacheInterval.value) {
434            this.cacheInterval.flag = true;
435            this.cacheInterval.value = Math.trunc(this.currentDuration / this.cacheInterval.interval)
436        } else {
437            this.cacheInterval.flag = false;
438        }
439        this.range.refresh = this.cacheInterval.flag;
440        if (this.pressedKeys.length > 0) {
441            if (this.pressedKeys[this.pressedKeys.length - 1] != ev.key.toLocaleLowerCase()) {
442                this.cancelPressFrame();
443                this.cancelUpFrame();
444                this.pressedKeys.push(ev.key.toLocaleLowerCase());
445                let dat = new Date();
446                dat.setTime(dat.getTime() - 400);
447                this.animaStartTime = dat.getTime();
448                this.keyboardKeyPressMap[this.pressedKeys[this.pressedKeys.length - 1]]?.bind(this)();
449            }
450        } else {
451            this.cancelPressFrame();
452            this.cancelUpFrame();
453            this.pressedKeys.push(ev.key.toLocaleLowerCase());
454            let dat = new Date();
455            dat.setTime(dat.getTime() - 400);
456            this.animaStartTime = dat.getTime();
457            this.keyboardKeyPressMap[this.pressedKeys[this.pressedKeys.length - 1]]?.bind(this)();
458        }
459    }
460
461    keyPressW() {
462        let animW = () => {
463            if (this.scale === 50) {
464                this.range.refresh = true;
465                this.notifyHandler(this.range);
466                this.range.refresh = false;
467                return;
468            }
469            this.range.startNS += (this.centerXPercentage * this.currentDuration * this.scale / this.p);
470            this.range.endNS -= ((1 - this.centerXPercentage) * this.currentDuration * this.scale / this.p);
471            this.fillX();
472            this.draw();
473            this.range.refresh = false;
474            this.pressFrameIdW = requestAnimationFrame(animW)
475        }
476        this.pressFrameIdW = requestAnimationFrame(animW)
477    }
478
479    keyPressS() {
480        let animS = () => {
481            if (this.range.startNS <= 0 && this.range.endNS >= this.range.totalNS) {
482                this.range.refresh = true;
483                this.notifyHandler(this.range);
484                this.range.refresh = false;
485                return;
486            }
487            this.range.startNS -= (this.centerXPercentage * this.scale / this.p * this.currentDuration);
488            this.range.endNS += ((1 - this.centerXPercentage) * this.scale / this.p * this.currentDuration);
489            this.fillX();
490            this.draw();
491            this.range.refresh = false;
492            this.pressFrameIdS = requestAnimationFrame(animS)
493        }
494        this.pressFrameIdS = requestAnimationFrame(animS)
495    }
496
497    keyPressA() {
498        let animA = () => {
499            if (this.range.startNS == 0) {
500                this.range.refresh = true;
501                this.notifyHandler(this.range);
502                this.range.refresh = false;
503                return;
504            }
505            let s = this.scale / this.p * this.currentDuration * .4;
506            this.range.startNS -= s;
507            this.range.endNS -= s;
508            this.fillX();
509            this.draw();
510            this.range.refresh = false;
511            this.pressFrameIdA = requestAnimationFrame(animA)
512        }
513        this.pressFrameIdA = requestAnimationFrame(animA)
514    }
515
516    keyPressD() {
517        let animD = () => {
518            if (this.range.endNS >= this.range.totalNS) {
519                this.range.refresh = true;
520                this.notifyHandler(this.range);
521                this.range.refresh = false;
522                return;
523            }
524            let s = this.scale / this.p * this.currentDuration * .4;
525            this.range.startNS += s;
526            this.range.endNS += s;
527            this.fillX();
528            this.draw();
529            this.range.refresh = false;
530            this.pressFrameIdD = requestAnimationFrame(animD)
531        }
532        this.pressFrameIdD = requestAnimationFrame(animD)
533    }
534
535    keyboardKeyPressMap: any = {
536        "w": this.keyPressW,
537        "s": this.keyPressS,
538        "a": this.keyPressA,
539        "d": this.keyPressD,
540    }
541
542    keyboardKeyUpMap: any = {
543        "w": this.keyUpW,
544        "s": this.keyUpS,
545        "a": this.keyUpA,
546        "d": this.keyUpD,
547    }
548
549    keyUp(ev: KeyboardEvent) {
550        this.cacheInterval.value = 0;
551        if (this.pressedKeys.length > 0) {
552            let number = this.pressedKeys.findIndex((value) => value === ev.key.toLocaleLowerCase());
553            if (number == this.pressedKeys.length - 1) {
554                this.animaStartTime = undefined;
555                this.cancelPressFrame();
556                this.keyboardKeyUpMap[ev.key]?.bind(this)();
557            }
558            if (number != -1) {
559                this.pressedKeys.splice(number, 1);
560            }
561        }
562    }
563
564
565    keyUpW() {
566        let startTime = new Date().getTime();
567        let animW = () => {
568            if (this.scale === 50) {
569                this.range.refresh = true;
570                this.notifyHandler(this.range);
571                this.range.refresh = false;
572                return;
573            }
574            let dur = (new Date().getTime() - startTime);
575            this.range.startNS += (this.centerXPercentage * 100 * this.scale / this.p);
576            this.range.endNS -= ((1 - this.centerXPercentage) * 100 * this.scale / this.p);
577            this.fillX();
578            this.draw();
579            this.range.refresh = false;
580            if (dur < 200) {
581                this.upFrameIdW = requestAnimationFrame(animW);
582            } else {
583                this.range.refresh = true;
584                this.notifyHandler(this.range);
585                this.range.refresh = false;
586            }
587        }
588        this.upFrameIdW = requestAnimationFrame(animW);
589    }
590
591    keyUpS() {
592        let startTime = new Date().getTime();
593        let animS = () => {
594            if (this.range.startNS <= 0 && this.range.endNS >= this.range.totalNS) {
595                this.range.refresh = true;
596                this.notifyHandler(this.range);
597                this.range.refresh = false;
598                return;
599            }
600            let dur = (new Date().getTime() - startTime);
601            this.range.startNS -= (this.centerXPercentage * 100 * this.scale / this.p);
602            this.range.endNS += ((1 - this.centerXPercentage) * 100 * this.scale / this.p);
603            this.fillX();
604            this.draw();
605            this.range.refresh = false;
606            if (dur < 200) {
607                this.upFrameIdS = requestAnimationFrame(animS);
608            } else {
609                this.range.refresh = true;
610                this.notifyHandler(this.range);
611                this.range.refresh = false;
612            }
613        }
614        this.upFrameIdS = requestAnimationFrame(animS);
615    }
616
617    keyUpA() {
618        let startTime = new Date().getTime();
619        let animA = () => {
620            if (this.range.startNS <= 0) {
621                this.range.refresh = true;
622                this.notifyHandler(this.range);
623                this.range.refresh = false;
624                return;
625            }
626            let dur = (new Date().getTime() - startTime);
627            let s = this.scale * 80 / this.p;
628            this.range.startNS -= s;
629            this.range.endNS -= s;
630            this.fillX();
631            this.draw();
632            this.range.refresh = false;
633            if (dur < 200) {
634                this.upFrameIdA = requestAnimationFrame(animA);
635            } else {
636                this.range.refresh = true;
637                this.notifyHandler(this.range);
638                this.range.refresh = false;
639            }
640        }
641        this.upFrameIdA = requestAnimationFrame(animA);
642    }
643
644    keyUpD() {
645        let startTime = new Date().getTime();
646        let animD = () => {
647            if (this.range.endNS >= this.range.totalNS) {
648                this.range.refresh = true;
649                this.notifyHandler(this.range);
650                this.range.refresh = false;
651                return;
652            }
653            let dur = (new Date().getTime() - startTime);
654            let s = this.scale * 80 / this.p;
655            this.range.startNS += s;
656            this.range.endNS += s;
657            this.fillX();
658            this.draw();
659            this.range.refresh = false;
660            if (dur < 200) {
661                this.upFrameIdD = requestAnimationFrame(animD);
662            } else {
663                this.range.refresh = true;
664                this.notifyHandler(this.range);
665                this.range.refresh = false;
666            }
667        }
668        this.upFrameIdD = requestAnimationFrame(animD);
669    }
670}
671