Лаборатория веб-возможностей

1. Введение и настройка

Веб-возможности

Мы хотим устранить разрыв в возможностях между веб-приложениями и нативными приложениями и облегчить разработчикам создание отличных возможностей в открытой сети. Мы твердо убеждены, что каждый разработчик должен иметь доступ к возможностям, необходимым для создания превосходного веб-интерфейса, и мы стремимся к созданию более функционального Интернета.

Однако есть некоторые возможности, такие как доступ к файловой системе и обнаружение простоя, которые доступны в встроенной версии, но недоступны в Интернете. Эти недостающие возможности означают, что некоторые типы приложений невозможно разместить в Интернете или они менее полезны.

Мы будем проектировать и развивать эти новые возможности открытым и прозрачным способом , используя существующие процессы стандартов открытых веб-платформ, одновременно получая раннюю обратную связь от разработчиков и других поставщиков браузеров по мере работы над дизайном, чтобы обеспечить совместимость дизайна.

Что ты построишь

В этой лаборатории кода вы поэкспериментируете с рядом совершенно новых веб-API или доступных только под флагом. Таким образом, эта лаборатория кода фокусируется на самих API и вариантах использования, которые эти API открывают, а не на создании конкретного конечного продукта.

Что вы узнаете

Эта лаборатория научит вас основам работы нескольких передовых API. Обратите внимание, что эта механика еще не высечена в камне, и мы очень ценим ваши отзывы о процессе разработки.

Что вам понадобится

Поскольку API, представленные в этой лаборатории кода, действительно находятся на переднем крае, требования к каждому API различаются. Пожалуйста, внимательно прочитайте информацию о совместимости в начале каждого раздела.

Как подойти к кодовой лаборатории

Лабораторию кода не обязательно следует прорабатывать последовательно. Каждый раздел представляет собой независимый API, поэтому не стесняйтесь выбирать то, что вас интересует больше всего.

2. API бейджинга

Цель API значков — привлечь внимание пользователей к событиям, происходящим в фоновом режиме. Для простоты демонстрации в этой лаборатории кода давайте воспользуемся API, чтобы привлечь внимание пользователей к чему-то, что происходит на переднем плане. Затем вы можете мысленно перенестись на события, происходящие на заднем плане.

Установить Эйрхонер

Чтобы этот API работал, вам нужен PWA, установленный на главном экране, поэтому первым шагом является установка PWA, такого как печально известный, всемирно известный airhorner.com . Нажмите кнопку «Установить» в правом верхнем углу или воспользуйтесь меню из трех точек для установки вручную.

8b7fa8b3c94c6bdd.png

Появится запрос на подтверждение, нажмите « Установить» .

98e90422167ac786.png

Теперь у вас есть новый значок в доке вашей операционной системы. Нажмите на нее, чтобы запустить PWA. Он будет иметь собственное окно приложения и работать в автономном режиме.

Установка значка

Теперь, когда у вас установлен PWA, вам нужны числовые данные (значки могут содержать только цифры) для отображения на них. В The Air Horner проще всего посчитать, сколько раз его прозвучали. Собственно, с установленным приложением Airhorner попробуйте подать сигнал и проверить значок. Он засчитывает единицу каждый раз, когда вы гудите.

b5e39de7a1775054.png

Итак, как это работает? По сути, код такой:

let hornCounter = 0;
const horn = document.querySelector('.horn');
horn.addEventListener('click', () => {
  navigator.setExperimentalAppBadge(++hornCounter);
});

Подайте звуковой сигнал пару раз и проверьте значок PWA: он будет обновляться каждый раз. одинокий. время. звучит звуковой сигнал. Вот так просто.

eed10c3ffe59999.png

Удаление значка

Счетчик доходит до 99, а затем начинается заново. Вы также можете сбросить его вручную. Откройте вкладку DevTools Console, вставьте строку ниже и нажмите Enter.

navigator.setExperimentalAppBadge(0);

Альтернативно вы также можете избавиться от значка, явно удалив его, как показано в следующем фрагменте. Значок вашего PWA теперь должен снова выглядеть так же, как в начале, четкий и без значка.

navigator.clearExperimentalAppBadge();

33eafb314a3a9f30.png

Обратная связь

Что вы думаете об этом API? Пожалуйста, помогите нам, кратко ответив на этот опрос:

Было ли использование этого API интуитивно понятным?

Да Нет

У вас получилось запустить пример?

Да Нет

Есть еще что сказать? Были ли недостающие функции? Пожалуйста, дайте краткую обратную связь в этом опросе . Спасибо!

3. API собственной файловой системы

API Native File System позволяет разработчикам создавать мощные веб-приложения, взаимодействующие с файлами на локальном устройстве пользователя. После того как пользователь предоставляет доступ к веб-приложению, этот API позволяет веб-приложениям читать или сохранять изменения непосредственно в файлах и папках на устройстве пользователя.

Чтение файла

«Привет, мир» API собственной файловой системы предназначен для чтения локального файла и получения его содержимого. Создайте простой файл .txt и введите текст. Затем перейдите на любой защищенный сайт (то есть сайт, обслуживаемый через HTTP S ), например example.com , и откройте консоль DevTools. Вставьте фрагмент кода ниже в консоль. Поскольку API собственной файловой системы требует жеста пользователя, мы прикрепляем к документу обработчик двойного щелчка. Дескриптор файла понадобится нам позже, поэтому мы просто сделаем его глобальной переменной.

document.ondblclick = async () => {
  window.handle = await window.chooseFileSystemEntries();
  const file = await handle.getFile();
  document.body.textContent = await file.text();
};

c02679081eb4d538.png

Если затем дважды щелкнуть в любом месте страницы example.com , появится средство выбора файлов.

d98962600d62d149.png

Выберите файл .txt , который вы создали ранее. Содержимое файла затем заменит фактическое содержимое body example.com .

eace3d15bd4f8192.png

Сохранение файла

Далее мы хотим внести некоторые изменения. Поэтому давайте сделаем body редактируемым, вставив фрагмент кода ниже. Теперь вы можете редактировать текст, как если бы браузер был текстовым редактором.

document.body.contentEditable = true;

ca32797417449343.png

Теперь мы хотим записать эти изменения обратно в исходный файл. Следовательно, нам нужен модуль записи для дескриптора файла, который мы можем получить, вставив приведенный ниже фрагмент в консоль. Нам снова нужен жест пользователя, поэтому на этот раз мы ждем клика по основному документу.

document.onclick = async () => {
  const writer = await handle.createWriter();
  await writer.truncate(0);
  await writer.write(0, document.body.textContent);
  await writer.close();
};

d2729a8f76f43073.png

Когда вы теперь щелкнете (а не дважды щелкните) документ, появится запрос на разрешение. Когда вы дадите разрешение, содержимое файла будет таким же, как вы ранее редактировали в body . Проверьте изменения, открыв файл в другом редакторе (или запустите процесс еще раз, дважды щелкнув документ и повторно открыв файл).

2eccf61fe4a46109.png

202263abdedae737.png

Поздравляем! Вы [citation needed] что создали самый маленький текстовый редактор в мире.

Обратная связь

Что вы думаете об этом API? Пожалуйста, помогите нам, кратко ответив на этот опрос:

Было ли использование этого API интуитивно понятным?

Да Нет

У вас получилось запустить пример?

Да Нет

Есть еще что сказать? Были ли недостающие функции? Пожалуйста, дайте краткую обратную связь в этом опросе . Спасибо!

4. API обнаружения формы

API обнаружения формы обеспечивает доступ к ускоренным детекторам формы (например, человеческих лиц) и работает с неподвижными изображениями и/или потоками изображений в реальном времени. Операционные системы оснащены производительными и высокооптимизированными детекторами функций, такими как Android FaceDetector . API обнаружения формы открывает эти собственные реализации и предоставляет их через набор интерфейсов JavaScript.

В настоящее время поддерживаются следующие функции: обнаружение лиц через интерфейс FaceDetector , обнаружение штрих-кода через интерфейс BarcodeDetector и обнаружение текста (оптическое распознавание символов) через интерфейс TextDetector .

Распознавание лиц

Интересной особенностью API Shape Detection является распознавание лиц. Чтобы проверить это, нам нужна страница с лицами. Эта страница с лицом автора — хорошее начало. Это будет выглядеть примерно так, как на скриншоте ниже. В поддерживаемом браузере будет распознаваться рамка лица и ориентиры лица.

Вы можете увидеть, как мало кода потребовалось для этого, переделав или отредактировав проект Glitch , особенно файл script.js .

f4aa7b77a0a1d1f5.png

Если вы хотите работать полностью динамично, а не просто работать с лицом автора, перейдите на эту страницу результатов поиска Google, полную лиц, на приватной вкладке или в гостевом режиме. Теперь на этой странице откройте Инструменты разработчика Chrome, щелкнув правой кнопкой мыши в любом месте и выбрав «Проверить» . Затем на вкладке «Консоль» вставьте фрагмент ниже. Код выделит обнаруженные лица полупрозрачной красной рамкой.

document.querySelectorAll('img[alt]:not([alt=""])').forEach(async (img) => {
  try {
    const faces = await new FaceDetector().detect(img);
    faces.forEach(face => {
      const div = document.createElement('div');
      const box = face.boundingBox;
      const computedStyle = getComputedStyle(img);
      const [top, right, bottom, left] = [
        computedStyle.marginTop,
        computedStyle.marginRight,
        computedStyle.marginBottom,
        computedStyle.marginLeft
      ].map(m => parseInt(m, 10));
      const scaleX = img.width / img.naturalWidth;
      const scaleY = img.height / img.naturalHeight;
      div.style.backgroundColor = 'rgba(255, 0, 0, 0.5)';
      div.style.position = 'absolute';
      div.style.top = `${scaleY * box.top + top}px`;
      div.style.left = `${scaleX * box.left + left}px`;
      div.style.width = `${scaleX * box.width}px`;
      div.style.height = `${scaleY * box.height}px`;
      img.before(div);
    });
  } catch(e) {
    console.error(e);
  }
});

Вы заметите, что есть некоторые сообщения DOMException , и не все изображения обрабатываются. Это связано с тем, что изображения в верхней части сгиба встроены как URI данных и, таким образом, к ним можно получить доступ, тогда как изображения в нижней части сгиба поступают из другого домена, который не настроен для поддержки CORS. Ради демонстрации нам не нужно об этом беспокоиться.

Обнаружение ориентиров лица

Помимо лиц как таковых, macOS также поддерживает обнаружение ориентиров на лицах. Чтобы проверить обнаружение ориентиров лиц, вставьте следующий фрагмент в консоль. Напоминание: состав ориентиров совсем не идеален из-за crbug.com/914348 , но вы можете видеть, к чему это приведет и насколько мощной может быть эта функция.

document.querySelectorAll('img[alt]:not([alt=""])').forEach(async (img) => {
  try {
    const faces = await new FaceDetector().detect(img);
    faces.forEach(face => {
      const div = document.createElement('div');
      const box = face.boundingBox;
      const computedStyle = getComputedStyle(img);
      const [top, right, bottom, left] = [
        computedStyle.marginTop,
        computedStyle.marginRight,
        computedStyle.marginBottom,
        computedStyle.marginLeft
      ].map(m => parseInt(m, 10));
      const scaleX = img.width / img.naturalWidth;
      const scaleY = img.height / img.naturalHeight;
      div.style.backgroundColor = 'rgba(255, 0, 0, 0.5)';
      div.style.position = 'absolute';
      div.style.top = `${scaleY * box.top + top}px`;
      div.style.left = `${scaleX * box.left + left}px`;
      div.style.width = `${scaleX * box.width}px`;
      div.style.height = `${scaleY * box.height}px`;
      img.before(div);

      const landmarkSVG = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
      landmarkSVG.style.position = 'absolute';
      landmarkSVG.classList.add('landmarks');
      landmarkSVG.setAttribute('viewBox', `0 0 ${img.width} ${img.height}`);
      landmarkSVG.style.width = `${img.width}px`;
      landmarkSVG.style.height = `${img.height}px`;
      face.landmarks.map((landmark) => {                    
        landmarkSVG.innerHTML += `<polygon class="landmark-${landmark.type}" points="${
        landmark.locations.map((point) => {          
          return `${scaleX * point.x},${scaleY * point.y} `;
        }).join(' ')
      }" /></svg>`;          
      });
      div.before(landmarkSVG);
    });
  } catch(e) {
    console.error(e);
  }
});

Обнаружение штрих-кода

Вторая функция API обнаружения формы — обнаружение штрих-кода. Как и раньше, нам нужна страница со штрих-кодами, например эта . Открыв его в браузере, вы увидите расшифрованные различные QR-коды. Сделайте ремикс или отредактируйте проект Glitch , особенно файл script.js, чтобы увидеть, как это делается.

7778003ff472389b.png

Если вы хотите чего-то более динамичного, мы снова можем использовать поиск изображений Google. На этот раз в браузере перейдите на эту страницу результатов поиска Google на приватной вкладке или в гостевом режиме. Теперь вставьте приведенный ниже фрагмент на вкладку консоли Chrome DevTools. Через некоторое время распознанные штрих-коды будут снабжены необработанным значением и типом штрих-кода.

document.querySelectorAll('img[alt]:not([alt=""])').forEach(async (img) => {
  try {
    const barcodes = await new BarcodeDetector().detect(img);
    barcodes.forEach(barcode => {
      const div = document.createElement('div');
      const box = barcode.boundingBox;
      const computedStyle = getComputedStyle(img);
      const [top, right, bottom, left] = [
        computedStyle.marginTop,
        computedStyle.marginRight,
        computedStyle.marginBottom,
        computedStyle.marginLeft
      ].map(m => parseInt(m, 10));
      const scaleX = img.width / img.naturalWidth;
      const scaleY = img.height / img.naturalHeight;
      div.style.backgroundColor = 'rgba(255, 255, 255, 0.75)';
      div.style.position = 'absolute';
      div.style.top = `${scaleY * box.top + top}px`;
      div.style.left = `${scaleX * box.left - left}px`;
      div.style.width = `${scaleX * box.width}px`;
      div.style.height = `${scaleY * box.height}px`;
      div.style.color = 'black';
      div.style.fontSize = '14px';      
      div.textContent = `${barcode.rawValue}`;
      img.before(div);
    });
  } catch(e) {
    console.error(e);
  }
});

Обнаружение текста

Последняя функция API обнаружения формы — обнаружение текста. Теперь вы знаете суть: нам нужна страница с изображениями, содержащими текст, как эта с результатами сканирования Google Книг. В поддерживаемых браузерах вы увидите распознанный текст и ограничительную рамку, нарисованную вокруг фрагментов текста. Сделайте ремикс или отредактируйте проект Glitch , особенно файл script.js, чтобы увидеть, как это делается.

ec2be17d1e4d01ba.png

Чтобы протестировать это в динамическом режиме, перейдите на эту страницу результатов поиска на приватной вкладке или в гостевом режиме. Теперь вставьте приведенный ниже фрагмент на вкладку консоли Chrome DevTools. Немного подождав, часть текста будет распознана.

document.querySelectorAll('img[alt]:not([alt=""])').forEach(async (img) => {
  try {
    const texts = await new TextDetector().detect(img);
    texts.forEach(text => {
      const div = document.createElement('div');
      const box = text.boundingBox;
      const computedStyle = getComputedStyle(img);
      const [top, right, bottom, left] = [
        computedStyle.marginTop,
        computedStyle.marginRight,
        computedStyle.marginBottom,
        computedStyle.marginLeft
      ].map(m => parseInt(m, 10));
      const scaleX = img.width / img.naturalWidth;
      const scaleY = img.height / img.naturalHeight;
      div.style.backgroundColor = 'rgba(255, 255, 255, 0.75)';
      div.style.position = 'absolute';
      div.style.top = `${scaleY * box.top + top}px`;
      div.style.left = `${scaleX * box.left - left}px`;
      div.style.width = `${scaleX * box.width}px`;
      div.style.height = `${scaleY * box.height}px`;
      div.style.color = 'black';
      div.style.fontSize = '14px';      
      div.innerHTML = text.rawValue;
      img.before(div);
    });
  } catch(e) {
    console.error(e);
  }
});

Обратная связь

Что вы думаете об этом API? Пожалуйста, помогите нам, кратко ответив на этот опрос:

Было ли использование этого API интуитивно понятным?

Да Нет

У вас получилось запустить пример?

Да Нет

Есть еще что сказать? Были ли недостающие функции? Пожалуйста, дайте краткую обратную связь в этом опросе . Спасибо!

5. Целевой веб-API

API-интерфейс Web Share Target позволяет установленным веб-приложениям регистрироваться в базовой операционной системе в качестве цели общего доступа для получения общего контента либо от API Web Share, либо от системных событий, таких как кнопка общего доступа на уровне операционной системы.

Установите PWA, чтобы поделиться

В качестве первого шага вам понадобится PWA, которым вы сможете поделиться. На этот раз Airhorner (к счастью) не справится с этой задачей, но вас поддержит демо-приложение Web Share Target . Установите приложение на главный экран вашего устройства.

925df16a12638bb2.png

Поделитесь чем-нибудь с PWA

Далее вам нужно чем-то поделиться, например, фотографией из Google Фото. Используйте кнопку «Поделиться» и выберите Scrapbook PWA в качестве цели для общего доступа.

7216e8bb1be6d6db.png

Когда вы коснетесь значка приложения, вы попадете прямо в Scrapbook PWA, и фотография окажется прямо там.

9016985cb4bb48fe.png

Итак, как это работает? Чтобы это узнать, изучите манифест веб-приложения Scrapbook PWA. Конфигурация, обеспечивающая работу API-интерфейса Web Share Target, находится в свойстве "share_target" манифеста, которое в поле "action" указывает на URL-адрес, украшенный параметрами, перечисленными в "params" .

Затем сторона, предоставляющая общий доступ, соответствующим образом заполняет этот шаблон URL-адреса (либо с помощью действия «Поделиться», либо контролируется программно разработчиком с помощью API Web Share ), чтобы принимающая сторона могла затем извлечь параметры и что-то с ними сделать, например отобразить их. .

{
  "action": "/_share-target",
  "enctype": "multipart/form-data",
  "method": "POST",
  "params": {
    "files": [{
      "name": "media",
      "accept": ["audio/*", "image/*", "video/*"]
    }]
  }
}

Обратная связь

Что вы думаете об этом API? Пожалуйста, помогите нам, кратко ответив на этот опрос:

Было ли использование этого API интуитивно понятным?

Да Нет

У вас получилось запустить пример?

Да Нет

Есть еще что сказать? Были ли недостающие функции? Пожалуйста, дайте краткую обратную связь в этом опросе . Спасибо!

6. API блокировки пробуждения

Чтобы избежать разрядки аккумулятора, большинство устройств быстро переходят в режим сна, если их не использовать. Хотя в большинстве случаев это нормально, некоторым приложениям необходимо держать экран или устройство в активном состоянии, чтобы завершить свою работу. API Wake Lock позволяет предотвратить затемнение и блокировку экрана устройства или его переход в спящий режим. Эта возможность открывает новые возможности, для которых до сих пор требовалось собственное приложение.

Настройте заставку

Чтобы протестировать API Wake Lock, вы должны сначала убедиться, что ваше устройство перейдет в спящий режим. Поэтому на панели настроек вашей операционной системы активируйте заставку по вашему выбору и убедитесь, что она запустится через 1 минуту. Убедитесь, что это работает, оставив устройство в покое именно на это время (да, я знаю, это больно). На скриншотах ниже показана macOS, но вы, конечно, можете попробовать это на своем мобильном устройстве Android или любой поддерживаемой настольной платформе.

6f345e8c2b6c22c.png

Установите блокировку пробуждения экрана

Теперь, когда вы знаете, что ваша заставка работает, вы можете использовать блокировку пробуждения типа "screen" , чтобы заставка не выполняла свою работу. Перейдите в демонстрационное приложение Wake Lock и нажмите кнопку «Активировать» .

флажок «Блокировка пробуждения screen ».

12ed15dd94f51d4d.png

С этого момента активна блокировка пробуждения. Если вы достаточно терпеливы, чтобы оставить свое устройство нетронутым на минуту, вы увидите, что заставка действительно не запустилась.

Так как же это работает? Чтобы узнать это, перейдите в проект Glitch для демонстрационного приложения Wake Lock и ознакомьтесь с файлом script.js . Суть кода приведена во фрагменте ниже. Откройте новую вкладку (или используйте любую открытую вкладку) и вставьте приведенный ниже код в консоль инструментов разработчика Chrome. Когда вы щелкнете по окну, вы должны увидеть блокировку пробуждения, активную ровно 10 секунд (см. журналы консоли), и ваша заставка не должна запуститься.

if ('wakeLock' in navigator && 'request' in navigator.wakeLock) {  
  let wakeLock = null;
  
  const requestWakeLock = async () => {
    try {
      wakeLock = await navigator.wakeLock.request('screen');
      wakeLock.addEventListener('release', () => {        
        console.log('Wake Lock was released');                    
      });
      console.log('Wake Lock is active');      
    } catch (e) {      
      console.error(`${e.name}, ${e.message}`);
    } 
  };

  requestWakeLock();
  window.setTimeout(() => {
    wakeLock.release();
  }, 10 * 1000);
}

621c2654d06a7cce.png

Обратная связь

Что вы думаете об этом API? Пожалуйста, помогите нам, кратко ответив на этот опрос:

Было ли использование этого API интуитивно понятным?

Да Нет

У вас получилось запустить пример?

Да Нет

Есть еще что сказать? Были ли недостающие функции? Пожалуйста, дайте краткую обратную связь в этом опросе . Спасибо!

7. API выбора контактов

API, который нам очень нравится, — это API выбора контактов. Это позволяет веб-приложению получать доступ к контактам из встроенного диспетчера контактов устройства, поэтому ваше веб-приложение имеет доступ к именам, адресам электронной почты и номерам телефонов ваших контактов. Вы можете указать, хотите ли вы только один или несколько контактов и хотите ли вы использовать все поля или только часть имен, адресов электронной почты и номеров телефонов.

Соображения конфиденциальности

Когда откроется окно выбора, вы сможете выбрать контакты, которыми хотите поделиться. Вы заметите, что здесь нет опции «выбрать все», что сделано намеренно: мы хотим, чтобы совместное использование было осознанным решением. Аналогично, доступ не является непрерывным, а скорее единовременным решением.

Доступ к контактам

Доступ к контактам — простая задача. Прежде чем откроется окно выбора, вы можете указать, какие поля вам нужны (варианты: name , email и telephone ), а также хотите ли вы получить доступ к нескольким контактам или только к одному. Вы можете протестировать этот API на устройстве Android, открыв демонстрационное приложение . Соответствующий раздел исходного кода по сути представляет собой фрагмент ниже:

getContactsButton.addEventListener('click', async () => {
  const contacts = await navigator.contacts.select(
      ['name', 'email'],
      {multiple: true});
  if (!contacts.length) {
    // No contacts were selected, or picker couldn't be opened.
    return;
  }
  console.log(contacts);
});

de94db2dfb7c67af.png

8. API асинхронного буфера обмена

Копирование и вставка текста

До сих пор не было возможности программного копирования и вставки изображений в буфер обмена системы. Недавно мы добавили поддержку изображений в API Async Clipboard.

так что теперь вы можете копировать и вставлять изображения. Новым является то, что вы также можете записывать изображения в буфер обмена. API асинхронного буфера обмена уже некоторое время поддерживает копирование и вставку текста. Вы можете скопировать текст в буфер обмена, вызвав navigator.clipboard.writeText(), а затем вставить этот текст, вызвав navigator.clipboard.readText().

Копирование и вставка изображений

Теперь вы также можете записывать изображения в буфер обмена. Чтобы это работало, вам нужны данные изображения в виде большого двоичного объекта, который затем передается конструктору элемента буфера обмена. Наконец, вы можете скопировать этот элемент буфера обмена, вызвав navigator.clipboard.write().

// Copy: Writing image to the clipboard
try {
  const imgURL = 'https://developers.google.com/web/updates/images/generic/file.png';
  const data = await fetch(imgURL);
  const blob = await data.blob();
  await navigator.clipboard.write([
    new ClipboardItem(Object.defineProperty({}, blob.type, {
      value: blob,
      enumerable: true
    }))
  ]);
  console.log('Image copied.');
} catch(e) {
  console.error(e, e.message);
}

Вставка изображения обратно из буфера обмена выглядит довольно сложной задачей, но на самом деле она заключается лишь в возвращении объекта из буфера обмена. Поскольку их может быть несколько, вам нужно просмотреть их, пока не найдете тот, который вас интересует. По соображениям безопасности сейчас это ограничено изображениями PNG, но в будущем могут поддерживаться и другие форматы изображений.

async function getClipboardContents() {
  try {
    const clipboardItems = await navigator.clipboard.read();
    for (const clipboardItem of clipboardItems) {
      try {
        for (const type of clipboardItem.types) {
          const blob = await clipboardItem.getType(type);
          console.log(URL.createObjectURL(blob));
        }
      } catch (e) {
        console.error(e, e.message);
      }
    }
  } catch (e) {
    console.error(e, e.message);
  }
}

Вы можете увидеть этот API в действии в демонстрационном приложении , соответствующие фрагменты его исходного кода встроены выше. Копирование изображений в буфер обмена можно выполнять без разрешения, но вам необходимо предоставить доступ для вставки из буфера обмена.

99f6dbf35ff4f393.png

После предоставления доступа вы можете прочитать изображение из буфера обмена и вставить его в приложение:

ace5945f4aca70ff.png

9. Вы сделали это!

Поздравляем, вы дошли до конца лаборатории кода. Опять же, это своего рода напоминание о том, что большинство API все еще находятся в стадии разработки и над ними активно работают. Поэтому команда очень ценит ваши отзывы , поскольку только взаимодействие с такими людьми, как вы, поможет нам правильно реализовать эти API.

Мы также рекомендуем вам часто просматривать нашу целевую страницу «Возможности» . Мы будем поддерживать его в актуальном состоянии, и в нем есть ссылки на все подробные статьи об API, над которыми мы работаем. Продолжайте зажигать!

Том и вся команда Capabilities 🐡