Home > Net >  Update height and width of image used for dragging using `setDragImage`
Update height and width of image used for dragging using `setDragImage`

Time:10-21

I am trying to use an image to show upon dragStart(), Tried updating the image height and width but no change seen. Here's sample code:

 var img = new Image(50, 40);  
 img.src = "https://images.unsplash.com/photo-1579353977828-2a4eab540b9a?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=774&q=80"
 ev.dataTransfer.setDragImage(img, 10, 10);

But the width and height, 50 and 40 updated is not reflecting to the image. I would like to fix dimensions for the image while dragging

Here's the sample link for the program https://jsfiddle.net/w6qkgc7t/

PS: Any solution without canvas would be better. ;)

CodePudding user response:

If the element passed to setDragImage() is an HTMLImageElement (<img>), its bitmap will be used as the source, it will thus ignore the CSS size set on the element.

Even though you said you'd prefer not to use a <canvas>, that's actually the best(/only cross-browser) way to do what you want.

You can actually pass any kind of element to that method, and the browser will be able to take a screenshot of the passed element. So one (e.g me), could have expected that creating an element, setting its background-image and CSS size to the ones required would have worked.
Unfortunately, for this to work, we need to have the element rendered in the page. Detached from the DOM, the CSS won't apply, visibility: hidden or opacity: 0, the browser will render a transparent rectangle, wrapped in a overflow: hidden parent, some browsers will make it work sometimes, if they already did render the element before, same if we try to move the element outside of the screen with position: fixed...

After a few attempts, I couldn't find a proper solution that would work in every browsers, and so I'm sorry to say that you should use a <canvas> to generate the new bitmap and use it as the source for an <img> element (passing the <canvas> directly wouldn't work the same in every browser either...). But this means that your image must have been served in a same-origin compliant way.

(async () => {
  const url = "https://images.unsplash.com/photo-1579353977828-2a4eab540b9a?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=774&q=80";
  const width = 50;
  const height = 40;

  const resp = await fetch(url);
  const blob = await resp.blob();
  const bmp  = await createImageBitmap(blob, {resizeWidth: width, resizeHeigth: height});

  const canvas  = Object.assign(document.createElement("canvas"), { width, height});
  canvas.getContext("2d").drawImage(bmp, 0, 0);
  const img = new Image();
  await new Promise((resolve) => {
    canvas.toBlob((blob) => {
      img.src = URL.createObjectURL(blob);
      resolve(img.decode());
    });
  });

  const target = document.getElementById("target");
  const source = document.getElementById("source");
  source.ondragstart = dragstart_handler;
  target.ondragover = dragover_handler;
  target.ondrop = drop_handler;

  function dragstart_handler(ev) {
   ev.dataTransfer.setData("text/plain", ev.target.id);
   ev.dataTransfer.setDragImage(img, 10, 10);
  }

  function dragover_handler(ev) {
   console.log("dragOver");
   ev.preventDefault();
  }

  function drop_handler(ev) {
   console.log("Drop");
   ev.preventDefault();
   var data = ev.dataTransfer.getData("text");
   ev.target.appendChild(document.getElementById(data));
  }
})().catch(console.error);
div.padme {
  margin: 0em;
  padding: 2em;
}
#source {
  color: blue;
  border: 1px solid black;
}
#target {
  border: 1px solid black;
}
<h1>Example of <code>DataTransfer.setDragImage()</code></h1>
<div >
 <p id="source" draggable="true">
   Select this element, drag it to the Drop Zone and then release the selection to move the element.</p>
</div>
<div id="target" >Drop Zone</div>
<div ></div>

  • Related