diff --git a/src/PainterBase.ts b/src/PainterBase.ts index 8775d1db..696641be 100644 --- a/src/PainterBase.ts +++ b/src/PainterBase.ts @@ -20,7 +20,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(opt?: CanvasPainterRefreshOpt | NullUndefined): void clear(): void diff --git a/src/canvas/Layer.ts b/src/canvas/Layer.ts index e1e3c391..33e84b7b 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'; @@ -156,7 +155,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); } @@ -399,8 +398,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 c047dc29..5b542ab4 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, { isIncrementalLayer, LayerConfig, LayerDrawCursor } from './Layer'; import requestAnimationFrame from '../animation/requestAnimationFrame'; @@ -267,7 +267,7 @@ export default class CanvasPainter implements PainterBase { this._opts = opts = util.extend({}, opts || {}) as CanvasPainterOption; - this.dpr = opts.devicePixelRatio || devicePixelRatio; + this.dpr = opts.devicePixelRatio || getDevicePixelRatio(); this._singleCanvas = singleCanvas; @@ -306,7 +306,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; @@ -1204,11 +1203,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; @@ -1217,7 +1227,7 @@ export default class CanvasPainter implements PainterBase { this._width = width as number; this._height = height as number; - this._ensureLayer(CANVAS_ZLEVEL).resize(width as number, height as number); + this._ensureLayer(CANVAS_ZLEVEL).resize(width as number, height as number, this.dpr); } else { const domRoot = this._domRoot; @@ -1236,12 +1246,12 @@ 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'; eachLayer(this._i, function (layer) { - layer.resize(width as number, height as number); + layer.resize(width as number, height as number, this.dpr); }); this.refresh({paintAll: true}); 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 417ea383..2a7df81a 100644 --- a/src/zrender.ts +++ b/src/zrender.ts @@ -360,12 +360,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(); }