cione-comp-lib
Version:
`$ yarn add cione-comp-lib` 或者 `$ npm i cione-comp-lib -S`
610 lines (609 loc) • 19.2 kB
JavaScript
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 };