使用 Canvas 和 JavaScript 实现图片编辑功能:添加、移动和调整贴纸
本文将介绍如何使用 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 上添加、移动和调整大小贴纸元素了。
原文地址: https://www.cveoy.top/t/topic/lOrB 著作权归作者所有。请勿转载和采集!