本文将介绍如何使用 Canvas 和 JavaScript 实现一个图片编辑功能,允许用户在图片上添加、移动和调整大小贴纸元素。我们将涵盖以下功能:

  • 从网络上获取图片并在 Canvas 中展示
  • 添加贴纸元素
  • 移动贴纸元素
  • 拖拽贴纸元素的边框放大和缩小
  • 清空贴纸元素内容

1. 获取网络图片并在 Canvas 中展示

首先,我们需要获取网络上的图片并在 Canvas 中进行展示。可以使用以下代码实现:

const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');

const img = new Image();
img.crossOrigin = 'anonymous';
img.onload = function() {
  canvas.width = img.width;
  canvas.height = img.height;
  ctx.drawImage(img, 0, 0);
};
img.src = 'https://example.com/image.jpg';

这里,我们获取了一个名为 canvas 的元素,并获取了它的上下文。然后,我们创建一个新的 Image 对象并指定它的源。设置 crossOrigin 属性以确保可以从不同的域加载图像。在图像加载完成后,我们将 canvas 的大小设置为图像的大小,并将图像绘制到 canvas 中。

2. 添加和移动贴纸元素

接下来,我们需要实现贴纸元素的添加和移动。可以创建一个 Sticker 类来表示贴纸,并在 canvas 上绘制它们。以下是一个简单的 Sticker 类的示例:

class Sticker {
  constructor(x, y, width, height, image) {
    this.x = x;
    this.y = y;
    this.width = width;
    this.height = height;
    this.image = image;
  }
  
draw(ctx) {
    ctx.drawImage(this.image, this.x, this.y, this.width, this.height);
  }
  
  contains(x, y) {
    return (x >= this.x && x <= this.x + this.width &&
            y >= this.y && y <= this.y + this.height);
  }
}

这里,我们定义了 x,y,width 和 height 属性来表示贴纸的位置和大小,并且有一个 image 属性来存储贴纸图像。绘制方法使用 drawImage 函数将图像绘制到 canvas 上。contains 方法检查给定的坐标是否在贴纸的范围内。

接下来,我们可以使用以下代码添加和移动贴纸:

const stickers = [];

canvas.addEventListener('mousedown', function(e) {
  const x = e.offsetX;
  const y = e.offsetY;
  
  for (let i = stickers.length - 1; i >= 0; i--) {
    if (stickers[i].contains(x, y)) {
      const sticker = stickers[i];
      stickers.splice(i, 1);
      stickers.push(sticker);
      let isDragging = true;
      let offsetX = x - sticker.x;
      let offsetY = y - sticker.y;
      
      canvas.addEventListener('mousemove', dragSticker);
      canvas.addEventListener('mouseup', function() {
        isDragging = false;
        canvas.removeEventListener('mousemove', dragSticker);
      });
      
      function dragSticker(e) {
        if (isDragging) {
          sticker.x = e.offsetX - offsetX;
          sticker.y = e.offsetY - offsetY;
          drawStickers();
        }
      }
      
      return;
    }
  }
  
  const sticker = new Sticker(x, y, 100, 100, stickerImage);
  stickers.push(sticker);
  drawStickers();
});

function drawStickers() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  ctx.drawImage(img, 0, 0);
  for (const sticker of stickers) {
    sticker.draw(ctx);
  }
}

这里,我们创建了一个空的贴纸数组,并在 canvas 上添加了一个 mousedown 事件监听器。如果鼠标点击在一个贴纸上,我们将该贴纸移到数组的末尾,并将其标记为正在拖动。我们还添加了 mousemove 和 mouseup 事件监听器来处理贴纸的拖动。如果鼠标点击不在任何贴纸上,则创建一个新的贴纸并将其添加到数组中。最后,我们定义了一个 drawStickers 函数来清除 canvas 并重新绘制所有贴纸。

3. 拖拽贴纸元素的边框放大和缩小

现在我们已经实现了添加和移动贴纸的功能。接下来,我们需要实现拖拽贴纸元素的边框放大和缩小的功能。可以使用以下代码实现:

let isResizing = false;
let stickerBeingResized = null;
let resizeHandleX = 0;
let resizeHandleY = 0;

canvas.addEventListener('mousedown', function(e) {
  const x = e.offsetX;
  const y = e.offsetY;
  
  for (let i = stickers.length - 1; i >= 0; i--) {
    const sticker = stickers[i];
    if (sticker.contains(x, y)) {
      if (e.offsetX > sticker.x + sticker.width - 10 && e.offsetY > sticker.y + sticker.height - 10) {
        isResizing = true;
        stickerBeingResized = sticker;
        resizeHandleX = sticker.x + sticker.width;
        resizeHandleY = sticker.y + sticker.height;
      } else {
        stickers.splice(i, 1);
        stickers.push(sticker);
        let isDragging = true;
        let offsetX = x - sticker.x;
        let offsetY = y - sticker.y;
        
        canvas.addEventListener('mousemove', dragSticker);
        canvas.addEventListener('mouseup', function() {
          isDragging = false;
          canvas.removeEventListener('mousemove', dragSticker);
        });
        
        function dragSticker(e) {
          if (isDragging) {
            sticker.x = e.offsetX - offsetX;
            sticker.y = e.offsetY - offsetY;
            drawStickers();
          }
        }
      }
      
      return;
    }
  }
});

canvas.addEventListener('mousemove', function(e) {
  if (isResizing) {
    const newWidth = e.offsetX - stickerBeingResized.x;
    const newHeight = e.offsetY - stickerBeingResized.y;
    stickerBeingResized.width = newWidth;
    stickerBeingResized.height = newHeight;
    drawStickers();
  }
});

canvas.addEventListener('mouseup', function() {
  isResizing = false;
});

function drawStickers() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  ctx.drawImage(img, 0, 0);
  for (const sticker of stickers) {
    sticker.draw(ctx);
    if (sticker === stickerBeingResized) {
      ctx.fillStyle = 'rgba(255, 255, 255, 0.5)';
      ctx.fillRect(sticker.x + sticker.width - 10, sticker.y + sticker.height - 10, 10, 10);
    }
  }
}

这里,我们添加了一个新的 mousedown 事件监听器来检测鼠标是否在贴纸的右下角。如果是,则标记为正在调整大小,存储当前贴纸和调整大小手柄的位置。我们还更新了 mousemove 事件监听器来调整贴纸的大小。最后,我们定义了一个更新 drawStickers 函数来绘制调整大小的手柄。

4. 清空贴纸元素

最后,我们需要添加一个清空贴纸元素的功能。可以使用以下代码实现:

const clearButton = document.getElementById('clear');
clearButton.addEventListener('click', function() {
  stickers.length = 0;
  drawStickers();
});

这里,我们获取一个名为 clear 的按钮并添加一个 click 事件监听器。当点击按钮时,我们将贴纸数组清空并重新绘制 canvas。

5. 完整代码

<canvas id="canvas"></canvas>
<button id="clear">Clear</button>
<script>
  const canvas = document.getElementById('canvas');
  const ctx = canvas.getContext('2d');
  const stickers = [];
  let isResizing = false;
  let stickerBeingResized = null;
  let resizeHandleX = 0;
  let resizeHandleY = 0;

  const img = new Image();
  img.crossOrigin = 'anonymous';
  img.onload = function() {
    canvas.width = img.width;
    canvas.height = img.height;
    ctx.drawImage(img, 0, 0);
  };
  img.src = 'https://example.com/image.jpg';

  const stickerImage = new Image();
  stickerImage.crossOrigin = 'anonymous';
  stickerImage.onload = function() {
    drawStickers();
  };
  stickerImage.src = 'https://example.com/sticker.png';

  canvas.addEventListener('mousedown', function(e) {
    const x = e.offsetX;
    const y = e.offsetY;

    for (let i = stickers.length - 1; i >= 0; i--) {
      const sticker = stickers[i];
      if (sticker.contains(x, y)) {
        if (e.offsetX > sticker.x + sticker.width - 10 && e.offsetY > sticker.y + sticker.height - 10) {
          isResizing = true;
          stickerBeingResized = sticker;
          resizeHandleX = sticker.x + sticker.width;
          resizeHandleY = sticker.y + sticker.height;
        } else {
          stickers.splice(i, 1);
          stickers.push(sticker);
          let isDragging = true;
          let offsetX = x - sticker.x;
          let offsetY = y - sticker.y;

          canvas.addEventListener('mousemove', dragSticker);
          canvas.addEventListener('mouseup', function() {
            isDragging = false;
            canvas.removeEventListener('mousemove', dragSticker);
          });

          function dragSticker(e) {
            if (isDragging) {
              sticker.x = e.offsetX - offsetX;
              sticker.y = e.offsetY - offsetY;
              drawStickers();
            }
          }
        }

        return;
      }
    }

    const sticker = new Sticker(x, y, 100, 100, stickerImage);
    stickers.push(sticker);
    drawStickers();
  });

  canvas.addEventListener('mousemove', function(e) {
    if (isResizing) {
      const newWidth = e.offsetX - stickerBeingResized.x;
      const newHeight = e.offsetY - stickerBeingResized.y;
      stickerBeingResized.width = newWidth;
      stickerBeingResized.height = newHeight;
      drawStickers();
    }
  });

  canvas.addEventListener('mouseup', function() {
    isResizing = false;
  });

  const clearButton = document.getElementById('clear');
  clearButton.addEventListener('click', function() {
    stickers.length = 0;
    drawStickers();
  });

  class Sticker {
    constructor(x, y, width, height, image) {
      this.x = x;
      this.y = y;
      this.width = width;
      this.height = height;
      this.image = image;
    }

    draw(ctx) {
      ctx.drawImage(this.image, this.x, this.y, this.width, this.height);
    }

    contains(x, y) {
      return (x >= this.x && x <= this.x + this.width &&
              y >= this.y && y <= this.y + this.height);
    }
  }

  function drawStickers() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    ctx.drawImage(img, 0, 0);
    for (const sticker of stickers) {
      sticker.draw(ctx);
      if (sticker === stickerBeingResized) {
        ctx.fillStyle = 'rgba(255, 255, 255, 0.5)';
        ctx.fillRect(sticker.x + sticker.width - 10, sticker.y + sticker.height - 10, 10, 10);
      }
    }
  }
</script>

您可以将以上代码复制到您的 HTML 文件中,并替换 image.jpg 和 sticker.png 的路径为您的实际图片地址。运行代码后,您就可以在 Canvas 上添加、移动和调整大小贴纸元素了。

使用 Canvas 和 JavaScript 实现图片编辑功能:添加、移动和调整贴纸

原文地址: https://www.cveoy.top/t/topic/lOrB 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录