开始和结束点到图像

huangapple go评论81阅读模式
英文:

Starting and ending point to images

问题

I'm trying to set a starting and ending point to images. So I have my canvas and my images, when I drop my images into the canvas I want that when I hover at the starting/ending point it lights a little red circle which means that I can create a connection with other images. For example: 1) Drag the image. 2) Drop the image inside the canvas. 3) Hover to the starting/ending point, and it lights up in a little red dot.

如何在画布上设置图像的起始和结束点?当我将图像拖放到画布上时,我希望在悬停在起始/结束点时出现一个小红点,表示我可以与其他图像创建连接。例如:1)拖动图像。2)将图像放在画布内。3)悬停在起始/结束点,它会亮起一个小红点。

As you can see, the red dots that only appear on hover.

如您所见,只有在悬停时才会出现的红点。

Another problem, but if you fix the first one is cool, the images don't follow the grid (squares).

还有一个问题,但如果您解决第一个问题就很好,图像不会遵循网格(方块)。

Here is an example of html/js:

这是一个HTML/JS的示例:

<!-- 嵌入代码 -->

The code provided, maybe that doesn't work on stackoverflow, try it locally. And if you use other images please provide the link.

提供的代码可能在Stack Overflow上无法正常工作,请尝试在本地运行。如果您使用其他图像,请提供链接。

英文:

I'm trying to set a starting and ending point to images. So I have my canvas and my images, when I drop my images into the canvas I want that when I hover at the starting/ending point it lights a little red circle which means that I can create a connection with other images. For example: 1) Drag the image. 2) Drop the image inside the canvas. 3) Hover to the starting/ending point, and it lights up in a little red dot.
开始和结束点到图像

As you can see, the red dots that only appear on hover. Another problem, but if you fix the first one is cool, the images don't follow the grill (squares).
Here is an example of html/js

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

const resistor = document.getElementById(&#39;component_circuit_resistor&#39;);
const condensator = document.getElementById(&#39;component_circuit_condensator&#39;);
const tranistor = document.getElementById(&#39;component_circuit_tranistor&#39;);
const alimentator = document.getElementById(&#39;component_circuit_alimentator&#39;);
const circuit = document.getElementById(&#39;components_circuit&#39;);
const back_button = document.getElementById(&#39;back-button&#39;);
const clear_button = document.getElementById(&#39;clear-button&#39;);
const draggable = document.querySelectorAll(&#39;.draggable&#39;);
const container = document.querySelectorAll(&#39;.container&#39;);
const canvas = document.getElementById(&#39;canvas&#39;);
const foward_button = document.getElementById(&#39;foward-button&#39;);


/** EDIT START */
const draggableImages = document.querySelectorAll(&#39;img[draggable]&#39;);

for (let i = 0; i &lt; draggableImages.length; i++)
  draggableImages[i].ondragstart = (ev) =&gt; {
    ev.dataTransfer.setData(&#39;text/plain&#39;, i.toString());
  };

canvas.ondragover = (ev) =&gt; ev.preventDefault(); // IMPORTANT

const orderStack = [];
const deletedOrderStack = [];

const drawnImageData = [];
const deletedImageData = [];

canvas.ondrop = (ev) =&gt; {
  const index = parseInt(ev.dataTransfer.getData(&#39;text/plain&#39;));
  const img = draggableImages[index];
  const x = ev.clientX - canvas.offsetLeft - img.width / 2;
  const y = ev.clientY - canvas.offsetTop - img.height / 2;
  const squareSize = 10; // adjust this to match the size of your squares
  const maxSize = 75; // maximum size of the image
  const aspectRatio = img.width / img.height;
  let width = maxSize;
  let height = maxSize / aspectRatio;
  if (height &gt; maxSize) {
    height = maxSize;
    width = height * aspectRatio;
  }
  const snappedX = Math.round(x / squareSize) * squareSize;
  const snappedY = Math.round(y / squareSize) * squareSize;
  ctx.drawImage(img, snappedX, snappedY, width, height);
  drawnImageData.push(ctx.getImageData(0, 0, canvas.width, canvas.height));
  orderStack.push(1);
  deletedImageData.length = 0;
  deletedOrderStack.length = 0;
  back_button.disabled = false;
  back_button.style.cursor = &#39;pointer&#39;;
  clear_button.disabled = false;
  clear_button.style.cursor = &#39;pointer&#39;;
  foward_button.disabled = true;
  foward_button.style.cursor = &#39;not-allowed&#39;;
  return false;
};

clear_button.disabled = true;
clear_button.style.cursor = &#39;not-allowed&#39;;
foward_button.disabled = true;
foward_button.style.cursor = &#39;not-allowed&#39;;
back_button.disabled = true;
back_button.style.cursor = &#39;not-allowed&#39;;
/** EDIT END */

canvas.width = 1900;

canvas.height = 1000;
canvas.style.backgroundColor = &#39;white&#39;;
circuit.appendChild(canvas);
canvas.style.borderRadius = &#39;10px&#39;;
canvas.style.marginLeft = &#39;auto&#39;;
canvas.style.marginRight = &#39;auto&#39;;
canvas.style.display = &#39;block&#39;;
const ctx = canvas.getContext(&#39;2d&#39;);

//const circles = [];
const lines = [];
const lines_c = [];
var deletedLines = [];

function drawSquares() {
  const squareSize = 10;
  const numColumns = Math.floor(canvas.width / squareSize);
  const numRows = Math.floor(canvas.height / squareSize);

  ctx.fillStyle = &quot;#FAF9F9&quot;;
  ctx.strokeStyle = &quot;#F4F1F0&quot;;
  ctx.lineWidth = 1;

  for (let i = 0; i &lt; numColumns; i++) {
    for (let j = 0; j &lt; numRows; j++) {
      const x = i * squareSize;
      const y = j * squareSize;

      if (i % 10 === 0 &amp;&amp; j % 10 === 0) {
        ctx.lineWidth = 2.6;
        ctx.fillStyle = &quot;#F1ECEB&quot;;
        ctx.strokeStyle = &quot;#E6E0DE&quot;; // set the stroke color to a darker shade
        ctx.strokeRect(x, y, squareSize * 10, squareSize * 10);
        ctx.fillStyle = &quot;#F4F1F0&quot;;
        ctx.strokeStyle = &quot;#F4F1F0&quot;; // reset the stroke color
        ctx.lineWidth = 1;
      } else {
        ctx.strokeRect(x, y, squareSize, squareSize);
      }
    }
  }
}

drawSquares();

<!-- language: lang-html -->

&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta http-equiv=&quot;X-UA-Compatible&quot; content=&quot;IE=edge&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;link rel=&quot;stylesheet&quot; href=&quot;https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@48,400,0,0&quot; /&gt;
    &lt;link rel=&quot;stylesheet&quot; href=&quot;style.css&quot;&gt;
    &lt;!-- &lt;title&gt;From Circuit to Breadboard&lt;/title&gt; --&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;div class=&quot;container&quot;&gt;
        &lt;div class=&quot;components&quot;&gt;
            &lt;div id=&quot;components_circuit&quot;&gt;
                &lt;h3 id =&quot;h3_componenti_circuit&quot;&gt;Componenti:&lt;/h3&gt;
                    &lt;ul id=&quot;components_circuit_border&quot;&gt;
                        &lt;li&gt;&lt;img id =&quot;component_circuit_resistor&quot; src=&quot;https://www.elprocus.com/wp-content/uploads/Resistor-Symbol-768x288.png&quot; height=&quot;50&quot; draggable=&quot;true&quot;&gt;&lt;/li&gt;
                        &lt;br&gt;&lt;br&gt;
                        &lt;li&gt;&lt;img id = &quot;component_circuit_condensator&quot; src=&quot;https://upload.wikimedia.org/wikipedia/commons/thumb/6/6d/Capacitor_Symbol_alternative.svg/1280px-Capacitor_Symbol_alternative.svg.png&quot; height=&quot;50&quot; draggable=&quot;true&quot;&gt;&lt;/li&gt;
                        &lt;br&gt;&lt;br&gt;
                        &lt;li&gt;&lt;img id=&quot;component_circuit_transistor&quot; src=&quot;images/circuit_transistor.png&quot; height=&quot;50&quot; draggable=&quot;true&quot;&gt;&lt;/li&gt;
                        &lt;br&gt;&lt;br&gt;
                        &lt;li&gt;&lt;img id=&quot;component_circuit_alimentator&quot; src=&quot;images/circuit_alimentator.png&quot; height=&quot;50&quot; draggable=&quot;true&quot;&gt;&lt;/li&gt;
                    &lt;/ul&gt;
                &lt;div class = &quot;elementi_disegno&quot;&gt;
                    &lt;h1 id =&quot;h1_disegna&quot;&gt;Disegna il tuo circuito!&lt;/h1&gt;
                &lt;button id=&quot;back-button&quot;&gt;Indietro
                    &lt;span class=&quot;material-symbols-outlined&quot;&gt;undo&lt;/span&gt;
                &lt;/button&gt;
                &lt;button id=&quot;foward-button&quot;&gt;Avanti
                    &lt;span class=&quot;material-symbols-outlined&quot;&gt;redo&lt;/span&gt;
                &lt;/button&gt;
                &lt;button id=&quot;clear-button&quot;&gt;Clear All
                    &lt;span class=&quot;material-symbols-outlined&quot;&gt;delete&lt;/span&gt;
                &lt;/button&gt;
                &lt;canvas id = &quot;canvas&quot; class = &quot;dropzone&quot;&gt;&lt;/canvas&gt;
                &lt;/div&gt;
            &lt;/div&gt;
    
    &lt;script src=&quot;script.js&quot;&gt;&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;

<!-- end snippet -->

The code provided, maybe that doesn't work on stackoverflow, try it locally. And if you use other images please provide the link.

答案1

得分: 3

你可以在一个数组中跟踪图像的x和y,并迭代该数组以检查鼠标指针是否与任何对象的一定距离,如果是,则绘制一个圆。在远程图像中,连接点位于两侧的中间位置,如果您计划添加多于2个显示的图像(不确定本地托管的图像),并且具有不同的起始和结束点,您需要根据图像更改值。但是,使用当前的设置,您可以直接硬编码它,这是我的实现:

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');
let images = [];

/** 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 orderStack = [];
const deletedOrderStack = [];

const drawnImageData = [];
const deletedImageData = [];
canvas.ondrop = (ev) => {

    const index = parseInt(ev.dataTransfer.getData('text/plain'));
    const img = draggableImages[index];
    const x = ev.clientX - canvas.offsetLeft - img.width / 2;
    const y = ev.clientY - canvas.offsetTop - img.height / 2;
    const squareSize = 10; // adjust this to match the size of your squares

    const maxSize = 75; // maximum size of the image
    const aspectRatio = img.width / img.height;
    let width = maxSize;
    let height = maxSize / aspectRatio;
    if (height > maxSize) {
      height = maxSize;
      width = height * aspectRatio;
    }
    const snappedX = Math.round(x / squareSize) * squareSize;
    const snappedY = Math.round(y / squareSize) * squareSize;
    ctx.drawImage(img, snappedX, snappedY, width, height);
    images.push({ img, x: snappedX, y: snappedY, width, height });
    // Add the image and its position to the images array

  };



clear_button.disabled = true;
clear_button.style.cursor = 'not-allowed';
foward_button.disabled = true;
foward_button.style.cursor = 'not-allowed';
back_button.disabled = true;
back_button.style.cursor = 'not-allowed';
/** EDIT END */

canvas.width = 1900;

canvas.height = 1000;
canvas.style.backgroundColor = 'white';
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 = [];

function drawSquares() {
  const squareSize = 10;
  const numColumns = Math.floor(canvas.width / squareSize);
  const numRows = Math.floor(canvas.height / squareSize);

  ctx.fillStyle = "#FAF9F9";
  ctx.strokeStyle = "#F4F1F0";
  ctx.lineWidth = 1;

  for (let i = 0; i < numColumns; i++) {
    for (let j = 0; j < numRows; j++) {
      const x = i * squareSize;
      const y = j * squareSize;

      if (i % 10 === 0 && j % 10 === 0) {
        ctx.lineWidth = 2.6;
        ctx.fillStyle = "#F1ECEB";
        ctx.strokeStyle = "#E6E0DE"; // set the stroke color to a darker shade
        ctx.strokeRect(x, y, squareSize * 10, squareSize * 10);
        ctx.fillStyle = "#F4F1F0";
        ctx.strokeStyle = "#F4F1F0"; // reset the stroke color
        ctx.lineWidth = 1;
      } else {
        ctx.strokeRect(x, y, squareSize, squareSize);
      }
    }
  }
}

drawSquares();

// Add a mousemove event to the canvas to show the red dot
  const redDotRadius = 5; // The radius of the red dots
  const hoverDistance = 10; // The distance from a point at which to show the dot

canvas.onmousemove = (ev) => {
    const mouseX = ev.clientX - canvas.offsetLeft;
    const mouseY = ev.clientY - canvas.offsetTop;

    // Clear the canvas and redraw everything
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    drawSquares();
    for (let i = 0; i < images.length; i++) {
      let image = images[i];
      ctx.drawImage(image.img, image.x, image.y, image.width, image.height);
    }

    // Check if the mouse is near a starting or ending point
    for (let i = 0; i < images.length; i++) {
      let image = images[i];
      let startX = image.x+5;
      let startY = image.y + image.height/2;
      let endX = image.x + image.width -5;
      let endY = image.y + image.height/2;

      if (Math.abs(mouseX - startX) < hoverDistance && Math.abs(mouseY - startY) < hoverDistance) {
        // Near the starting point, draw a red dot
        ctx.beginPath();
        ctx.arc(startX, startY, redDotRadius, 0, 2 * Math.PI, false);
        ctx.fillStyle = 'red';
        ctx.fill();
      } else if (Math.abs(mouseX - endX) < hoverDistance && Math.abs(mouseY - endY) < hoverDistance) {
        // Near the ending point, draw a red dot
        ctx.beginPath();
        ctx.arc(endX, endY, redDotRadius, 0, 2 * Math.PI, false);
        ctx.fillStyle = 'red';
        ctx.fill();
      }
    }
  };

我没有更改HTML。

英文:

you can keep track of the x and y of the images in an array and iterate through the array to check if the mouse pointer is a certain distance from any object and if so draw a circle, In the remote images the connections are at the half way point in both sides if you are planning to add more than the 2 images that show up (Idk about the images that are hosted locally) with different start and end point you will need to change the values depending on the image however with the current setup you can just hard code it, here is my implementation:

const resistor = document.getElementById(&#39;component_circuit_resistor&#39;);
const condensator = document.getElementById(&#39;component_circuit_condensator&#39;);
const tranistor = document.getElementById(&#39;component_circuit_tranistor&#39;);
const alimentator = document.getElementById(&#39;component_circuit_alimentator&#39;);
const circuit = document.getElementById(&#39;components_circuit&#39;);
const back_button = document.getElementById(&#39;back-button&#39;);
const clear_button = document.getElementById(&#39;clear-button&#39;);
const draggable = document.querySelectorAll(&#39;.draggable&#39;);
const container = document.querySelectorAll(&#39;.container&#39;);
const canvas = document.getElementById(&#39;canvas&#39;);
const foward_button = document.getElementById(&#39;foward-button&#39;);
let images = [];
/** EDIT START */
const draggableImages = document.querySelectorAll(&#39;img[draggable]&#39;);
for (let i = 0; i &lt; draggableImages.length; i++)
draggableImages[i].ondragstart = (ev) =&gt; {
ev.dataTransfer.setData(&#39;text/plain&#39;, i.toString());
};
canvas.ondragover = (ev) =&gt; ev.preventDefault(); // IMPORTANT
const orderStack = [];
const deletedOrderStack = [];
const drawnImageData = [];
const deletedImageData = [];
canvas.ondrop = (ev) =&gt; {
const index = parseInt(ev.dataTransfer.getData(&#39;text/plain&#39;));
const img = draggableImages[index];
const x = ev.clientX - canvas.offsetLeft - img.width / 2;
const y = ev.clientY - canvas.offsetTop - img.height / 2;
const squareSize = 10; // adjust this to match the size of your squares
const maxSize = 75; // maximum size of the image
const aspectRatio = img.width / img.height;
let width = maxSize;
let height = maxSize / aspectRatio;
if (height &gt; maxSize) {
height = maxSize;
width = height * aspectRatio;
}
const snappedX = Math.round(x / squareSize) * squareSize;
const snappedY = Math.round(y / squareSize) * squareSize;
ctx.drawImage(img, snappedX, snappedY, width, height);
images.push({ img, x: snappedX, y: snappedY, width, height });
// Add the image and its position to the images array
};
clear_button.disabled = true;
clear_button.style.cursor = &#39;not-allowed&#39;;
foward_button.disabled = true;
foward_button.style.cursor = &#39;not-allowed&#39;;
back_button.disabled = true;
back_button.style.cursor = &#39;not-allowed&#39;;
/** EDIT END */
canvas.width = 1900;
canvas.height = 1000;
canvas.style.backgroundColor = &#39;white&#39;;
circuit.appendChild(canvas);
canvas.style.borderRadius = &#39;10px&#39;;
canvas.style.marginLeft = &#39;auto&#39;;
canvas.style.marginRight = &#39;auto&#39;;
canvas.style.display = &#39;block&#39;;
const ctx = canvas.getContext(&#39;2d&#39;);
//const circles = [];
const lines = [];
const lines_c = [];
var deletedLines = [];
function drawSquares() {
const squareSize = 10;
const numColumns = Math.floor(canvas.width / squareSize);
const numRows = Math.floor(canvas.height / squareSize);
ctx.fillStyle = &quot;#FAF9F9&quot;;
ctx.strokeStyle = &quot;#F4F1F0&quot;;
ctx.lineWidth = 1;
for (let i = 0; i &lt; numColumns; i++) {
for (let j = 0; j &lt; numRows; j++) {
const x = i * squareSize;
const y = j * squareSize;
if (i % 10 === 0 &amp;&amp; j % 10 === 0) {
ctx.lineWidth = 2.6;
ctx.fillStyle = &quot;#F1ECEB&quot;;
ctx.strokeStyle = &quot;#E6E0DE&quot;; // set the stroke color to a darker shade
ctx.strokeRect(x, y, squareSize * 10, squareSize * 10);
ctx.fillStyle = &quot;#F4F1F0&quot;;
ctx.strokeStyle = &quot;#F4F1F0&quot;; // reset the stroke color
ctx.lineWidth = 1;
} else {
ctx.strokeRect(x, y, squareSize, squareSize);
}
}
}
}
drawSquares();
// Add a mousemove event to the canvas to show the red dot
const redDotRadius = 5; // The radius of the red dots
const hoverDistance = 10; // The distance from a point at which to show the dot
canvas.onmousemove = (ev) =&gt; {
const mouseX = ev.clientX - canvas.offsetLeft;
const mouseY = ev.clientY - canvas.offsetTop;
// Clear the canvas and redraw everything
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawSquares();
for (let i = 0; i &lt; images.length; i++) {
let image = images[i];
ctx.drawImage(image.img, image.x, image.y, image.width, image.height);
}
// Check if the mouse is near a starting or ending point
for (let i = 0; i &lt; images.length; i++) {
let image = images[i];
let startX = image.x+5;
let startY = image.y + image.height/2;
let endX = image.x + image.width -5;
let endY = image.y + image.height/2;
if (Math.abs(mouseX - startX) &lt; hoverDistance &amp;&amp; Math.abs(mouseY - startY) &lt; hoverDistance) {
// Near the starting point, draw a red dot
ctx.beginPath();
ctx.arc(startX, startY, redDotRadius, 0, 2 * Math.PI, false);
ctx.fillStyle = &#39;red&#39;;
ctx.fill();
} else if (Math.abs(mouseX - endX) &lt; hoverDistance &amp;&amp; Math.abs(mouseY - endY) &lt; hoverDistance) {
// Near the ending point, draw a red dot
ctx.beginPath();
ctx.arc(endX, endY, redDotRadius, 0, 2 * Math.PI, false);
ctx.fillStyle = &#39;red&#39;;
ctx.fill();
}
}
};

I didn't change the html

huangapple
  • 本文由 发表于 2023年5月7日 16:37:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/76192912.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定