简体   繁体   中英

How to solve problems with odd numbers as HTML-canvas size?

I'm working with the HTML-canvas-element.

 var canvas = document.getElementById('c'); var ctx = canvas.getContext('2d'); ctx.beginPath(); ctx.fillStyle = "#FF0000"; ctx.rect(0, 0, canvas.width / 3, canvas.height / 3); ctx.fill(); ctx.closePath(); ctx.beginPath(); ctx.fillStyle = "#FF0000"; ctx.rect(canvas.width / 3, 0, canvas.width / 3, canvas.height / 3); ctx.fill(); ctx.closePath(); 
 <canvas id="c" width="541" height="541"></canvas> 

The problem: When I choose an odd number (in this case the prime number 541) as canvas size and draw a rectangle on it (size: 1/3 of the whole canvas).

But this is the result:

在此处输入图片说明

zoomed in:

在此处输入图片说明

As you can see: There is an unwanted line in the between the 2 rectangles. How can I fix this problem?

Rounding the values with Math.floor() , Math.round() and Math.ceil() is (probably) not an option because the sum of the widths of the 3 rectangles must be equal to the width of the canvas.

Looks like you are using a HiDPI (High DPI, Retina) mode (with OS-level zoom of more than 100%) while your canvas approach is not HiDPI-compatible.

The solution is to increase the values of the CANVAS element's width and height HTML attributes (or the element's DOM properties) proportionally with window.devicePixelRatio while setting its corresponding CSS properties to what you current size is. Then your canvas will be HiDPI compatible and blur-free. That's what I used in my web demo of nonblurry integer-ratio scaling:

var pixelRatio = window.devicePixelRatio;

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

canvas.style.width  = '' + 541 + 'px';
canvas.style.height = '' + 541 + 'px';

An alternative approach is to use the scale() method of context object instead of setting CSS size. That's what Paul Lewis from HTML5Rocks recommends :

var pixelRatio = window.devicePixelRatio;

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

canvas.getContext('2d').scale(pixelRatio, pixelRatio);

Works fine if you use the style tag or a css file

 var canvas = document.getElementById('c'); var ctx = canvas.getContext('2d'); ctx.beginPath(); ctx.fillStyle = "#FF0000"; ctx.rect(0, 0, canvas.width / 3, canvas.height / 3); ctx.fill(); ctx.closePath(); ctx.beginPath(); ctx.fillStyle = "#FF0000"; ctx.rect(canvas.width / 3, 0, canvas.width / 3, canvas.height / 3); ctx.fill(); ctx.closePath(); 
 .canvas { width: 541px; height: 541px; } 
 <canvas id="c" class="canvas"></canvas> 

Not sure if you like this solution but you could use Math.floor() only on x2

 var canvas = document.getElementById('c'); var ctx = canvas.getContext('2d'); ctx.beginPath(); ctx.fillStyle = "#FF0000"; ctx.rect(0, 0, canvas.width / 3, canvas.height / 3); ctx.fill(); ctx.closePath(); // use here to make sure that the start position of the secound rect is right var x2 = Math.floor(canvas.width / 3); ctx.beginPath(); ctx.fillStyle = "#FF0000"; ctx.rect(x2, 0, canvas.width / 3, canvas.height / 3); ctx.fill(); ctx.closePath(); 
 <canvas id="c" width="541" height="541"></canvas> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM