2017-03-03 107 views
0

我使用canvas元素製作了一個非常簡單的矩形。但是,如果fillRect(x,y,width,height)中x和y的參數是除0和0之外的任何其他任何值,則在放大和/或移動設備上時,所有邊看起來完全模糊。如果x和y爲0和0,則矩形的頂部和左側邊緣是超級定義的,即使放大,但底部和右側邊緣模糊不清。我使用Chrome/Firefox以及使用Safari的750x1334移動屏幕在1920x1080屏幕上渲染。如何修復HTML5畫布中的模糊形狀邊緣?

這在放大到100%時在桌面上不是問題,但在移動設備上它看起來像垃圾。如果您完全放大Chrome和Firefox以及JSFiddle,則可以清楚地看到模糊的邊緣。我不使用CSS調整畫布上的寬度和高度。它使用畫布屬性和/或JS完成。我用來在瀏覽器上測試的HTML如下。

<!DOCTYPE html> 
<html> 
    <head> 
     <meta charset="utf-8"> 
     <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width"> 
    </head> 

    <body> 
     <canvas id="gameCanvas" width="150" height="150">A game.</canvas> 

     <script> 
      var canvas = document.getElementById("gameCanvas"); 
      var ctx = canvas.getContext("2d"); 

      ctx.fillRect(0, 0, 100, 100); 
     </script> 
    </body> 
</html> 

編輯:我沒有試圖繪製1像素線。我嘗試了半像素值的嘗試,但它使模糊的邊緣變得更糟。

前兩個屏幕截圖分別來自Safari上的iPhone 7屏幕,非縮放和縮放。最後的屏幕截圖位於1920x1080筆記本電腦屏幕上,在Chrome上放大。

enter image description here

enter image description here

test

+0

[畫布附圖中,類似的線條,是模糊的(可能的重複http://stackoverflow.com/questions/8696631/canvas-drawings像線一樣模糊) –

+0

我試着用半像素值進行試驗,但它只是讓它們變得更糟。而且我不繪製1像素線,我畫矩形。 – Pearu

+0

http://stackoverflow.com/q/28057881/215552相同的修復。 –

回答

1

我想通了,什麼是錯誤的。這是該設備的device-pixel-ratio屬性。除了值1之外的任何值都會導致像素化的畫布內容。在瀏覽器中調整變焦會改變device-pixel-ratio,並且某些設備具有較高的設備像素比例,如視網膜顯示屏iPhone。

你必須使用Javascript對此進行解釋。沒有其他辦法。 I wrote about this in more detail on my blog, and provide some other sources as well.

您可以在下面看到最終結果。

使用香草JavaScript的響應帆布:

var aWrapper = document.getElementById("aWrapper"); 
 
var canvas = document.getElementById("myCanvas"); 
 

 
//Accesses the 2D rendering context for our canvasdfdf 
 
var ctx = canvas.getContext("2d"); 
 

 
function setCanvasScalingFactor() { 
 
    return window.devicePixelRatio || 1; 
 
} 
 

 
function resizeCanvas() { 
 
    //Gets the devicePixelRatio 
 
    var pixelRatio = setCanvasScalingFactor(); 
 

 
    //The viewport is in portrait mode, so var width should be based off viewport WIDTH 
 
    if (window.innerHeight > window.innerWidth) { 
 
     //Makes the canvas 100% of the viewport width 
 
     var width = Math.round(1.0 * window.innerWidth); 
 
    } 
 
    //The viewport is in landscape mode, so var width should be based off viewport HEIGHT 
 
    else { 
 
     //Makes the canvas 100% of the viewport height 
 
     var width = Math.round(1.0 * window.innerHeight); 
 
    } 
 

 
    //This is done in order to maintain the 1:1 aspect ratio, adjust as needed 
 
    var height = width; 
 

 
    //This will be used to downscale the canvas element when devicePixelRatio > 1 
 
    aWrapper.style.width = width + "px"; 
 
    aWrapper.style.height = height + "px"; 
 

 
    canvas.width = width * pixelRatio; 
 
    canvas.height = height * pixelRatio; 
 
} 
 

 
var cascadeFactor = 255; 
 
var cascadeCoefficient = 1; 
 

 
function draw() { 
 
    //The number of color block columns and rows 
 
    var columns = 5; 
 
    var rows = 5; 
 
    //The length of each square 
 
    var length = Math.round(canvas.width/columns) - 2; 
 
    
 
    //Increments or decrements cascadeFactor by 1, based on cascadeCoefficient 
 
    cascadeFactor += cascadeCoefficient; 
 

 
    //Makes sure the canvas is clean at the beginning of a frame 
 
    ctx.clearRect(0, 0, canvas.width, canvas.height); 
 

 
    for (var i = columns; i >= 1; i--) { 
 
    for (var j = rows; j >= 1; j--) { 
 
     //Where the color magic happens 
 
     ctx.fillStyle = "rgba(" + (j*i*(cascadeFactor-110)) + "," + (i*cascadeFactor) + "," + (j*cascadeFactor) + "," + 0.6 + ")"; 
 
     
 
     ctx.fillRect((length*(i-1)) + ((i-1)*2), (length*(j-1)) + ((j-1)*2), length, length); 
 
    } 
 
    } 
 
    
 
    if (cascadeFactor > 255 || cascadeFactor < 0) { 
 
    //Resets the color cascade 
 
    cascadeCoefficient = -cascadeCoefficient; 
 
    } 
 
    //Continuously calls draw() again until cancelled 
 
    var aRequest = window.requestAnimationFrame(draw); 
 
} 
 

 
window.addEventListener("resize", resizeCanvas, false); 
 

 
resizeCanvas(); 
 
draw();
#aWrapper { 
 
    /*Horizontally centers the canvas*/ 
 
    margin: 0 auto; 
 
} 
 

 
#myCanvas { 
 
    /*This eliminates inconsistent rendering across browsers, canvas is supposed to be a block-level element across all browsers anyway*/ 
 
    display: block; 
 

 
    /*myCanvas will inherit its CSS width and style property values from aWrapper*/ 
 
    width: 100%; 
 
    height: 100%; 
 
} 
 
asdfasdf
<div id="aWrapper"> 
 
    <!--Include some fallback content on the 0.00001% chance your user's browser doesn't support canvas --> 
 
    <canvas id="myCanvas">Fallback content</canvas> 
 
</div>