Quark-Renderer-----第八篇

2021SC@SDUSC

总述

在上次学习中,我们对CanvasPainter.js中的一些方法进行了学习,如delLayer方法、eachLayer方法、resize方法、getRenderedCanvas方法等,这些方法主要是针对画布的大小和内容等进行重新渲染来实现一些需求。本次我们接着学习canvas画布的一些方法,这些方法也主要集中在CanvasPainter.js中。

pathToImage(path, dpr) 方法

该方法传入两个参数。一个是路径,一个是dpr(像素度),在函数开始,先获得所有的关于canvas的一些属性,如dpr、ctx(Canvas 绘图上下文,此属性在调用 initContext() 方法之后初始化,初始化之前此属性为 null)、rect(边界矩阵)、style(样式)、shadowBlurSize、shadowOffsetX(影像x轴偏移量)、shadowOffsetY(影像y轴偏移量)、lineWidth、leftMargin(左边缘)、rightMargin(右边缘)、topMarigin(上边缘)、bottomMargin(地边缘)、width、height等。并且使用width和height以及dpr给新创建的canvas的宽高进行赋值,并且给ctx的scale进行赋值,并且对于边界矩阵进行赋值,同时将ctx.dpr=dpr,接着定义对象pathTransform,其中包含position(位置)、rotation(旋转角度)以及scale(大小比例)。

接着需要给传入的path进行赋值操作,同样的对其position、rotation、scale、skew(倾斜角)进行赋值操作,同时对path调用composeParentTransform()方法,下端主要介绍该composeParentTransform方法。接着判断path,然后设置path的ctx,以及对path进行渲染,然后新建image,设置初始样式,图像就是画布canvas,然后通过判断pathTransform的position、rotation、scale等属性是否为null,如若不为null,则用这三个属性的值分别对img、path的position、rotation、scale等分别进行赋值,最后返回img图像。

    dpr = dpr || this.dpr;

    let canvas = canvasUtil.createCanvas(); //创建隐藏的 canvas,在内存中。
    let ctx = canvasUtil.getContext(canvas);
    let rect = path.getBoundingRect();
    let style = path.style;
    let shadowBlurSize = style.shadowBlur * dpr;
    let shadowOffsetX = style.shadowOffsetX * dpr;
    let shadowOffsetY = style.shadowOffsetY * dpr;
    let lineWidth = style.hasStroke() ? style.lineWidth : 0;

    let leftMargin = mathMax(lineWidth / 2, -shadowOffsetX + shadowBlurSize);
    let rightMargin = mathMax(lineWidth / 2, shadowOffsetX + shadowBlurSize);
    let topMargin = mathMax(lineWidth / 2, -shadowOffsetY + shadowBlurSize);
    let bottomMargin = mathMax(lineWidth / 2, shadowOffsetY + shadowBlurSize);
    let width = rect.width + leftMargin + rightMargin;
    let height = rect.height + topMargin + bottomMargin;

    canvas.width = width * dpr;
    canvas.height = height * dpr;

    ctx.scale(dpr, dpr);
    ctx.clearRect(0, 0, width, height);
    ctx.dpr = dpr;

    let pathTransform = {
    
    
      position: path.position,
      rotation: path.rotation,
      scale: path.scale,
    };
    path.position = [leftMargin - rect.x1, topMargin - rect.y1];
    path.rotation = 0;
    path.scale = [1, 1];
    path.skew = [0, 0];
    path.composeParentTransform();
    if (path) {
    
    
      path.ctx = ctx;
      path.render();
    }

    let img = new Image({
    
    
      style: {
    
    
        x: 0,
        y: 0,
        image: canvas,
      },
    });

    if (pathTransform.position != null) {
    
    
      img.position = path.position = pathTransform.position;
    }

    if (pathTransform.rotation != null) {
    
    
      img.rotation = path.rotation = pathTransform.rotation;
    }

    if (pathTransform.scale != null) {
    
    
      img.scale = path.scale = pathTransform.scale;
    }

    return img;
  }

getBoundingRect()

该函数的作用是获取当前元素的边界矩形,该方法出现在上述方法中的关于let rect = path.getBoundingRect();的处理,对于该方法,首先要进行style的设置var style = this.style; ,原因是每次都要优化,避免正常化。对于该方法中调用getStroke()方法,传入的style.textStoke属性是将textStroke可以设置为一些颜色作为默认值在上层应用程序,其中textStroke宽度的默认值应该是0,以确保用户可以选择不使用textStroke。然后对于rect var rect = textUtil.getBoundingRect(style.text + '', style.font, style.textAlign, style.textVerticalAlign, style.textPadding, style.textLineHeight, style.rich)的一些属性进行设置,在rect创建时,需要style的一些属性进行初始化,这些都是必须的初始化。而后对于rect的x1,y1,x2,y2以及宽高等进行设置,最后将rect赋给this.__boundingRect属性,最后将该属性返回。需要注意一点,此方法返回的是没有经过 transform(translate/scale/rotate/skew) 处理的边界矩形,但是对 shape 属性直接进行的修改会反映在获取的边界矩形上。例如,用代码直接对 this.shape.width 进行赋值,那么在计算边界矩形时就会用新的 width 属性进行计算。这是需要注意的地方,因此需要对rect进行一些处理,才能进行操作。

关键代码段

 rect.x2 = rect.x1 + rect.width;
        rect.y2 = rect.y1 + rect.height;
        rect.x1 = parseInt(rect.x1);
        rect.y1 = parseInt(rect.y1);
        rect.x2 = parseInt(rect.x2);
        rect.y2 = parseInt(rect.y2);
        rect.width = parseInt(rect.width);
        rect.height = parseInt(rect.height);
        this.__boundingRect = rect;

该段代码中主要是对getBoundingRect方法中的text以及rect等进行创建和赋值,以及对于rect的x1,y1、以及width、height等进行赋值操作。

var text = style.text;
        text != null ? text += '' : text = '';
        var rect = textUtil.getBoundingRect(style.text + '', style.font, style.textAlign, style.textVerticalAlign, style.textPadding, style.textLineHeight, style.rich);
        rect.x1 += style.x || 0;
        rect.y1 += style.y || 0;

        if (textUtil.getStroke(style.textStroke, style.textStrokeWidth)) {
    
    
          var w = style.textStrokeWidth;
          rect.x1 -= w / 2;
          rect.y1 -= w / 2;
          rect.width += w;
          rect.height += w;

总结

通过本次学习,我们主要了解了两个方法,以及其中的一些小的连接方法,这两个方法是对边界矩阵的创建(getBoundingRect)、关键图像生成(pathToImage)等方法,由于其他原因,剩下的方法我们下次再继续学习。

猜你喜欢

转载自blog.csdn.net/qq_53259920/article/details/121271280
今日推荐