我试图用我制作的尺寸在画布内拖放一些图像,但不起作用。
//Javascript per la creazione di cirucuiti elettrici
const NUMERO_CICLO = 990;
const NUMERO_CICLO_INTERNO = 60;
const resistor = document.getElementById("component_circuit_resistor");
const condensator = document.getElementById("component_circuit_condensator");
const tranistor = document.getElementById("component_circuit_tranistor");
const alimentator = document.getElementById("component_circuit_alimentator");
const circuit = document.getElementById("components_circuit");
const back_button = document.getElementById("back-button");
const clear_button = document.getElementById("clear-button");
const draggable = document.querySelectorAll(".draggable");
const container = document.querySelectorAll(".container");
const canvas = document.getElementById("canvas");
const foward_button = document.getElementById("foward-button");
canvas.width = 1500;
canvas.height = 855;
canvas.style.backgroundColor = "lightgrey";
circuit.appendChild(canvas);
canvas.style.borderRadius = "10px";
canvas.style.marginLeft = "auto";
canvas.style.marginRight = "auto";
canvas.style.display = "block";
const ctx = canvas.getContext("2d");
const circles = [];
const lines = [];
const lines_c = [];
var deletedLines = [];
for (let y = 20; y <= NUMERO_CICLO; y += 20) {
for (let i = 0; i < NUMERO_CICLO_INTERNO; i++) {
circles.push({
x: 13 + i * 25,
y,
radius: 5,
color: "grey",
});
}
}
let startCircle = null;
let endCircle = null;
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
circles.forEach((circle) => {
ctx.beginPath();
ctx.arc(circle.x, circle.y, circle.radius, 0, Math.PI * 2);
ctx.fillStyle = circle.color;
ctx.fill();
});
lines.forEach((line) => {
ctx.beginPath();
ctx.lineWidth = 4;
ctx.moveTo(line.start.x, line.start.y);
ctx.lineTo(line.end.x, line.end.y);
ctx.stroke();
});
if (startCircle && endCircle) {
ctx.beginPath();
ctx.lineWidth = 4;
ctx.moveTo(startCircle.x, startCircle.y);
ctx.lineTo(endCircle.x, endCircle.y);
ctx.stroke();
}
requestAnimationFrame(draw);
}
draw();
function goBack() {
if (lines.length > 0 && back_clicked == true) {
const eliminato = lines.pop();
deletedLines.push(eliminato);
}
else if(foward_clicked == true && deletedLines.length > 0){
const lastDeleted = deletedLines[deletedLines.length - 1];
if (!lines.includes(lastDeleted)) {
lines.push(lastDeleted);
deletedLines.pop();
}
}
//se non ci sono linee da eliminare mando alert
else if (lines.length == 0 && back_clicked == true) {
alert("There are no lines to delete");
}
}
function clearCanvas() {
if(confirm("Are you sure you want to delete the circuit?")){
lines.length = 0;
deletedLines.length = 0;
lastDeleted = null;
}
}
function getNearestCircle(x, y) {
let nearestCircle = null;
let nearestDistance = Infinity;
circles.forEach((circle) => {
const distance = Math.sqrt((circle.x - x) ** 2 + (circle.y - y) ** 2);
if (distance < nearestDistance && distance < 30) {
nearestCircle = circle;
nearestDistance = distance;
}
});
return nearestCircle;
}
let isDrawing = false;
canvas.addEventListener("mousedown", (event) => {
const x = event.offsetX;
const y = event.offsetY;
const circle = getNearestCircle(x, y);
if (circle) {
startCircle = circle;
endCircle = { x, y };
isDrawing = true;
}
});
canvas.addEventListener("mousemove", (event) => {
if (isDrawing) {
endCircle.x = event.offsetX;
endCircle.y = event.offsetY;
} else {
const x = event.offsetX;
const y = event.offsetY;
const circle = getNearestCircle(x, y);
if (circle) {
circles.forEach((circle) => {
circle.color = "grey";
});
circle.color = "red";
} else {
circles.forEach((circle) => {
circle.color = "grey";
});
}
}
});
canvas.addEventListener("mouseup", () => {
if (isDrawing) {
const x = endCircle.x;
const y = endCircle.y;
const circle = getNearestCircle(x, y);
if (circle) {
lines.push({
start: startCircle,
end: circle,
});
}
isDrawing = false;
startCircle = null;
endCircle = null;
}
});
//back_button.addEventListener("click", goBack);
//foward_button.addEventListener("click", goBack);
clear_button.addEventListener("click", clearCanvas);
var back_clicked = false;
back_button.addEventListener("click", function(){
back_clicked = true;
goBack();
back_clicked = false;
})
var foward_clicked = false;
foward_button.addEventListener("click", function () {
foward_clicked = true;
goBack();
foward_clicked = false;
})
//risposta stack overflow
const draggableImages = document.querySelectorAll('img[draggable]');
for (const img of draggableImages)
img.ondragstart = (ev) => {
ev.dataTransfer.setData('text', img.src);
};
canvas.ondragover = (ev) => ev.preventDefault(); // IMPORTANT
canvas.ondrop = (ev) => {
const img = new Image();
img.src = ev.dataTransfer.getData('text');
img.onload = () => {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(img, 0, 0);
};
};
@import url('https://fonts.googleapis.com/css2?family=Poppins&display=swap');
html,body{
margin: 0;
padding: 0;
height: 100%;
width: 100%;
background-color: #ede7e1;
font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
font-size: 14px;
color: #333;
line-height: 1.5;
overflow-x: hidden;
}
img{
width: 100%;
height: 100%;
}
#h1_disegna{
text-align: center;
}
#h1_breadboard{
text-align: center;
position: relative;
top: -550px;
}
#h1_titolo{
font-size: 60px;
text-align: center;
}
#h3_componenti_circuit{
border-style: solid;
width: 100px;
border-color: black rigid 1px;
list-style-type: none;
margin-left: 0px;
padding-left: 0px;
background-color: sandybrown;
position: relative;
top: 85px;
}
#h3_componenti_br{
border-style: solid;
width: 100px;
border-color: black rigid 1px;
list-style-type: none;
margin-left: 0px;
padding-left: 0px;
background-color: sandybrown;
position: relative;
top: -500px;
}
#h4_footer{
font-size: 26px;
}
.elementi_disegno{
position: relative;
top: -520px;
}
#canvas{
position: relative;
top: -520px;
}
#back-button{
position: relative;
top: 62%;
left: 42.5%;
transform: translate(-50%, -50%);
font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
font-size: 24px;
background-color: rgba(244, 165, 96, 0.473);
border-radius: 6px;
cursor: pointer;
}
#foward-button{
position: relative;
top: 62%;
left: 43%;
transform: translate(-50%, -50%);
font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
font-size: 24px;
background-color: rgba(244, 165, 96, 0.473);
border-radius: 6px;
cursor: pointer;
}
#clear-button{
border-radius: 6px;
position: relative;
top: 62%;
left: 44.5%;
transform: translate(-50%, -50%);
font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
font-size: 24px;
background-color: rgba(244, 165, 96, 0.473);
cursor: pointer;
}
#components_circuit_border{
border-style: solid;
width: 100px;
border-color: black rigid 1px;
list-style-type: none;
margin-left: 0px;
padding-left: 0px;
background-color: antiquewhite;
cursor: move;
position: relative;
top: 85px;
}
#components_br_border{
border-style: solid;
width: 100px;
border-color: black rigid 1px;
list-style-type: none;
margin-left: 0px;
padding-left: 0px;
background-color: antiquewhite;
cursor: move;
position: relative;
top: -500px;
}
#components_circuit{
list-style-type: none;
margin-left: 0px;
padding-left: 0px;
}
.footer{
text-align: center;
background-color: darkgray;
left: 0;
margin-bottom: 0;
height: 40px;
width: 100%;
}
.material-symbols-outlined{
display: inline-flex;
vertical-align: -3px;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@48,400,0,0" />
<link rel="stylesheet" href="style.css">
<title>From Circuit to Breadboard</title>
</head>
<body>
<h1 id="h1_titolo">From Circuit to Breadboard</h1>
<div class="container">
<div class="components">
<div id="components_circuit">
<h3 id ="h3_componenti_circuit">Componenti:</h3>
<ul id="components_circuit_border">
<li><img id ="component_circuit_resistor" src="images/circuit_resistor.png" height="50" draggable></li>
<br><br>
<li><img id = "component_circuit_condensator" src="images/circuit_condensator.png" height="50" draggable></li>
<br><br>
<li><img id="component_circuit_transistor" src="images/circuit_transistor.png" height="50" draggable></li>
<br><br>
<li><img id="component_circuit_alimentator" src="images/circuit_alimentator.png" height="50" draggable></li>
<!-- <li><img
src="https://i.kym-cdn.com/entries/icons/original/000/006/428/637738.jpg"
height="50px"
draggable
/></li>
<li>
<img
src="https://ftw.usatoday.com/wp-content/uploads/sites/90/2017/05/spongebob.jpg?w=1000&h=600&crop=1"
height="50px"
draggable
/>
</li>
<li>
<img
src="https://pyxis.nymag.com/v1/imgs/0f9/f96/029acbf4c6d8c67e138e1eb06a277204bf-05-patrick.rsquare.w700.jpg"
height="50px"
draggable
/>
</li> -->
</ul>
<div class = "elementi_disegno">
<h1 id ="h1_disegna">Disegna il tuo circuito!</h1>
<button id="back-button">Indietro
<span class="material-symbols-outlined">undo</span>
</button>
<button id="foward-button">Avanti
<span class="material-symbols-outlined">redo</span>
</button>
<button id="clear-button">Clear All
<span class="material-symbols-outlined">delete</span>
</button>
<canvas id = "canvas" class = "dropzone"></canvas>
</div>
</div>
<br>
<br>
<div id="components_br">
<h1 id = "h1_breadboard">Breadboard</h1>
<h3 id ="h3_componenti_br">Componenti:</h3>
<ul id="components_br_border">
<li><img id = "component_br_resistor" src="images/br_resistor.png" height="50" draggable="true"></li>
<br><br>
<li><img id = "component_br_condensator" src="images/br_condensator.png" height="50" draggable="true"></li>
<br><br>
<li><img id = "component_br_transistor" src="images/br_transistor.png" height="50" draggable="true"></li>
<br><br>
<li><img id="component_br_alimentator" src="images/br_alimentator.png" height="50" draggable="true"></li>
</ul>
</div>
</div>
</div>
<footer class="footer">
<div>
<h4 id ="h4_footer">Website made by Skerdi Velo, Davide Rossini, Andrea Quagliotti<span class="material-symbols-outlined">copyright</span></h4>
</div>
</footer>
<script src="script.js"></script>
</body>
</html>
我正在尝试在画布中拖放一些图像。它可以让我拖动它,但当我想放下它时,它就不起作用了。这是代码:
<div class="container">
<div class="components">
<div id="components_circuit">
<h3 class ="h3_componenti" id ="h3_componenti_circuit">Componenti:</h3>
<ul id="components_circuit_border">
<li><img id ="component_circuit_resistor" src="images/circuit_resistor.png" height="50"></li>
<li><img id = "component_circuit_condensator" src="images/circuit_condensator.png" height="50" draggable="true"></li>
<li><img id="component_circuit_transistor" src="images/circuit_transistor.png" height="50" draggable="true"></li>
<li><img id="component_circuit_alimentator" src="images/circuit_alimentator.png" height="50" draggable="true"></li>
</ul>
<canvas id = "canvas"></canvas>
</div>
</div>
</div>
这是HTML的一个例子,正如你所看到的,我有我的图像,我想放在我的画布上。这是画布的JavaScript:
const draggableClass = document.getElementsByClassName("draggable");
const draggable = document.querySelectorAll(".draggable");
const container = document.querySelectorAll(".container");
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
canvas.width = 1500;
canvas.height = 855;
canvas.style.backgroundColor = "lightgrey";
canvas.style.borderRadius = "10px";
canvas.style.marginLeft = "auto";
canvas.style.marginRight = "auto";
canvas.style.display = "block";
开始:
//Javascript per la creazione di cirucuiti elettrici
const NUMERO_CICLO = 990;
const NUMERO_CICLO_INTERNO = 60;
const resistor = document.getElementById('component_circuit_resistor');
const condensator = document.getElementById('component_circuit_condensator');
const tranistor = document.getElementById('component_circuit_tranistor');
const alimentator = document.getElementById('component_circuit_alimentator');
const circuit = document.getElementById('components_circuit');
const back_button = document.getElementById('back-button');
const clear_button = document.getElementById('clear-button');
const draggable = document.querySelectorAll('.draggable');
const container = document.querySelectorAll('.container');
const canvas = document.getElementById('canvas');
const foward_button = document.getElementById('foward-button');
/** EDIT START */
const draggableImages = document.querySelectorAll('img[draggable]');
for (let i = 0; i < draggableImages.length; i++)
draggableImages[i].ondragstart = (ev) => {
ev.dataTransfer.setData('text/plain', i.toString());
};
canvas.ondragover = (ev) => ev.preventDefault(); // IMPORTANT
const drawnImageData = [];
canvas.ondrop = (ev) => {
const index = parseInt(ev.dataTransfer.getData('text/plain'));
const img = draggableImages[index];
drawnImageData.push({ img, x: ev.offsetX, y: ev.offsetY });
};
/** EDIT END */
canvas.width = 1500;
canvas.height = 855;
canvas.style.backgroundColor = 'lightgrey';
circuit.appendChild(canvas);
canvas.style.borderRadius = '10px';
canvas.style.marginLeft = 'auto';
canvas.style.marginRight = 'auto';
canvas.style.display = 'block';
const ctx = canvas.getContext('2d');
const circles = [];
const lines = [];
const lines_c = [];
var deletedLines = [];
for (let y = 20; y <= NUMERO_CICLO; y += 20) {
for (let i = 0; i < NUMERO_CICLO_INTERNO; i++) {
circles.push({
x: 13 + i * 25,
y,
radius: 5,
color: 'grey',
});
}
}
let startCircle = null;
let endCircle = null;
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
circles.forEach((circle) => {
ctx.beginPath();
ctx.arc(circle.x, circle.y, circle.radius, 0, Math.PI * 2);
ctx.fillStyle = circle.color;
ctx.fill();
});
lines.forEach((line) => {
ctx.beginPath();
ctx.lineWidth = 4;
ctx.moveTo(line.start.x, line.start.y);
ctx.lineTo(line.end.x, line.end.y);
ctx.stroke();
});
if (startCircle && endCircle) {
ctx.beginPath();
ctx.lineWidth = 4;
ctx.moveTo(startCircle.x, startCircle.y);
ctx.lineTo(endCircle.x, endCircle.y);
ctx.stroke();
}
/** EDIT START */
for (const data of drawnImageData)
ctx.drawImage(data.img, data.x, data.y, data.img.width, data.img.height);
/** EDIT END */
requestAnimationFrame(draw);
}
draw();
function goBack() {
if (lines.length > 0 && back_clicked == true) {
const eliminato = lines.pop();
deletedLines.push(eliminato);
} else if (foward_clicked == true && deletedLines.length > 0) {
const lastDeleted = deletedLines[deletedLines.length - 1];
if (!lines.includes(lastDeleted)) {
lines.push(lastDeleted);
deletedLines.pop();
}
}
//se non ci sono linee da eliminare mando alert
else if (lines.length == 0 && back_clicked == true) {
alert('There are no lines to delete');
}
}
function clearCanvas() {
if (confirm('Are you sure you want to delete the circuit?')) {
lines.length = 0;
deletedLines.length = 0;
lastDeleted = null;
}
}
function getNearestCircle(x, y) {
let nearestCircle = null;
let nearestDistance = Infinity;
circles.forEach((circle) => {
const distance = Math.sqrt((circle.x - x) ** 2 + (circle.y - y) ** 2);
if (distance < nearestDistance && distance < 30) {
nearestCircle = circle;
nearestDistance = distance;
}
});
return nearestCircle;
}
let isDrawing = false;
canvas.addEventListener('mousedown', (event) => {
const x = event.offsetX;
const y = event.offsetY;
const circle = getNearestCircle(x, y);
if (circle) {
startCircle = circle;
endCircle = { x, y };
isDrawing = true;
}
});
canvas.addEventListener('mousemove', (event) => {
if (isDrawing) {
endCircle.x = event.offsetX;
endCircle.y = event.offsetY;
} else {
const x = event.offsetX;
const y = event.offsetY;
const circle = getNearestCircle(x, y);
if (circle) {
circles.forEach((circle) => {
circle.color = 'grey';
});
circle.color = 'red';
} else {
circles.forEach((circle) => {
circle.color = 'grey';
});
}
}
});
canvas.addEventListener('mouseup', () => {
if (isDrawing) {
const x = endCircle.x;
const y = endCircle.y;
const circle = getNearestCircle(x, y);
if (circle) {
lines.push({
start: startCircle,
end: circle,
});
}
isDrawing = false;
startCircle = null;
endCircle = null;
}
});
//back_button.addEventListener("click", goBack);
//foward_button.addEventListener("click", goBack);
clear_button.addEventListener('click', clearCanvas);
var back_clicked = false;
back_button.addEventListener('click', function () {
back_clicked = true;
goBack();
back_clicked = false;
});
var foward_clicked = false;
foward_button.addEventListener('click', function () {
foward_clicked = true;
goBack();
foward_clicked = false;
});
<h1 id="h1_titolo">From Circuit to Breadboard</h1>
<div class="container">
<div class="components">
<div id="components_circuit">
<h3 id="h3_componenti_circuit">Componenti:</h3>
<ul id="components_circuit_border">
<li>
<img
id="component_circuit_resistor"
src="https://i.kym-cdn.com/entries/icons/original/000/006/428/637738.jpg"
height="50"
draggable
/>
</li>
<br /><br />
<li>
<img
id="component_circuit_condensator"
src="https://ftw.usatoday.com/wp-content/uploads/sites/90/2017/05/spongebob.jpg"
height="50"
draggable
/>
</li>
<br /><br />
<li>
<img
id="component_circuit_transistor"
src="https://pyxis.nymag.com/v1/imgs/0f9/f96/029acbf4c6d8c67e138e1eb06a277204bf-05-patrick.rsquare.w700.jpg"
height="50"
draggable
/>
</li>
<br /><br />
</ul>
<div class="elementi_disegno">
<h1 id="h1_disegna">Disegna il tuo circuito!</h1>
<button id="back-button">
Indietro
<span class="material-symbols-outlined">undo</span>
</button>
<button id="foward-button">
Avanti
<span class="material-symbols-outlined">redo</span>
</button>
<button id="clear-button">
Clear All
<span class="material-symbols-outlined">delete</span>
</button>
<canvas id="canvas" class="dropzone"></canvas>
</div>
</div>
您可以使用接受HTMLImageElement
的CanvasRenderingContext2D.drawImage()
将图像加载到画布中。您可以将可拖动的图像存储在数组中,并在拖动开始时传递图像的索引。
const draggableImages = document.querySelectorAll('img[draggable]');
for (let i = 0; i < draggableImages.length; i++)
draggableImages[i].ondragstart = (ev) => {
ev.dataTransfer.setData('text/plain', i.toString());
};
由于使用的是动画帧,因此需要存储画布上绘制的图像以及它们的位置。为了简单起见,我使用了一个数组,但如果你想允许删除、重新拖动、调整大小等,你可能需要其他东西。
const drawnImageData[] = [];
现在要在画布上触发drop
事件,需要防止ondragover
事件的默认行为。
canvas.ondragover = (ev) => ev.preventDefault();
然后在ondrop
事件触发时获取图像的索引。将图像放在drawnImages
的简介中,并附上指示在何处绘制的x和y坐标。我使用的是相对于画布左上角的位置。
canvas.ondrop = (ev) => {
const index = parseInt(ev.dataTransfer.getData('text/plain'));
const img = draggableImages[index];
drawnImageData.push({ img, x: ev.offsetX, y: ev.offsetY });
};
现在在draw
函数中绘制图像。
for (const data of drawnImageData)
ctx.drawImage(data.img, data.x, data.y, data.img.width, data.img.height);