# Layer 类

# 概述

创建 canvas

调用情况:

  • Painter 类构造函数中,如果是单层应用时, id 为 canvas 对象
  • Painter 类 getLayer 方法,在 get 时,如果没有 layer 会调用创建 id 为字符串
  • Painter 类 getRenderedCanvas 方法, id 为 'image'

# 构造函数

# id

层的 id,可能值为 string 或者 object,为 string 的时候,直接赋值给 this.id,如果是 object 的话,一般情况下为单 canvas 应用。 this.id 会取值 canvasidcanvas 会赋值 this.dom

# painter

Painter 类的实例,一般情况下,是在 Painter 类中

# dpr

画布大小与容器大小之比 devicePixelRatio

# 流程

如果是单层应用,会直接使用外面的 canvas ,如果是多层应用,会创建新的 canvas

function createDom(id, painter, dpr) {
    var newDom = util.createCanvas();
    var width = painter.getWidth();
    var height = painter.getHeight();

    var newDomStyle = newDom.style;
    if (newDomStyle) {  // In node or some other non-browser environment
        newDomStyle.position = 'absolute';
        newDomStyle.left = 0;
        newDomStyle.top = 0;
        newDomStyle.width = width + 'px';
        newDomStyle.height = height + 'px';

        newDom.setAttribute('data-zr-dom-id', id);
    }

    newDom.width = width * dpr;
    newDom.height = height * dpr;

    return newDom;
}

# 字段

# id

canvas 层的id

# dom

canvas 元素

# domBack

# ctxBack

# painter

Painter 类实例

# config

# clearColor

每次清空画布的颜色

# motionBlur

是否开启动态模糊

# lastFrameAlpha

在开启动态模糊的时候使用,与上一帧混合的alpha值,值越大尾迹越明显

# dpr

画布大小与容器大小之比 devicePixelRatio

# 原型字段

# __dirty

是否需要更新

# __used

是否被应用

# __drawIndex

incrementaltrue 时, __drawIndex 可能不等同于 __endIndex ,其他时候等同于 __endIndex

# __startIndex

当前层在所有元素中开始的索引

# __endIndex

当前层在所有元素中结束的索引

# virtual

暂时未发现有改属性赋值

# __builtin__

是否创建吗?

# 原型方法

# getElementCount

获取当前层元素数量

getElementCount: function () {
    return this.__endIndex - this.__startIndex;
}

# initContext

初始化绘画上下文

initContext: function () {
    this.ctx = this.dom.getContext('2d');
    this.ctx.dpr = this.dpr;
}

# createBackBuffer

createBackBuffer: function () {
    var dpr = this.dpr;

    this.domBack = createDom('back-' + this.id, this.painter, dpr);
    this.ctxBack = this.domBack.getContext('2d');

    if (dpr !== 1) {
        this.ctxBack.scale(dpr, dpr);
    }
}

# resize

resize: function (width, height) {
    var dpr = this.dpr;

    var dom = this.dom;
    var domStyle = dom.style;
    var domBack = this.domBack;

    if (domStyle) {
        domStyle.width = width + 'px';
        domStyle.height = height + 'px';
    }

    dom.width = width * dpr;
    dom.height = height * dpr;

    if (domBack) {
        domBack.width = width * dpr;
        domBack.height = height * dpr;

        if (dpr !== 1) {
            this.ctxBack.scale(dpr, dpr);
        }
    }
}

# clear

清空该层画布

clear: function (clearAll, clearColor) {
    var dom = this.dom;
    var ctx = this.ctx;
    var width = dom.width;
    var height = dom.height;

    var clearColor = clearColor || this.clearColor;
    var haveMotionBLur = this.motionBlur && !clearAll;
    var lastFrameAlpha = this.lastFrameAlpha;

    var dpr = this.dpr;

    if (haveMotionBLur) {
        if (!this.domBack) {
            this.createBackBuffer();
        }

        this.ctxBack.globalCompositeOperation = 'copy';
        this.ctxBack.drawImage(
            dom, 0, 0,
            width / dpr,
            height / dpr
        );
    }

    ctx.clearRect(0, 0, width, height);
    if (clearColor && clearColor !== 'transparent') {
        var clearColorGradientOrPattern;
        // Gradient
        if (clearColor.colorStops) {
            // Cache canvas gradient
            clearColorGradientOrPattern = 
                clearColor.__canvasGradient || Style.getGradient(ctx, clearColor, {
                x: 0,
                y: 0,
                width: width,
                height: height
            });

            clearColor.__canvasGradient = clearColorGradientOrPattern;
        }
        // Pattern
        else if (clearColor.image) {
            clearColorGradientOrPattern = 
                Pattern.prototype.getCanvasPattern.call(clearColor, ctx);
        }
        ctx.save();
        ctx.fillStyle = clearColorGradientOrPattern || clearColor;
        ctx.fillRect(0, 0, width, height);
        ctx.restore();
    }

    if (haveMotionBLur) {
        var domBack = this.domBack;
        ctx.save();
        ctx.globalAlpha = lastFrameAlpha;
        ctx.drawImage(domBack, 0, 0, width, height);
        ctx.restore();
    }
}