Chrome 84’ten bu yana, ResizeObserver adı verilen yeni bir kutu ölçümünü desteklemektedir. devicePixelContentBox
öğenin boyutunu şu şekilde ölçer: fiziksel piksel. Bu, özellikle yüksek yoğunluklu ekranlar bağlamında mükemmel piksel grafiklerinin oluşturulmasını sağlar.
- Chrome 84, Desteklenir 84
- Firefox 93, Desteklenir 93
- Kenar 84, Desteklenen 84
- Safari, desteklenmiyor
Arka plan: CSS pikselleri, tuval pikselleri ve fiziksel pikseller #
Genellikle soyut uzunluk birimleriyle çalışırken em
, %
veya vh
, her şey piksellere indirgenir. CSS’de bir öğenin boyutunu veya konumunu belirttiğimizde, tarayıcının düzen motoru sonunda bu değeri piksele dönüştürür (px
). Bunlar, çok fazla geçmişi olan ve yalnızca ekranınızdaki piksellerle gevşek bir ilişkisi olan “CSS Pikselleri”dir.
Uzun bir süre boyunca, herhangi birinin ekran piksel yoğunluğunu 96DPI (“nokta/inç”) ile tahmin etmek oldukça mantıklıydı, yani herhangi bir monitörde kabaca cm başına 38 piksel olurdu. Zamanla monitörler büyüdü ve/veya küçüldü ya da aynı yüzey alanında daha fazla piksele sahip olmaya başladı. Bunu, web’deki pek çok içeriğin yazı tipi boyutları da dahil olmak üzere boyutlarını tanımladığı gerçeğiyle birleştirin. px
ve bu yüksek yoğunluklu (“HiDPI”) ekranlarda okunaksız metinlerle karşılaşıyoruz. Karşı önlem olarak, tarayıcılar monitörün gerçek piksel yoğunluğunu gizler ve bunun yerine kullanıcının 96 DPI ekrana sahip olduğunu varsayar. bu px
CSS’deki birim, bu sayfadaki bir pikselin boyutunu temsil eder. sanal 96 DPI ekran, dolayısıyla “CSS Piksel” adı. Bu birim sadece ölçüm ve konumlandırma için kullanılır. Herhangi bir gerçek işleme gerçekleşmeden önce, fiziksel piksellere bir dönüştürme gerçekleşir.
Bu sanal ekrandan kullanıcının gerçek ekranına nasıl geçebiliriz? Girmek devicePixelRatio
. Bu global değer size kaç tane olduğunu söyler. fiziksel tek bir CSS pikseli oluşturmanız gerekir. Eğer devicePixelRatio
(dPR) 1
, kabaca 96DPI ile bir monitör üzerinde çalışıyorsunuz. Bir retina ekranınız varsa, dPR’niz muhtemelen 2
. Telefonlarda, aşağıdakiler gibi daha yüksek (ve daha garip) dPR değerleriyle karşılaşmak alışılmadık bir durum değildir: 2
, 3
ya da 2.65
. Bu değerin olduğuna dikkat etmek önemlidir. bire bir aynıancak monitörün verilerini türetmenize izin vermiyor gerçek DPI değeri. bir dPR 2
1 CSS pikselinin eşleneceği anlamına gelir Kesinlikle 2 fiziksel piksel.
Örnek
Monitörümün dPR’si var 1
Chrome’a göre…
1
Chrome’a göre… 3440 piksel genişliğe sahiptir ve görüntüleme alanı 79cm genişliğindedir. Bu, 110 DPI çözünürlüğe yol açar. 96’ya yakın ama tam değil. Bu yüzden de bir <div style="width: 1cm; height: 1cm">
çoğu ekranda tam olarak 1 cm boyutunda olmaz.
Son olarak dPR, tarayıcınızın yakınlaştırma özelliğinden de etkilenebilir. Yakınlaştırırsanız, tarayıcı bildirilen dPR’yi artırarak her şeyin daha büyük görünmesine neden olur. eğer kontrol edersen devicePixelRatio
DevTools Konsolunda yakınlaştırma yaparken kesirli değerlerin göründüğünü görebilirsiniz.
devicePixelRatio
yakınlaştırma nedeniyle.ekleyelim <canvas>
karışıma eleman. Kullanarak tuvalin kaç piksele sahip olmasını istediğinizi belirtebilirsiniz. width
Ve height
Öznitellikler. Bu yüzden <canvas width=40 height=30>
40’a 30 piksellik bir tuval olurdu. Ancak bu olacağı anlamına gelmez görüntülenen 40 x 30 pikselde. Varsayılan olarak, tuval width
Ve height
özniteliğini tanımlayabilir, ancak bildiğiniz ve sevdiğiniz tüm CSS özelliklerini kullanarak tuvali istediğiniz gibi yeniden boyutlandırabilirsiniz. Şimdiye kadar öğrendiğimiz her şeye rağmen, bunun her senaryo için ideal olmayacağı aklınıza gelebilir. Tuval üzerindeki bir piksel birden çok fiziksel pikseli veya fiziksel bir pikselin yalnızca bir kısmını kaplayabilir. Bu, hoş olmayan görsel eserlere yol açabilir.
Özetlemek gerekirse: Tuval öğeleri, çizebileceğiniz alanı tanımlamak için belirli bir boyuta sahiptir. Tuval piksellerinin sayısı, tuvalin CSS piksellerinde belirtilen görüntü boyutundan tamamen bağımsızdır. CSS piksellerinin sayısı, fiziksel piksellerin sayısıyla aynı değildir.
Piksel mükemmelliği #
Bazı senaryolarda, tuval piksellerinden fiziksel piksellere tam bir eşlemenin olması arzu edilir. Bu eşleme elde edilirse buna “mükemmel piksel” denir. Mükemmel piksel oluşturma, özellikle metin kullanırken metnin okunaklı bir şekilde oluşturulması için çok önemlidir. alt piksel oluşturma veya sıkıca hizalanmış değişken parlaklık çizgileriyle grafikleri görüntülerken.
Web’de mümkün olduğunca mükemmel bir tuvale yakın bir şey elde etmek için, bu aşağı yukarı başvurulacak yaklaşım olmuştur:
style>
/* … styles that affect the canvas' size … */
</style>
canvas id="myCanvas"></canvas>
script>
const cvs = document.querySelector('#myCanvas');
// Get the canvas' size in CSS pixels
const rectangle = cvs.getBoundingClientRect();
// Convert it to real pixels. Ish.
cvs.width = rectangle.width * devicePixelRatio;
cvs.height = rectangle.height * devicePixelRatio;
// Start drawing…
</script>
Akıllı okuyucu, dPR bir tamsayı değeri olmadığında ne olacağını merak ediyor olabilir. Bu iyi bir soru ve tam olarak tüm bu sorunun özünde yatıyor. Ayrıca, bir öğenin konumunu veya boyutunu yüzdelerle belirtirseniz, vh
, veya diğer dolaylı değerler, kesirli CSS piksel değerlerine çözümlenmeleri mümkündür. ile bir eleman margin-left: 33%
bunun gibi bir dikdörtgenle sonuçlanabilir:
getBoundingClientRect()
Arama.CSS pikselleri tamamen sanaldır, bu nedenle bir pikselin kesirlerine sahip olmak teoride iyidir, ancak tarayıcı fiziksel piksellerle eşlemeyi nasıl anlar? Çünkü kesirli fiziksel piksel bir şey değildir.
Piksel yakalama #
Öğeleri fiziksel piksellerle hizalamakla ilgilenen birim dönüştürme işleminin parçası “piksel yakalama” olarak adlandırılır ve kutuda söylediklerini yapar: Kesirli piksel değerlerini tamsayı, fiziksel piksel değerlerine yaslar. Bunun tam olarak nasıl gerçekleştiği tarayıcıdan tarayıcıya değişir. Genişliğe sahip bir elemanımız varsa 791.984px
dPR’nin 1 olduğu bir ekranda, bir tarayıcı öğeyi şu adreste görüntüleyebilir: 792px
fiziksel pikseller, başka bir tarayıcı ise 791px
. Bu sadece tek bir piksel eksiğidir, ancak tek bir piksel, mükemmel piksel olması gereken işlemeler için zararlı olabilir. Bu, bulanıklığa veya hatta aşağıdaki gibi daha görünür eserlere yol açabilir: Moiré efekti.
(Herhangi bir ölçekleme uygulanmadan görmek için bu resmi yeni bir sekmede açmanız gerekebilir.)
devicePixelContentBox
#
devicePixelContentBox
size bir öğenin içerik kutusunu aygıt pikseli (yani fiziksel piksel) birimlerinde verir. bu bir parçası ResizeObserver
. Sırasında ResizeObserver artık tüm büyük tarayıcılarda destekleniyor Safari 13.1’den bu yana, devicePixelContentBox
özelliği şimdilik yalnızca Chrome 84+ sürümündedir.
belirtildiği gibi ResizeObserver
: gibi document.onresize
elemanlar için, a öğesinin geri arama işlevi ResizeObserver
boyadan önce ve düzenden sonra çağrılacaktır. Bu şu anlama gelir: entries
geri aramanın parametresi, gözlenen tüm öğelerin boyanmadan hemen önceki boyutlarını içerecektir. Yukarıda özetlenen tuval sorunumuz bağlamında, bu fırsatı tuvalimizdeki piksel sayısını ayarlamak için kullanabiliriz ve tuval pikselleri ile fiziksel pikseller arasında tam bire bir eşleme elde ettiğimizden emin oluruz.
const observer = new ResizeObserver((entries) => {
const entry = entries.find((entry) => entry.target === canvas);
canvas.width = entry.devicePixelContentBoxSize[0].inlineSize;
canvas.height = entry.devicePixelContentBoxSize[0].blockSize;/* … render to canvas … */
});
observer.observe(canvas, {box: ['device-pixel-content-box']});
bu box
için seçenekler nesnesindeki özellik observer.observe()
hangi boyutları istediğinizi tanımlamanıza izin verir gözlemlemek. Yani her ResizeObserverEntry
her zaman sağlayacak borderBoxSize
, contentBoxSize
Ve devicePixelContentBoxSize
(tarayıcının desteklemesi koşuluyla), geri arama yalnızca gözlenen kutu ölçümleri değişir.
Bu yeni özellikle, tuvalimizin boyutunu ve konumunu canlandırabiliriz (kesirli piksel değerlerini etkili bir şekilde garanti ederek) ve işleme üzerinde Moiré efektleri görmeyiz. Kullanarak yaklaşımda Moiré etkisini görmek isterseniz getBoundingClientRect()
ve nasıl yeni ResizeObserver
özelliği bundan kaçınmanıza izin verir, şuna bir göz atın: gösteri Chrome 84 veya sonraki sürümlerde!
Özellik algılama #
Bir kullanıcının tarayıcısının şunları destekleyip desteklemediğini kontrol etmek için devicePixelContentBox
herhangi bir öğeyi gözlemleyebilir ve özelliğin üzerinde olup olmadığını kontrol edebiliriz. ResizeObserverEntry
:
function hasDevicePixelContentBox() {
return new Promise((resolve) => {
const ro = new ResizeObserver((entries) => {
resolve(entries.every((entry) => 'devicePixelContentBoxSize' in entry));
ro.disconnect();
});
ro.observe(document.body, {box: ['device-pixel-content-box']});
}).catch(() => false);
}if (!(await hasDevicePixelContentBox())) {
// The browser does NOT support devicePixelContentBox
}
Çözüm #
Pikseller, web’de şaşırtıcı derecede karmaşık bir konudur ve şimdiye kadar, bir öğenin kullanıcının ekranında kapladığı tam fiziksel piksel sayısını bilmenizin hiçbir yolu yoktu. Yeni devicePixelContentBox
mülkiyet bir ResizeObserverEntry
size bu bilgiyi verir ve mükemmel piksel işlemeler yapmanızı sağlar. <canvas>
. devicePixelContentBox
Chrome 84+’de desteklenir.