Cuantos pixeles hay De Verdad en un lienzo?

Desde Chrome 84, ResizeObserver admite una nueva medida de caja llamada device-pixel-content-box, que mide la dimensión del elemento en físico píxeles. Esto permite renderizar gráficos con píxeles perfectos, especialmente en el contexto de pantallas de alta densidad.

Fondo: píxeles CSSConcepto de CSS¿Qué es el CSS?CSS es un lenguaje de programación que se usa para definir el estilo y el aspecto de un documento que se ha escrito mediante de un lenguaje de etiquetas, como HTML. Conocido además como hojas de estilo en cascada, es el que se emplea para dar colores, indicar tipos de letra o inclusive resaltar aspectos como el espacio entre items para dotar de estilo a más, píxeles de lienzo y píxeles físicos

Si bien a menudo trabajamos con unidades abstractas de longitud como em, % o vh, todo se reduce a píxeles. Siempre que especifiquemos el tamaño o la posición de un elemento en CSS, el motor de diseño del navegadorUn navegador (además: browser) es una herramienta informática que te permite ver documentos y datos y navegar por la red. Los navegadores pueden mostrar distintos tipos de recursos de información; principalmente documentos HTML, a pesar de todo, además son posibles otros tipos de archivos y contenido multimedia, como PDF, JPEG, MPEG, GIF o el lenguaje de meta marcado. A través el uso de complementos especiales y la configuración respectivo, los más eventualmente convertirá ese valor en píxeles (px). Estos son «Píxeles CSS», que tienen mucho historial y solo tienen una relación poco precisa con los píxeles que tienes en tu pantalla.

Durante mucho tiempo, fue bastante razonable estimar la densidad de píxeles de la pantalla de cualquier persona con 96 ppp («puntos por pulgada»), lo que significa que cualquier monitor tendría aproximadamente 38 píxeles por cm. Con el tiempo, los monitores crecieron y / o encogieron o empezaron a tener más píxeles en la misma superficie. Combine eso con el hecho de que una gran cantidad de contenidoEl contenido puede ser muy difícil de definir con precisión. Es una definición que se refiere a las declaraciones contenidas en un documento o publicación de cualquier tipo y puede incluir las tecnologías de la información y la comunicación. Esto cubre todos los tipos de medios como imágenes y texto. A parte de esto, en el campo de la optimización de motores de búsqueda, los términos duplicar contenido, contenido único, más en la web define sus dimensiones, incluidos los tamaños de fuente, en px, y terminamos con texto ilegible en estas pantallas de alta densidad («HiDPI»). Como contramedida, los navegadoresConcepto de Navegadores¿Qué son los Navegadores?Los Navegadores son herramientas informáticas que utilizamos para, normalmente, navegar por Internet y visitar cualquier página web, al mismo tiempo de para hacer otras tareas como ver documentos, observar vídeos o reproducir contenido multimedia de cualquier tipo. Son un tipo de software sencillamente usual y bastante utilizado hoy en día.Insistimos en que es algo que se utiliza con mucha frecuencia, puesto que moverse por Internet más ocultan la densidad de píxeles real del monitor y, en su lugar, fingen que el usuario tiene una pantalla de 96 DPI. los px unidad en CSS representa el tamaño de un píxel en este virtual Pantalla de 96 DPI, de ahí el nombre «CSS Pixel». Esta unidad solo se utiliza para medición y posicionamiento. Antes de que ocurra cualquier renderizado real, ocurre una conversiónConversión es una acción precisa que lleva a cabo un usuario al visitar un portal web. Algunas formas clásica de conversión son, por ejemplo, una compra, una descarga o una suscripción a la newsletter. Un parte del SEO o del Marketing Online es la Optimización de Ratio de Conversión (CRO). En el Marketing de afiliación se usa para la conversión de los editores. Información general Hay diferentes indicadores para medir más a píxeles físicos.

¿Cómo pasamos de esta pantalla virtual a la pantalla real del usuario? Entrar devicePixelRatio. Este valor global le dice cuántos físico píxeles que necesita para formar un solo píxel CSS. Si devicePixelRatio (dPR) es 1, está trabajando en un monitor con aproximadamente 96 ppp. Si tiene una pantalla de retina, probablemente su dPR sea 2. En los teléfonos, no es raro encontrar valores dPR más altos (y más extraños) como 2, 3 o incluso 2.65. Es fundamental tener en cuenta que este valor es exacto, pero no le permite derivar el monitor real Valor de DPI. Un dPR de 2 significa que 1 píxel CSS se asignará a exactamente 2 píxeles físicos.

Mi monitor tiene un dPR de 1 según Chrome …

Tiene 3440 píxeles de ancho y el área de visualización es de 79 cm de ancho. Eso conduce a una resolución de 110 DPI. Cerca de 96, pero no del todo. Ésa es también la razón por la que <div style="width: 1cm; height: 1cm">
no medirá exactamente 1 cm de tamaño en la mayoría de las pantallas.

Finalmente, dPR también puede verse afectado por la función de zoom de su navegador. Si hace zoom, el navegador aumenta el dPR informado, lo que hace que todo se vea más grande. Si miras devicePixelRatio en una Consola de DevTools mientras hace zoom, puede ver que aparecen valores fraccionarios.

dprs-1305951
DevTools que muestra una variedad de devicePixelRatio debido al zoom.

Agreguemos el <canvas> elemento a la mezcla. Puede especificar cuántos píxeles desea que tenga el lienzo utilizando el width y height atributos. Entonces <canvas width=40 height=30> sería un lienzo de 40 por 30 píxeles. Sin embargo, esto no significa que será desplegado a 40 por 30 píxeles. De forma predeterminada, el lienzo utilizará el width y height atributoAtributo es una definición que se usa en varios campos de IT. Generalmente, un atributo se usa para describir un fichero o un campo de datos con más detalle. En la programación orientada a objetos, los atributos son una propiedad o característica que se puede asignar a un objeto (elemento). A través el uso de atributos se pueden asignar valores específicos a ciertos items. Áreas de aplicación Las tres áreas más para definir su tamaño intrínseco, pero puede cambiar el tamaño del lienzo arbitrariamente utilizando todas las propiedades CSS que conoce y ama. Con todo lo que hemos aprendido hasta ahora, se le puede ocurrir que esto no será ideal en todos los escenarios. Un píxel en el lienzo puede terminar cubriendo varios píxeles físicos o solo una fracción de un píxel físico. Esto puede generar artefactos visuales desagradables.

Para resumir: Los elementos del lienzo tienen un tamaño determinado para definir el área en la que puede dibujar. El número de píxeles del lienzo es completamente independiente del tamaño de visualización del lienzo, especificado en píxeles CSS. El número de píxeles CSS no es el mismo que el número de píxeles físicos.

Perfección de píxeles

En algunos escenarios, es deseable tener un mapeo exacto de los píxeles del lienzo a los píxeles físicos. Si se logra este mapeo, se llama «píxel perfecto». La representación perfecta de píxeles es crucial para la representación legible de texto, especialmente cuando se usa representación de subpíxeles o al mostrar gráficos con líneas muy alineadas de brillo alterno.

Para lograr algo lo más cercano posible a un lienzo de píxeles perfectos en la web, este ha sido más o menos el enfoque a seguir:

<style>
</style>
<canvas id="myCanvas"></canvas>
<script>
const cvs = document.querySelector('#myCanvas');
const rectangle = cvs.getBoundingClientRect();
cvs.width = rectangle.width * devicePixelRatio;
cvs.height = rectangle.height * devicePixelRatio;
</script>

El lector astuto podría preguntarse qué sucede cuando dPR no es un valor entero. Esa es una buena pregunta y exactamente dónde radica el meollo de todo este problema. Además, si especifica la posición o el tamaño de un elemento mediante porcentajes, vhu otros valores indirectos, es posible que se resuelvan en valores de píxeles de CSS fraccionarios. Un elemento con margin-left: 33% puede terminar con un rectángulo como este:

fractional-pixels-9178262
DevTools que muestra valores de píxeles fraccionarios como resultado de una getBoundingClientRect() llamada.

Los píxeles CSS son puramente virtuales, por lo que tener fracciones de un píxel está bien en teoría, pero ¿cómo calcula el navegador la asignación a los píxeles físicos? Porque fraccional físico los píxeles no son una cosa.

Ajuste de píxeles

La parte del proceso de conversión de unidades que se encarga de alinear elementos con píxeles físicos se denomina «ajuste de píxeles», y hace lo que dice en la lata: ajusta valores de píxeles fraccionarios a valores de píxeles físicos enteros. La forma en que esto sucede exactamente es diferente de un navegador a otro. Si tenemos un elemento con un ancho de 791.984px en una pantalla donde dPR es 1, un navegador puede representar el elemento en 792px píxeles físicos, mientras que otro navegador puede representarlo en 791px. Eso es solo un píxel menos, pero un solo píxel puede ser perjudicial para las representaciones que deben ser perfectas en píxeles. Esto puede provocar borrosidad o incluso artefactos más visibles como el Efecto moiré.

side-by-side-5944113
La imagen superior es una trama de píxeles de diferentes colores. La imagen inferior es la misma que la anterior, pero el ancho y la altura se han reducido en un píxel mediante la escala bilineal. El patrón emergente se llama efecto Moiré.
(Puede que tenga que abrir esta imagen en una nueva pestaña para verla sin aplicarle ninguna escala).

devicePixelContentBox

devicePixelContentBox le ofrece el cuadro de contenido de un elemento en unidades de píxeles del dispositivo (es decir, píxeles físicos). Es parte de ResizeObserver. Mientras ResizeObserver ahora es compatible con todos los navegadores principales desde Safari 13.1, el devicePixelContentBox La propiedad solo está en Chrome 84+ por ahora.

Como se menciona en ResizeObserver: es como document.onresize para elementos, la función de devolución de llamada de un ResizeObserver se llamará antes de pintar y después del diseño. Eso significa que el entries El parámetro de la devolución de llamada contendrá los tamaños de todos los elementos observados justo antes de que se pinten. En el contexto de nuestro problema de lienzo descrito anteriormente, podemos aprovechar esta oportunidad para ajustar la cantidad de píxeles en nuestro lienzo, asegurándonos de que terminemos con un mapeo exacto uno a uno entre los píxeles del lienzo y los píxeles físicos.

const observer = new ResizeObserver((entries) => {
const entry = entries.find((entry) => entry.targetConcepto de Target¿Qué es el Target?El Target es uno de los conceptos primordiales del marketing. Se usa para hablar del público al que se destinan las acciones y estrategias de cualquier campaña publicitaria o comercial. Es el objetivo al que ha de hablarle marca para suministrarle sus servicios o productos, aquellos a los que les interesa lo que brindan o pueda resultarle interesante por afinidad o por necesidades.Es uno de más === canvas);
canvas.width = entry.devicePixelContentBoxSize[0].inlineSize;
canvas.height = entry.devicePixelContentBoxSize[0].blockSize;


});
observer.observe(canvas, {box: ['device-pixel-content-box']});

los box propiedad en el objeto de opciones para observer.observe() le permite definir qué tamaños desea observar. Así que mientras cada ResizeObserverEntry siempre proporcionará borderBoxSize, contentBoxSize y devicePixelContentBoxSize (siempre que el navegador lo admita), la devolución de llamada solo se invocará si alguno de los observado las métricas de caja cambian.

Todas las métricas de caja son matrices para permitir ResizeObserver para manejar la fragmentación en el futuro. En el momento de escribir este artículo, la matriz siempre tiene una longitud de 1.

Con esta nueva propiedad, incluso podemos animar el tamaño y la posición de nuestro lienzo (garantizando efectivamente valores de píxeles fraccionarios) y no ver ningún efecto Moiré en el renderizado. Si desea ver el efecto Moiré en el enfoque utilizando getBoundingClientRect()y como el nuevo ResizeObserver propiedad le permite evitarlo, eche un vistazo a la manifestación en Chrome 84 o posterior.

Detección de características

Para comprobar si el navegador de un usuario es compatible con devicePixelContentBox, podemos observar cualquier elemento y comprobar si la propiedad está presente en el 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())) {
}

Conclusión

Los píxeles son un tema sorprendentemente complejo en la web y hasta ahora no había forma de saber el número exacto de píxeles físicos que ocupa un elemento en la pantalla del usuario. El nuevo devicePixelContentBox propiedad en una ResizeObserverEntry le brinda esa información y le permite hacer representaciones perfectas en píxeles con <canvas>. devicePixelContentBox es compatible con Chrome 84+.