【问题标题】:Pasting directly to an HTML img element直接粘贴到 HTML img 元素
【发布时间】:2020-10-10 04:26:43
【问题描述】:

回复:问题。 鉴于以下仅适用于 Firefox,是否有跨浏览器解决方案?还是剪贴板 API 太新(2020 年)。

原问题:


在 Firefox 中使用剪贴板 API。我能够复制图像并将其粘贴到画布中。

const canvas = document.createElement("canvas");
canvas.setAttribute("contenteditable", "true")
document.body.appendChild(canvas);
canvas.style = "border:solid black 1px";
canvas.addEventListener("paste", element_paste(canvas, "canvas"));

function element_paste(element, type) {
  switch (type) {
    case "image":
      return function(e) {
        element.src = image_data_transfer(e.clipboardData || window.clipboardData);
      }
    case "canvas":
      return function(e) {
        const im = new Image();
        im.src = image_data_transfer(e.clipboardData || window.clipboardData);
        im.onload = () => {
          element.width = im.width;
          element.height = im.height;
          element.getContext("2d").drawImage(im, 0, 0);
          URL.revokeObjectURL(im.src);
          delete im;
        };
      }
    default:
      return function(e) {
        var p = (e.clipboardData || window.clipboardData).getData("text");
        var t = document.createTextNode(p);
        element.appendChild(t);
      }
  }
}

function image_data_transfer(e) {
  const p = e.items;
  try {
    return URL
      .createObjectURL(Array
        .apply(null, Array(p.length))
        .map((_, i) => p[i])
        .find(e => e.kind == "file" && /image/.test(e.type))
        .getAsFile()
      );
  } catch (e) {
    console.log(e);
    return "";
  }
}

这完全符合画布的预期。 但是,如果画布更改为img;使用 "image" 作为 element_paste 中的类型,如果 html 元素允许粘贴到它,这将起作用。

我知道我可以“轻松”地将画布覆盖在图像上,并且效果完全符合预期。我解决这个问题的问题是((我正在玩弄另一个对象只是为了作为一种解决方法,我不妨使用画布来保存 DOM 混乱。)(它很难看。))

是否有任何标志实验性或其他允许直接粘贴到 img 的标志?


const img = document.createElement("img");
const image_paste = element_paste(img,"image");

document.body.appendChild(img);
img.setAttribute("contenteditable","true");
img.addEventListener("paste",image_paste);

img.style="border:solid black 1px;min-width:100px;min-height:100px";

以上是我想做的工作;下面是一个 hack。


const canvas = document.createElement("canvas");
const img = document.createElement("img");
const image_paste = element_paste(img,"image");

document.body.appendChild(img);
document.body.appendChild(canvas);
canvas.setAttribute("contenteditable","true");
canvas.addEventListener("paste",image_paste);

canvas.style="border:solid black 1px;";
img.style="border:solid black 1px;min-width:100px;min-height:100px";

如果有一种方法可以在没有任何脚本的情况下工作,那就更好了!

来源:

【问题讨论】:

  • 似乎画布上有一个toDataURL() (developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/…),它很容易设置为图像 url,因为它已经为你格式化了。在转换为数据 URL 之前有一个屏幕外/隐藏的画布来处理粘贴事件可能仍然是最简单的选择,即使它“更多工作”。可能有一种方法可以将剪贴板数据格式化为 dataURL 并完全跳过画布。
  • 最终示例画布中的画布仅需要作为粘贴事件的入口点,因为我找不到让 img 接受的方法。否则 img 是完全有能力的
  • ourcodeworld.com/articles/read/491/… 这似乎将图像数据作为 blob 或 base64 获取,并将其直接设置为图像元素。但是,要获得 base64,它仍然首先使用画布。但是,如果您正在为粘贴事件处理程序的放置位置而苦苦挣扎,您可以随时将其放在 DOM 链的更上方,即使在文档 body 本身上也是如此。
  • 正如你所说,将粘贴粘贴到身体上会起作用......这是一个解决方案,虽然我不知道使用帆布覆盖是否更清洁;至少对于多个​​对象,因为必须提供当前选择的对象。而且我认为您可能会丢失右键粘贴,这会破坏这种特定类型的可用性。
  • 即使使用 body,您仍然拥有 event.target,它可以帮助您确定要将数据应用到哪个图像。在这种情况下,您不需要为每个图像添加多个叠加层。

标签: javascript html image cross-browser clipboard


【解决方案1】:

这需要几个不同的想法并将它们组合在一起:您的剪贴板数据过滤器(稍作修改),并使用FileReader 类将其转换为dataurl,可以应用于img 对象。

有趣的是......虽然...选择了图像对象本身时似乎并不工作。

const image = document.getElementById('img')
document.addEventListener('paste', convertToImage)

function convertToImage(e) {
  var blob = image_data_transfer(e.clipboardData)
  if (blob !== null) {
    var reader = new FileReader();
    reader.onload = function(event) {
      console.log(event.target.result);
      image.src = event.target.result
      alert('pasted!')
    }; // data url!
    reader.readAsDataURL(blob);
  } else {
    console.log("couldn't read image data from clipboard")
  }


}

function image_data_transfer(clipboardData) {
  const p = clipboardData.items;
  try {
    return Array
      .apply(null, Array(p.length))
      .map((_, i) => p[i])
      .find(e => e.kind == "file" && /image/.test(e.type))
      .getAsFile()
    // URL.createObjectURL();
  } catch (e) {
    console.log(e);
    return null;
  }
}
img{
  width: 300px;
  height: 300px;
  border: 1px solid;
  background: #ccc;
}
<div>
  Paste here!
</div>

<img id="img" src="" onpaste="convertToImage">

【讨论】:

  • 虽然,由于图像标签似乎无法获取focus,您可能需要考虑使用 div 和&lt;element&gt;.style.backgroundImage = "url('theDataURL')" 属性。
  • 我无法将图像粘贴到您当前的 snip-it 中。也许有些东西被误删了?
  • 它在 chrome 中对我有用,但在图像本身被聚焦时不起作用,即使事件仍然触发并且您在技术上无法聚焦图像。
  • 我可以尝试将监听器放在文档上
  • 将监听器移至文档,适用于 FF 和 Chrome。试试看,@haelmic
猜你喜欢
  • 2014-12-26
  • 2015-05-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-26
  • 2016-08-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多