Soru Yerleşik tuval işlevlerini kullanarak çizim yapmak için Web İşçilerini kullanma


Bir göndermek mümkün CanvasPixelArray üzerinden elde edilen getImageData çalışan komut dosyasına ve çalışan komut dosyasının arka plandaki iş parçacığındaki pikselleri işlemesine izin verin ve sonuçta değiştirilmiş piksel dizisini geri gönderin.

Ancak, yerel tuval çizim işlevlerini kullanıyorum drawImage. drawImage aramalar şu anda UI iş parçacığını engelliyor. Bu, düğmelerin yavaş bir şekilde yeniden çizilmesine ve bir düğmeye basıldığında göze çarpan bir gecikmeye neden olur ve sadece birkaç sakıncaya isim verir. (Düzenle: Artık küçük bir iyileştirme ile tamamlanabilir ctx.imageSmoothingEnabled = falseEn azından WebKit ile webkit önek.)

Web işçileri kullanarak çizimi ana iş parçacığından arka plan iş parçacığına taşımak istiyorum. Ancak, tuvali veya içeriği işçiye gönderebilecek gibi görünmüyorum.

Buldum MDN'de bu uyarı:

Not: Her zamanki gibi, arka plandaki iş parçacıkları (işçiler dahil) DOM'ı değiştiremez. Arka plan iş parçacığı tarafından gerçekleştirilen işlemlerin DOM'ta değişikliklerle sonuçlanması gerekiyorsa, bu işi yapmak için içerik oluşturucularına ileti göndermeleri gerekir.

Ama DOM'ı olduğu gibi bırakmak istiyorum; Sadece bir tuval elemanında bir şeyler çizmek istiyorum. Bu mümkün mü, yoksa Web Çalışanlar gerçekten sadece hesaplamak ve çizmemek için izin verilir mi?

(Ya da belki de drawImage manipüle etmek CanvasPixelArray tuval üzerine çizim yapmak yerine?)


25
2017-11-17 16:11


Menşei




Cevaplar:


[topluluk düzenlemesi: Bu cevap 2011 yılında yazılmıştır ve kabul edilmiştir. Web Çalışanları ve Tuval'in daha iyi birlikte bulunmasına olanak tanıyan başka teknolojiler ortaya çıkmıştır (ya da ortaya çıkmaktadır); Okuyucu, bu yanıtın yanı sıra bu sayfadaki tüm cevapların farkında olmalıdır.]

Bir tuval nesnesini veya tuval içeriğini bir çalışan iş parçacığına geçiremezsiniz, çünkü tuval DOM'nin bir parçasıdır.


11
2017-11-27 21:13



Ne yazık. Doğru mu, temel olarak çizim için ana ipliği kullanmaya zorlandım mı? Gerçekten de çizmenin bir yolu yok mu? CanvasPixelArray? - pimvdb
Evet. Eşdeğer bir API'ye sahip olsanız bile drawImage() üzerinde çalışan CanvasPixelArrayBu verileri hala gerçek çizim için kullanıcı arayüzüne göndermeniz gerekir. Bu durumlarda kullanmak için bir offscreen Canvas sözünü duydum ama uygulamak için tarayıcı satıcıları beklemeniz gereken bir şey var. - John Watson
Birisi tuval API'sini saf javascript ile uyguladıysa, web çalışanlarına kullanabilmemiz harika olmaz mıydı? - Drew LeSueur
Yapabilirsin JSON.stringify  CanvasPixelArray, işçide manipüle et, ve sonucunu geri aldığında, jsonu ayrıştır ve kullan putImageData sonucu tuval üzerine koymak - bigblind
Bunu yapmak için yeni bir API var (bir pref'i etkinleştirirseniz sadece Firefox'ta desteklenir). Görmek developer.mozilla.org/en-US/docs/Web/API/OffscreenCanvas ve hacks.mozilla.org/2016/01/webgl-off-the-main-thread. - Marco


[Düzenle ~ 5 yıl sonra: bunun bir kısmı değişmeye başlıyor ve aslında bir İşçi'den bir tuvalin oluşturulmasına izin veren yeni web platformu özellikleri var! Daha fazla bilgi için bu bloga bakın: https://hacks.mozilla.org/2016/01/webgl-off-the-main-thread/ - cevabın geri kalanı 2011 dönemi için sağlanmıştır;)]

Web çalışanları yalnızca DOM'u değiştiremez, değiştiremez ya da bir tuvale çizilecek aramaları yapabilir. Ancak, söylediğiniz gibi, bir web işçisine orada işlemek ve geri göndermek için bir piksel dizisi yayınlayabilirsiniz. Bu zaman uyumsuz olduğundan, web çalışanı yanıt verene kadar kasıtlı olarak engellemediğiniz sürece, neden UI iş parçacığında herhangi bir yavaşlamaya neden olacağını anlamıyorum.

Yani garip görünüyor ki drawImage Aramalar çok uzun sürüyor UI'yi etkiliyor. Çoğu tuval bu günlerde donanım hızlandırıldı, bu yüzden güzel bir şekilde geçmeleri gerekiyor. Tahminim, bir web çalışanı aracılığıyla bir tuval piksel dizisine çizim yapıyorsunuz her çerçeveBu, etkili bir şekilde, tuvalin oluşturulmasını sağlayan yazılım anlamına gelir javascript’te. Javascript bunu yapmak için hala çok yavaştır - hatta C ++ yazılım oluşturucuları yavaştır, bu nedenle donanım hızlandırmanın önemi vardır. Böylece, bir web çalışanındaki bir tuval piksel dizisine bir şey verebilirsiniz bir Zamanlarve sonuç elde ettiğinizde önbelleğe Image  bir Zamanlarve sonra çizin Image tuvaline istediğin kadar. Bu hala çok hızlı olmalı.

Düzenleme: Piksel efektlerini işlemek için çok az program olan parça gölgelendiricileri yazabileceğiniz WebGL'ye bakmak isteyebilirsiniz. Tamamen grafik kartında çalışıyorlar, bu yüzden aptalca hızlılar.


31
2017-11-28 19:21



Aslında henüz Web Çalışanı kullanmadım, bu yüzden şu anda engelleme yapıyor. WebGL ilginç görünüyor; Yeni bir işleme ve çizim dünyasına benziyor. Önerilerin için teşekkürler. (Donanım hızlandırması, bazı nedenlerle bilgisayarımda Chrome'da yazılımın oluşturulmasından çok daha yavaştır, dolayısıyla hızlandırmanın etkinleştirilmesi bir olasılık değildir (henüz)). - pimvdb


Gönderebilirsiniz ImageData manipüle edilen Web İşçisine ImageData arayan kişiye (Ana UI)

Örneğin.:

  1. Bir Web Çalışanı Oluşturun:

    this.renderer = yeni İşçi ("renderer.js");
  2. Gönderin ImageData tuvalden Web Çalışanı'na oluşturulan:

    var ctx = this.canvas.getContext ('2d');
    var imageData = ctx.createImageData (genişlik, yükseklik);
    this.renderer.postMessage ({image: imageData});
  3. Yap ImageData Web Çalışmasında manipülasyon ve Ana iş parçacığına geri gönderin:

    onmessage = işlev (e) {
       var processedImage = self.doImageProcessing (e.data.image);
       postMessage ({image: processedImage});
    };

  4. Manipüle ayarlayın ImageData Ana iş parçasındaki tuvale:

    this.renderer.onmessage = işlev (e) {
       var ctx = this.canvas.getContext ('2d');
       ctx.putImageData (e.data.image, 0, 0);
    }


9
2017-07-07 09:57



Şimdi sadece birisi bir CanvasRenderingContext2D üzerinde çalışmak imageData web çalışanı üzerinde - Andy
Bu çalışır ama performans oldukça hayal kırıklığı yaratıyor. - hvdd
@ hvdd, denedin mi? [imageData] ikinci argümanında postMessage? - Pacerier


Bunu yapmak için yeni bir API var (şu anda bir pref'i etkinleştirirseniz, sadece Firefox'ta desteklenir).

Görmek https://developer.mozilla.org/en-US/docs/Web/API/OffscreenCanvas ve https://hacks.mozilla.org/2016/01/webgl-off-the-main-thread/.


3
2018-02-08 10:45



Bunun Osi'nin cevabının daha hızlı bir versiyonu olması mı gerekiyor? Ya da benzer performans? - Pacerier
Evet, daha hızlı olmalı. - Marco