71232

HTML5 Canvas Drag and Drop Item

Question:

Been struggling to get this work work. Here's my code:

<canvas id="graphCanvas" ondrop="drop(event)" ondragover="allowDrop(event)" height=600 width=1000 style="border:1px solid #000000;"></canvas> <img id="img1" src="./images/arrow_up.svg" draggable="true" onmousedown="get_pos(event)" ondragstart="drag(event)"/> <script type="text/javascript"> function init() { var canvas = document.getElementById("graphCanvas"); var context = canvas.getContext("2d"); context.lineWidth = 2; } var pos; function allowDrop(ev) { ev.preventDefault(); } function get_pos(ev){ pos = [ev.pageX, ev.pageY]; } function drag(ev) { ev.dataTransfer.setData("Text",ev.target.id); } function drop(ev) { ev.preventDefault(); var offset = ev.dataTransfer.getData("text/plain").split(','); var data=ev.dataTransfer.getData("Text"); var img = canvas = document.getElementById("img1"); var dx = pos[0] - img.offsetLeft; var dy = pos[1] - img.offsetTop; document.getElementById("graphCanvas").getContext("2d").drawImage(document.getElementById(data), ev.pageX - dx, ev.pageY - dy); } </script>

It's suppose to be a draggable image that I can drop into a canvas. Once the image is in the canvas, the user can then move that image around. Unfortunately I can not seem to get it work. The image should appear if you drop it in near the top left, but the image appears near the bottom right.

How can I fix this problem?

Answer1:

You can use html5 draggable to drop an image element on canvas.

Then you can drawImage a copy of that image on the canvas.

<strong>You need this info to draw a copy of the draggable image on the canvas:</strong>

<ul><li>

The mouse position relative to the draggable image (see mousedown below)

</li> <li>

The canvas position relative to the document (canvasElement.offsetLeft & canvasElement.offsetTop).

</li> <li>

The mouse position relative to the document at the drop ( dropEvent.clientX & dropEvent.clientY )

</li> <li>

The Id of the draggable element (stored and retrieved in dragEvent.dataTransfer)

</li> </ul>

With this info you can drawImage a copy of the draggable element like this:

function drop(ev) { ev.preventDefault(); var dropX=ev.clientX-canvasLeft-startOffsetX; var dropY=ev.clientY-canvasTop-startOffsetY; var id=ev.dataTransfer.getData("Text"); var dropElement=document.getElementById(id); // draw the drag image at the drop coordinates ctx.drawImage(dropElement,dropX,dropY); }

Here's example code and a Demo: <a href="http://jsfiddle.net/m1erickson/WyEPh/" rel="nofollow">http://jsfiddle.net/m1erickson/WyEPh/</a>

<!doctype html> <html> <head> <link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css --> <script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script> <style> body{ background-color: ivory; padding:20px; } #graphCanvas{border:1px solid #000000;} </style> <script> $(function(){ var canvas=document.getElementById("graphCanvas"); var ctx=canvas.getContext("2d"); var canvasLeft=canvas.offsetLeft; var canvasTop=canvas.offsetTop; canvas.ondrop=drop; canvas.ondragover=allowDrop; // var img=document.getElementById("img1"); img.onmousedown=mousedown; img.ondragstart=dragstart; // this is the mouse position within the drag element var startOffsetX,startOffsetY; function allowDrop(ev) { ev.preventDefault(); } function mousedown(ev){ startOffsetX=ev.offsetX; startOffsetY=ev.offsetY; } function dragstart(ev) { ev.dataTransfer.setData("Text",ev.target.id); } function drop(ev) { ev.preventDefault(); var dropX=ev.clientX-canvasLeft-startOffsetX; var dropY=ev.clientY-canvasTop-startOffsetY; var id=ev.dataTransfer.getData("Text"); var dropElement=document.getElementById(id); // draw the drag image at the drop coordinates ctx.drawImage(dropElement,dropX,dropY); } }); // end $(function(){}); </script> </head> <body> <canvas id="graphCanvas" height=300 width=300></canvas> <img id="img1" src="house32x32.png" draggable="true" /> </body> </html>

<strong>However...images drawn on the canvas are just painted pixels and therefore not draggable</strong>

You can use a canvas library like KineticJS to create "retained" images that can be dragged after they are drawn on the canvas.

Here's a Demo using KineticJS to allow dropped images to later be dragged around the canvas:

<a href="http://jsfiddle.net/m1erickson/LuZbV/" rel="nofollow">http://jsfiddle.net/m1erickson/LuZbV/</a>

Recommend

  • HTML 5 drag and drop How to figure out whether an element accepts a drop
  • Drag and drop (replace) in HTML 5
  • Coffeescript .bind seems to be wrapped inside a function when compiled to js and is not called
  • is event.pageX null check needed?
  • How to get the date when calendar rendering date cells
  • calculate position of a point on image in percentage
  • Mouseenter and Mouseleave to trigger timer on/off
  • tooltip position near the mouse click
  • JavaScript draw a circle on mouse click - cordinates don't match
  • Check if mouse is within element's bounds
  • Moving elements by dragging in Dart
  • Adding a Dropdown inside Kendo Grid
  • ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS in not firing
  • Get Clipboard String Encoding (java)
  • How I can I delay the expansion of a collapsible until its content is fetched?
  • Bootstrap Carousel Next/Prev not working
  • JQuery Mobile 1.4 How to Disable Hover Effect on Mobile Devices
  • Give wx.StaticBitmap a transparent background? wxpython
  • Onclick or href which is best for opening an link in button
  • C++ how to get substring after get position of its index
  • Is it possible to disable esc/F11 key during full screen mode of webpage, programmatically?
  • How to move again MainActivity after sending the mail?
  • Android - Call default browser with and redirect to a designated url
  • Monotouch crashes with NullReferenceException on non nullable object
  • How to plot large time series (thousands of administration times/doses of a medication)?
  • Android distinguish between tap and double tap
  • Subclassing QGraphicsItem prevents me from being able to use itemAt() on a QGraphicsScene/View
  • MySQL WHERE-condition in procedure ignored
  • Shallow update not allowed (git > 1.9)
  • jquery mobile loadPage not working
  • Web-crawler for facebook in python
  • align graphs with different xlab
  • How to delete a row from a dynamic generate table using jquery?
  • How to include full .NET prerequisite for Wix Burn installer
  • trying to dynamically update Highchart column chart but series undefined
  • using HTMLImports.whenReady not working in chrome
  • Qt: Run a script BEFORE make
  • Authorize attributes not working in MVC 4
  • EntityFramework adding new object to nested object collection
  • java string with new operator and a literal