0

I am having trouble with blurry lines on the element.

ctx.moveTo(2,2);
ctx.lineTo(50,2);
ctx.arc(27,2,25,0,3.1415926);
ctx.stroke();

I tried making the linewidth 0.5 but that didn't fix it. Everything I try doesn't seem to do anything.

The result turns out very pixely. See result on https://rawgit.com/Mythius/uploads/master/Platformer.html

If anyone knows how to fix this please let me know.

Sébastien
  • 11,860
  • 11
  • 58
  • 78
Matthias S
  • 205
  • 2
  • 8

2 Answers2

2

Do not set your canvas size in CSS alone.

The displayed size of the canvas can be changed using a stylesheet. The image is scaled during rendering to fit the styled size. If your renderings seem distorted, try specifying your width and height attributes explicitly in the attributes, and not using CSS.

Default canvas size

var canvas = document.getElementById('cnvs');
var ctx = canvas.getContext('2d');
ctx.lineWidth = 1;
ctx.translate(0.5, 0.5);

draw();

function draw() {

  ctx.moveTo(0, 0);
  ctx.lineTo(50, 0);
  ctx.arc(25, 0, 25, 0, Math.PI);
  ctx.stroke();

}
body {
  background-color: #aaa;
}

#cnvs {
  background-color: #fff;
  border: 1px solid #000;
}
<canvas id="cnvs"></canvas>

With size specified on the canvas element attributes

var canvas = document.getElementById('cnvs');
var ctx = canvas.getContext('2d');
ctx.lineWidth = 1;
ctx.translate(0.5, 0.5);

draw();

function draw() {

  ctx.moveTo(0, 0);
  ctx.lineTo(50, 0);
  ctx.arc(25, 0, 25, 0, Math.PI);
  ctx.stroke();

}
body {
  background-color: #aaa;
}

#cnvs {
  width: 500px;
  height: 500px;
  background-color: #fff;
  border: 1px solid #000;
}
<canvas id="cnvs" width="500" height="500"></canvas>
Sébastien
  • 11,860
  • 11
  • 58
  • 78
-1

As an addendum to Sébastien's answer: The 'blockiness' of a canvas image sits at the confluence of screen resolution, canvas dimensions, and styling properties. Depending on these factors an image can appear more or less blocky/sharp - but there's only so much you can do.

Some people say that drawing to a larger canvas and styling it proportionally smaller improves the appearance of fine detail -- by the principle that small images made large look block so large images made small will look less blocky -- while others are not convinced.

Below is a snippet which draws the same content onto four canvases at two different sizes and resolutions, but all canvas are styled to the same on-screen dimensions. How blocky are they on your gear? To me they look pretty much the same, but when I save them I do notice a difference.

(function(doc) {

    function $(a) {
        switch (a.slice(0, 1)) {
            case "#":
                return doc.getElementById(a.slice(1));
            case ".":
                return [].slice.call(doc.getElementsByClassName(a.slice(1)));
        }
    }

    function save(e) {
        var cnv = $(e.target.getAttribute('data-canvas')),
            lnx = $('#savelink');

        lnx.href = cnv.toDataURL();
        lnx.download = e.target.getAttribute('data-res') +
            '_ ' + cnv.width + 'x' +
            cnv.height + '.png';

        lnx.click();
    }

    function lowRes(cnv, ctx) {
        var img = new Image;

        img.addEventListener('load', function() {
            ctx.clearRect(0, 0, cnv.width, cnv.height);
            ctx.drawImage(this, 0, 0);
        });

        img.src = cnv.toDataURL('image/jpeg', 0.64);
    };

    function draw(id, wh, lw, res) {
        var cnv = $(id),
            ctx = cnv.getContext('2d'),
            xy = wh / 2,
            fc = 8,
            shrink = (xy * 0.9) / fc,
            flag = !1;

        cnv.width = wh,
        cnv.height = wh,

        ctx.lineWidth = lw;
        ctx.fillStyle = '#eee';

        ctx.fillRect(0,0,cnv.width,cnv.height);

        ctx.beginPath();
        ctx.moveTo(0, xy);
        ctx.lineTo(cnv.width, xy);
        while (--fc) {
            ctx.arc(xy, xy, shrink * fc, 0, Math.PI, flag);
            flag = !flag;
        }
        ctx.stroke();

        ctx.fillStyle = '#777';
        ctx.font = Math.round(cnv.height * 0.025) + 'px serif';
        ctx.textAlign = 'right';
        ctx.textBaseline = 'middle';

        ctx.beginPath();
        ctx.fillText(
            ('lineWidth = ' + lw +
            ', width/height = ' + wh + 'px, ' +
            (res ? 'low-res' : 'hi-res')),
            Math.round(cnv.width * 0.9),
            Math.round(cnv.height * 0.96)
        );

        res && lowRes(cnv, ctx);
    }

    doc.addEventListener('DOMContentLoaded', function() {
        [
            ['#c1', 500, 1, !1],
            ['#c2', 1500, 3, !1],
            ['#c3', 500, 1, !0],
            ['#c4', 1500, 3, !0]
        ].forEach(function(n) {
            draw.apply(null, n);
        });

        $('.save').forEach(function(n) {
            n.addEventListener('click', save, !1);
        });
    }, false);

}(document));
.ch {
    position:relative;
    width:500px;
    height:500px;
    border:1px solid #999;
    margin:2rem auto;
}
.ch canvas {
    position:absolute;
    top:0;
    left:0;
    width:100%;
    height:100%;
    display:block;
}
.ch .save {
    position:absolute;
    top:2%;
    left:2%;
    color:#aaa;
    font-size:2rem;
    font-weight:600;
    cursor:pointer;
    display:inline-block;
    transition:color 333ms;
}
.ch .save:hover {
    color:#000;
}
<div class="ch">
    <canvas id="c1"></canvas>
    <div class="save" title=" Save Image " data-canvas="#c1" data-res="hi">&#8681;</div>
</div>
<div class="ch">
    <canvas id="c2"></canvas>
    <div class="save" title=" Save Image " data-canvas="#c2" data-res="hi">&#8681;</div>
</div>
<div class="ch">
    <canvas id="c3"></canvas>
    <div class="save" title=" Save Image " data-canvas="#c3" data-res="lo">&#8681;</div>
</div>
<div class="ch">
    <canvas id="c4"></canvas>
    <div class="save" title=" Save Image " data-canvas="#c4" data-res="lo">&#8681;</div>
</div>

<a id="savelink" href="" download="" target="_blank"></a>
Brian Peacock
  • 1,801
  • 16
  • 24