UNPKG

cione-comp-lib

Version:

`$ yarn add cione-comp-lib` 或者 `$ npm i cione-comp-lib -S`

610 lines (609 loc) 19.2 kB
import { devicePixelRatio } from "../config.mjs"; import { each, merge, logError, indexOf, extend, disableUserSelect } from "../core/util.mjs"; import Layer from "./Layer.mjs"; import requestAnimationFrame from "../animation/requestAnimationFrame.mjs"; import env from "../core/env.mjs"; import { brush, brushSingle } from "./graphic.mjs"; import { REDRAW_BIT } from "../graphic/constants.mjs"; import { getSize } from "./helper.mjs"; var HOVER_LAYER_ZLEVEL = 1e5; var CANVAS_ZLEVEL = 314159; var EL_AFTER_INCREMENTAL_INC = 0.01; var INCREMENTAL_INC = 1e-3; function isLayerValid(layer) { if (!layer) { return false; } if (layer.__builtin__) { return true; } if (typeof layer.resize !== "function" || typeof layer.refresh !== "function") { return false; } return true; } function createRoot(width, height) { var domRoot = document.createElement("div"); domRoot.style.cssText = [ "position:relative", "width:" + width + "px", "height:" + height + "px", "padding:0", "margin:0", "border-width:0" ].join(";") + ";"; return domRoot; } var CanvasPainter = function() { function CanvasPainter2(root, storage, opts, id) { this.type = "canvas"; this._zlevelList = []; this._prevDisplayList = []; this._layers = {}; this._layerConfig = {}; this._needsManuallyCompositing = false; this.type = "canvas"; var singleCanvas = !root.nodeName || root.nodeName.toUpperCase() === "CANVAS"; this._opts = opts = extend({}, opts || {}); this.dpr = opts.devicePixelRatio || devicePixelRatio; this._singleCanvas = singleCanvas; this.root = root; var rootStyle = root.style; if (rootStyle) { disableUserSelect(root); root.innerHTML = ""; } this.storage = storage; var zlevelList = this._zlevelList; this._prevDisplayList = []; var layers = this._layers; if (!singleCanvas) { this._width = getSize(root, 0, opts); this._height = getSize(root, 1, opts); var domRoot = this._domRoot = createRoot(this._width, this._height); root.appendChild(domRoot); } else { var rootCanvas = root; var width = rootCanvas.width; var height = rootCanvas.height; if (opts.width != null) { width = opts.width; } if (opts.height != null) { height = opts.height; } this.dpr = opts.devicePixelRatio || 1; rootCanvas.width = width * this.dpr; rootCanvas.height = height * this.dpr; this._width = width; this._height = height; var mainLayer = new Layer(rootCanvas, this, this.dpr); mainLayer.__builtin__ = true; mainLayer.initContext(); layers[CANVAS_ZLEVEL] = mainLayer; mainLayer.zlevel = CANVAS_ZLEVEL; zlevelList.push(CANVAS_ZLEVEL); this._domRoot = root; } } CanvasPainter2.prototype.getType = function() { return "canvas"; }; CanvasPainter2.prototype.isSingleCanvas = function() { return this._singleCanvas; }; CanvasPainter2.prototype.getViewportRoot = function() { return this._domRoot; }; CanvasPainter2.prototype.getViewportRootOffset = function() { var viewportRoot = this.getViewportRoot(); if (viewportRoot) { return { offsetLeft: viewportRoot.offsetLeft || 0, offsetTop: viewportRoot.offsetTop || 0 }; } }; CanvasPainter2.prototype.refresh = function(paintAll) { var list = this.storage.getDisplayList(true); var prevList = this._prevDisplayList; var zlevelList = this._zlevelList; this._redrawId = Math.random(); this._paintList(list, prevList, paintAll, this._redrawId); for (var i = 0; i < zlevelList.length; i++) { var z = zlevelList[i]; var layer = this._layers[z]; if (!layer.__builtin__ && layer.refresh) { var clearColor = i === 0 ? this._backgroundColor : null; layer.refresh(clearColor); } } if (this._opts.useDirtyRect) { this._prevDisplayList = list.slice(); } return this; }; CanvasPainter2.prototype.refreshHover = function() { this._paintHoverList(this.storage.getDisplayList(false)); }; CanvasPainter2.prototype._paintHoverList = function(list) { var len = list.length; var hoverLayer = this._hoverlayer; hoverLayer && hoverLayer.clear(); if (!len) { return; } var scope = { inHover: true, viewWidth: this._width, viewHeight: this._height }; var ctx; for (var i = 0; i < len; i++) { var el = list[i]; if (el.__inHover) { if (!hoverLayer) { hoverLayer = this._hoverlayer = this.getLayer(HOVER_LAYER_ZLEVEL); } if (!ctx) { ctx = hoverLayer.ctx; ctx.save(); } brush(ctx, el, scope, i === len - 1); } } if (ctx) { ctx.restore(); } }; CanvasPainter2.prototype.getHoverLayer = function() { return this.getLayer(HOVER_LAYER_ZLEVEL); }; CanvasPainter2.prototype.paintOne = function(ctx, el) { brushSingle(ctx, el); }; CanvasPainter2.prototype._paintList = function(list, prevList, paintAll, redrawId) { if (this._redrawId !== redrawId) { return; } paintAll = paintAll || false; this._updateLayerStatus(list); var _a = this._doPaintList(list, prevList, paintAll), finished = _a.finished, needsRefreshHover = _a.needsRefreshHover; if (this._needsManuallyCompositing) { this._compositeManually(); } if (needsRefreshHover) { this._paintHoverList(list); } if (!finished) { var self_1 = this; requestAnimationFrame(function() { self_1._paintList(list, prevList, paintAll, redrawId); }); } else { this.eachLayer(function(layer) { layer.afterBrush && layer.afterBrush(); }); } }; CanvasPainter2.prototype._compositeManually = function() { var ctx = this.getLayer(CANVAS_ZLEVEL).ctx; var width = this._domRoot.width; var height = this._domRoot.height; ctx.clearRect(0, 0, width, height); this.eachBuiltinLayer(function(layer) { if (layer.virtual) { ctx.drawImage(layer.dom, 0, 0, width, height); } }); }; CanvasPainter2.prototype._doPaintList = function(list, prevList, paintAll) { var _this = this; var layerList = []; var useDirtyRect = this._opts.useDirtyRect; for (var zi = 0; zi < this._zlevelList.length; zi++) { var zlevel = this._zlevelList[zi]; var layer = this._layers[zlevel]; if (layer.__builtin__ && layer !== this._hoverlayer && (layer.__dirty || paintAll)) { layerList.push(layer); } } var finished = true; var needsRefreshHover = false; var _loop_1 = function(k2) { var layer2 = layerList[k2]; var ctx = layer2.ctx; var repaintRects = useDirtyRect && layer2.createRepaintRects(list, prevList, this_1._width, this_1._height); var start = paintAll ? layer2.__startIndex : layer2.__drawIndex; var useTimer = !paintAll && layer2.incremental && Date.now; var startTime = useTimer && Date.now(); var clearColor = layer2.zlevel === this_1._zlevelList[0] ? this_1._backgroundColor : null; if (layer2.__startIndex === layer2.__endIndex) { layer2.clear(false, clearColor, repaintRects); } else if (start === layer2.__startIndex) { var firstEl = list[start]; if (!firstEl.incremental || !firstEl.notClear || paintAll) { layer2.clear(false, clearColor, repaintRects); } } if (start === -1) { console.error("For some unknown reason. drawIndex is -1"); start = layer2.__startIndex; } var i; var repaint = function(repaintRect) { var scope = { inHover: false, allClipped: false, prevEl: null, viewWidth: _this._width, viewHeight: _this._height }; for (i = start; i < layer2.__endIndex; i++) { var el = list[i]; if (el.__inHover) { needsRefreshHover = true; } _this._doPaintEl(el, layer2, useDirtyRect, repaintRect, scope, i === layer2.__endIndex - 1); if (useTimer) { var dTime = Date.now() - startTime; if (dTime > 15) { break; } } } if (scope.prevElClipPaths) { ctx.restore(); } }; if (repaintRects) { if (repaintRects.length === 0) { i = layer2.__endIndex; } else { var dpr = this_1.dpr; for (var r = 0; r < repaintRects.length; ++r) { var rect = repaintRects[r]; ctx.save(); ctx.beginPath(); ctx.rect(rect.x * dpr, rect.y * dpr, rect.width * dpr, rect.height * dpr); ctx.clip(); repaint(rect); ctx.restore(); } } } else { ctx.save(); repaint(); ctx.restore(); } layer2.__drawIndex = i; if (layer2.__drawIndex < layer2.__endIndex) { finished = false; } }; var this_1 = this; for (var k = 0; k < layerList.length; k++) { _loop_1(k); } if (env.wxa) { each(this._layers, function(layer2) { if (layer2 && layer2.ctx && layer2.ctx.draw) { layer2.ctx.draw(); } }); } return { finished, needsRefreshHover }; }; CanvasPainter2.prototype._doPaintEl = function(el, currentLayer, useDirtyRect, repaintRect, scope, isLast) { var ctx = currentLayer.ctx; if (useDirtyRect) { var paintRect = el.getPaintRect(); if (!repaintRect || paintRect && paintRect.intersect(repaintRect)) { brush(ctx, el, scope, isLast); el.setPrevPaintRect(paintRect); } } else { brush(ctx, el, scope, isLast); } }; CanvasPainter2.prototype.getLayer = function(zlevel, virtual) { if (this._singleCanvas && !this._needsManuallyCompositing) { zlevel = CANVAS_ZLEVEL; } var layer = this._layers[zlevel]; if (!layer) { layer = new Layer("zr_" + zlevel, this, this.dpr); layer.zlevel = zlevel; layer.__builtin__ = true; if (this._layerConfig[zlevel]) { merge(layer, this._layerConfig[zlevel], true); } else if (this._layerConfig[zlevel - EL_AFTER_INCREMENTAL_INC]) { merge(layer, this._layerConfig[zlevel - EL_AFTER_INCREMENTAL_INC], true); } if (virtual) { layer.virtual = virtual; } this.insertLayer(zlevel, layer); layer.initContext(); } return layer; }; CanvasPainter2.prototype.insertLayer = function(zlevel, layer) { var layersMap = this._layers; var zlevelList = this._zlevelList; var len = zlevelList.length; var domRoot = this._domRoot; var prevLayer = null; var i = -1; if (layersMap[zlevel]) { return; } if (!isLayerValid(layer)) { return; } if (len > 0 && zlevel > zlevelList[0]) { for (i = 0; i < len - 1; i++) { if (zlevelList[i] < zlevel && zlevelList[i + 1] > zlevel) { break; } } prevLayer = layersMap[zlevelList[i]]; } zlevelList.splice(i + 1, 0, zlevel); layersMap[zlevel] = layer; if (!layer.virtual) { if (prevLayer) { var prevDom = prevLayer.dom; if (prevDom.nextSibling) { domRoot.insertBefore(layer.dom, prevDom.nextSibling); } else { domRoot.appendChild(layer.dom); } } else { if (domRoot.firstChild) { domRoot.insertBefore(layer.dom, domRoot.firstChild); } else { domRoot.appendChild(layer.dom); } } } layer.__painter = this; }; CanvasPainter2.prototype.eachLayer = function(cb, context) { var zlevelList = this._zlevelList; for (var i = 0; i < zlevelList.length; i++) { var z = zlevelList[i]; cb.call(context, this._layers[z], z); } }; CanvasPainter2.prototype.eachBuiltinLayer = function(cb, context) { var zlevelList = this._zlevelList; for (var i = 0; i < zlevelList.length; i++) { var z = zlevelList[i]; var layer = this._layers[z]; if (layer.__builtin__) { cb.call(context, layer, z); } } }; CanvasPainter2.prototype.eachOtherLayer = function(cb, context) { var zlevelList = this._zlevelList; for (var i = 0; i < zlevelList.length; i++) { var z = zlevelList[i]; var layer = this._layers[z]; if (!layer.__builtin__) { cb.call(context, layer, z); } } }; CanvasPainter2.prototype.getLayers = function() { return this._layers; }; CanvasPainter2.prototype._updateLayerStatus = function(list) { this.eachBuiltinLayer(function(layer2, z) { layer2.__dirty = layer2.__used = false; }); function updatePrevLayer(idx) { if (prevLayer) { if (prevLayer.__endIndex !== idx) { prevLayer.__dirty = true; } prevLayer.__endIndex = idx; } } if (this._singleCanvas) { for (var i_1 = 1; i_1 < list.length; i_1++) { var el = list[i_1]; if (el.zlevel !== list[i_1 - 1].zlevel || el.incremental) { this._needsManuallyCompositing = true; break; } } } var prevLayer = null; var incrementalLayerCount = 0; var prevZlevel; var i; for (i = 0; i < list.length; i++) { var el = list[i]; var zlevel = el.zlevel; var layer = void 0; if (prevZlevel !== zlevel) { prevZlevel = zlevel; incrementalLayerCount = 0; } if (el.incremental) { layer = this.getLayer(zlevel + INCREMENTAL_INC, this._needsManuallyCompositing); layer.incremental = true; incrementalLayerCount = 1; } else { layer = this.getLayer(zlevel + (incrementalLayerCount > 0 ? EL_AFTER_INCREMENTAL_INC : 0), this._needsManuallyCompositing); } if (!layer.__builtin__) { logError("ZLevel " + zlevel + " has been used by unkown layer " + layer.id); } if (layer !== prevLayer) { layer.__used = true; if (layer.__startIndex !== i) { layer.__dirty = true; } layer.__startIndex = i; if (!layer.incremental) { layer.__drawIndex = i; } else { layer.__drawIndex = -1; } updatePrevLayer(i); prevLayer = layer; } if (el.__dirty & REDRAW_BIT && !el.__inHover) { layer.__dirty = true; if (layer.incremental && layer.__drawIndex < 0) { layer.__drawIndex = i; } } } updatePrevLayer(i); this.eachBuiltinLayer(function(layer2, z) { if (!layer2.__used && layer2.getElementCount() > 0) { layer2.__dirty = true; layer2.__startIndex = layer2.__endIndex = layer2.__drawIndex = 0; } if (layer2.__dirty && layer2.__drawIndex < 0) { layer2.__drawIndex = layer2.__startIndex; } }); }; CanvasPainter2.prototype.clear = function() { this.eachBuiltinLayer(this._clearLayer); return this; }; CanvasPainter2.prototype._clearLayer = function(layer) { layer.clear(); }; CanvasPainter2.prototype.setBackgroundColor = function(backgroundColor) { this._backgroundColor = backgroundColor; each(this._layers, function(layer) { layer.setUnpainted(); }); }; CanvasPainter2.prototype.configLayer = function(zlevel, config) { if (config) { var layerConfig = this._layerConfig; if (!layerConfig[zlevel]) { layerConfig[zlevel] = config; } else { merge(layerConfig[zlevel], config, true); } for (var i = 0; i < this._zlevelList.length; i++) { var _zlevel = this._zlevelList[i]; if (_zlevel === zlevel || _zlevel === zlevel + EL_AFTER_INCREMENTAL_INC) { var layer = this._layers[_zlevel]; merge(layer, layerConfig[zlevel], true); } } } }; CanvasPainter2.prototype.delLayer = function(zlevel) { var layers = this._layers; var zlevelList = this._zlevelList; var layer = layers[zlevel]; if (!layer) { return; } layer.dom.parentNode.removeChild(layer.dom); delete layers[zlevel]; zlevelList.splice(indexOf(zlevelList, zlevel), 1); }; CanvasPainter2.prototype.resize = function(width, height) { if (!this._domRoot.style) { if (width == null || height == null) { return; } this._width = width; this._height = height; this.getLayer(CANVAS_ZLEVEL).resize(width, height); } else { var domRoot = this._domRoot; domRoot.style.display = "none"; var opts = this._opts; var root = this.root; width != null && (opts.width = width); height != null && (opts.height = height); width = getSize(root, 0, opts); height = getSize(root, 1, opts); domRoot.style.display = ""; if (this._width !== width || height !== this._height) { domRoot.style.width = width + "px"; domRoot.style.height = height + "px"; for (var id in this._layers) { if (this._layers.hasOwnProperty(id)) { this._layers[id].resize(width, height); } } this.refresh(true); } this._width = width; this._height = height; } return this; }; CanvasPainter2.prototype.clearLayer = function(zlevel) { var layer = this._layers[zlevel]; if (layer) { layer.clear(); } }; CanvasPainter2.prototype.dispose = function() { this.root.innerHTML = ""; this.root = this.storage = this._domRoot = this._layers = null; }; CanvasPainter2.prototype.getRenderedCanvas = function(opts) { opts = opts || {}; if (this._singleCanvas && !this._compositeManually) { return this._layers[CANVAS_ZLEVEL].dom; } var imageLayer = new Layer("image", this, opts.pixelRatio || this.dpr); imageLayer.initContext(); imageLayer.clear(false, opts.backgroundColor || this._backgroundColor); var ctx = imageLayer.ctx; if (opts.pixelRatio <= this.dpr) { this.refresh(); var width_1 = imageLayer.dom.width; var height_1 = imageLayer.dom.height; this.eachLayer(function(layer) { if (layer.__builtin__) { ctx.drawImage(layer.dom, 0, 0, width_1, height_1); } else if (layer.renderToCanvas) { ctx.save(); layer.renderToCanvas(ctx); ctx.restore(); } }); } else { var scope = { inHover: false, viewWidth: this._width, viewHeight: this._height }; var displayList = this.storage.getDisplayList(true); for (var i = 0, len = displayList.length; i < len; i++) { var el = displayList[i]; brush(ctx, el, scope, i === len - 1); } } return imageLayer.dom; }; CanvasPainter2.prototype.getWidth = function() { return this._width; }; CanvasPainter2.prototype.getHeight = function() { return this._height; }; return CanvasPainter2; }(); var CanvasPainter$1 = CanvasPainter; export { CanvasPainter$1 as default };