canvas放大模糊问题及拖拽

738 阅读2分钟

    最近在使用Canvas绘图,里面有一个功能点是实现随鼠标滚轮滚动放大和缩小的功能,但放大之后的会出现字体模糊的情况,之前查了好多方法也都不太好用,经过翻看文档,终于找到了解决方法。

放大模糊

    通过修改CSS可以实现canvas的放大和缩小,但是放大后的canvas会模糊。也有通过devicePixelRatio来实现的,但是devicePixcelRatio是用来获取屏幕像素比,用于在不同像素比的屏幕切换是可行的,但不适用于像素比不变的屏幕的中做放大模糊处理。

解决方案

<canvas id="canvas"></canvas>
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext("2d");

let zoomNum = 1;

const init = () => {
  canvas.width = 800;
  canvas.height = 800;
  ctx.scale(zoomNum, zoomNum);
  ctx.translate(x, y);
  const text = '字体放大模糊';
  drawText(ctx, text, { x: 30, y: 30 });
};

const wheelEvent = (e) => {
  if (e.deltaY < 0) {
    zoomNum += 0.3;
  } else {
    zoomNum -= 0.3;
  }
};

const bindEvent = () => {
  canvas.addEventListener("wheel", wheelEvent, false);
}

init()
bindEvent()

    使用canvas本身的的scale来实现内容的缩放并能保持清晰度,不会修改canvas本身的大小,只是对canvas的内容进行放大。随着内容的放大,内容的宽高会超过canvas本身的大小,这时就需要通过拖拽来查看超出的显示区域的内容。

拖拽

    这里的拖拽是根据鼠标的移动,然后对canvas进行偏移来实现的,代码如下:

const bindEvent = () => {
  canvas.addEventListener("mousedown", mouseDownEvent, false);
  canvas.addEventListener("mousemove", mouseMoveEvent, false);
  canvas.addEventListener("mouseup", mouseUpEvent, false);
};

let x = 0;
let y = 0;
let lastClickPoint = {
  x: 0,
  y: 0
};

let diff = {
  x: 0,
  y: 0
};
let isDragging = false;

const mouseDownEvent = (e) => {
  isDragging = true;
  lastClickPoint.x = e.clientX;
  lastClickPoint.y = e.clientY;
};
const mouseMoveEvent = (e) => {
  if (isDragging) {
    const currentX = e.clientX;
    const currentY = e.clientY;
    diff.x = currentX - lastClickPoint.x;
    diff.y = currentY - lastClickPoint.y;
    lastClickPoint.x = currentX
    lastClickPoint.y = currentY
    x += diff.x / zoomNum
    y += diff.y / zoomNum
  }
};
const mouseUpEvent = (e) => {
  isDragging = false;
};

    鼠标按下即作为开始拖拽的标志,同时记录开始拖拽的坐标,通过计算鼠标移动的坐标差值就能得到canvas偏移的多少,然后调用canvas的translate方法就可以实现拖拽功能了。

    无论是缩放还是拖拽,都需要清空canvas的画布进行重绘,所以需要添加一个重绘的方法。

重绘

    重绘其实就是清空现有画布之后然后重新调用初始化的方法。代码如下:

const reRenderCanvas = () => {
  clearCanvas();
  init();
};

const clearCanvas = () => {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
};

    至此,canvas的放大模糊问题就解决了。
    完整代码如下: