diff --git a/src/PainterBase.ts b/src/PainterBase.ts index fa42c37a..68a936c8 100644 --- a/src/PainterBase.ts +++ b/src/PainterBase.ts @@ -19,7 +19,7 @@ export interface PainterBase { // constructor(dom: HTMLElement, storage: Storage, opts: PainterOption, id: number): void - resize(width?: number | string, height?: number | string): void + resize(width?: number | string, height?: number | string, devicePixelRatio?: number): void refresh(): void clear(): void diff --git a/src/canvas/Layer.ts b/src/canvas/Layer.ts index c887d884..1aab0b59 100644 --- a/src/canvas/Layer.ts +++ b/src/canvas/Layer.ts @@ -1,5 +1,4 @@ import * as util from '../core/util'; -import {devicePixelRatio} from '../config'; import { ImagePatternObject } from '../graphic/Pattern'; import CanvasPainter from './Painter'; import { GradientObject, InnerGradientObject } from '../graphic/Gradient'; @@ -108,7 +107,7 @@ export default class Layer extends Eventful { super(); let dom; - dpr = dpr || devicePixelRatio; + dpr = dpr || 1; if (typeof id === 'string') { dom = createDom(id, painter, dpr); } @@ -354,8 +353,28 @@ export default class Layer extends Eventful { return (this._paintRects || []).slice(); } - resize(width: number, height: number) { - const dpr = this.dpr; + /** + * Update dpr and keep context markers in sync. + * Returns true if dpr changed. + */ + updateDpr(dpr?: number): boolean { + if (dpr != null && dpr !== this.dpr) { + this.dpr = dpr; + // Keep a custom dpr marker in sync for downstream brush logic. + if (this.ctx) { + (this.ctx as ZRCanvasRenderingContext).dpr = dpr; + } + if (this.ctxBack) { + (this.ctxBack as ZRCanvasRenderingContext).dpr = dpr; + } + return true; + } + return false; + } + + resize(width: number, height: number, dpr?: number) { + this.updateDpr(dpr); + dpr = this.dpr; const dom = this.dom; const domStyle = dom.style; diff --git a/src/canvas/Painter.ts b/src/canvas/Painter.ts index 56888569..34e97d74 100644 --- a/src/canvas/Painter.ts +++ b/src/canvas/Painter.ts @@ -1,4 +1,4 @@ -import {devicePixelRatio} from '../config'; +import { getDevicePixelRatio } from '../config'; import * as util from '../core/util'; import Layer, { LayerConfig } from './Layer'; import requestAnimationFrame from '../animation/requestAnimationFrame'; @@ -122,7 +122,7 @@ export default class CanvasPainter implements PainterBase { /** * @type {number} */ - this.dpr = opts.devicePixelRatio || devicePixelRatio; + this.dpr = opts.devicePixelRatio || getDevicePixelRatio(); /** * @type {boolean} * @private @@ -175,7 +175,6 @@ export default class CanvasPainter implements PainterBase { // TODO sting? height = opts.height as number; } - this.dpr = opts.devicePixelRatio || 1; // Use canvas width and height directly rootCanvas.width = width * this.dpr; @@ -835,11 +834,22 @@ export default class CanvasPainter implements PainterBase { /** * 区域大小变化后重绘 + * @param width 宽度 + * @param height 高度 + * @param devicePixelRatio 设备像素比,如果未指定,则自动获取当前设备像素比 */ resize( width?: number | string, - height?: number | string + height?: number | string, + devicePixelRatio?: number ) { + const newDpr = devicePixelRatio || getDevicePixelRatio(); + + const dprChanged = newDpr !== this.dpr; + if (dprChanged) { + this.dpr = newDpr; + } + if (!this._domRoot.style) { // Maybe in node or worker if (width == null || height == null) { return; @@ -848,7 +858,7 @@ export default class CanvasPainter implements PainterBase { this._width = width as number; this._height = height as number; - this.getLayer(CANVAS_ZLEVEL).resize(width as number, height as number); + this.getLayer(CANVAS_ZLEVEL).resize(width as number, height as number, this.dpr); } else { const domRoot = this._domRoot; @@ -867,13 +877,13 @@ export default class CanvasPainter implements PainterBase { domRoot.style.display = ''; // 优化没有实际改变的resize - if (this._width !== width || height !== this._height) { + if (this._width !== width || height !== this._height || dprChanged) { domRoot.style.width = width + 'px'; domRoot.style.height = height + 'px'; for (let id in this._layers) { if (this._layers.hasOwnProperty(id)) { - this._layers[id].resize(width, height); + this._layers[id].resize(width, height, this.dpr); } } diff --git a/src/config.ts b/src/config.ts index fe7528ab..d8662852 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,14 +1,16 @@ import env from './core/env'; -let dpr = 1; - -// If in browser environment -if (env.hasGlobalWindow) { - dpr = Math.max( - window.devicePixelRatio - || (window.screen && (window.screen as any).deviceXDPI / (window.screen as any).logicalXDPI) - || 1, 1 - ); +export function getDevicePixelRatio(): number { + let dpr = 1; + + // If in browser environment + if (env.hasGlobalWindow) { + dpr = window.devicePixelRatio + || (window.screen && (window.screen as any).deviceXDPI / (window.screen as any).logicalXDPI) + || 1; + } + + return dpr; } /** @@ -18,10 +20,6 @@ if (env.hasGlobalWindow) { */ export const debugMode = 0; -// retina 屏幕优化 -export const devicePixelRatio = dpr; - - /** * Determine when to turn on dark mode based on the luminance of backgroundColor */ diff --git a/src/core/PathProxy.ts b/src/core/PathProxy.ts index a6af1151..1139df5c 100644 --- a/src/core/PathProxy.ts +++ b/src/core/PathProxy.ts @@ -9,7 +9,6 @@ import * as vec2 from './vector'; import BoundingRect from './BoundingRect'; -import {devicePixelRatio as dpr} from '../config'; import { fromLine, fromCubic, fromQuadratic, fromArc } from './bbox'; import { cubicLength, cubicSubdivide, quadraticLength, quadraticSubdivide } from './curve'; @@ -177,6 +176,7 @@ export default class PathProxy { // Compat. Previously there is no segmentIgnoreThreshold. segmentIgnoreThreshold = segmentIgnoreThreshold || 0; if (segmentIgnoreThreshold > 0) { + const dpr = this.dpr || 1; this._ux = mathAbs(segmentIgnoreThreshold / dpr / sx) || 0; this._uy = mathAbs(segmentIgnoreThreshold / dpr / sy) || 0; } diff --git a/src/zrender.ts b/src/zrender.ts index f2a38237..c6555626 100644 --- a/src/zrender.ts +++ b/src/zrender.ts @@ -338,12 +338,13 @@ class ZRender { resize(opts?: { width?: number| string height?: number | string + devicePixelRatio?: number }) { if (this._disposed) { return; } opts = opts || {}; - this.painter.resize(opts.width, opts.height); + this.painter.resize(opts.width, opts.height, opts.devicePixelRatio); this.handler.resize(); }