VTable
VTable copied to clipboard
[Bug] 放大页面后,图片变模糊
Version
1.5.3
Link to Minimal Reproduction
https://codesandbox.io/p/sandbox/vtable-export-umd-forked-c33q9r?file=%2Fsrc%2Findex.ts%3A78%2C1
Steps to Reproduce
mac触摸板放大,图片模糊
Current Behavior
图片模糊
Expected Behavior
图片高清适配
Environment
- OS:
- Browser:
- Framework:
Any additional comments?
No response
这个是canvas的 已经生成的情况下 用浏览器的发个功能确实会这样哦
不过可以监听浏览器缩放事件 处理重绘。有兴趣的可以提pr
不过可以监听浏览器缩放事件 处理重绘。有兴趣的可以提pr
改了下 解决了 懒得PR了
import { type ListTable } from '@visactor/vtable';
import { debounce } from 'lodash';
const MIN_DEVICE_PIXEL_RATIO = 1;
function isMobile(device?: string) {
if (device === 'mobile') {
return true;
}
return /(iPhone|iPad|SymbianOS|Windows Phone|iPod|iOS|Android)/i.test(navigator.userAgent);
}
export class HdAdapter {
private viewport = window as typeof window & { visualViewport: Element };
private devicePixelRatioMedia: MediaQueryList;
private listTableInstance: ListTable;
private isDevicePixelRatioChange = false;
constructor(instance: ListTable) {
this.listTableInstance = instance;
}
public init = () => {
this.initDevicePixelRatioListener();
this.initDeviceZoomListener();
};
public destroy = () => {
this.removeDevicePixelRatioListener();
this.removeDeviceZoomListener();
};
private initDevicePixelRatioListener() {
this.devicePixelRatioMedia = window.matchMedia(`(resolution: ${window.devicePixelRatio}dppx)`);
if (this.devicePixelRatioMedia?.addEventListener) {
this.devicePixelRatioMedia.addEventListener('change', this.renderByDevicePixelRatioChanged);
} else {
this.devicePixelRatioMedia.addListener(this.renderByDevicePixelRatioChanged);
}
}
private removeDevicePixelRatioListener = () => {
if (this.devicePixelRatioMedia?.removeEventListener) {
this.devicePixelRatioMedia.removeEventListener('change', this.renderByDevicePixelRatioChanged);
} else {
this.devicePixelRatioMedia.removeListener(this.renderByDevicePixelRatioChanged);
}
};
private initDeviceZoomListener = () => {
if (isMobile()) {
return;
}
// VisualViewport support browser zoom & mac touch tablet
this.viewport?.visualViewport?.addEventListener('resize', this.renderByZoomScaleWithoutResizeEffect);
};
private removeDeviceZoomListener = () => {
if (isMobile()) {
return;
}
this.viewport?.visualViewport?.removeEventListener('resize', this.renderByZoomScaleWithoutResizeEffect);
};
/**
* DPR 改变也会触发 visualViewport 的 resize 事件, 预期是只监听双指缩放, 所以这里规避掉
*/
private renderByZoomScaleWithoutResizeEffect = (event: Event & { target: VisualViewport }) => {
this.isDevicePixelRatioChange = false;
this.renderByZoomScale(event);
};
private renderByDevicePixelRatioChanged = () => {
this.isDevicePixelRatioChange = true;
this.renderByDevicePixelRatio();
};
private renderByDevicePixelRatio = (ratio = window.devicePixelRatio) => {
const {
options: { pixelRatio },
} = this.listTableInstance;
const canvas = this.listTableInstance.canvas;
if (pixelRatio === ratio || !canvas) {
return;
}
// 缩放时, 以向上取整后的缩放比为准
// 设备像素比改变时, 取当前和用户配置中最大的, 保证显示效果
const _pixelRatio = Math.max(ratio, devicePixelRatio, MIN_DEVICE_PIXEL_RATIO);
this.listTableInstance.setPixelRatio(_pixelRatio);
};
private renderByZoomScale = debounce((event: Event & { target: VisualViewport }) => {
const ratio = Math.ceil(event.target.scale);
if (ratio >= 1 && !this.isDevicePixelRatioChange) {
this.renderByDevicePixelRatio(ratio);
}
}, 350);
}