Вставка непосредственно в элемент HTML img - PullRequest
1 голос
/ 19 июня 2020

Re: вопрос. Учитывая, что следующее применимо только к Firefox, существует ли кросс-браузерное решение? или API буфера обмена слишком новый (2020).

Исходный вопрос:


В игре с API буфера обмена в Firefox. Мне удалось скопировать изображение и вставить его на холст.

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";

Вышесказанное - это то, над чем я хотел бы работать; ниже приведен хак, который работает.


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";

Если есть способ, чтобы это работало без какого-либо скрипта, даже лучше!

источники:

1 Ответ

1 голос
/ 20 июня 2020

Это берет несколько разных идей и объединяет их: ваш фильтр данных буфера обмена (немного изменен) и использует класс 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;
}
image
...