如何使用html5和(画布或svg)绘制网格


77

我想绘制一个如图所示的网格,但是我完全不知道应该从哪里开始。我应该使用SVG还是将CanvasHTML5一起使用以及如何绘制。
请对此进行指导。我希望此网格在其上绘制矩形,圆形或其他图表,然后我将计算该图表的面积,例如正方形的面积。

在此处输入图片说明


您只想绘制网格?我不想沿其他方向前进,但我想知道您是否可以background-repeat使用较小的网格图像来显示较大的网格。当然,如果要根据计算结果进行绘制,则最好使用canvas
Tanzeel Kazi

Answers:


149

SVG可以使用模式很好地做到这一点:

<svg width="100%" height="100%" xmlns="http://www.w3.org/2000/svg">
  <defs>
    <pattern id="smallGrid" width="8" height="8" patternUnits="userSpaceOnUse">
      <path d="M 8 0 L 0 0 0 8" fill="none" stroke="gray" stroke-width="0.5"/>
    </pattern>
    <pattern id="grid" width="80" height="80" patternUnits="userSpaceOnUse">
      <rect width="80" height="80" fill="url(#smallGrid)"/>
      <path d="M 80 0 L 0 0 0 80" fill="none" stroke="gray" stroke-width="1"/>
    </pattern>
  </defs>

  <rect width="100%" height="100%" fill="url(#grid)" />
</svg>

我将width和设置height100%,因此您可以为内联SVG定义实际使用的宽度和高度:

<div style="width:400px;height:300px">
  <svg width="100%" height="100%" xmlns="http://www.w3.org/2000/svg">
    <defs>
      <pattern id="smallGrid" width="8" height="8" patternUnits="userSpaceOnUse">
        <path d="M 8 0 L 0 0 0 8" fill="none" stroke="gray" stroke-width="0.5"/>
      </pattern>
      <pattern id="grid" width="80" height="80" patternUnits="userSpaceOnUse">
        <rect width="80" height="80" fill="url(#smallGrid)"/>
        <path d="M 80 0 L 0 0 0 80" fill="none" stroke="gray" stroke-width="1"/>
      </pattern>
    </defs>

    <rect width="100%" height="100%" fill="url(#grid)" />
  </svg>
</div>

<img>元素:

<img src="https://svgshare.com/i/9Eo.svg" width="700" height="200"/>

结果是:

<img src="https://svgshare.com/i/9Eo.svg" width="241" height="401"/>

结果是

请注意,对于此特定网格,如果希望网格以粗笔画开始和结束,则必须使用表格的宽度和高度n x 80 + 1(可以n是任何整数)。


如果需要在网格线之间的距离有多宽,或者使用什么颜色,笔划宽度和背景色方面更灵活的网格,也可以轻松实现。随时询问您是否需要任何进一步的帮助。
Thomas W

我真的很喜欢这个解决方案。但是在firefox和safari中,如果将svg拉伸得很大(通过设置为:100%并使用非常小的视口),似乎存在舍入误差,这会导致小网格和大网格无法完美对齐:imgur.com/ qitOro2是否可以解决此问题?
Laszlo Korte 2015年

当您增加笔触宽度(例如尝试使用4.0)时,它可以与细线配合使用,显示一些不对称问题。
引导

@ThomasW我们如何更改网格线的宽度?
Gaurav Ramanan

10

我使用我的张贴代码canvas在这里SO,但我也创建上的jsfiddle工作示例这里

<!DOCTYPE html>
<html>
<head>
    <title>StackOverflow test bed</title>
    <script type="text/javascript">
        function drawGrid() {
            var cnv = document.getElementById("cnv");

            var gridOptions = {
                minorLines: {
                    separation: 5,
                    color: '#00FF00'
                },
                majorLines: {
                    separation: 30,
                    color: '#FF0000'
                }
            };

            drawGridLines(cnv, gridOptions.minorLines);
            drawGridLines(cnv, gridOptions.majorLines);

            return;
        }

        function drawGridLines(cnv, lineOptions) {


            var iWidth = cnv.width;
            var iHeight = cnv.height;

            var ctx = cnv.getContext('2d');

            ctx.strokeStyle = lineOptions.color;
            ctx.strokeWidth = 1;

            ctx.beginPath();

            var iCount = null;
            var i = null;
            var x = null;
            var y = null;

            iCount = Math.floor(iWidth / lineOptions.separation);

            for (i = 1; i <= iCount; i++) {
                x = (i * lineOptions.separation);
                ctx.moveTo(x, 0);
                ctx.lineTo(x, iHeight);
                ctx.stroke();
            }


            iCount = Math.floor(iHeight / lineOptions.separation);

            for (i = 1; i <= iCount; i++) {
                y = (i * lineOptions.separation);
                ctx.moveTo(0, y);
                ctx.lineTo(iWidth, y);
                ctx.stroke();
            }

            ctx.closePath();

            return;
        }

    </script>
</head>
<body onload="drawGrid()">
    <canvas id="cnv" width="500" height="500"></canvas>
</body>
</html>

使用该canvas方法,可以通过更改separation参数来使栅格大小动态化。

但是,如果您的网格尺寸将是静态的,我觉得也许您不需要绘制网格。只是为了显示网格可以使用CSS重复的背景图像作为小提琴证明用户着想这里。这也将提高页面性能。


是否可以减小这些线上的笔划宽度?我尝试使用小于1的数字。在上面的SVG示例中效果很好,但是我无法使用此Canvas解决方案复制它的清晰度。
John

1
您所指的清晰度是因为画布如何渲染线条。请参阅本文mobtowers.com/html5-canvas-crisp-lines-every-time。也为您提供了一个更新的jsFiddle jsfiddle.net/B2EBw/137
Tanzeel Kazi

6

为了覆盖,基于CSS的方法怎么样?

<!DOCTYPE html>
<html>
  <head>
      <style>
      html {
        height: 100%;
      }

      body {
        margin: 0;
        padding: 0;
        height: 100%;
        background-color: #434343;    
        background-size: 75px 75px;
        background-image: linear-gradient(0deg, transparent 24%, rgba(255, 255, 255, .05) 25%, rgba(255, 255, 255, .05) 26%, transparent 27%, transparent 74%, rgba(255, 255, 255, .05) 75%, rgba(255, 255, 255, .05) 76%, transparent 77%, transparent), linear-gradient(90deg, transparent 24%, rgba(255, 255, 255, .05) 25%, rgba(255, 255, 255, .05) 26%, transparent 27%, transparent 74%, rgba(255, 255, 255, .05) 75%, rgba(255, 255, 255, .05) 76%, transparent 77%, transparent);
      }

      canvas {
          width:100%;
          height:100%;
          position:absolute;

          background-color: transparent;
          background-size: 15px 15px;
          background-image: linear-gradient(0deg, transparent 24%, rgba(255, 255, 255, .05) 25%, rgba(255, 255, 255, .05) 26%, transparent 27%, transparent 74%, rgba(255, 255, 255, .05) 75%, rgba(255, 255, 255, .05) 76%, transparent 77%, transparent), linear-gradient(90deg, transparent 24%, rgba(255, 255, 255, .05) 25%, rgba(255, 255, 255, .05) 26%, transparent 27%, transparent 74%, rgba(255, 255, 255, .05) 75%, rgba(255, 255, 255, .05) 76%, transparent 77%, transparent);
      }

      </style>
  </head>
  <body>
      <canvas></canvas>
  </body>
</html>

4

使用画布非常容易,这就是我的建议。我在这里对移动设备做出了快速响应,但是即使下面的psuedocode不太正确,您也应该了解一下:

您将遇到如下循环:

// "Ctx" is your canvas context
// "Width," "Height," and other vars that start with a capital letter are set according
//   to your canvas size or preference

var i;
for (i=0; i < Height; i += GridSize) {
   ctx.lineWidth(1.0+((i%10)==0));
   ctx.moveTo(0,i);
   ctx.lineTo(Width,i);
   ctx.stroke();
}
for (i=0; i < Width; i += GridSize) {
   ctx.lineWidth(1.0+((i%10)==0));
   ctx.moveTo(i,0);
   ctx.lineTo(i,Height);
   ctx.stroke();
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.