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() adlı cihazı çağırdığında Chrome, kullanıcıdan bir sekme, pencere 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).

Yakalanan Yüzey Denetimi'ni neden kullanmalısınız?

Tüm video konferans uygulamaları aynı dezavantajdan yararlanır: Kullanıcı, yakalanan bir sekme veya pencereyle etkileşimde bulunmak isterse bu yüzeye geçerek onu video konferans uygulamasından uzaklaştırır. Bu durum bazı zorluklara yol açar:

  • 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 uzaktaki 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ı, video konferans uygulamasından uzaktayken video konferans uygulamasının gösterdiği denetimlere (örneğin, yerleşik sohbet uygulaması, emoji tepkileri, görüşmeye katılmak isteyen kullanıcılarla ilgili bildirimler, multimedya ve düzen denetimleri ve diğer yararlı video konferans özellikleri) erişimini kaybeder.
  • Sunucu, uzak katılımcılara kontrol yetkisi veremez. Bu durum, uzaktan kullanıcıların sunucunun slaytını değiştirmesini, biraz yukarı aşağı kaydırmasını veya yakınlaştırma seviyesini ayarlamasını istediği çok tanıdık bir senaryoya yol açar.

Captured Surface Control API bu sorunları ele alır.

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

Yakalanan Yüzey Denetimi'nin başarıyla kullanılması için birkaç adım gerekir. Örneğin, bir tarayıcı sekmesinin açıkça yakalanması ve yakalanan sekmeyi kaydırıp yakınlaştırabilmek için kullanıcıdan izin alınması gerekir.

Tarayıcı sekmesini kaydet

İlk olarak kullanıcıdan getDisplayMedia() ile paylaşacak bir yüzey seçmesini isteyin ve bu süreçte yakalama oturumuyla bir CaptureController nesnesini ilişkilendirin. En kısa zamanda, yakalanan yüzeyi kontrol etmek için o 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 durum şimdilik kapsam dışındadır ancak kullanıcı bir sekmeyi paylaşmayı seçerse işleme 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 söz konusu CaptureController nesnesi üzerinde bu yöntemlerin diğer çağrıları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 sayfadaki gezinmede geçerliliğini korur.

Kullanıcıya izin istemi göstermek için kullanıcı hareketi gereklidir. Yalnızca sendWheel() ve setZoomLevel() çağrıları için ve yalnızca istemin gösterilmesi gerekiyorsa kullanıcı hareketi gereklidir. Kullanıcı, web uygulamasında bir yakınlaştırma veya uzaklaştırma düğmesini tıklarsa bu kullanıcı hareketi verilir. Ancak, uygulama önce kaydırma denetimi sunmak isterse geliştiriciler kaydırmanın bir kullanıcı hareketi olmadığını unutmamalıdır. Olasılıklardan biri, aşağıdaki örneğe göre önce kullanıcıya 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 ile doğrudan kullanıcı etkileşimlerinden ayırt edilemez.

Yakalama uygulamasının "previewTile" adında bir <video> öğesi kullandığı varsayıldığında, aşağıdaki kodda, gönderme tekerlek etkinliklerinin yakalanan sekmeye nasıl geçeceği 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: 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)];
}

Daha önceki 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ı, sendWheel() uygulamasına izin 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 düzeyiyle etkileşim, aşağıdaki CaptureController yüzeyleri üzerinden gerçekleştirilir:

  • 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() ürününde bulunan herhangi bir tam sayı değerine ayarlar ve sekme başarılı olduğunda taahhüt döndürür. Yakalama oturumunun sonunda yakınlaştırma düzeyinin sıfırlanmadığına dikkat edin.
  • 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() için yapılan aramalar izinle denetlenir. Diğer salt okunur yakınlaştırma yöntemlerine yapılan çağrılar, etkinlikleri dinlemede olduğu gibi "ücretsiz"dir.

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 seviyesi değişikliklerine tepki vermeniz gösterilmektedir:

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

Özellik algılama

Çark etkinlikleri göndermenin desteklenip desteklenmediğini kontrol etmek için şunu kullanın:

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" izin politikası, yakalama uygulamanızın ve yerleştirilmiş üçüncü taraf iframe'lerin Yakalanan Yüzey Kontrolü'ne nasıl erişeceğini yönetmenizi sağlar. Güvenlikle ilgili dengeleri anlamak için Yakalanan Yüzey Kontrolü açıklayıcısının Gizlilik ve Güvenlikle İlgili 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 Kontrolü ile ilgili bilmeniz gereken bazı önemli davranış farklılıkları aşağıda verilmiştir:

  • Chrome 124 ve önceki sürümlerde:
    • İzin verildiyse, yakalama kaynağının değil, söz konusu CaptureController ile ilişkili yakalama oturumuna göre belirlenir.
  • Chrome 122'de:
    • getZoomLevel(), sekmenin mevcut yakınlaştırma seviyesiyle bir taahhüt döndürür.
    • Kullanıcı, uygulamaya kullanım izni vermediyse sendWheel(), "No permission." hata mesajıyla reddedilen bir sözü 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ğe çoklu dolgu yapabilirsiniz.

Geri bildirim

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

Bize 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 ihtiyacınız olan eksik yöntemler veya özellikler mi var? Güvenlik modeliyle ilgili sorunuz veya yorumunuz mu var? GitHub deposunda spesifikasyon sorunu oluşturun veya mevcut bir soruna düşüncelerinizi ekleyin.

Uygulamayla ilgili bir sorun mu var?

Chrome'un uygulanmasıyla ilgili bir hata buldunuz mu? Yoksa uygulama, spesifikasyondan farklı mı? https://new.crbug.com adresinde bir hata bildirin. Olabildiğince çok ayrıntıyı ve yeniden oluşturma talimatlarını eklemeyi unutmayın. Glitch, yeniden üretilebilir hataları paylaşmak için idealdir.