як намалювати сітку за допомогою html5 та (canvas або svg)


78

Я хочу намалювати сітку, як показано на зображенні, але я абсолютно не знаю, з чого мені починати. Чи слід використовувати SVG, чи слід використовувати Canvas з HTML5 та як його малювати.
Будь ласка, керівництво щодо цього. Я хочу, щоб ця сітка намалювала на ньому прямокутник, коло чи інші діаграми, і я буду обчислювати площу цієї діаграми як площу квадрата.

введіть тут опис зображення


Ви просто хочете намалювати сітку? Я не хочу рухатись в якомусь іншому напрямку, але мені було цікаво, чи можете ви background-repeatотримати невелике зображення сітки для відображення більшої сітки. Звичайно, якщо ви хочете намалювати його на основі розрахунків, то вам краще використовувати canvas.
Tanzeel Kazi

Відповіді:


154

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і heightдо 100%, так що ви можете визначити фактичну ширину і висоту на використанні, або для вбудованого 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 + 1nбудь-яким цілим числом), якщо ви хочете, щоб сітка починалася та закінчувалась щільним штрихом.


Якщо вам потрібна більш гнучка сітка з точки зору того, наскільки широка відстань між лініями сітки, або якого кольору, ширини обведення та кольору фону використовуються, це також можна легко зробити. Не соромтеся запитувати, чи потрібна вам подальша допомога з цього приводу.
Thomas W

Мені дуже подобається це рішення. Однак у Firefox та сафарі, якщо svg get розтягнуто дійсно великим (встановивши: 100% та використовуючи дійсно малий вікно перегляду), здається, виникають помилки округлення, через які маленька сітка та велика сітка не вирівнюються ідеально: imgur.com/ qitOro2 чи є спосіб це виправити?
Ласло Корте

Це добре працює з тонкими лініями, коли при збільшенні ширини штриху (наприклад, спробуйте 4.0), з’являються деякі асиметричні проблеми.
Guid

@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.
JohnDevelops

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

це дуже просто зробити за допомогою полотна, ось що я рекомендую. Я тут швидко реагую на мобільний, але ви повинні зрозуміти ідею, навіть якщо вказаний нижче пседокод не ДУЖЕ правильний:

у вас буде цикл приблизно такий:

// "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();
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.