Canvas实现画图、橡皮擦、保存图片、清空画板功能

<!DOCTYPE html>
<html>
  <head>
    <title>阿赛画板asai.cc</title>
    <style>
      #asaicanvas {
        border: 5px solid black;
      }
    </style>
  </head>
  <body>
    <div
      style="
        background-image: url('https://www.estun.com/skin/images/logo.gif');
        background-color: yellow;
      "
    >
      <button onclick="drawType()">切换</button>
      <button onclick="saveCanvas()">下载</button>
      <button onclick="clearCanvas()">清空</button>
      <canvas id="asaicanvas" width="800" height="600"></canvas>
    </div>
    <script>
      // 获取canvas元素,并将其引用赋值给变量canvas
      const canvas = document.getElementById("asaicanvas");

      // 获取canvas元素的2d渲染上下文,并将其引用赋值给变量ctx
      const ctx = canvas.getContext("2d");

      // 加载图片,注意:异步时机问题
      const image = new Image();
      image.src = "test.png"; // 设置一张源图,可编辑
      image.onload = function () {
        ctx.drawImage(image, 0, 0);
      };

      // 基本监听
      canvas.addEventListener("mousedown", startDrawing);
      canvas.addEventListener("mousemove", draw);
      canvas.addEventListener("mouseup", stopDrawing);
      canvas.addEventListener("mouseout", stopDrawing);

      // 声明一个变量isDrawing,并设置其初始值为false。这个变量用于判断用户是否正在画板上绘制
      let isDrawing = false;
      // 声明一个变量lastX,并设置其初始值为0。这个变量用于存储上一个点的x坐标
      let lastX = 0;
      // 声明一个变量lastY,并设置其初始值为0。这个变量用于存储上一个点的y坐标
      let lastY = 0;
      // 声明一个变量lineColor,并设置其初始值为'black'。这个变量用于存储线条的颜色
      let lineColor = "black";
      // 声明一个变量lineWidth,并设置其初始值为1。这个变量用于存储线条的宽度
      let lineWidth = 20;
      // 声明一个变量lineStyle,并设置其初始值为'solid'。这个变量用于存储线条的样式(实线、虚线等)
      let lineStyle = "solid";
      // 声明一个变量fillStyle,并设置其初始值为'transparent'。这个变量用于存储填充样式(颜色或透明)
      let fillStyle = "transparent";
      // 声明一个变量isErasing,并设置其初始值为false。这个变量用于判断用户是否正在使用橡皮擦功能
      let isErasing = false;

      // 切换画笔与橡皮擦
      function drawType() {
        isErasing = !isErasing;
      }

      // 定义startDrawing函数,该函数在用户按下鼠标时被调用。它设置isDrawing为true并存储当前鼠标位置作为上一个点的坐标
      function startDrawing(event) {
        isDrawing = true;
        [lastX, lastY] = [event.clientX, event.clientY];
      }

      // 定义draw函数,该函数在用户移动鼠标时被调用。它根据isDrawing的值绘制线条,并根据需要设置线条的颜色、宽度和样式等属性
      function draw(event) {
        if (!isDrawing) return; // 如果用户没有在画板上绘制,则不执行任何操作
        ctx.beginPath(); // 开始绘制新的路径或线段

        // 启用橡皮擦功能globalCompositeOperation
        if (isErasing) {
          ctx.globalCompositeOperation = "destination-out";
        }

        ctx.lineCap = "round"; // 比默认butt要涂的更干净
        ctx.moveTo(lastX, lastY); // 将画笔移动到上一个点的位置
        ctx.lineTo(event.clientX, event.clientY); // 将画笔移动到当前鼠标位置,并创建一条线段连接这两个点
        ctx.strokeStyle = lineColor; // 设置线条的颜色为lineColor变量的值
        ctx.lineWidth = lineWidth; // 设置线条的宽度为lineWidth变量的值
        ctx.lineStyle = lineStyle; // 设置线条的样式为lineStyle变量的值(例如实线、虚线等)
        ctx.stroke(); // 绘制线条(执行上一步设置的线条属性)
        ctx.fillStyle = fillStyle; // 设置填充样式为fillStyle变量的值(例如颜色或透明)
        ctx.fill(); // 填充形状(如果设置了填充样式)
        [lastX, lastY] = [event.clientX, event.clientY]; // 更新上一个点的坐标为当前鼠标位置,以便下次绘制时使用正确的起点
      }

      // 定义stopDrawing函数,该函数在用户释放鼠标按钮时被调用。它设置isDrawing为false,表示用户已经停止绘制操作
      function stopDrawing() {
        isDrawing = false;
      }

      // 定义clearCanvas函数,该函数在用户点击“清除画板”按钮时被调用。它使用clearRect方法清除画板上的所有内容,并重新初始化所有绘图相关的变量和状态(例如上一个点的坐标、线条颜色、线条宽度等)
      function clearCanvas() {
        ctx.clearRect(0, 0, canvas.width, canvas.height); // 清除整个画板区域的内容和所有绘制的线条和形状等图形元素,恢复到初始状态
      }

      // 保存canvas上面的图像,转base64
      function saveCanvas() {
        const link = document.createElement("a");
        const base64Canvas = canvas.toDataURL("image/png"); // 将canvas转为Base64格式的图片数据URL
        console.log(666.909, base64Canvas);
        link.href = base64Canvas;
        link.download = "base64Canvas.png"; // 设置下载的文件名
        link.click(); // 触发下载
      }
    </script>
  </body>
</html>
  • 9
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
实现 Canvas 上的图片标注、缩放、移动、保存历史状态、橡皮擦功能,可以通过以下步骤来完成: 1. 加载图片。使用 JavaScript 中的 Image 对象加载图片,并在图片加载完成后将其绘制到 Canvas 上。 ```javascript const img = new Image(); // 创建 Image 对象 img.onload = function() { ctx.drawImage(img, 0, 0); // 将图片绘制到画布上 }; img.src = 'image.jpg'; // 设置图片路径 ``` 2. 实现标注功能。通过鼠标事件监听用户的操作,使用 Canvas 的 API 绘制标注。例如,监听鼠标点击事件,在点击位置绘制一个圆形。 ```javascript canvas.addEventListener('mousedown', function(e) { ctx.beginPath(); ctx.arc(e.offsetX, e.offsetY, 5, 0, 2 * Math.PI); ctx.fill(); }); ``` 3. 实现缩放和移动功能。通过鼠标滚轮事件监听用户的操作,使用 Canvas 的 API 实现缩放和移动。例如,监听鼠标滚轮事件,在滚轮滚动时根据滚动方向调整画布的缩放比例。 ```javascript canvas.addEventListener('wheel', function(e) { const delta = e.deltaY > 0 ? 0.1 : -0.1; const scale = Math.max(0.1, Math.min(10, currentScale + delta)); ctx.scale(scale, scale); currentScale = scale; }); ``` 4. 实现保存历史状态功能。使用 JavaScript 中的数组来保存历史状态,每当用户进行操作时,将当前状态保存到数组中。撤销操作时,从数组中取出上一个状态并恢复到画布上。 ```javascript const states = []; // 保存历史状态的数组 function saveState() { states.push(canvas.toDataURL()); // 保存当前状态 } function undo() { if (states.length > 0) { const img = new Image(); img.onload = function() { ctx.clearRect(0, 0, canvas.width, canvas.height); // 清空画布 ctx.drawImage(img, 0, 0); // 绘制上一个状态 }; img.src = states.pop(); // 取出上一个状态 } } ``` 5. 实现橡皮擦功能。通过监听鼠标事件,在鼠标位置绘制一个与背景相同的矩形,来模拟橡皮擦的效果。 ```javascript canvas.addEventListener('mousemove', function(e) { if (erasing) { ctx.fillStyle = '#ffffff'; // 设置橡皮擦颜色为白色 ctx.fillRect(e.offsetX - 5, e.offsetY - 5, 10, 10); // 绘制矩形 } }); ``` 完整示例代码如下: ```html <!DOCTYPE html> <html> <body> <canvas id="canvas" width="600" height="400"></canvas> <button onclick="undo()">撤销</button> <button onclick="erasing = !erasing">橡皮擦</button> <script> const canvas = document.getElementById('canvas'); const ctx = canvas.getContext('2d'); let currentScale = 1; let erasing = false; const states = []; const img = new Image(); img.onload = function() { ctx.drawImage(img, 0, 0); saveState(); }; img.src = 'image.jpg'; canvas.addEventListener('mousedown', function(e) { ctx.beginPath(); ctx.arc(e.offsetX, e.offsetY, 5, 0, 2 * Math.PI); ctx.fill(); saveState(); }); canvas.addEventListener('mousemove', function(e) { if (erasing) { ctx.fillStyle = '#ffffff'; ctx.fillRect(e.offsetX - 5, e.offsetY - 5, 10, 10); } }); canvas.addEventListener('wheel', function(e) { const delta = e.deltaY > 0 ? 0.1 : -0.1; const scale = Math.max(0.1, Math.min(10, currentScale + delta)); ctx.scale(scale, scale); currentScale = scale; }); function saveState() { states.push(canvas.toDataURL()); } function undo() { if (states.length > 1) { const img = new Image(); img.onload = function() { ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.drawImage(img, 0, 0); }; img.src = states[states.length - 2]; states.pop(); } } </script> </body> </html> ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿赛工作室

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值