كيفية لصق الصور

الطريقة الحديثة

استخدام Async Clipboard API

لقراءة الصور من حافظة المستخدم آليًا، أي بعد النقر على زر، يمكنك استخدام طريقة read() في Async Clipboard API. إذا لم يتم منح الإذن بالقراءة من الحافظة بعد، سيطلب استدعاء navigator.clipboard.read() ذلك عند استدعاء الطريقة لأول مرة.

const pasteButton = document.querySelector('#paste-button');

pasteButton.addEventListener('click', async () => {
  try {
    const clipboardItems = await navigator.clipboard.read();
    for (const clipboardItem of clipboardItems) {
      const imageTypes = clipboardItem.types.find(type => type.startsWith('image/'))
      for (const imageType of imageTypes) {
        const blob = await clipboardItem.getType(imageType);
        // Do something with the image blob.
      }
    }
  } catch (err) {
    console.error(err.name, err.message);
  }
});

Browser Support

  • Chrome: 76.
  • Edge: 79.
  • Firefox: 127.
  • Safari: 13.1.

Source

الطريقة الكلاسيكية

الاستماع إلى حدث paste

الطريقة التقليدية للصق الصور هي استخدام واجهة برمجة التطبيقات للحافظة (المتزامنة)، والتي تتيح لك الوصول إلى الحقل clipboardData داخل حدث المستند: paste. ومع ذلك، يتضمّن هذا الأسلوب قيودًا، مثلاً لأنّه متزامن، فقد يؤدي لصق كميات كبيرة من البيانات إلى حظر الصفحة.

document.addEventListener('paste', async (e) => {
  e.preventDefault();

  for (const clipboardItem of e.clipboardData.files) {
    if (clipboardItem.type.startsWith('image/')) {
      // Do something with the image file.
    }
  }
});

Browser Support

  • Chrome: 66.
  • Edge: 79.
  • Firefox: 63.
  • Safari: 13.1.

Source

التحسين التدريجي

بالنسبة إلى المتصفحات التي لا تتوافق مع Async Clipboard API، يتعذّر الوصول إلى حافظة المستخدم آليًا (على سبيل المثال، عند النقر على زر). وبالتالي، للوصول إلى حافظة المستخدم عند وقوع حدث paste، يمكنك استخدام Async Clipboard API والرجوع إلى Clipboard API (المتزامن).

تحتوي عناصر ClipboardItem الواردة من navigator.clipboard.read على الحقل types الذي يمثّل مصفوفة، بينما تحتوي عناصر File الواردة من event.clipboardData.files على الحقل type الذي يمثّل سلسلة. يمكنك التحقّق بشكل مشروط من كل من الحقلَين type أو types بحثًا عن صور في الحافظة:

document.addEventListener('paste', async (e) => {
  e.preventDefault();
  const clipboardItems = typeof navigator?.clipboard?.read === 'function' ? await navigator.clipboard.read() : e.clipboardData.files;

  for (const clipboardItem of clipboardItems) {
    let blob;
    if (clipboardItem.type?.startsWith('image/')) {
      // For files from `e.clipboardData.files`.
      blob = clipboardItem
      // Do something with the blob.
    } else {
      // For files from `navigator.clipboard.read()`.
      const imageTypes = clipboardItem.types?.filter(type => type.startsWith('image/'))
      for (const imageType of imageTypes) {
        blob = await clipboardItem.getType(imageType);
        // Do something with the blob.
      }
    }
  }
});

محتوى إضافي للقراءة

  • ‫Clipboard API على شبكة مطوّلي Mozilla
  • إزالة حظر الوصول إلى الحافظة على web.dev

عرض توضيحي

HTML

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <link
      rel="icon"
      href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>🎉</text></svg>"
    />
    <title>How to paste images</title>
  </head>
  <body>
    <h1>How to paste images</h1>
    <p>Hit <kbd>⌘</kbd> + <kbd>v</kbd> (for macOS) or <kbd>ctrl</kbd> + <kbd>v</kbd>
      (for other operating systems) to paste images anywhere in this page.
    </p>
  </body>
</html>

CSS


        :root {
  color-scheme: dark light;
}

html {
  box-sizing: border-box;
}

*,
*:before,
*:after {
  box-sizing: inherit;
}

body {
  margin: 1rem;
  font-family: system-ui, sans-serif;
}

button {
  display: block;
}
        

JS


        document.addEventListener('paste', async (e) => {
  e.preventDefault();
  const clipboardItems = typeof navigator?.clipboard?.read === 'function' ? await navigator.clipboard.read() : e.clipboardData.files;

  for (const clipboardItem of clipboardItems) {
    let blob;
    if (clipboardItem.type?.startsWith('image/')) {
      // For files from `e.clipboardData.files`.
      blob = clipboardItem
      // Do something with the blob.
      appendImage(blob);
    } else {
      // For files from `navigator.clipboard.read()`.
      const imageTypes = clipboardItem.types?.filter(type => type.startsWith('image/'))
      for (const imageType of imageTypes) {
        blob = await clipboardItem.getType(imageType);
        // Do something with the blob.
        appendImage(blob);
      }
    }
  }
});

const appendImage = (blob) => {
  const img = document.createElement('img');
  img.src = URL.createObjectURL(blob);
  document.body.append(img);
};