From 30feb66ccdeef21856050990fcf8fd1460243760 Mon Sep 17 00:00:00 2001 From: lijinke666 Date: Mon, 13 Feb 2023 20:01:47 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=202k=20=E6=98=BE?= =?UTF-8?q?=E7=A4=BA=E5=99=A8=E5=88=87=E6=8D=A2=E5=88=B0=20MacBook=20?= =?UTF-8?q?=E5=90=8E=E8=A1=A8=E6=A0=BC=E6=B8=B2=E6=9F=93=E6=A8=A1=E7=B3=8A?= =?UTF-8?q?=20close=20#2072?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../unit/ui/hd-adapter/index-spec.ts | 29 +++++++++++++------ packages/s2-core/src/ui/hd-adapter/index.ts | 20 +++++++++++-- 2 files changed, 37 insertions(+), 12 deletions(-) diff --git a/packages/s2-core/__tests__/unit/ui/hd-adapter/index-spec.ts b/packages/s2-core/__tests__/unit/ui/hd-adapter/index-spec.ts index 1546223122..e13de584e9 100644 --- a/packages/s2-core/__tests__/unit/ui/hd-adapter/index-spec.ts +++ b/packages/s2-core/__tests__/unit/ui/hd-adapter/index-spec.ts @@ -1,13 +1,17 @@ -import { createFakeSpreadSheet, sleep } from 'tests/util/helpers'; +import { createPivotSheet, sleep } from 'tests/util/helpers'; +import type { S2Options } from '../../../../src'; import type { SpreadSheet } from '@/sheet-type/spread-sheet'; import { HdAdapter } from '@/ui/hd-adapter'; jest.mock('@/interaction/event-controller'); jest.mock('@/interaction/root'); -// eslint-disable-next-line jest/no-disabled-tests -describe.skip('HD Adapter Tests', () => { +describe('HD Adapter Tests', () => { const DPR = 2; + const s2Options: S2Options = { + width: 600, + height: 600, + }; let s2: SpreadSheet; let hdAdapter: HdAdapter; @@ -25,7 +29,7 @@ describe.skip('HD Adapter Tests', () => { configurable: true, }); - s2 = createFakeSpreadSheet(); + s2 = createPivotSheet(s2Options); hdAdapter = new HdAdapter(s2); hdAdapter.init(); @@ -36,7 +40,7 @@ describe.skip('HD Adapter Tests', () => { s2.options.height * DPR, ], ) => { - const canvas: HTMLCanvasElement = s2.container.get('el'); + const canvas = s2.getCanvasElement(); expect(canvas.style.width).toEqual(`${width}px`); expect(canvas.style.height).toEqual(`${height}px`); expect(canvas.width).toEqual(updatedWidth); @@ -46,6 +50,7 @@ describe.skip('HD Adapter Tests', () => { afterEach(() => { hdAdapter.destroy(); + s2.destroy(); Object.defineProperty(visualViewport, 'scale', { value: 1, @@ -59,11 +64,12 @@ describe.skip('HD Adapter Tests', () => { }); test('should not be update container size when zoom scale changed, but scale less than current DPR', async () => { + const render = jest.spyOn(s2, 'render').mockImplementationOnce(() => {}); visualViewport.dispatchEvent(new Event('resize')); await sleep(500); expectContainerSize(); - expect(s2.render).not.toHaveBeenCalled(); + expect(render).not.toHaveBeenCalled(); }); // eslint-disable-next-line jest/expect-expect @@ -85,6 +91,7 @@ describe.skip('HD Adapter Tests', () => { }); test('should use DPR for update container size when zoom scale changed, and scale less than current DPR', async () => { + const render = jest.spyOn(s2, 'render').mockImplementationOnce(() => {}); Object.defineProperty(visualViewport, 'scale', { value: 1, configurable: true, @@ -92,10 +99,12 @@ describe.skip('HD Adapter Tests', () => { visualViewport.dispatchEvent(new Event('resize')); await sleep(500); - expect(s2.render).not.toHaveBeenCalled(); + expect(render).not.toHaveBeenCalled(); }); test('should not rerender when zoom event destroyed', async () => { + const render = jest.spyOn(s2, 'render').mockImplementationOnce(() => {}); + hdAdapter.destroy(); Object.defineProperty(visualViewport, 'scale', { value: 3, @@ -104,10 +113,12 @@ describe.skip('HD Adapter Tests', () => { visualViewport.dispatchEvent(new Event('resize')); await sleep(500); - expect(s2.render).not.toHaveBeenCalled(); + expect(render).not.toHaveBeenCalled(); }); test('should not rerender when zoom event destroyed on mobile device', async () => { + const render = jest.spyOn(s2, 'render').mockImplementationOnce(() => {}); + hdAdapter.destroy(); Object.defineProperty(navigator, 'userAgent', { value: 'iPhone', @@ -119,6 +130,6 @@ describe.skip('HD Adapter Tests', () => { await sleep(500); expectContainerSize(); - expect(s2.render).not.toHaveBeenCalled(); + expect(render).not.toHaveBeenCalled(); }); }); diff --git a/packages/s2-core/src/ui/hd-adapter/index.ts b/packages/s2-core/src/ui/hd-adapter/index.ts index 9c3b925cd8..7de6c6ed1f 100644 --- a/packages/s2-core/src/ui/hd-adapter/index.ts +++ b/packages/s2-core/src/ui/hd-adapter/index.ts @@ -10,6 +10,8 @@ export class HdAdapter { private spreadsheet: SpreadSheet; + private isDevicePixelRatioChange = false; + constructor(spreadsheet: SpreadSheet) { this.spreadsheet = spreadsheet; } @@ -60,7 +62,7 @@ export class HdAdapter { // VisualViewport support browser zoom & mac touch tablet this.viewport?.visualViewport?.addEventListener( 'resize', - this.renderByZoomScale, + this.renderByZoomScaleWithoutResizeEffect, ); }; @@ -70,11 +72,23 @@ export class HdAdapter { } this.viewport?.visualViewport?.removeEventListener( 'resize', - this.renderByZoomScale, + this.renderByZoomScaleWithoutResizeEffect, ); }; + /** + * DPR改变也会触发 visualViewport 的 resize 事件, 预期是只监听双指缩放, 所以这里规避掉 + * @see https://github.com/antvis/S2/issues/2072 + */ + private renderByZoomScaleWithoutResizeEffect = ( + event: Event & { target: VisualViewport }, + ) => { + this.isDevicePixelRatioChange = false; + this.renderByZoomScale(event); + }; + private renderByDevicePixelRatioChanged = () => { + this.isDevicePixelRatioChange = true; this.renderByDevicePixelRatio(); }; @@ -107,7 +121,7 @@ export class HdAdapter { private renderByZoomScale = debounce( (event: Event & { target: VisualViewport }) => { const ratio = Math.ceil(event.target.scale); - if (ratio >= 1) { + if (ratio >= 1 && !this.isDevicePixelRatioChange) { this.renderByDevicePixelRatio(ratio); } },