jsPDF 中的 Matrix 类在 React 中无法访问

问题描述 投票:0回答:2

我使用 jsPDF 作为 ReactJS 项目的一部分,我尝试使用方法 jsPDF.setCurrentTransformationMatrix() ,它需要一个

Matrix
实例。但是 jsPDF 包没有导出 Matrix 类。

我想知道这是 jsPDF 的问题还是我做错了什么?

作为参考,这里是我想要运行的代码的简化版本 - 这个想法是在绘制线条之前应用变换(平移和/或旋转):

import React from 'react';
import { jsPDF, Matrix } from 'jspdf';

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.generatePdf = this.generatePdf.bind(this);
  }

  generatePdf() {
    const pdf = new jsPDF('p', 'mm', 'A4');
    const lines = [[100, 100], [-100, 100], [-100, -100], [100, -100]];
    const matrix = new Matrix();
    pdf.setCurrentTransformationMatrix(matrix);
    pdf.lines(lines, 105, 140);
    pdf.save('test.pdf');
  }

  render() {
    return (
      <button onClick={this.generatePdf}>Generate PDF</button>
    );
  }
}

export default MyComponent;
reactjs jspdf
2个回答
0
投票

如果有人需要这个矩阵,我会从源代码中获取这个矩阵并将其更改为打字稿版本。所以它来了:

class Point {
  protected _x = 0;
  protected _y = 0;

  protected _type = 'pt';

  constructor(x: number, y: number) {
    this._x = x || 0;
    this._y = y || 0;
  }

  get x(): number {
    return this._x;
  }

  set x(value: string | number) {
    if (!isNaN(value as any)) {
      this._x = parseFloat(value as any);
    }
  }

  get y(): number {
    return this._y;
  }

  set y(value: number | string) {
    if (!isNaN(value as any)) {
      this._y = parseFloat(value as any);
    }
  }

  get type(): string {
    return this._type;
  }

  set type(value: any) {
    this._type = value.toString();
  }
}

class Rectangle extends Point {
  protected _w = 0;
  protected _h = 0;

  constructor(x: number, y: number, w: number, h: number) {
    super(x, y);
    this.type = 'rect';
    this.w = w;
    this.h = h;
  }

  get w(): number {
    return this._w;
  }

  set w(value: number | string) {
    if (!isNaN(value as any)) {
      this._w = parseFloat(value as any);
    }
  }

  get h(): number {
    return this._h;
  }

  set h(value: number | string) {

    if (!isNaN(value as any)) {
      this._h = parseFloat(value as any);
    }
  }
}

/**
 * A matrix object for 2D homogenous transformations: <br>
 * | a b 0 | <br>
 * | c d 0 | <br>
 * | e f 1 | <br>
 * pdf multiplies matrices righthand: v' = v x m1 x m2 x ...
 *
 */
class Matrix {
  protected matrix: number[] = [];

  precision!: number;

  constructor(
    sx: number,
    shy: number,
    shx: number,
    sy: number,
    tx: number,
    ty: number
  ) {
    this.sx = !isNaN(sx) ? sx : 1;
    this.shy = !isNaN(shy) ? shy : 0;
    this.shx = !isNaN(shx) ? shx : 0;
    this.sy = !isNaN(sy) ? sy : 1;
    this.tx = !isNaN(tx) ? tx : 0;
    this.ty = !isNaN(ty) ? ty : 0;
  }

  get sx(): number {
    return this.matrix[0];
  }

  set sx(value: number) {
    this.matrix[0] = value;
  }

  get shy(): number {
    return this.matrix[1];
  }

  set shy(value: number) {
    this.matrix[1] = value;
  }

  get shx(): number {
    return this.matrix[2];
  }

  set shx(value: number) {
    this.matrix[2] = value;
  }

  get sy(): number {
    return this.matrix[3];
  }

  set sy(value: number) {
    this.matrix[3] = value;
  }

  get tx(): number {
    return this.matrix[4];
  }

  set tx(value: number) {
    this.matrix[4] = value;
  }

  get ty(): number {
    return this.matrix[5];
  }

  set ty(value: number) {
    this.matrix[5] = value;
  }

  get a(): number {
    return this.matrix[0];
  }

  set a(value) {
    this.matrix[0] = value;
  }

  get b(): number {
    return this.matrix[1];
  }

  set b(value: number) {
    this.matrix[1] = value;
  }

  get c(): number {
    return this.matrix[2];
  }

  set c(value) {
    this.matrix[2] = value;
  }

  get d(): number {
    return this.matrix[3];
  }

  set d(value: number) {
    this.matrix[3] = value;
  }

  get e(): number {
    return this.matrix[4];
  }

  set e(value: number) {
    this.matrix[4] = value;
  }

  get f(): number {
    return this.matrix[5];
  }

  set f(value: number) {
    this.matrix[5] = value;
  }

  get rotation(): number {
    return Math.atan2(this.shx, this.sx);
  }

  get scaleX(): number {
    return this.decompose().scale.sx;
  }

  get scaleY(): number {
    return this.decompose().scale.sy;
  }

  get isIdentity(): boolean {
    if (this.sx !== 1) {
      return false;
    }
    if (this.shy !== 0) {
      return false;
    }
    if (this.shx !== 0) {
      return false;
    }
    if (this.sy !== 1) {
      return false;
    }
    if (this.tx !== 0) {
      return false;
    }
    if (this.ty !== 0) {
      return false;
    }

    return true;
  }

  join(parm1: string): string {
    return ([this.sx, this.shy, this.shx, this.sy, this.tx, this.ty]).join(parm1);
  }

  multiply(matrix: Matrix): Matrix {
    const sx = matrix.sx * this.sx + matrix.shy * this.shx;
    const shy = matrix.sx * this.shy + matrix.shy * this.sy;
    const shx = matrix.shx * this.sx + matrix.sy * this.shx;
    const sy = matrix.shx * this.shy + matrix.sy * this.sy;
    const tx = matrix.tx * this.sx + matrix.ty * this.shx + this.tx;
    const ty = matrix.tx * this.shy + matrix.ty * this.sy + this.ty;

    return new Matrix(sx, shy, shx, sy, tx, ty);
  }

  decompose(): { scale: Matrix, translate: Matrix, rotate: Matrix, skew: Matrix } {
    let a = this.sx;
    let b = this.shy;
    let c = this.shx;
    let d = this.sy;
    const e = this.tx;
    const f = this.ty;

    let scaleX = Math.sqrt(a * a + b * b);

    a /= scaleX;
    b /= scaleX;

    let shear = a * c + b * d;

    c -= a * shear;
    d -= b * shear;

    const scaleY = Math.sqrt(c * c + d * d);

    c /= scaleY;
    d /= scaleY;
    shear /= scaleY;

    if (a * d < b * c) {
      a = -a;
      b = -b;
      shear = -shear;
      scaleX = -scaleX;
    }

    return {
      scale: new Matrix(scaleX, 0, 0, scaleY, 0, 0),
      translate: new Matrix(1, 0, 0, 1, e, f),
      rotate: new Matrix(a, b, -b, a, 0, 0),
      skew: new Matrix(1, 0, shear, 1, 0, 0)
    };
  }

  reverse(): Matrix {
    const det = this.a * this.d - this.b * this.c;
    if (!det) {
      return new Matrix(1, 0, 0, 1, 0, 0);
    }
    return new Matrix(
      this.a / det,
      -this.b / det,
      -this.c / det,
      this.d / det,
      (this.b * this.f - this.d * this.e) / det,
      (this.c * this.e - this.a * this.f) / det
    );
  }

  toString(parmPrecision: number): string {
    return [this.sx, this.shy, this.shx, this.sy, this.tx, this.ty].join(' ');
  }

  inversed(): Matrix {
    const a = this.sx;
    const b = this.shy;
    const c = this.shx;
    const d = this.sy;
    const e = this.tx;
    const f = this.ty;

    const quot = 1 / (a * d - b * c);
    const aInv = d * quot;
    const bInv = -b * quot;
    const cInv = -c * quot;
    const dInv = a * quot;
    const eInv = -aInv * e - cInv * f;
    const fInv = -bInv * e - dInv * f;

    return new Matrix(aInv, bInv, cInv, dInv, eInv, fInv);
  }

  applyToPoint(pt: Point): Point {
    const x = pt.x * this.sx + pt.y * this.shx + this.tx;
    const y = pt.x * this.shy + pt.y * this.sy + this.ty;

    return new Point(x, y);
  }

  applyToRectangle(rect: Rectangle): Rectangle {
    const pt1 = this.applyToPoint(new Point(rect.x, rect.y));
    const pt2 = this.applyToPoint(new Point(rect.x + rect.w, rect.y + rect.h));
    return new Rectangle(pt1.x, pt1.y, pt2.x - pt1.x, pt2.y - pt1.y);
  }

  clone(): Matrix {
    const sx = this.sx;
    const shy = this.shy;
    const shx = this.shx;
    const sy = this.sy;
    const tx = this.tx;
    const ty = this.ty;

    return new Matrix(sx, shy, shx, sy, tx, ty);
  }
}

因此,当您在 jsPdf 中使用此设置时,您需要使用 as any 并且它应该可以工作。


0
投票

您可以使用pdf.Matrix

pdf.advancedAPI(pdf => {
 pdf.Matrix(...)
})
© www.soinside.com 2019 - 2024. All rights reserved.