CB's blog

Рисование простых ломаных линий div’ами на JavaScript

Май 19, 2007

На этот раз я опишу как при помощи div’ов и JavaScript можно рисовать несложные ломаные линии — только из горизонтальных и вертикальных сегментов. Для особо нетерпеливых читателей сразу ссылка на демку. Для тех, кто хочет рисовать дивами что-то сложное, ссылка на неплохую библиотеку от Walter Zorn wz_jsgraphics.js. А теперь по порядку.

Первым простым объектом будет точка (Point), состоит только из двух координат x и y:

function Point(x, y) {
   this.x = x;
   this.y = y;
}

Добавим теперь объект линию (Line). Чтобы задать линию, нам нужен массив точек, через которые эта линия проходит (то что линия может состоять только из горизонтальных или вертикальных сегментов добавляет некоторые ограничения, эти ограничения тут не проверяется, считается что дан “правильный массив точек”), и id — идентификатор линии. parentId — id HTML элемента, в котором линия будет содержаться. Линия состоит из сегментов (массив segments) — это как раз те div’ы, которыми будет рисоваться линия. this.create() будет создавать линию на основе этих данных:

function Line(id, parentId, points) {
   this.id = id;
   this.parentId = parentId;
   this.points = points;
   this.segments = [];
   this.create();
}

Функция создания линии create заполняет массив segments созданными div’ами, присваивает им id по id линии и номеру сегмента, присваивает CSS скласс segment, и добавляеть эти div’ы в родительский элемент, при этом пока сегменты невидимы (display: none;) :

Line.prototype.create = function() {
   for(var i=0; i<=this.points.length-2; i++) {
      this.segments[i] = document.createElement('div');
      this.segments[i].id = this.id + '_' + 'segment' + i;
      this.segments[i].className = 'segment';
      this.segments[i].style.display = 'none';
      document.getElementById(this.parentId).appendChild(this.segments[i]);
   }
}

И, наконец, функция draw рисует саму линию — применяет к сегментам вычисленные CSS стили (координаты top и left, ширина и высота (одна из этих двух величин всегда 0), this.segments[i].style.display = 'block'; делает сегмент видимым) на основе соседних двух точек, образующих сегмент:

Line.prototype.draw = function() {
   for(var i=0; i<=this.points.length-2; i++) {
      var x1 = this.points[i].x;
      var y1 = this.points[i].y;

      var x2 = this.points[i+1].x;
      var y2 = this.points[i+1].y;

      this.segments[i].style.top = Math.min(y1, y2) + 'px';
      this.segments[i].style.left = Math.min(x1, x2) + 'px';

      this.segments[i].style.width = Math.abs(x1 - x2) + 'px';
      this.segments[i].style.height = Math.abs(y1 - y2) + 'px';

      this.segments[i].style.display = 'block';
   }
}

И немного CSS кода для сегментов, в данном случае само рисование производится за счет границ сегментов, и позиционируются они абсолютно:

.segment {
   position: absolute;
   border: 1px solid red;
   overflow: hidden;
}

CSS для контейнера линий:

#linesContainer {
   border: 1px solid #777;
   margin: 0 auto;
   position: relative;
   width: 800px;
   height: 600px;
   background: #fff url('../i/b.png') repeat 0 0;
}

Для небольшой демонстрации я написал небольшую функцию, которая делает случайные линии

function makeRandomLine() {
   var points_count = parseInt(document.getElementById('points_count').value)
   var dir = Math.random()<0.5;
   var points = [];
   var max_x = 800;
   var max_y = 600;

   points[0]= new Point(Math.floor(Math.random()*max_x), Math.floor(Math.random()*max_y));

   for(var i=1; i<=points_count-1; i++, dir = !dir) {
      points[i] = dir ? new Point(points[i-1].x, Math.floor(Math.random()*max_y))
                      : new Point(Math.floor(Math.random()*max_x), points[i-1].y);
   }

   var parentId = 'linesContainer';
   document.getElementById(parentId).innerHTML = '';
   var line = new Line('line1', parentId, points);
   line.draw();
}

Это выглядит приблизительно так (скриншот):

Картинка с линией, нарисованной div'ами

Работающий пример.

Комментарии (8) на “Рисование простых ломаных линий div’ами на JavaScript”

  1. Maria:

    Зачем это все????????

  2. svoloshyn:

    2Maria: Практического применения данный пример еще не нашел, я просто посчитал его забавным и, возможно, кому-то интересным

  3. Максим:

    а где же здесь divы?
    один день с javascript, css и html… а уже задание как раз такое же есть-)

  4. svoloshyn:

    2Максим: this.segments[i] = document.createElement(’div’);

  5. Angel_N_Ig:

    Элементы электрической цепи в графическом редакторе соединять.

  6. Dimas:

    Прикольно, можно какой нибудь редактор наваять,
    Линии по диагонали рисокать тоже просто, нужно 2 прозрачные gif или png с линиеей по диагонали нарисованной [\] и [/] , береш масштабируеш как надо - вот тебе и линия по диагонали

    PS: где-то это описано только не помню где, там в примере обьемный кубик вертится,

  7. ko7:

    Спасибо! Как раз то, что мне нужно!

  8. Тестер:

    А как реализовать кривые?

Добавить комментарий