(四)Angular2 Canvas简单实现

一、非流畅实现

1.canvas.component.html

<button (click)="switchMark(1)">画笔</button>
<button (click)="switchMark(2)">矩形</button>
<button (click)="switchMark(3)">圆形</button>
<button (click)="switchMark(4)">文字</button>
<button (click)="switchMark(0)">撤销</button>
<input type="text" [(ngModel)]="text">
<canvas class="vp-canvas" #canvas1 width="470" height="300" style="border: 1px solid #ccc;">您的浏览器不支持画布!</canvas>
View Code

2.canvas.component.ts

  // canvas
  @ViewChild('canvas1')
  public canvasRef: ElementRef;
  // canvas1
  public canvas1;
  // contex1
  public context1;
  // 操作次数
  public canvasIndex = -1;
  // canvas图片
  public canvasData = [];
  // 轨迹结束判断
  public isSameMove = false;
  // 起点对象
  public startXY = { x1: 0, y1: 0, x2: 0, y2: 0 };
  // 开关
  public switchType = null;
  // 文字
  public Text = null;
  // 初始化canvas
  public initCanvas() {
    this.canvas1 = null;
    this.context1 = null;
    this.canvasIndex = -1;
    this.canvasData = [];
    this.isSameMove = false;
    this.startXY = { x1: 0, y1: 0, x2: 0, y2: 0 };
    this.switchType = null;
    this.Text = null;
  }
  // 生成canvas内容及事件
  public createCanvas(base64PImg) {
    this.initCanvas();
    this.canvas1 = this.canvasRef.nativeElement;
    const context1 = this.canvasRef.nativeElement.getContext('2d');
    var img = new Image();
    img.onload = function () {
      context1.drawImage(img, 0, 0, 470, 300);
    }
    img.src = base64PImg;
    this.context1 = context1;
    // 添加默认图片到历史记录
    this.canvasIndex++;
    this.canvasData.push(base64PImg);
    // 绑定canvas参数
    this.canvas1.canvas1 = this.canvasRef.nativeElement;
    this.canvas1.context1 = this.canvasRef.nativeElement.getContext('2d');
    this.canvas1.canvasIndex = this.canvasIndex;
    this.canvas1.canvasData = this.canvasData;
    this.canvas1.startXY = this.startXY;
    this.canvas1.switchType = this.switchType;
    this.canvas1.Text = this.Text;
    // 绑定canvas方法
    this.canvas1.windowToCanvas = this.windowToCanvas;
    // 绑定canvas事件
    this.canvas1.onmousedown = this.canvasMouseDown;
    this.canvas1.onmouseup = this.canvasMouseUp;
    this.canvas1.onmousemove = this.canvasMouseMove;
  }
  // 增加文字内容
  public updateText(ev) {
    this.canvas1.Text = ev;
  }
  // 切换绘制
  public switchMark(type) {
    if (type === 0) {
      this.undo();
    }
    if (type === 0) {
      this.switchType = null;
      this.canvas1.switchType = this.switchType;
      return;
    }
    this.switchType = type;
    this.canvas1.switchType = this.switchType;
  }
  // 撤销
  public undo() {
    if (this.canvas1.canvasIndex > 0) {
      this.canvasData.pop();
      this.canvas1.canvasIndex--;
      this.context1.clearRect(0, 0, 470, 300);
      var context1 = this.canvasRef.nativeElement.getContext('2d');
      var img = new Image();
      img.onload = function () {
        context1.drawImage(img, 0, 0, 470, 300);
      }
      img.src = this.canvasData[this.canvas1.canvasIndex];
    } else {
      console.log('不能再继续撤销了');
    }
  }
  // 求鼠标坐标函数
  public windowToCanvas(canvas, x, y) {
    var rect = canvas.getBoundingClientRect();
    return {
      x: x - rect.left * (canvas.width / rect.width),
      y: y - rect.top * (canvas.height / rect.height)
    };
  }
  // 鼠标按下开始绘制图形函数
  public canvasMouseDown(e) {
    if (this.switchType === null) {
      return;
    }
    this.context1.strokeStyle = 'red';
    this.context1.fillStyle = 'red';
    // 绘制曲线
    if (this.switchType === 1) {
      this.isSameMove = true;
      var ele = this.windowToCanvas(this.canvas1, e.clientX, e.clientY);
      this.context1.beginPath();
      this.context1.moveTo(ele.x, ele.y);
    }
    // 绘制矩形
    if (this.switchType === 2) {
      var ele = this.windowToCanvas(this.canvas1, e.clientX, e.clientY);
      this.startXY.x1 = ele.x;
      this.startXY.y1 = ele.y;
    }
    // 绘制圆形
    if (this.switchType === 3) {
      var ele = this.windowToCanvas(this.canvas1, e.clientX, e.clientY);
      this.startXY.x1 = ele.x;
      this.startXY.y1 = ele.y;
    }
    // 绘制文字
    if (this.switchType === 4) {
      var str = this.Text;
      var ele = this.windowToCanvas(this.canvas1, e.clientX, e.clientY);
      this.startXY.x1 = ele.x;
      this.startXY.y1 = ele.y;
      this.context1.font = "24px Arial";
      this.context1.fillText(str, ele.x, ele.y);
    }
  }
  // 鼠标弹起
  public canvasMouseUp(e) {
    if (this.switchType === null) {
      return;
    }
    // 曲线
    if (this.switchType === 1) {
      this.isSameMove = false;
    }
    // 矩形
    if (this.switchType === 2) {
      var ele = this.windowToCanvas(this.canvas1, e.clientX, e.clientY);
      this.startXY.x2 = ele.x;
      this.startXY.y2 = ele.y;
      this.context1.strokeRect(this.startXY.x1, this.startXY.y1, this.startXY.x2 - this.startXY.x1, this.startXY.y2 - this.startXY.y1);
    }
    // 圆形
    if (this.switchType === 3) {
      var ele = this.windowToCanvas(this.canvas1, e.clientX, e.clientY);
      this.startXY.x2 = ele.x;
      this.startXY.y2 = ele.y;
      this.context1.beginPath();
      var cx = (this.startXY.x1 + this.startXY.x2) / 2;
      var cy = (this.startXY.y1 + this.startXY.y2) / 2;
      var rx = Math.abs((this.startXY.x1 - this.startXY.x2) / 2);
      var ry = Math.abs((this.startXY.y1 - this.startXY.y2) / 2);
      this.context1.ellipse(cx, cy, rx, ry, 0, 0, Math.PI * 2);
      this.context1.stroke();
    }
    this.canvas1.canvasIndex++;
    this.canvasData.push(this.canvas1.toDataURL());
  }
  // 鼠标移动
  public canvasMouseMove(e) {
    if (this.switchType === 1) {
      if (this.isSameMove) {
        var ele = this.windowToCanvas(this.canvas1, e.clientX, e.clientY);
        this.context1.lineTo(ele.x, ele.y);
        this.context1.stroke();
        this.context1.save();
      }
    }
  }
View Code

 二、流畅实现

1.canvas.component.html

<canvas class="vp-canvas1" #canvas1 [width]="canvasWidth" [height]="canvasHeight">您的浏览器不支持画布!</canvas>
<canvas class="vp-canvas2" #canvas2 [width]="canvasWidth" [height]="canvasHeight">您的浏览器不支持画布!</canvas>
View Code

2.canvas.component.ts

  /** canvas1 */
  @ViewChild('canvas1')
  public canvas1Ref: ElementRef;
  /** canvas2 */
  @ViewChild('canvas2')
  public canvas2Ref: ElementRef;
  /** 绘制类型 */
  public readonly markCfg = [
    { value: 2, label: '矩形', class: 'mark-rectangle' },
    { value: 3, label: '圆形', class: 'mark-ellipse' },
    { value: 1, label: '曲线', class: 'mark-curves' },
    { value: 4, label: '文字', class: 'mark-text' },
    { value: 0, label: '撤销', class: 'rotation-anticw-d2' },
  ];
  /** 当前绘制类型 */
  public switchMarkType: number;
  /** 鼠标按下状态 */
  public isMouseDown: boolean;
  /** 文字绘制 */
  public MarkTexts: string;
  /** 文字绘制弹窗 */
  public nzmdMarkText: boolean;
  /** 绘制颜色 */
  public readonly markColorCfg = ['#ef4343', '#ef7c43'];
  /** 默认绘制颜色 */
  public defaultMarkColor: string;
  /** canvas1 */
  public canvas1;
  /** canvas1的contex1 */
  public context1;
  /** canvas2 */
  public canvas2;
  /** canvas2的contex2 */
  public context2;
  /** canvas宽度 */
  public canvasWidth: number = 952;
  /** canvas高度 */
  public canvasHeight: number = 477;
  /** canvas操作次数 */
  public canvasIndex: number;
  /** canvas图像源 */
  public canvasData;
  /** 鼠标坐标 */
  public mouseXY = { x1: 0, y1: 0, x2: 0, y2: 0 };
  /** 初始化canvas */
  public initCanvas() {
    this.switchMarkType = null;
    this.isMouseDown = false;
    this.MarkTexts = null;
    this.nzmdMarkText = false;
    this.defaultMarkColor = '#ef4343';
    this.canvasIndex = -1;
    this.canvasData = [];
    this.mouseXY = { x1: 0, y1: 0, x2: 0, y2: 0 };
  }
  /** 生成canvas图像及绑定参数和事件 */
  public createCanvas(base64PImg) {
    this.initCanvas();
    this.canvas1 = this.canvas1Ref.nativeElement;
    this.context1 = this.canvas1Ref.nativeElement.getContext('2d');
    this.canvas2 = this.canvas2Ref.nativeElement;
    this.context2 = this.canvas2Ref.nativeElement.getContext('2d');
    // 绑定canvas变量
    this.canvas1.canvasIndex = this.canvasIndex;
    this.canvas1.canvasData = this.canvasData;
    // 绑定canvas事件
    this.canvas1.onmousedown = this.canvasMouseDown;
    this.canvas1.onmouseup = this.canvasMouseUp;
    this.canvas1.onmousemove = this.canvasMouseMove;
    // 添加默认图片到历史记录
    this.setCanvasImage(this.context2, this.canvas2, base64PImg, this.canvasWidth, this.canvasHeight, (url) => {
      this.canvas1.canvasIndex++;
      this.canvasData.push(url);
    });
  }
  /** 切换绘制 */
  public switchMark(markType: number) {
    if (markType === 0) {
      this.undo();
    }
    if (markType !== 4) {
      this.nzmdMarkText = false;
    }
    if (this.switchMarkType === markType || markType === 0) {
      this.switchMarkType = null;
      return;
    }
    this.switchMarkType = markType;
  }
  /** 提交文字绘制 */
  public MarkText() {
    this.context1.font = "24px Arial";
    if(isNull(this.MarkTexts)) return console.log('文字内容不能为空');
    this.context1.fillText(this.MarkTexts, this.mouseXY.x1, this.mouseXY.y1);
    this.setCanvasImage(this.context2, this.canvas2, this.canvas1.toDataURL(), this.canvasWidth, this.canvasHeight, (url) => {
      this.context1.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
      this.canvas1.canvasIndex++;
      this.canvasData.push(url);
    })
    this.MarkTextCancel();
  }
  /** 取消文字绘制 */
  public MarkTextCancel() {
    this.MarkTexts = null;
    this.nzmdMarkText = false;
  }
  /** 撤销 */
  public undo() {
    if (this.canvas1.canvasIndex > 0) {
      this.canvasData.pop();
      this.canvas1.canvasIndex--;
      this.setCanvasImage(this.context2, this.canvas2, this.canvasData[this.canvas1.canvasIndex], this.canvasWidth, this.canvasHeight, (url) => {
        return;
      });
    } else {
      this.nzmsgSrv.warning('不能再继续撤销了');
    }
  }
  /** 设置绘制颜色 */
  public colorChange(color: string) {
    this.defaultMarkColor = color;
  }
  /** 鼠标按下 */
  public canvasMouseDown = (e) => {
    if (this.switchMarkType === null) {
      return;
    }
    this.isMouseDown = true;
    // 设置线条样式
    this.context1.lineWidth = '2';
    this.context1.strokeStyle = this.defaultMarkColor;
    this.context1.fillStyle = this.defaultMarkColor;
    // 设置起点坐标
    this.setMouseXY(true, e);
    // 绘制曲线
    if (this.switchMarkType === 1) {
      this.context1.beginPath();
      this.context1.moveTo(this.mouseXY.x1, this.mouseXY.y1);
    }
    // 设置文字坐标
    if (this.switchMarkType === 4) {
      this.nzmdMarkText = true;
    }
  }
  /** 鼠标弹起 */
  public canvasMouseUp = (e) => {
    this.isMouseDown = false;
    if (this.switchMarkType === null || this.switchMarkType === 4) {
      return;
    }
    this.setCanvasImage(this.context2, this.canvas2, this.canvas1.toDataURL(), this.canvasWidth, this.canvasHeight, (url) => {
      this.context1.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
      this.canvas1.canvasIndex++;
      this.canvasData.push(url);
    })
  }
  /** 鼠标移动 */
  public canvasMouseMove = (e) => {
    if (this.isMouseDown) {
      // 清除canvas1上的图像
      this.context1.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
      // 绘制线
      if (this.switchMarkType === 1) {
        // 记录起点坐标
        this.setMouseXY(true, e);
        this.context1.lineTo(this.mouseXY.x1, this.mouseXY.y1);
        this.context1.stroke();
        this.context1.save();
      }
      // 记录终点坐标
      this.setMouseXY(false, e);
      // 绘制矩形
      if (this.switchMarkType === 2) {
        this.context1.strokeRect(this.mouseXY.x1, this.mouseXY.y1, this.mouseXY.x2 - this.mouseXY.x1, this.mouseXY.y2 - this.mouseXY.y1);
      }
      // 绘制圆形
      if (this.switchMarkType === 3) {
        this.context1.beginPath();
        var cx = (this.mouseXY.x1 + this.mouseXY.x2) / 2;
        var cy = (this.mouseXY.y1 + this.mouseXY.y2) / 2;
        var rx = Math.abs((this.mouseXY.x1 - this.mouseXY.x2) / 2);
        var ry = Math.abs((this.mouseXY.y1 - this.mouseXY.y2) / 2);
        this.context1.ellipse(cx, cy, rx, ry, 0, 0, Math.PI * 2);
        this.context1.stroke();
      }
      // 在canvas1上绘制图像
      this.context1.drawImage(this.canvas1, 0, 0, this.canvasWidth, this.canvasHeight);
    }
  }

  /** 根据宽高生成canvas图像 */
  public setCanvasImage(context, canvas, base64PImg, canvasWidth: number, canvasHeight: number, callback) {
    let img = new Image();
    img.onload = function () {
      context.drawImage(img, 0, 0, canvasWidth, canvasHeight);
      callback(canvas.toDataURL());
    }
    img.src = base64PImg;
  }
  /** 求鼠标坐标函数 */
  public windowToCanvas(canvas, x, y) {
    const rect = canvas.getBoundingClientRect();
    return {
      x: x - rect.left * (canvas.width / rect.width),
      y: y - rect.top * (canvas.height / rect.height)
    };
  }
  /** 记录坐标 */
  public setMouseXY(start: boolean, e) {
    const ele = this.windowToCanvas(this.canvas1, e.clientX, e.clientY);
    if (start) {
      this.mouseXY.x1 = ele.x;
      this.mouseXY.y1 = ele.y;
    } else {
      this.mouseXY.x2 = ele.x;
      this.mouseXY.y2 = ele.y;
    }
  }
View Code
原文地址:https://www.cnblogs.com/chendongbky/p/12027481.html