Introducción
Estoy tratando de lidiar con imágenes borrosas en mi animación de lienzo. La borrosidad es especialmente frecuente en dispositivos móviles, retina y pantallas de alto dpi (puntos por pulgada).
Estoy buscando una manera de garantizar que los píxeles que se dibujan con el lienzo se vean lo mejor posible en pantallas de dpi baja y pantallas de dpi alta. Como solución a este problema, redacté varios artículos sobre la reducción de escala del lienzo y seguí este tutorial:
https://www.kirupa.com/canvas/canvas_high_dpi_retina.htm
Integración de la reducción de escala en el proyecto
El proyecto en el que quiero implementar la reducción de escala se puede encontrar a continuación y consta de algunas características importantes:
Pregunta
Lo que estoy tratando de lograr: el problema al que me enfrento parece bastante simple. Cuando el sitio web (con el lienzo) se abre en un dispositivo móvil (por ejemplo, un Iphone, con más píxeles por pulgada que una computadora de escritorio normal). Las imágenes aparecen más borrosas. Lo que realmente estoy tratando de lograr es eliminar este desenfoque de las imágenes. Redacté esto y decía que la borrosidad se puede eliminar mediante la reducción de resolución. Traté de incorporar esta técnica en el código proporcionado, pero no funcionó por completo. Las imágenes se hicieron más grandes y no pude escalar las imágenes al tamaño original. fragmento no está implementado correctamente, la salida sigue siendo borrosa. ¿Qué hice mal y cómo puedo solucionar este problema?
Explicación del fragmento de código
La variable devicePixelRatio se establece en 2 para simular una pantalla de teléfono de alto dpi, las pantallas de bajo dpi tienen un devicePixelRatio de 1. Múltiples lienzos prerenderizados generados son la función de spawn es el fragmento hay 5 lienzos diferentes, pero en el entorno de producción hay de 10
Si falta alguna información o preguntas sobre esta publicación, hágamelo saber. ¡Muchas gracias!
Fragmento de código
var canvas = document.querySelector('canvas'); var c = canvas.getContext('2d' ); var circles = []; //Simulate Retina screen = 2, Normal screen = 1 let devicePixelRatio = 2 function mainCanvasPixelRatio() { // get current size of the canvas let rect = canvas.getBoundingClientRect(); // increase the actual size of our canvas canvas.width = rect.width * devicePixelRatio; canvas.height = rect.height * devicePixelRatio; // ensure all drawing operations are scaled c.scale(devicePixelRatio, devicePixelRatio); // scale everything down using CSS canvas.style.width = rect.width + 'px'; canvas.style.height = rect.height + 'px'; } // Initial Spawn function spawn() { for (let i = 0; i < 2; i++) { //Set Radius let radius = parseInt(i*30); //Give position let x = Math.round((canvas.width/devicePixelRatio) / 2); let y = Math.round((canvas.height /devicePixelRatio) / 2); //Begin Prerender canvas let PreRenderCanvas = document.createElement('canvas'); const tmp = PreRenderCanvas.getContext("2d"); //Set PreRenderCanvas width and height let PreRenderCanvasWidth = ((radius*2)*1.5)+1; let PreRenderCanvasHeight = ((radius*2)*1.5)+1; //Increase the actual size of PreRenderCanvas PreRenderCanvas.width = PreRenderCanvasWidth * devicePixelRatio; PreRenderCanvas.height = PreRenderCanvasHeight * devicePixelRatio; //Scale PreRenderCanvas down using CSS PreRenderCanvas.style.width = PreRenderCanvasWidth + 'px'; PreRenderCanvas.style.height = PreRenderCanvasHeight + 'px'; //Ensure PreRenderCanvas drawing operations are scaled tmp.scale(devicePixelRatio, devicePixelRatio); //Init image const image= new Image(); //Get center of PreRenderCanvas let m_canvasCenterX = (PreRenderCanvas.width/devicePixelRatio) * .5; let m_canvasCenterY = (PreRenderCanvas.height/devicePixelRatio) * .5; //Draw red circle on PreRenderCanvas tmp.strokeStyle = "red"; tmp.beginPath(); tmp.arc((m_canvasCenterX), (m_canvasCenterY), ((PreRenderCanvas.width/devicePixelRatio)/3) , 0, 2 * Math.PI); tmp.lineWidth = 2; tmp.stroke(); tmp.restore(); tmp.closePath() //Set Image image .src= "https://play-lh.googleusercontent.com/IeNJWoKYx1waOhfWF6TiuSiWBLfqLb18lmZYXSgsH1fvb8v1IYiZr5aYWe0Gxu-pVZX3" //Get padding let paddingX = (PreRenderCanvas.width/devicePixelRatio)/5; let paddingY = (PreRenderCanvas.height/devicePixelRatio)/5; //Load image image.onload = function () { tmp.beginPath() tmp.drawImage(image, paddingX,paddingY, (PreRenderCanvas.width/devicePixelRatio)-(paddingX*2),(PreRenderCanvas.height/devicePixelRatio)-(paddingY*2)); tmp.closePath() } let circle = new Circle(x, y, c ,PreRenderCanvas); circles.push(circle) } } // Circle parameters function Circle(x, y, c ,m_canvas) { this.x = x; this.y = y; this.c = c; this.m_canvas = m_canvas; } //Draw circle on canvas Circle.prototype = { //Draw circle on canvas draw: function () { this.c.drawImage( this.m_canvas, (this.x - (this.m_canvas.width)/2), (this.y - this.m_canvas.height/2)); } }; // Animate function animate() { //Clear canvas each time c.clearRect(0, 0, (canvas.width /devicePixelRatio), (canvas.height /devicePixelRatio)); //Draw in reverse for info overlap circles.slice().reverse().forEach(function( circle ) { circle.draw(); }); requestAnimationFrame(animate); } mainCanvasPixelRatio() spawn() animate() #mainCanvas { background:blue; } <canvas id="mainCanvas"></canvas> <br>