Skip to content

Commit

Permalink
fix: 修复 2k 显示器切换到 MacBook 后表格渲染模糊 close #2072 (#2074)
Browse files Browse the repository at this point in the history
* fix: 修复 2k 显示器切换到 MacBook 后表格渲染模糊 close #2072

* test: 增加测试

* test: 修复高清测试

* test: 修复测试

* test: 修复测试
  • Loading branch information
lijinke666 authored Feb 14, 2023
1 parent 4602b42 commit a98d3fd
Show file tree
Hide file tree
Showing 8 changed files with 115 additions and 26 deletions.
5 changes: 3 additions & 2 deletions packages/s2-core/__tests__/bugs/issue-1191-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
*/
import * as mockDataConfig from 'tests/data/simple-data.json';
import { getContainer } from 'tests/util/helpers';
import type { S2Options } from '@/common/interface';
import type { S2DataConfig, S2Options } from '@/common/interface';
import { PivotSheet, SpreadSheet } from '@/sheet-type';

const s2options: S2Options = {
Expand All @@ -25,9 +25,10 @@ const s2options: S2Options = {
interaction: {
linkFields: ['province'],
},
hdAdapter: false,
};

const dataCfg = {
const dataCfg: S2DataConfig = {
...mockDataConfig,
fields: {
rows: ['province', 'city'],
Expand Down
1 change: 1 addition & 0 deletions packages/s2-core/__tests__/bugs/issue-1624-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { PivotSheet } from '@/sheet-type';
const s2Options: S2Options = {
width: 800,
height: 600,
hdAdapter: false,
};

describe('Data Cell Border Tests', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ const dataCfg: S2DataConfig = {
const options: S2Options = {
width: 800,
height: 600,
hdAdapter: false,
showSeriesNumber: true,
placeholder: '',
style: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
} from '@/common/constant';

jest.mock('@/interaction/event-controller');
jest.mock('@/ui/hd-adapter');

describe('Interaction Data Cell Multi Selection Tests', () => {
let dataCellMultiSelection: DataCellMultiSelection;
Expand Down
1 change: 1 addition & 0 deletions packages/s2-core/__tests__/unit/interaction/root-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import { getCellMeta } from '@/utils/interaction/select-event';

jest.mock('@/sheet-type');
jest.mock('@/interaction/event-controller');
jest.mock('@/ui/hd-adapter');
jest.mock('@/utils/interaction/merge-cell', () => {
return {
mergeCell: jest.fn(),
Expand Down
97 changes: 79 additions & 18 deletions packages/s2-core/__tests__/unit/ui/hd-adapter/index-spec.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
import { createFakeSpreadSheet, sleep } from 'tests/util/helpers';
/* eslint-disable @typescript-eslint/ban-ts-comment */
/* eslint-disable jest/expect-expect */
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', () => {
const DPR = 2;
const DPR = 1;
const s2Options: S2Options = {
width: 600,
height: 600,
devicePixelRatio: DPR,
hdAdapter: true,
};

let s2: SpreadSheet;
let hdAdapter: HdAdapter;
let expectContainerSize: (
size?: [number, number],
updatedSize?: [number, number],
Expand All @@ -25,9 +32,8 @@ describe.skip('HD Adapter Tests', () => {
configurable: true,
});

s2 = createFakeSpreadSheet();
hdAdapter = new HdAdapter(s2);
hdAdapter.init();
s2 = createPivotSheet(s2Options);
s2.render();

expectContainerSize = (
[width, height] = [s2.options.width, s2.options.height],
Expand All @@ -36,7 +42,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);
Expand All @@ -45,7 +51,7 @@ describe.skip('HD Adapter Tests', () => {
});

afterEach(() => {
hdAdapter.destroy();
s2.destroy();

Object.defineProperty(visualViewport, 'scale', {
value: 1,
Expand All @@ -59,16 +65,16 @@ describe.skip('HD Adapter Tests', () => {
});

test('should not be update container size when zoom scale changed, but scale less than current DPR', async () => {
const renderSpy = jest.spyOn(s2, 'render').mockImplementationOnce(() => {});
visualViewport.dispatchEvent(new Event('resize'));
await sleep(500);

expectContainerSize();
expect(s2.render).not.toHaveBeenCalled();
expect(renderSpy).not.toHaveBeenCalled();
});

// eslint-disable-next-line jest/expect-expect
test('should update container size when zoom scale changed, and scale more than current DPR', async () => {
const scale = 2;
const scale = 3;
Object.defineProperty(visualViewport, 'scale', {
value: scale,
configurable: true,
Expand All @@ -82,43 +88,98 @@ describe.skip('HD Adapter Tests', () => {
[s2.options.width, s2.options.height],
[s2.options.width * scale, s2.options.height * scale],
);

// 双指缩放回原始比例, 还原为默认宽高
Object.defineProperty(visualViewport, 'scale', {
value: 1,
configurable: true,
});
visualViewport.dispatchEvent(new Event('resize'));
await sleep(500);

expectContainerSize(
[s2.options.width, s2.options.height],
[s2.options.width * DPR, s2.options.height * DPR],
);
});

test('should use DPR for update container size when zoom scale changed, and scale less than current DPR', async () => {
const renderSpy = jest.spyOn(s2, 'render').mockImplementationOnce(() => {});
Object.defineProperty(visualViewport, 'scale', {
value: 1,
configurable: true,
});
visualViewport.dispatchEvent(new Event('resize'));

await sleep(500);
expect(s2.render).not.toHaveBeenCalled();
expect(renderSpy).not.toHaveBeenCalled();
});

test('should not rerender when zoom event destroyed', async () => {
hdAdapter.destroy();
const renderSpy = jest.spyOn(s2, 'render').mockImplementationOnce(() => {});

s2.destroy();

Object.defineProperty(visualViewport, 'scale', {
value: 3,
configurable: true,
});
visualViewport.dispatchEvent(new Event('resize'));

await sleep(500);
expect(s2.render).not.toHaveBeenCalled();
expect(renderSpy).not.toHaveBeenCalled();
});

test('should not rerender when zoom event destroyed on mobile device', async () => {
hdAdapter.destroy();
const renderSpy = jest.spyOn(s2, 'render').mockImplementationOnce(() => {});

s2.hdAdapter.destroy();

Object.defineProperty(navigator, 'userAgent', {
value: 'iPhone',
configurable: true,
});
hdAdapter.init();
visualViewport.dispatchEvent(new Event('resize'));

await sleep(500);

expectContainerSize();
expect(s2.render).not.toHaveBeenCalled();
expect(renderSpy).not.toHaveBeenCalled();
});

test('should update canvas size if DPR changed', () => {
const ratio = 3;
Object.defineProperty(window, 'devicePixelRatio', {
value: ratio,
});
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore 模拟 matchMedia 触发
s2.hdAdapter.renderByDevicePixelRatioChanged();

expectContainerSize(
[s2.options.width, s2.options.height],
[s2.options.width * ratio, s2.options.height * ratio],
);
});

// https://github.com/antvis/S2/issues/2072
test('should ignore visualViewport resize effect', () => {
const renderByDevicePixelRatioSpy = jest
.spyOn(s2.hdAdapter as any, 'renderByDevicePixelRatio')
.mockImplementationOnce(() => {});

const ratio = 3;

Object.defineProperty(window, 'devicePixelRatio', {
value: ratio,
});

// @ts-ignore
s2.hdAdapter.renderByDevicePixelRatioChanged();
visualViewport.dispatchEvent(new Event('resize'));
// @ts-ignore 模拟 matchMedia 触发后 visualViewport resize 事件触发
s2.hdAdapter.isDevicePixelRatioChange = true;

expect(renderByDevicePixelRatioSpy).toHaveBeenCalledTimes(1);
});
});
15 changes: 12 additions & 3 deletions packages/s2-core/__tests__/util/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,10 @@ export const createFakeSpreadSheet = () => {
}

const s2 = new FakeSpreadSheet() as unknown as SpreadSheet;
s2.options = DEFAULT_OPTIONS;
s2.options = {
...DEFAULT_OPTIONS,
hdAdapter: false,
};
s2.dataCfg = {
meta: null,
data: [],
Expand Down Expand Up @@ -180,7 +183,10 @@ export const createPivotSheet = (
return new PivotSheet(
getContainer(),
useSimpleData ? simpleDataConfig : dataConfig,
s2Options,
{
hdAdapter: false,
...s2Options,
},
);
};

Expand All @@ -191,6 +197,9 @@ export const createTableSheet = (
return new TableSheet(
getContainer(),
useSimpleData ? simpleDataConfig : dataConfig,
s2Options,
{
hdAdapter: false,
...s2Options,
},
);
};
20 changes: 17 additions & 3 deletions packages/s2-core/src/ui/hd-adapter/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ export class HdAdapter {

private spreadsheet: SpreadSheet;

private isDevicePixelRatioChange = false;

constructor(spreadsheet: SpreadSheet) {
this.spreadsheet = spreadsheet;
}
Expand Down Expand Up @@ -60,7 +62,7 @@ export class HdAdapter {
// VisualViewport support browser zoom & mac touch tablet
this.viewport?.visualViewport?.addEventListener(
'resize',
this.renderByZoomScale,
this.renderByZoomScaleWithoutResizeEffect,
);
};

Expand All @@ -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();
};

Expand Down Expand Up @@ -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);
}
},
Expand Down

0 comments on commit a98d3fd

Please sign in to comment.