体验地址
技术栈
- Vue3: 用于构建用户界面。
- HTML5 Canvas: 用于绘制和合并图片。
- JavaScript: 处理拖拽和下载逻辑。
功能概述
- 拖拽小图片: 用户可以通过鼠标拖拽小图片到大图片的任意位置。
- 边界限制: 确保小图片不会超出大图片的边界。
- 下载合并后的图片: 用户可以点击按钮下载合并后的图片。
实现步骤
1. 创建 Vue 组件
<template><div class="image-container" @mousemove="handleMouseMove" @mouseup="handleMouseUp"><img:src="largeImageUrl"alt="Large Image"class="large-image"ref="largeImageRef"crossorigin="anonymous"/><img:src="smallImageUrl"alt="Small Image"class="small-image"ref="smallImageRef"width="60":style="{ left: smallImagePosition.x + 'px', top: smallImagePosition.y + 'px' }"crossorigin="anonymous"@mousedown="handleMouseDown"/></div>
</template><script>
import { ref, onMounted } from "vue";
import { uploadFileFun } from "@/utils/minio.js";
import { dataURLtoFile } from "@/utils/methods";export default {setup() {const largeImageUrl ="https://";const smallImageUrl ="https:/";const smallImagePosition = ref({ x: 0, y: 0 });const largeImageRef = ref(null);const smallImageRef = ref(null);let isDragging = false;let dragStart = { x: 0, y: 0 };const handleMouseDown = (event) => {isDragging = true;dragStart = {x: event.clientX - smallImagePosition.value.x,y: event.clientY - smallImagePosition.value.y,};};const handleMouseMove = (event) => {if (!isDragging) return;const largeImage = largeImageRef.value;const smallImage = smallImageRef.value;const smallImageWidth = smallImage.width;const smallImageHeight = smallImage.height;let newX = event.clientX - dragStart.x;let newY = event.clientY - dragStart.y;// 边界限制,考虑小图片的大小newX = Math.max(0, Math.min(newX, largeImage.width - smallImageWidth));newY = Math.max(0, Math.min(newY, largeImage.height - smallImageHeight));smallImagePosition.value = { x: newX, y: newY };};const handleMouseUp = () => {isDragging = false;};const saveAsImage = async () => {const largeImage = largeImageRef.value;const smallImage = smallImageRef.value;// 获取大图片的缩放比例const scaleX = largeImage.naturalWidth / largeImage.width;const scaleY = largeImage.naturalHeight / largeImage.height;const canvas = document.createElement("canvas");canvas.width = largeImage.naturalWidth;canvas.height = largeImage.naturalHeight;const ctx = canvas.getContext("2d");// 绘制大图片ctx.drawImage(largeImage, 0, 0);// 计算小图片在Canvas上的缩放后位置const scaledX = smallImagePosition.value.x * scaleX;const scaledY = smallImagePosition.value.y * scaleY;// 绘制小图片ctx.drawImage(smallImage,scaledX,scaledY,smallImage.width * scaleX, // 小图片的缩放宽度smallImage.height * scaleY // 小图片的缩放高度);const dataUrl = canvas.toDataURL("image/png");const link = document.createElement("a");link.href = dataUrl;link.download = "combined-image.png";link.click();};onMounted(() => {const saveButton = document.createElement("button");saveButton.innerText = "下载";saveButton.onclick = saveAsImage;document.body.appendChild(saveButton);});return {largeImageUrl,smallImageUrl,smallImagePosition,largeImageRef,smallImageRef,handleMouseDown,handleMouseMove,handleMouseUp,};},
};
</script><style scoped>
.image-container {position: relative;width: 350px;height: 450px;
}
.large-image {width: 100%;height: 100%;
}
.small-image {position: absolute;cursor: move;
}
</style>
2. 拖拽小图片
使用 ref
来引用大图片和小图片,并通过监听鼠标事件来实现拖拽功能。
handleMouseDown
: 当用户按下鼠标左键时,记录拖拽起点的位置。handleMouseMove
: 当用户移动鼠标时,更新小图片的位置,并限制其在大图片范围内移动。handleMouseUp
: 当用户释放鼠标左键时,停止拖拽。
3. 下载合并后的图片
使用 HTML5 Canvas 来绘制合并后的图片,并提供下载功能。
saveAsImage
: 创建一个 Canvas 元素,绘制大图片和小图片,然后将 Canvas 内容转换为 Data URL,并生成一个下载链接。
4. 添加下载按钮
在组件挂载完成后,动态创建一个下载按钮并添加到页面中。
onMounted(() => {const saveButton = document.createElement("button");saveButton.innerText = "下载";saveButton.onclick = saveAsImage;document.body.appendChild(saveButton);
});