最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - html 5 canvas LineTo() line color issues - Stack Overflow

programmeradmin1浏览0评论

I am drawing five horizontal lines to an HMTL 5 2D canvas:

var canvas_ctx = my_canvas.getContext("2d");
    canvas_ctx.lineWidth = 0.5;
    canvas_ctx.strokeStyle = "black";

    {
        let line_x = 0;
        let line_length = canvas_ctx.width;
        let offset = 5;
        let numLines = 5;
        let numYincrement = 10;
        for (let i=0;i<numLines * numYincrement;i+=numYincrement) {
            //canvas_ctx.beginPath();
            canvas_ctx.moveTo(line_x,i + offset);
            canvas_ctx.lineTo(line_length,i + offset);
            canvas_ctx.stroke();
            //canvas_ctx.closePath();
        }
    }

This should, ideally result in 5 black lines. Instead, the color of the lines seems to fade with each new line (as if it's a gradient!), so that line 5 is gray. If I unment canvas_ctx.beginPath(); and canvas_ctx.closePath();, all lines bee gray. Why is this happening??

I am drawing five horizontal lines to an HMTL 5 2D canvas:

var canvas_ctx = my_canvas.getContext("2d");
    canvas_ctx.lineWidth = 0.5;
    canvas_ctx.strokeStyle = "black";

    {
        let line_x = 0;
        let line_length = canvas_ctx.width;
        let offset = 5;
        let numLines = 5;
        let numYincrement = 10;
        for (let i=0;i<numLines * numYincrement;i+=numYincrement) {
            //canvas_ctx.beginPath();
            canvas_ctx.moveTo(line_x,i + offset);
            canvas_ctx.lineTo(line_length,i + offset);
            canvas_ctx.stroke();
            //canvas_ctx.closePath();
        }
    }

This should, ideally result in 5 black lines. Instead, the color of the lines seems to fade with each new line (as if it's a gradient!), so that line 5 is gray. If I unment canvas_ctx.beginPath(); and canvas_ctx.closePath();, all lines bee gray. Why is this happening??

Share asked Apr 9, 2018 at 13:04 shopofoliveshopofolive 2654 silver badges16 bronze badges 0
Add a ment  | 

1 Answer 1

Reset to default 13

Strokes do overlap from both sides of the coordinates.

var ctx = c.getContext('2d');
ctx.strokeStyle="red";
// draw big
ctx.scale(30, 30);
ctx.beginPath();
ctx.moveTo(5, 0);
ctx.lineTo(5, 10);
ctx.stroke();

drawPixelGrid();


function drawPixelGrid() {
  // simply renders where the pixel bounds are
  ctx.beginPath();
  // remove the zoom
  ctx.setTransform(1,0,0,1,0,0);
  ctx.strokeStyle = 'gray';
  ctx.lineWidth = 2; // avoid the problem we are demonstrating by using a perfect lineWidth ;-)

  for(let y=0; y<=300; y+=30) {
    ctx.moveTo(0, y);
    ctx.lineTo(300, y);
    for(let x=0; x<=300; x+=30) {
      ctx.moveTo(x, 0);
      ctx.lineTo(x, 300);
    }
  }
  ctx.stroke();
}
<canvas id="c" height=300></canvas>

But obviously, a pixel can't be set to two colors at the same time. So browsers apply antialiasing, which will fade your pixel color to an other color, being the result of mixing the background and the foreground color. So for a black stroke over a white or transparent background, this leads to actual gray pixels being rendered. Here I'll keep using red as an example:

var ctx = c.getContext('2d');
ctx.strokeStyle="red";
// first draw as on a 10*10 canvas
ctx.beginPath();
ctx.moveTo(5, 0);
ctx.lineTo(5, 10);
ctx.stroke();

// zoom it
ctx.imageSmoothingEnabled = 0;
ctx.globalCompositeOperation = 'copy';
ctx.drawImage(c, 0,0,9000,9000);

drawPixelGrid();

// this is not red...

function drawPixelGrid() {
  ctx.globalCompositeOperation = 'source-over';
  ctx.beginPath();
  ctx.setTransform(1,0,0,1,0,0);
  ctx.strokeStyle = 'gray';
  ctx.lineWidth = 2;

  for(let y=0; y<=300; y+=30) {
    ctx.moveTo(0, y);
    ctx.lineTo(300, y);
    for(let x=0; x<=300; x+=30) {
      ctx.moveTo(x, 0);
      ctx.lineTo(x, 300);
    }
  }
  ctx.stroke();
}
<canvas id="c" height=300></canvas>

One way to avoid it is generally to apply an offset on your coordinates so that the line extends correctly on pixels boundaries. E.g for a 1px lineWidth, you would apply a 0.5 offset:

var ctx = c.getContext('2d');
ctx.strokeStyle="red";
// first draw as on a 10*10 canvas
ctx.beginPath();
ctx.moveTo(5.5, 0); // offset +0.5px
ctx.lineTo(5.5, 10);
ctx.stroke();

// zoom it
ctx.imageSmoothingEnabled = 0;
ctx.globalCompositeOperation = 'copy';
ctx.drawImage(c, 0,0,9000,9000);

drawPixelGrid();
// now we've got a real red

function drawPixelGrid() {
  ctx.globalCompositeOperation = 'source-over';
  ctx.beginPath();
  ctx.setTransform(1,0,0,1,0,0);
  ctx.strokeStyle = 'gray';
  ctx.lineWidth = 2;

  for(let y=0; y<=300; y+=30) {
    ctx.moveTo(0, y);
    ctx.lineTo(300, y);
    for(let x=0; x<=300; x+=30) {
      ctx.moveTo(x, 0);
      ctx.lineTo(x, 300);
    }
  }
  ctx.stroke();
}
<canvas id="c" height=300></canvas>

With a lineWidth of 2, you wouldn't need any offset.

But in your case, you are drawing at 0.5px lineWidth, so no offset will be able to get rid of this antialiasing.

So if you want perfect color, choose a correct lineWidth.

发布评论

评论列表(0)

  1. 暂无评论
ok 不同模板 switch ($forum['model']) { /*case '0': include _include(APP_PATH . 'view/htm/read.htm'); break;*/ default: include _include(theme_load('read', $fid)); break; } } break; case '10': // 主题外链 / thread external link http_location(htmlspecialchars_decode(trim($thread['description']))); break; case '11': // 单页 / single page $attachlist = array(); $imagelist = array(); $thread['filelist'] = array(); $threadlist = NULL; $thread['files'] > 0 and list($attachlist, $imagelist, $thread['filelist']) = well_attach_find_by_tid($tid); $data = data_read_cache($tid); empty($data) and message(-1, lang('data_malformation')); $tidlist = $forum['threads'] ? page_find_by_fid($fid, $page, $pagesize) : NULL; if ($tidlist) { $tidarr = arrlist_values($tidlist, 'tid'); $threadlist = well_thread_find($tidarr, $pagesize); // 按之前tidlist排序 $threadlist = array2_sort_key($threadlist, $tidlist, 'tid'); } $allowpost = forum_access_user($fid, $gid, 'allowpost'); $allowupdate = forum_access_mod($fid, $gid, 'allowupdate'); $allowdelete = forum_access_mod($fid, $gid, 'allowdelete'); $access = array('allowpost' => $allowpost, 'allowupdate' => $allowupdate, 'allowdelete' => $allowdelete); $header['title'] = $thread['subject']; $header['mobile_link'] = $thread['url']; $header['keywords'] = $thread['keyword'] ? $thread['keyword'] : $thread['subject']; $header['description'] = $thread['description'] ? $thread['description'] : $thread['brief']; $_SESSION['fid'] = $fid; if ($ajax) { empty($conf['api_on']) and message(0, lang('closed')); $apilist['header'] = $header; $apilist['extra'] = $extra; $apilist['access'] = $access; $apilist['thread'] = well_thread_safe_info($thread); $apilist['thread_data'] = $data; $apilist['forum'] = $forum; $apilist['imagelist'] = $imagelist; $apilist['filelist'] = $thread['filelist']; $apilist['threadlist'] = $threadlist; message(0, $apilist); } else { include _include(theme_load('single_page', $fid)); } break; default: message(-1, lang('data_malformation')); break; } ?>