canvas常用简单绘制方法封装

81 阅读3分钟

绘制点

/**
 * 画点
 * @param {*} x 起点坐标X
 * @param {*} y 起点坐标Y
 * @param {*} radius 点半径
 * @param {*} fillStyle 填充颜色
 */
export function drawDot(ctx, x, y, radius, fillStyle = 'rgb(191, 191, 191)') {
  ctx.beginPath();
  ctx.arc(x, y, radius, 0, 2 * Math.PI);
  ctx.fillStyle = fillStyle;
  ctx.fill();
  ctx.closePath();
}

绘制线

/**
 * 画线
 * @param {*} x 起点坐标X
 * @param {*} y 起点坐标Y
 * @param {*} lineWidth 线宽度
 * @param {*} length 线长度
 * @param {*} type 水平、垂直
 * @param {*} strokeStyle 颜色
 */
export function drawLin(ctx, x, y, lineWidth, length, strokeStyle = "rgb(0,32,96)", type = "horizontal") {
  ctx.beginPath();
  ctx.lineWidth = lineWidth;
  ctx.strokeStyle = strokeStyle;
  ctx.moveTo(x, y);
  ctx.lineCap = 'round ';
  // 水平线
  if (type == "horizontal") {
    ctx.lineTo(x + length, y);
  }
  // 垂直线
  if (type == "vertical") {
    ctx.lineTo(x, y + length);
  }
  ctx.stroke();
}

绘制虚线

/**
 * 画虚线
 * @param {*} x x坐标
 * @param {*} y y坐标
 * @param {*} lineLength 线长度
 * @param {*} lineWidth 先宽度
 * @param {*} strokeStyle 颜色
 */
export function drawDashed(ctx, x, y, lineLength, lineWidth, strokeStyle) {
  ctx.lineWidth = lineWidth;
  ctx.strokeStyle = strokeStyle;
  ctx.beginPath();
  ctx.setLineDash([10, 5]);
  ctx.moveTo(x, y);
  ctx.lineTo(x + lineLength, y);
  ctx.stroke();
  ctx.setLineDash([]);
}

绘制三角形

/**
 * 画三角形
 * @param {*} x1 第一个点x坐标
 * @param {*} y1 第一个点y坐标
 * @param {*} x2 第二个点x坐标
 * @param {*} y2 第二个点y坐标
 * @param {*} x3 第三个点x坐标
 * @param {*} y3 第三个点y坐标
 * @param {*} fillStyle 颜色
 */
export function drawDelta(ctx, x1, y1, x2, y2, x3, y3, fillStyle) {
  ctx.beginPath();
  ctx.moveTo(x1, y1);
  ctx.lineTo(x2, y2);
  ctx.lineTo(x3, y3);
  ctx.fillStyle = fillStyle;
  ctx.closePath();
  ctx.fill();
}

绘制长方形框

// 空心框
ctx.lineWidth = lineWidth;
ctx.strokeStyle = strokeStyle
ctx.strokeRect(x, y, width, height);
// 实心框
ctx.fillStyle = fillStyle;
ctx.fillRect(x, y, width, height)

绘制箭头

/**
 * 画箭头
 * @param {*} fromX 起点坐标X
 * @param {*} fromY 起点坐标Y
 * @param {*} toX 终点坐标 X
 * @param {*} toY 终点坐标 Y
 * @param {*} theta 三角斜边一直线夹角
 * @param {*} headlen 三角斜边长度
 * @param {*} width 箭头线宽度
 * @param {*} color 箭头颜色
 */
export function drawArrow(ctx, fromX, fromY, toX, toY, theta, headlen, width, color) {

  theta = typeof (theta) != 'undefined' ? theta : 30;
  headlen = typeof (theta) != 'undefined' ? headlen : 10;
  width = typeof (width) != 'undefined' ? width : 1;
  color = typeof (color) != 'color' ? color : 'rgb(0,32,96)';

  // 计算各角度和对应的P2,P3坐标
  var angle = Math.atan2(fromY - toY, fromX - toX) * 180 / Math.PI,
    angle1 = (angle + theta) * Math.PI / 180,
    angle2 = (angle - theta) * Math.PI / 180,
    topX = headlen * Math.cos(angle1),
    topY = headlen * Math.sin(angle1),
    botX = headlen * Math.cos(angle2),
    botY = headlen * Math.sin(angle2);

  ctx.save();
  ctx.beginPath();

  var arrowX = fromX - topX,
    arrowY = fromY - topY;

  ctx.moveTo(arrowX, arrowY);
  ctx.moveTo(fromX, fromY);
  ctx.lineTo(toX, toY);
  arrowX = toX + topX;
  arrowY = toY + topY;
  ctx.moveTo(arrowX, arrowY);
  ctx.lineTo(toX, toY);
  arrowX = toX + botX;
  arrowY = toY + botY;
  ctx.lineTo(arrowX, arrowY);
  ctx.strokeStyle = color;
  ctx.lineWidth = width;
  ctx.stroke();
}

绘制文本

    • fillText(text, x, y [, maxWidth])
    • strokeText(text, x, y [, maxWidth])

文本样式属性:

字体: font

对齐方式 :textAlign 值:start end left right center 默认:start

基线对齐方式:textBaseline 值:ophanging middle alphabetic ideographic bottom 默认: alphabetic

方向 : direction 值: ltr rtl inherit 默认:inherit

// html
	<canvas id="tutorial" width="150" height="150"></canvas>

// js
		// canvas 绘制文本
    const canvasEle = document.querySelector("#tutorial");
    const cxt = canvasEle.getContext("2d");

    const documentElement = document.documentElement;
    // 设置canvas的宽高全屏
    canvasEle.width = documentElement.clientWidth;
    canvasEle.height = documentElement.clientHeight;
    cxt.fillText("heihei", 100, 100)

    // 文字样式
    cxt.font = "20px serif"
    cxt.textAlign = "center"
    cxt.textBaseline = "middle"
    cxt.fillText("heihei", 100, 100)

绘制多行文本

/**
 * 文本分段
 * @param {*} text 文本
 * @param {*} maxWidth 每行最大宽度
 */
export function getWrapText(ctx, text, maxWidth) {
  if (!text) {
    return []
  }
  let txtList = [];
  let str = "";
  for (let i = 0, len = text.length; i < len; i++) {
    str += text.charAt(i);
    if (ctx.measureText(str).width > maxWidth) {
      txtList.push(str.substring(0, str.length - 1))
      str = ""
      i--
    }
  }
  txtList.push(str)
  return txtList;
}

/**
 * 画多行文本
 * @param {*} x 起点坐标X
 * @param {*} y 起点坐标Y
 * @param {*} text 文本数组
 * @param {*} font 文本样式
 * @param {*} fillStyle 文本颜色
 */
export function drawText(ctx, x, y, wrapTexts, font = "14px Arial", fillStyle = 'rgb(0,32,96)', lineHeight = 15, maxWidth = 150) {
  ctx.font = font;
  ctx.fillStyle = fillStyle;
  let height = wrapTexts.length * lineHeight
  wrapTexts.forEach((txt, index) => {
    ctx.fillText(txt, x, y + lineHeight * index, maxWidth);
  })
  return height
}

绘制图片

/**
 * 加载图片
 * @param {*} url 图片地址
 * @param {*} isRight 是否在右侧
 * @param {*} imgWidth 图片宽度
 * @param {*} imgHeight 图片高度
 */
export function loadImage(url, imgWidth, imgHeight) {
  return new Promise((resolve, reject) => {
    //创建img元素
    let img = new Image();
    //设置图片源地址
    img.src = url;
    // 跨域
    img.setAttribute("crossOrigin", 'Anonymous');
    img.onload = function () {
      let width = imgWidth;
      let height = imgHeight;
      let x = 0, y = 0;
      if (this.height / this.width <= (height / width)) {
        let oldHeight = height;
        height = this.height / (this.width / width);
        y = (oldHeight - height) / 2;
      } else {
        let oldWidth = width;
        width = this.width / (this.height / height);
        x = (oldWidth - width) / 2;
      }
      resolve({
        img,
        width, // 图片实际宽度
        height, // 图片实际高度
        x, // 图片左右的留白
        y // 图片上下的留白
      })
    }
    img.onerror = function (err) {
      console.log(err);
      reject()
    }
  })
}

async test() {
  // 画图片
  let {img, width: iWidth, height: iHeight} = await loadImage(url, imgWidth, imgHeight)
  ctx.drawImage(img, x, y, iWidth, iHeight)
}

设置高清canvas

注意: 先把canvas设为高清,再画东西,

当使用canvas宽度时,要用设置高清之前的canvas宽度

/**
 * 高清canvas
 * @param {*} canvas 要高清的canvas
 */
export function createHDCanvas(canvas) {
  var ratio = 3
  let lowCanvas = document.getElementById('eventLine')
  let ctx = canvas.getContext('2d');
  canvas.width = Math.floor(lowCanvas.width * ratio); // 实际渲染像素
  canvas.height = Math.floor(lowCanvas.height * ratio); // 实际渲染像素
  canvas.style.width = `${canvas.width}px`; // 控制显示大小
  canvas.style.height = `${canvas.height}px`; // 控制显示大小
  ctx.scale(ratio, ratio);
  return canvas;
}