Yakalanan bir sekmeyi kaydırın ve yakınlaştırın

François Beaufort
François Beaufort

Sekme, pencere ve ekran paylaşımı, web platformunda Screen Capture API ile zaten mümkündür. Bir web uygulaması getDisplayMedia() çağrısı yaptığında Chrome, kullanıcıdan bir sekmeyi, pencereyi veya ekranı web uygulamasıyla MediaStreamTrack videosu olarak paylaşmasını ister.

getDisplayMedia() kullanan birçok web uygulaması, kullanıcıya yakalanan yüzeyin video önizlemesini gösterir. Örneğin, video konferans uygulamaları genellikle bu videoyu uzaktaki kullanıcılara aktarırken yerel bir HTMLVideoElement'a da oluşturur. Böylece yerel kullanıcı, paylaştığı içeriğin önizlemesini sürekli olarak görebilir.

Bu dokümanda, Chrome'daki yeni Captured Surface Control API (Yakalanan Yüzey Kontrol API'si) tanıtılmaktadır. Bu API, web uygulamanızın yakalanan bir sekmeyi kaydırmasına ve yakalanan sekmenin yakınlaştırma düzeyini okumasına ve yazmasına olanak tanır.

Kullanıcı, yakalanan bir sekmede kaydırma ve yakınlaştırma yapıyor (demo).

Neden yakalanan yüzey kontrolünü kullanmalısınız?

Tüm görüntülü konferans uygulamalarında aynı dezavantaj vardır: Kullanıcı, yakalanan bir sekme veya pencereyle etkileşim kurmak isterse video konferans uygulamasından ayrılarak bu yüzeye geçmesi gerekir. Bu durum bazı zorluklar doğurur:

  • Kullanıcı, pencere içinde pencere özelliğini veya görüntülü konferans sekmesi ile paylaşılan sekme için ayrı yan yana pencereler kullanmadığı sürece, yakalanan uygulamayı ve uzak kullanıcıların videolarını aynı anda göremez. Bu işlem, küçük ekranlarda zor olabilir.
  • Kullanıcı, video konferans uygulaması ile yakalanan yüzey arasında geçiş yapmak zorunda kalır.
  • Kullanıcı, görüntülü konferans uygulamasından ayrıldığında uygulama tarafından sunulan denetimlere (ör. yerleşik sohbet uygulaması, emoji tepkiler, görüşmeye katılmak isteyen kullanıcılarla ilgili bildirimler, multimedya ve düzen denetimleri ve diğer kullanışlı görüntülü konferans özellikleri) erişemez.
  • Sunucu, uzak katılımcılara kontrol yetkisi veremez. Bu durum, uzaktaki kullanıcıların sunucunun slaytı değiştirmesini, biraz yukarı veya aşağı kaydırmasını ya da yakınlaştırma seviyesini ayarlamasını istediği çok tanıdık bir senaryoya yol açar.

Captured Surface Control API bu sorunları giderir.

Yakalanan Yüzey Denetimi'ni nasıl kullanırım?

Yakalanan Yüzey Denetimi'ni başarılı bir şekilde kullanmak için birkaç adım gerekir. Örneğin, bir tarayıcı sekmesini açıkça yakalamak ve yakalanan sekmeyi kaydırıp yakınlaştırmadan önce kullanıcıdan izin almak gerekir.

Tarayıcı sekmesi yakalama

Kullanıcıdan getDisplayMedia() kullanarak paylaşılacak bir yüzey seçmesini isteyerek başlayın ve bu süreçte yakalama oturumuyla bir CaptureController nesnesi ilişkilendirin. Yakında yakalanan yüzeyi kontrol etmek için bu nesneyi kullanacağız.

const controller = new CaptureController();
const stream = await navigator.mediaDevices.getDisplayMedia({ controller });

Ardından, yakalanan yüzeyin <video> öğesi biçiminde yerel bir önizlemesini oluşturun:

const previewTile = document.querySelector('video');
previewTile.srcObject = stream;

Kullanıcı bir pencere veya ekran paylaşmayı seçerse bu işlem şu anda kapsam dışındadır. Ancak kullanıcı bir sekme paylaşmayı seçerse devam edebiliriz.

const [track] = stream.getVideoTracks();

if (track.getSettings().displaySurface !== 'browser') {
  // Bail out early if the user didn't pick a tab.
  return;
}

İzin istemi

Belirli bir CaptureController nesnesinde sendWheel() veya setZoomLevel() işlevinin ilk çağrılması bir izin istemi oluşturur. Kullanıcı izin verirse bu CaptureController nesnesinde bu yöntemlerin daha fazla çağrılmasına izin verilir. Kullanıcı izin vermezse döndürülen söz reddedilir.

CaptureController nesnelerinin belirli bir capture-session ile benzersiz şekilde ilişkilendirildiğini, başka bir capture-session ile ilişkilendirilemediğini ve tanımlandıkları sayfaya gidip gelindiğinde varlığını sürdürmediğini unutmayın. Ancak, yakalama oturumları, yakalanan sayfanın gezinme işleminde yaşamaya devam eder.

Kullanıcıya izin istemi göstermek için kullanıcı hareketi gerekir. Yalnızca sendWheel() ve setZoomLevel() aramaları için kullanıcı hareketi gerekir ve bu da yalnızca istemin gösterilmesi gerektiğinde geçerlidir. Kullanıcı web uygulamasında yakınlaştırma veya uzaklaştırma düğmesini tıklarsa bu kullanıcı hareketi geçerlidir. Ancak uygulama önce kaydırma kontrolü sunmak istiyorsa geliştiricilerin kaydırmanın kullanıcı hareketi olmadığını göz önünde bulundurması gerekir. Bir olasılık, aşağıdaki örnekte gösterildiği gibi kullanıcıya önce bir "kaydırmaya başla" düğmesi sunmaktır:

const startScrollingButton = document.querySelector('button');

startScrollingButton.addEventListener('click', async () => {
  try {
    const noOpWheelAction = {};

    await controller.sendWheel(noOpWheelAction);
    // The user approved the permission prompt.
    // You can now scroll and zoom the captured tab as shown later in the article.
  } catch (error) {
    return; // Permission denied. Bail.
  }
});

Kaydırma

sendWheel() kullanarak yakalama uygulaması, bir sekmenin görüntü alanındaki koordinatlar üzerinde kendi seçtiği büyüklükte tekerlek etkinlikleri yayınlayabilir. Etkinlik, yakalanan uygulama tarafından doğrudan kullanıcı etkileşiminden ayırt edilemez.

Kaydeden uygulamanın "previewTile" adlı bir <video> öğesi kullandığı varsayıldığında, aşağıdaki kodda tekerlek etkinliklerinin yakalanan sekmeye nasıl aktarılacağı gösterilmektedir:

const previewTile = document.querySelector('video');

previewTile.addEventListener('wheel', async (event) => {
  // Translate the offsets into coordinates which sendWheel() can understand.
  // The implementation of this translation is explained further below.
  const [x, y] = translateCoordinates(event.offsetX, event.offsetY);
  const [wheelDeltaX, wheelDeltaY] = [-event.deltaX, -event.deltaY];

  try {
    // Relay the user's action to the captured tab.
    await controller.sendWheel({ x, y, wheelDeltaX, wheelDeltaY });
  } catch (error) {
    // Inspect the error.
    // ...
  }
});

sendWheel() yöntemi, iki değer grubu içeren bir sözlük alır:

  • x ve y: Dönen tekerlek etkinliğinin yayınlanacağı koordinatlar.
  • wheelDeltaX ve wheelDeltaY: Sırasıyla yatay ve dikey kaydırmalar için kaydırmaların piksel cinsinden büyüklükleri. Bu değerlerin, orijinal tekerlek etkinliğine kıyasla ters çevrildiğini unutmayın.

translateCoordinates() öğesinin olası bir uygulaması:

function translateCoordinates(offsetX, offsetY) {
  const previewDimensions = previewTile.getBoundingClientRect();
  const trackSettings = previewTile.srcObject.getVideoTracks()[0].getSettings();

  const x = trackSettings.width * offsetX / previewDimensions.width;
  const y = trackSettings.height * offsetY / previewDimensions.height;

  return [Math.floor(x), Math.floor(y)];
}

Yukarıdaki kodda üç farklı boyutun kullanıldığını unutmayın:

  • <video> öğesinin boyutu.
  • Yakalanan karelerin boyutu (burada trackSettings.width ve trackSettings.height olarak gösterilir).
  • Sekmenin boyutu.

<video> öğesinin boyutu tamamen yakalama uygulamasının alanındadır ve tarayıcı tarafından bilinmez. Sekmenin boyutu tamamen tarayıcının alanındadır ve web uygulaması tarafından bilinmez.

Web uygulaması, <video> öğesine göre ofsetleri video parçasının kendi koordinatlar alanındaki koordinatlara dönüştürmek için translateCoordinates() öğesini kullanır. Tarayıcı da yakalanan karelerin boyutu ile sekmenin boyutu arasında çeviri yapar ve kaydırma etkinliğini web uygulamasının beklentisine karşılık gelen bir ofsette yayınlar.

sendWheel() tarafından döndürülen söz aşağıdaki durumlarda reddedilebilir:

  • Yakalama oturumu henüz başlatılmamışsa veya sendWheel() işlemi tarayıcı tarafından işlenirken eşzamansız olarak durdurulmuşsa.
  • Kullanıcı, uygulamaya sendWheel() kullanma izni vermediyse.
  • Kaydetme uygulaması, [trackSettings.width, trackSettings.height] dışındaki koordinatlarda kaydırma etkinliği yayınlamaya çalışırsa. Bu değerlerin eşzamansız olarak değişebileceğini unutmayın. Bu nedenle, hatayı yakalayıp yoksaymak iyi bir fikirdir. (0, 0'ün normalde sınırların dışında olmayacağını, bu nedenle kullanıcıdan izin istemek için bu öğeleri kullanmanın güvenli olduğunu unutmayın.)

Tarih aralığını

Yakalanan sekmenin yakınlaştırma seviyesiyle etkileşim aşağıdaki CaptureController yüzeyleri aracılığıyla yapılır:

  • getSupportedZoomLevels(), tarayıcı tarafından desteklenen yakınlaştırma düzeylerinin listesini döndürür. Bu liste, %100 olarak tanımlanan "varsayılan yakınlaştırma düzeyinin" yüzdeleri olarak gösterilir. Bu liste monoton olarak artar ve 100 değerini içerir.
  • getZoomLevel(), sekmenin mevcut yakınlaştırma seviyesini döndürür.
  • setZoomLevel(), sekmenin yakınlaştırma düzeyini getSupportedZoomLevels() içinde bulunan herhangi bir tam sayı değerine ayarlar ve başarılı olduğunda bir promise döndürür. Yakınlaştırma düzeyinin, çekim oturumunun sonunda sıfırlanmadığını unutmayın.
  • oncapturedzoomlevelchange, kullanıcılar yakınlaştırma düzeyini yakalama uygulaması üzerinden veya yakalanan sekmeyle doğrudan etkileşim kurarak değiştirebileceğinden, yakalanan sekmenin yakınlaştırma düzeyindeki değişiklikleri dinlemenize olanak tanır.

setZoomLevel() çağrıları izine bağlıdır; diğer salt okuma yakınlaştırma yöntemlerine yapılan çağrılar ve etkinliklerin dinlenmesi "ücretsizdir".

Aşağıdaki örnekte, mevcut bir yakalama oturumunda yakalanan bir sekmenin yakınlaştırma düzeyini nasıl artıracağınız gösterilmektedir:

const zoomIncreaseButton = document.getElementById('zoomInButton');

zoomIncreaseButton.addEventListener('click', async (event) => {
  const levels = CaptureController.getSupportedZoomLevels();
  const index = levels.indexOf(controller.getZoomLevel());
  const newZoomLevel = levels[Math.min(index + 1, levels.length - 1)];

  try {
    await controller.setZoomLevel(newZoomLevel);
  } catch (error) {
    // Inspect the error.
    // ...
  }
});

Aşağıdaki örnekte, yakalanan bir sekmenin yakınlaştırma düzeyi değişikliklerine nasıl tepki vereceğiniz gösterilmektedir:

controller.addEventListener('capturedzoomlevelchange', (event) => {
  const zoomLevel = controller.getZoomLevel();
  document.querySelector('#zoomLevelLabel').textContent = `${zoomLevel}%`;
});

Özellik algılama

Tekerlek etkinlikleri göndermenin desteklenip desteklenmediğini kontrol etmek için:

if (!!window.CaptureController?.prototype.sendWheel) {
  // CaptureController sendWheel() is supported.
}

Yakınlaştırmayı kontrol etmenin desteklenip desteklenmediğini kontrol etmek için:

if (!!window.CaptureController?.prototype.setZoomLevel) {
  // CaptureController setZoomLevel() is supported.
}

Yakalanan Yüzey Denetimini Etkinleştirme

Captured Surface Control API, Chrome'da masaüstünde Captured Surface Control işaretinin arkasında bulunur ve chrome://flags/#captured-surface-control adresinden etkinleştirilebilir.

Bu özellik, masaüstünde Chrome 122'den itibaren kaynak denemesine giriyor. Bu sayede geliştiriciler, sitelerinin ziyaretçilerine gerçek kullanıcılardan veri toplamaları için bu özelliği etkinleştirebilir. Kaynak denemeleri ve bunların işleyiş şekli hakkında daha fazla bilgi için Kaynak denemelerini kullanmaya başlama başlıklı makaleyi inceleyin.

Güvenlik ve gizlilik

"captured-surface-control" İzin politikası, yakalama uygulamanızın ve yerleştirilmiş üçüncü taraf iFrame'lerinin, yakalanan yüzey kontrolüne nasıl erişeceğini yönetmenizi sağlar. Güvenlikle ilgili avantajları ve dezavantajları anlamak için, yakalanan yüzey kontrolüyle ilgili açıklamanın Gizlilik ve Güvenlik Konusunda Dikkat Edilmesi Gerekenler bölümüne göz atın.

Demo

Glitch'te demoyu çalıştırarak Captured Surface Control ile oynayabilirsiniz. Kaynak koduna göz atmayı unutmayın.

Chrome'un önceki sürümlerine kıyasla yapılan değişiklikler

Yakalanan Yüzey Denetimi ile ilgili bilmeniz gereken bazı önemli davranış farklılıkları aşağıda belirtilmiştir:

  • Chrome 124 ve önceki sürümlerde:
    • İzin (verilirse) yakalama kaynağına değil, söz konusu CaptureController ile ilişkili yakalama oturumuna göre kapsamlandırılır.
  • Chrome 122'de:
    • getZoomLevel(), sekmenin mevcut yakınlaştırma seviyesini içeren bir promise döndürür.
    • sendWheel(), kullanıcı uygulamaya kullanım izni vermediyse "No permission." hata mesajıyla reddedilen bir promise döndürür. Chrome 123 ve sonraki sürümlerde hata türü "NotAllowedError"'tür.
    • oncapturedzoomlevelchange kullanılamıyor. setInterval() kullanarak bu özelliği polyfill olarak doldurabilirsiniz.

Geri bildirim

Chrome Ekibi ve web standartları topluluğu, Captured Surface Control ile ilgili deneyimlerinizi öğrenmek istiyor.

Tasarım hakkında bilgi verin

Yakalanan Yüzey Yakalama özelliğiyle ilgili olarak beklediğiniz gibi çalışmayan bir şey mi var? Yoksa fikrinizi uygulamak için ihtiyaç duyduğunuz yöntemler veya özellikler eksik mi? Güvenlik modeliyle ilgili sorunuz veya yorumunuz mu var? GitHub deposunda spesifikasyon sorunu oluşturun veya mevcut bir soruna düşüncelerinizi ekleyin.

Uygulamayla ilgili sorun mu yaşıyorsunuz?

Chrome'un uygulamasında bir hata mı buldunuz? Yoksa uygulama, spesifikasyondan farklı mı? https://new.crbug.com adresinden hata bildirin. Mümkün olduğunca fazla ayrıntı ve sorunun yeniden üretilmesiyle ilgili talimatlar eklediğinizden emin olun. Hatalı, yeniden üretilebilir hataları paylaşmak için idealdir.