基于canvas通过鼠标在浏览器图像上画线条自动吸附到图片灰色区域
时间: 2023-05-27 11:08:06 浏览: 127
这个问题需要使用一些数学和计算机图形学的知识来解决。具体步骤如下:
1. 获取图片并绘制到canvas上。
2. 监听鼠标事件,获取鼠标位置。
3. 根据鼠标位置,计算出线条的起点和终点。
4. 计算线条与图片灰色区域的交点。
5. 将线条的终点自动吸附到交点上。
下面是一个简单的实现示例:
```
// 1. 获取图片并绘制到canvas上
const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');
const img = new Image();
img.src = 'image.jpg';
img.onload = () => {
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0);
};
// 2. 监听鼠标事件,获取鼠标位置
let isDrawing = false;
let lastX = 0;
let lastY = 0;
canvas.addEventListener('mousedown', e => {
isDrawing = true;
lastX = e.offsetX;
lastY = e.offsetY;
});
canvas.addEventListener('mousemove', e => {
if (!isDrawing) return;
const currentX = e.offsetX;
const currentY = e.offsetY;
// 3. 根据鼠标位置,计算出线条的起点和终点
ctx.beginPath();
ctx.moveTo(lastX, lastY);
ctx.lineTo(currentX, currentY);
ctx.strokeStyle = '#000';
ctx.stroke();
// 4. 计算线条与图片灰色区域的交点
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
const data = imageData.data;
const length = data.length;
const grayPixels = [];
for (let i = 0; i < length; i += 4) {
const gray = (data[i] + data[i + 1] + data[i + 2]) / 3;
if (gray < 128) {
grayPixels.push({
x: (i / 4) % canvas.width,
y: Math.floor(i / (4 * canvas.width)),
});
}
}
const intersections = [];
for (let i = 0; i < grayPixels.length - 1; i++) {
const p1 = grayPixels[i];
const p2 = grayPixels[i + 1];
const intersection = getLineIntersection(lastX, lastY, currentX, currentY, p1.x, p1.y, p2.x, p2.y);
if (intersection) {
intersections.push(intersection);
}
}
// 5. 将线条的终点自动吸附到交点上
if (intersections.length > 0) {
const closestIntersection = getClosestPoint(currentX, currentY, intersections);
ctx.beginPath();
ctx.moveTo(lastX, lastY);
ctx.lineTo(closestIntersection.x, closestIntersection.y);
ctx.strokeStyle = '#000';
ctx.stroke();
lastX = closestIntersection.x;
lastY = closestIntersection.y;
} else {
lastX = currentX;
lastY = currentY;
}
});
canvas.addEventListener('mouseup', () => {
isDrawing = false;
});
// 计算两条直线的交点
function getLineIntersection(x1, y1, x2, y2, x3, y3, x4, y4) {
const d = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);
if (d === 0) {
return null;
}
const x = ((x1 * y2 - y1 * x2) * (x3 - x4) - (x1 - x2) * (x3 * y4 - y3 * x4)) / d;
const y = ((x1 * y2 - y1 * x2) * (y3 - y4) - (y1 - y2) * (x3 * y4 - y3 * x4)) / d;
if (x < 0 || x > canvas.width || y < 0 || y > canvas.height) {
return null;
}
return { x, y };
}
// 计算与目标点最近的交点
function getClosestPoint(x, y, points) {
let minDistance = Number.MAX_VALUE;
let closestPoint = null;
for (const point of points) {
const distance = Math.sqrt((x - point.x) ** 2 + (y - point.y) ** 2);
if (distance < minDistance) {
minDistance = distance;
closestPoint = point;
}
}
return closestPoint;
}
```
注意,这只是一个简单的实现示例,还有很多细节需要考虑,比如线条的宽度、灰色区域的阈值、交点的判断等等。
阅读全文