javascript - 如何在 html Canvas 中绘制细但更清晰的线条?

标签 javascript html5-canvas

我有以下 javascript 代码来绘制图表。但问题是当我打印输出时,细线看起来并不清晰。当您缩放 html 页面时,问题就会显现出来。我希望线条更锐利。但宽度应该是一样的。是否可以?请帮忙。

function drawBkg(canvasElem, squareSize, minorLineWidthStr, lineColStr)
{
    var nLinesDone = 0;
    var i, curX, curY;
    var ctx = canvasElem.getContext('2d');
    ctx.clearRect(0,0,canvasElem.width,canvasElem.height);

    // draw the vertical lines
    curX=0;
    ctx.strokeStyle = lineColStr;
while (curX < canvasElem.width)
{

    if (nLinesDone % 5 == 0)
        ctx.lineWidth = 0.7;
    else
        ctx.lineWidth = minorLineWidthStr;

    ctx.beginPath();
    ctx.moveTo(curX, 0);
    ctx.lineTo(curX, canvasElem.height);
    ctx.stroke();

    curX += squareSize;
    nLinesDone++;
}

    // draw the horizontal lines
    curY=0;
    nLinesDone = 0;
    while (curY < canvasElem.height)
    {
        if (nLinesDone % 5 == 0)
            ctx.lineWidth = 0.7;
    else
        ctx.lineWidth = minorLineWidthStr;
    ctx.beginPath();
    ctx.moveTo(0, curY);
    ctx.lineTo(canvasElem.width, curY);
    ctx.stroke();

    curY += squareSize;
    nLinesDone++;
}
}

drawBkg(byId('canvas'), 3.78, "0.35", "green");

最佳答案

您遇到的是屏幕的 PPI 之间的差异和您打印机的 DPI .

Canvas 输出是光栅图像,如果将其尺寸设置为 96px,则分辨率为 96ppi 的显示器会将其输出为一英寸大图像,但 300ppi 的打印机会将其输出为 3.125 英寸图像.
执行此操作时,打印操作将对图像进行缩减采样,使其适合新的尺寸。 (每个像素将被乘以覆盖更大的区域)。

但是 Canvas context2d 有一个 scale() method ,因此,如果您的所有绘图都是基于矢量的1,您可以:

  • 在打印之前创建更大的 Canvas ,
  • 将其上下文的比例设置为所需的系数,
  • 调用与较小 Canvas 上相同的绘图
  • 如果您直接从浏览器的“打印页面”进行打印,请设置更大的 Canvas style.widthstyle.height属性为 widthheight较小的属性,
  • 用较大的 Canvas 节点替换较小的 Canvas 节点,
  • 打印,
  • 用原来的 Canvas 替换更大的 Canvas

为此,您需要稍微重写您的函数,以便它不会将传递的 Canvas 的宽度/高度作为值,而是您选择的值。

function drawBkg(ctx, width, height, squareSize, minorLineWidthStr, lineColStr) {
  var nLinesDone = 0;
  var i, curX, curY;
  ctx.clearRect(0, 0, width, height);

  // draw the vertical lines
  curX = 0;
  ctx.strokeStyle = lineColStr;
  while (curX < width) {
    if (nLinesDone % 5 == 0)
      ctx.lineWidth = 0.7;
    else
      ctx.lineWidth = minorLineWidthStr;
    ctx.beginPath();
    ctx.moveTo(curX, 0);
    ctx.lineTo(curX, height);
    ctx.stroke();
    curX += squareSize;
    nLinesDone++;
  }

  // draw the horizontal lines
  curY = 0;
  nLinesDone = 0;
  while (curY < height) {
    if (nLinesDone % 5 == 0)
      ctx.lineWidth = 0.7;
    else
      ctx.lineWidth = minorLineWidthStr;
    ctx.beginPath();
    ctx.moveTo(0, curY);
    ctx.lineTo(width, curY);
    ctx.stroke();

    curY += squareSize;
    nLinesDone++;
  }
}


// your drawings
var smallCanvas = document.getElementById('smallCanvas');
var smallCtx = smallCanvas.getContext('2d');
drawBkg(smallCtx, smallCanvas.width, smallCanvas.height, 3.78, "0.35", "green");


// a function to get the screen's ppi
function getPPI() {
  var test = document.createElement('div');
  test.style.width = "1in";
  test.style.height = 0;
  document.body.appendChild(test);
  var dpi = devicePixelRatio || 1;
  var ppi = parseInt(getComputedStyle(test).width) * dpi;
  document.body.removeChild(test);
  return ppi;
}

function scaleAndPrint(outputDPI) {
  var factor = outputDPI / getPPI();
  var bigCanvas = smallCanvas.cloneNode();
  // set the required size of our "printer version" canvas
  bigCanvas.width = smallCanvas.width * factor;
  bigCanvas.height = smallCanvas.height * factor;
  // set the display size the same as the original one to don't brake the page's layout
  var rect = smallCanvas.getBoundingClientRect();
  bigCanvas.style.width = rect.width + 'px';
  bigCanvas.style.height = rect.height + 'px';
  var bigCtx = bigCanvas.getContext('2d');

  // change the scale of our big context
  bigCtx.scale(factor, factor);

  // tell the function we want the height and width of the small canvas
  drawBkg(bigCtx, smallCanvas.width, smallCanvas.height, 3.78, "0.35", "green");
  // replace our original canvas with the bigger one
  smallCanvas.parentNode.replaceChild(bigCanvas, smallCanvas);
  // call the printer
  print();
  // set the original one back
  bigCanvas.parentNode.replaceChild(smallCanvas, bigCanvas);
}

btn_o.onclick = function() { print(); };
btn_s.onclick = function() { scaleAndPrint(300);};
<button id="btn_o">print without scaling</button>
<button id="btn_s">print with scaling</button>
<br>
<canvas id="smallCanvas" width="250" height="500"></canvas>

<子>1。 Canvas 上的所有绘图操作都是基于矢量的,除了 drawImage() ,和putImageData()

关于javascript - 如何在 html Canvas 中绘制细但更清晰的线条?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34506036/

相关文章:

cocoa - Quartz 2D 实现 html5 canvas globalCompositeOperation

javascript - JavaScript 中的奇怪数组行为

javascript - 来自 javascript 的字符串 "true"在 php 中无法识别为该字符串值

javascript - 如何翻转 HTML Canvas 上绘制的路径

javascript - (正则表达式)\b 和 NOT\B 之间的错误差异

javascript - 为什么这个回调函数没有添加bind.(this)?

javascript - html5 Canvas 文本动画新闻自动收报机

css - javascript中的弹跳球动画

javascript - CROPPER JS 获取裁剪 Canvas 不适用于较大的文件

javascript - 更改 Ext.js TreePanel 复选框元素