canvas 缩放/拖动/还原/封装和实例--开箱即用

5 篇文章 0 订阅

一、预览

如果是小程序,可以看这里小程序canvas缩放/拖动/还原/封装和实例

最近需要用到canvas的缩放、拖动、还原等操作,网上有些资料,但用起来都不太方便,自己重新写了一个操作类,能满足上述使用情况,而且用起来很方便,也很灵活。

  • 支持画布尺寸和css尺寸不一致
  • 支持触摸/鼠标拖拽
  • 支持滚轮/按钮缩放
  • 支持还原、清除画布等操作

效果如下:

在这里插入图片描述

二、使用

2.1 创建和配置

 // 创建对象并进行配置
 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 方法

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

三、重点说明

3.1 配置里有2个宽高设置

 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>

对应canvas元素的2个宽高属性,分别是画布和css。
二者可以不一致,也就是说画布也可以1000px,但css设置为500px,你实际看到的是画布缩小了1倍来显示,主要方便css的页面布局

3.2 分开设置事件

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

你可以根据实际情况只添加滚轮事件或者拖动事件,或者都不添加

四、源码

<!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

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

  • 18
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值