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

هاري ثيودولو
هاري ثيودولو

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

استخدام 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);
  }
});

التوافق مع المتصفح

  • 86
  • 79
  • 13

المصدر

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

الاستماع إلى حدث 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.
    }
  }
});

التوافق مع المتصفح

  • 66
  • 79
  • 63
  • 13

المصدر

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

بالنسبة إلى المتصفّحات التي لا تتيح استخدام Async Clipboard API، من المستحيل الوصول إلى حافظة المستخدم بشكل آلي (بالنقر على زر مثلاً). للوصول إلى حافظة المستخدم في حدث paste، يمكنك استخدام Async 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 على MDN
  • إزالة حظر الوصول إلى الحافظة على 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);
};