Canvas zoom/drag/restore/wrapper and instancing -- out of the box

1. Preview

If it is a small program, you can see here the small program canvas zoom/drag/restore/encapsulation and examples

Recently, I need to use canvas zooming, dragging, restoring and other operations. There are some information on the Internet, but it is not very convenient to use. I re-wrote an operation class by myself, which can meet the above usage conditions, and it is very convenient and flexible to use. .

  • Support canvas size and css size inconsistency
  • Support touch/mouse drag
  • Support wheel/button zoom
  • Support restore, clear canvas and other operations

The effect is as follows:

insert image description here

Two, use

2.1 Creation and configuration

 // 创建对象并进行配置
 var canvas = new CanvasOperation({
    
    
    ele: document.getElementById("canvas"), // 画布对象
    draw: userDraw, // 用户绘图方法
    width: 500, // 画布宽
    height: 500, // 画布高
    cssWidth: 500, // css设置的宽(对应css style的width)
    cssHeight: 500, // css设置的高(对应css style的height)
    maxScale: 8, // 缩放最大倍数(缩放比率倍数)
    minScale: 0.4, // 缩放最小倍数(缩放比率倍数)
    scaleStep: 0.2, // 缩放比率
 });

 canvas.addMusewheelEvent(); // 添加滚轮放大缩小事件
 canvas.addDragEvent(); // 添加拖动事件
 canvas.draw(); // 开始绘图

  // 用户绘图(这里写你的绘图方法)
  function userDraw() {
    
    
    this.ctx.fillStyle = "#f00";
    this.ctx.fillRect(0, 0, 100, 100);
    this.ctx.fillStyle = "#00f";
    this.ctx.fillRect(150, 150, 200, 200);
    this.ctx.fillStyle = "#0f0";
    this.ctx.fillRect(400, 400, 100, 100);
  }

2.2 Method

canvas.addMusewheelEvent(); // 添加滚轮放大缩小事件
canvas.addDragEvent(); // 添加拖动事件
canvas.draw(); // 绘图
canvas.zoomIn(); // 中心放大
canvas.zoomOut(); // 中心缩小
canvas.reset(); // 还原
canvas.clear(); // 清除画布

3. Highlights

3.1 There are 2 width and height settings in the configuration

 width: 500, // 画布宽
 height: 500, // 画布高
 cssWidth: 500, // css设置的宽(对应css style的width)
 cssHeight: 500, // css设置的高(对应css style的height)
<canvas id="canvas" width="500" height="500" style="width: 500px; height: 500px"></canvas>

Corresponding to the two width and height attributes of the canvas element, they are canvas and css.
The two can be inconsistent, that is to say, the canvas can also be 1000px, but the css is set to 500px, what you actually see is that the canvas is reduced by 1 times to display, which is mainly convenient for the page layout of css

3.2 Set events separately

 canvas.addMusewheelEvent(); // 添加滚轮放大缩小事件
 canvas.addDragEvent(); // 添加拖动事件

You can add only the wheel event or the drag event, or neither according to the actual situation

4. Source code

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>canvas 缩放/拖动/还原/封装和实例</title>
  </head>
  <body>
    <div class="container">
      <h1>canvas 缩放/拖动/还原/封装和实例 -- 大话主席</h1>
      <div class="btns">
        <button onclick="zoomIn()">放大</button>
        <button onclick="zoomOut()">缩小</button>
        <button onclick="reset()">还原</button>
      </div>
      <canvas
        id="canvas"
        width="500"
        height="500"
        style="width: 500px; height: 500px"
      ></canvas>
    </div>

    <script type="text/javascript">
      // 创建对象并进行配置
      var canvas = new CanvasOperation({
      
      
        ele: document.getElementById("canvas"), // 画布对象
        draw: userDraw, // 用户绘图方法
        width: 500, // 画布宽
        height: 500, // 画布高
        cssWidth: 500, // css设置的宽(对应css style的width)
        cssHeight: 500, // css设置的高(对应css style的height)
        maxScale: 8, // 缩放最大倍数(缩放比率倍数)
        minScale: 0.4, // 缩放最小倍数(缩放比率倍数)
        scaleStep: 0.2, // 缩放比率
      });

      canvas.addMusewheelEvent(); // 添加滚轮放大缩小事件
      canvas.addDragEvent(); // 添加拖动事件
      canvas.draw();

      // 用户绘图
      function userDraw() {
      
      
        this.ctx.fillStyle = "#f00";
        this.ctx.fillRect(0, 0, 100, 100);
        this.ctx.fillStyle = "#00f";
        this.ctx.fillRect(150, 150, 200, 200);
        this.ctx.fillStyle = "#0f0";
        this.ctx.fillRect(400, 400, 100, 100);
      }

      // 放大
      function zoomIn() {
      
      
        canvas.zoomIn();
      }

      // 缩小
      function zoomOut() {
      
      
        canvas.zoomOut();
      }

      // 还原
      function reset() {
      
      
        canvas.reset();
      }

      // canvas操作类
      function CanvasOperation(option) {
      
      
        if (!option.ele || !option.draw) return;
        this.ele = option.ele; // 画布对象
        this.userDraw = option.draw; // 用户绘图方法
        this.width = option.width || 500; // 画布宽
        this.height = option.height || 500; // 画布高
        this.cssWidth = option.cssWidth || this.width; // css设置的宽
        this.cssHeight = option.cssHeight || this.height; // css设置的高
        this.maxScale = option.maxScale || 8; // 缩放最大倍数(缩放比率倍数)
        this.minScale = option.minScale || 0.4; // 缩放最小倍数(缩放比率倍数)
        this.scaleStep = option.scaleStep || 0.2; // 缩放比率
        this.ctx = this.ele.getContext("2d");
        var _this = this;
        var scale = 1; // 当前缩放
        var preScale = 1;
        var offset = {
      
       x: 0, y: 0 }; // 拖动偏移
        var curOffset = {
      
       x: 0, y: 0 }; // 当前偏移
        var mousePos = {
      
       x: 0, y: 0 }; // 鼠标位置
        var widthRatio = this.width / this.cssWidth; // 画布和css宽比率
        var heightRatio = this.height / this.cssHeight; //  画布和css高比率
        console.log(widthRatio);
        console.log(heightRatio);

        // 判断是否移动端,移动端使用触摸事件
        var isTouchPad = /hp-tablet/gi.test(navigator.appVersion);
        var hasTouch = "ontouchstart" in window && !isTouchPad;
        var touchStart = hasTouch ? "touchstart" : "mousedown";
        var touchMove = hasTouch ? "touchmove" : "mousemove";
        var touchEnd = hasTouch ? "touchend" : "mouseup";

        // 绘图(会进行缩放和位移)
        this.draw = function () {
      
      
          this.clearCanvas();
          this.ctx.translate(offset.x, offset.y);
          this.ctx.scale(scale, scale);
          _this.userDraw();
        };

        // 放大
        this.zoomIn = function (isMouse) {
      
      
          scale += this.scaleStep;
          if (scale > this.maxScale) {
      
      
            scale = this.maxScale;
            return;
          }
          zoom.call(this, isMouse);
        };

        // 缩小
        this.zoomOut = function (isMouse) {
      
      
          scale -= this.scaleStep;
          if (scale < this.minScale) {
      
      
            scale = this.minScale;
            return;
          }
          zoom.call(this, isMouse);
        };

        /**
         * 缩放操作
         * isMouse 是否鼠标为中心缩放,true:鼠标中心缩放 false:画布中间缩放
         */
        zoom = function (isMouse) {
      
      
          // 是否居中放大
          if (isMouse) {
      
      
            mousePos.x *= widthRatio;
            mousePos.y *= heightRatio;
          } else {
      
      
            mousePos.x = this.width / 2;
            mousePos.y = this.height / 2;
          }

          offset.x = mousePos.x - ((mousePos.x - offset.x) * scale) / preScale;
          offset.y = mousePos.y - ((mousePos.y - offset.y) * scale) / preScale;
          this.draw();
          preScale = scale;
          curOffset.x = offset.x;
          curOffset.y = offset.y;
        };

        // 还原
        this.reset = function () {
      
      
          this.clear();
          this.draw();
        };

        // 仅清除地图
        this.clearCanvas = function () {
      
      
          // 重设canvas尺寸会清空地图并重置canvas内置的scale等
          this.ele.width = this.width;
        };

		// 清除地图并还原对象所有设置
        this.clear = function(){
      
      
          this.clearCanvas()
          scale = 1; // 当前缩放
          preScale = 1; // 当前缩放
          offset = {
      
       x: 0, y: 0 }; // 拖动偏移
          curOffset = {
      
       x: 0, y: 0 }; // 当前偏移
          mousePos = {
      
       x: 0, y: 0 }; //
        },

        //  添加滚轮事件
        this.addMusewheelEvent = function () {
      
      
          // 兼容FireFox
          const eventType = document.mozFullScreen
            ? "DOMMouseScroll"
            : "mousewheel";
          this.ele.addEventListener(eventType, mouseWheel);

          function mouseWheel(e) {
      
      
            mousePos.x = e.offsetX;
            mousePos.y = e.offsetY;
            var b = true;
            if (e.wheelDelta) {
      
      
              b = e.wheelDelta > 0;
            } else {
      
      
              b = e.detail < 0;
            }
            if (b) {
      
      
              _this.zoomIn(true);
            } else {
      
      
              _this.zoomOut(true);
            }
            if (e.preventDefault) {
      
      
              e.preventDefault();
            }
            return false;
          }
        };

        // 添加拖动事件
        this.addDragEvent = function () {
      
      
          this.ele.addEventListener(touchStart, dragStart);
          let x = 0;
          let y = 0;

          function dragMove(e) {
      
      
            offset.x = curOffset.x + (e.x - x) * widthRatio;
            offset.y = curOffset.y + (e.y - y) * heightRatio;
            _this.draw();
          }
          function dragEnd() {
      
      
            curOffset.x = offset.x;
            curOffset.y = offset.y;
            window.removeEventListener(touchMove, dragMove);
            window.removeEventListener(touchEnd, dragEnd);
          }

          function dragStart(e) {
      
      
            x = e.x;
            y = e.y;
            window.addEventListener(touchMove, dragMove);
            window.addEventListener(touchEnd, dragEnd);
          }
        };
      }
    </script>

    <style type="text/css">
      * {
      
      
        margin: 0;
        padding: 0;
      }
      body {
      
      
        background: #ccc;
      }
      h1 {
      
      
        padding: 30px;
      }
      .btns button {
      
      
        margin: 10px;
        padding: 3px 10px;
        cursor: pointer;
      }
      .container {
      
      
        text-align: center;
      }
      #canvas {
      
      
        margin: 0 auto;
        background: #fff;
        cursor: move;
      }
    </style>
  </body>
</html>

https://gitee.com/dhzx/canvas-operation

兄弟,如果帮到你,点个赞再走

おすすめ

転載: blog.csdn.net/iamlujingtao/article/details/119683552