gpt4 book ai didi

javascript - 如何获取html canvas标签的坐标

转载 作者:行者123 更新时间:2023-12-04 01:07:50 25 4
gpt4 key购买 nike

我想获取放置在 HTML canvas 标记中的图像的绘制区域的坐标,并将其发送到数据库。并将其填充到另一页中该图像的同一区域。以及如何通过单击重置按钮重置或清除绘制区域?

JSfiddle example

var canvas = document.getElementById("canvas");
var img = document.getElementById("imagearea"),
ctx = canvas.getContext("2d"),
painting = false,
lastX = 0,
lastY = 0,
lineThickness = 1;

canvas.width = canvas.height = 600;
ctx.fillRect(0, 0, 600, 600);
ctx.drawImage(img, 10, 10);

canvas.onmousedown = function(e) {
painting = true;
ctx.fillStyle = "#ff0000";
lastX = e.pageX - this.offsetLeft;
lastY = e.pageY - this.offsetTop;
};

canvas.onmouseup = function(e){
painting = false;
}

canvas.onmousemove = function(e) {
if (painting) {
mouseX = e.pageX - this.offsetLeft;
mouseY = e.pageY - this.offsetTop;

// find all points between
var x1 = mouseX,
x2 = lastX,
y1 = mouseY,
y2 = lastY;


var steep = (Math.abs(y2 - y1) > Math.abs(x2 - x1));
if (steep){
var x = x1;
x1 = y1;
y1 = x;

var y = y2;
y2 = x2;
x2 = y;
}
if (x1 > x2) {
var x = x1;
x1 = x2;
x2 = x;

var y = y1;
y1 = y2;
y2 = y;
}

var dx = x2 - x1,
dy = Math.abs(y2 - y1),
error = 0,
de = dy / dx,
yStep = -1,
y = y1;

if (y1 < y2) {
yStep = 1;
}

lineThickness = 5 - Math.sqrt((x2 - x1) *(x2-x1) + (y2 - y1) * (y2-y1))/10;
if(lineThickness < 1){
lineThickness = 1;
}

for (var x = x1; x < x2; x++) {
if (steep) {
ctx.fillRect(y, x, lineThickness , lineThickness );
} else {
ctx.fillRect(x, y, lineThickness , lineThickness );
}

error += de;
if (error >= 0.5) {
y += yStep;
error -= 1.0;
}
}



lastX = mouseX;
lastY = mouseY;

}
}
<canvas id="canvas">
</canvas>
<img id="imagearea" src="https://media.istockphoto.com/photos/green-apple-with-leaf-and-cut-isolated-on-white-picture-id1141004606?k=6&m=1141004606&s=170667a&w=0&h=zwbN4lLc7MFb6f_aZ4npNL3i4Tgde-yINlYTztlI1QQ=" style="display: none;" />

<button> Reset </button>

最佳答案

为了实现您正在寻找的目标,您需要存储(顶部,左侧)位置的最小(x,y)坐标和(底部,右侧)位置的最大(x,y)坐标,如果您要删除该区域上的绘图,则无法在同一 Canvas 上获取图像。使用相对于 Canvas 具有绝对位置的 HTML 元素作为区域框架,附加一个事件来裁剪,并显示另一个目标区域以将其删除。

这是一个有很多注释的工作示例,应该很清楚。点击显示预览的区域,“x”上的去掉随图一起画,可以处理多个区域。

const source = "https://media.istockphoto.com/photos/green-apple-with-leaf-and-cut-isolated-on-white-picture-id1141004606?k=6&m=1141004606&s=170667a&w=0&h=zwbN4lLc7MFb6f_aZ4npNL3i4Tgde-yINlYTztlI1QQ=";
const container = document.querySelector("#container");
const canvas = container.querySelector("canvas");
const ctx = canvas.getContext("2d");
const resetButton = document.querySelector("button");

let lastDrawnArea = [[Infinity, Infinity], [0, 0]];
let image;
let painting = false;
let lastX = 0;
let lastY = 0;
let lineThickness = 1;

init();

async function init() {

await loadDrawImage();

// Start Event Listening
canvas.onmousedown = function(e) {
painting = true;
ctx.fillStyle = "#ff0000";
lastX = e.pageX - this.offsetLeft;
lastY = e.pageY - this.offsetTop;
};

canvas.onmouseup = function(e){
painting = false;
// Set the drawing area
setDrawingArea();
}

canvas.onmousemove = function(e) {
if (painting) {
mouseX = e.pageX - this.offsetLeft;
mouseY = e.pageY - this.offsetTop;

// find all points between
var x1 = mouseX,
x2 = lastX,
y1 = mouseY,
y2 = lastY;


var steep = (Math.abs(y2 - y1) > Math.abs(x2 - x1));
if (steep){
var x = x1;
x1 = y1;
y1 = x;

var y = y2;
y2 = x2;
x2 = y;
}
if (x1 > x2) {
var x = x1;
x1 = x2;
x2 = x;

var y = y1;
y1 = y2;
y2 = y;
}

var dx = x2 - x1,
dy = Math.abs(y2 - y1),
error = 0,
de = dy / dx,
yStep = -1,
y = y1;

if (y1 < y2) {
yStep = 1;
}

lineThickness = 5 - Math.sqrt((x2 - x1) *(x2-x1) + (y2 - y1) * (y2-y1))/10;
if(lineThickness < 1){
lineThickness = 1;
}

for (var x = x1; x < x2; x++) {
if (steep) {
ctx.fillRect(y, x, lineThickness , lineThickness );
} else {
ctx.fillRect(x, y, lineThickness , lineThickness );
}

error += de;
if (error >= 0.5) {
y += yStep;
error -= 1.0;
}
}

lastX = mouseX;
lastY = mouseY;

// Set The min, max coordinate of the current drawing
// to define the current drawing area
lastDrawnArea = [
[// Top left min([x, y]) coords
Math.min(lastDrawnArea[0][0], mouseX),
Math.min(lastDrawnArea[0][1], mouseY)
],
[// Bottom right max([x, y]) coords
Math.max(lastDrawnArea[1][0], mouseX),
Math.max(lastDrawnArea[1][1], mouseY)
]
]
}
}
}

async function loadDrawImage() {
image = new Image();

// Load the image
await new Promise(resolve => {
image.onload = resolve;
image.src = source;
});

const [width, height] = [image.naturalWidth, image.naturalHeight];

// Set the container and canvas size
container.style.width = `${width}px`;
container.style.height = `${height}px`;
canvas.width = width;
canvas.height = height;

// Set the container in the background
container.style.background = `url(${image.src})`;
}

function setDrawingArea(){
const [TOP_LEFT, BOTTOM_RIGHT, X, Y] = [0, 1, 0, 1];
const container = document.querySelector("#container");
const template = document.querySelector("#areaTemplate");
const area = template.content.firstElementChild.cloneNode(true);

// You should replace this with the lineThickness
const offset = 10;

// Get the area size
const width = lastDrawnArea[BOTTOM_RIGHT][X] - lastDrawnArea[TOP_LEFT][X];
const height = lastDrawnArea[BOTTOM_RIGHT][Y] - lastDrawnArea[TOP_LEFT][Y];

area.style.left = `${lastDrawnArea[TOP_LEFT][X] - offset}px`;
area.style.top = `${lastDrawnArea[TOP_LEFT][Y] - offset}px`;
area.style.width = `${width + (offset * 2)}px`;
area.style.height = `${height + (offset * 2)}px`;

// Draw the template
container.append(area);

// Add the events
area.onclick = previewArea; // Preveiw event
area.querySelector("b").onclick = removeArea; // Remove event

// Reset "lastDrawnArea" value
lastDrawnArea = [[Infinity, Infinity], [0, 0]];

}

function previewArea(e) {
const preview = document.querySelector("#preview");
const previewCanvas = preview.querySelector("canvas");
const previewCtx = previewCanvas.getContext("2d");

// Get the drawing area coords
const area = e.target;
const [x, y, width, height] = [
parseFloat(area.style.left),
parseFloat(area.style.top),
parseFloat(area.style.width),
parseFloat(area.style.height)
];

// Draw the preview area
previewCanvas.width = width;
previewCanvas.height = height;
previewCtx.drawImage(image,
x, y, width, height,
0, 0, width, height);
}

function removeArea(e) {
const area = e.target.parentElement;
const [x, y, width, height] = [
parseFloat(area.style.left),
parseFloat(area.style.top),
parseFloat(area.style.width),
parseFloat(area.style.height)
];

ctx.clearRect(x, y, width, height);

area.remove();
}

resetButton.onclick = () => {
ctx.clearRect(0, 0, canvas.width, canvas.height);
document.querySelectorAll('.area').forEach(el => el.remove());
}
body {
display: flex;
}

#container {
position: relative;
}

.area {
position: absolute;
border: 2px solid #333;
color: #333;
cursor: pointer;
}

.area b {
position: absolute;
right: 0;
top: 0;
transform: translate(100%, -100%);
color: red;
cursor: pointer;
}
<div id="container">
<canvas></canvas>
</div>

<div id="preview">
<canvas></canvas>
</div>

<template id="areaTemplate">
<div class="area">
<b>x</b>
</div>
</template>

<button> Reset All </button>

如果两个区域重叠,则此示例存在一个问题,绘图将在两个区域的交集处被删除,要解决此问题,您需要将每个绘图保留在自己的 Canvas 上(...需要大量工作)。

最后但同样重要的是,如果您使用 fabric js 这样的库,您可以轻松获得相同的结果并更好地控制 Canvas 及其元素。 ,看看这个 freedrawing 的例子,您将免费获得绘图坐标,并且您仍然可以在同一 Canvas 上拥有所有内容(图像或您需要添加到 Canvas 的任何内容以及所有没有重叠的绘图......),初始学习曲线可能需要一些时间时间,但到一天结束时,您将对 HTML canvas 有一个整体的更好的理解。

旁注:您使用的图像有跨源限制,您应该使用来自同一域或允许跨源的域的图像。

关于javascript - 如何获取html canvas标签的坐标,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65810478/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com