БлогNot. Рисуем деревья с листьями на Javascript

Рисуем деревья с листьями на Javascript

Я за свою жизнь посадил, наверное, целый лес, скажем, на "трудовых практиках" в сельской школе. С годами мои деревья стали, в основном, виртуальными, но такие палки, как по этой ссылке, вдохновляют мало, давайте сделаем лучше небольшую рощицу.

вид приложения "Деревья" в работе (скриншот)
вид приложения "Деревья" в работе (скриншот)

Открыв приложение, можно выбрать настройки из списков и перерисовать картинку или нажать "Сохранить", чтобы вывести в новую вкладку понравившуюся картинку (а оттуда сохраните её средствами браузера, например, нажав комбинацию клавиш Ctrl+S) (см. замечание в конце). Ниже - ссылка и исходники.

 Выполнить приложение "Деревья" онлайн, новое окно/вкладка

Исходники приведены на момент написания, онлайн-версия может чем-то отличаться. Предполагается, что оба файла сохранены в кодировке Юникода UTF-8.

Файл index.html
<!DOCTYPE html>
<html lang="ru-RU">
<head>
 <meta charset="utf-8">
 <style>
  #redrawItem {
   text-decoration: underline;
   cursor: pointer;
  }
  #canvas {
   border: 1px dotted #c0c0c0;
  }
 </style>
 <title>Trees</title>
</head>
<body>

 <div align="center" id="canvasContainer">
  <canvas id="canvas"></canvas>
 </div>
 <div align="center" id="formContainer">
  <form>
   <p>
    <span id="redrawItem">Перерисовать</span>
    <label class="description" for="spread">Разрастание:</label>
    <select id="spread" name="spread"> 
     <option value="0.3">Сильное</option>
     <option value="0.6" selected>Среднее</option>
     <option value="0.9">Слабое</option>
    </select>
    <label for="leaveType">Листья:</label>
     <select id="leaveType"> 
      <option value="50">Маленькие</option>
      <option value="250" selected>Обычные</option>
      <option value="650">Большие</option>
      <option value="1000">Узкие</option>
     </select>
    <label for="treeCnt">Деревьев:</label>
     <select id="treeCnt"> 
      <option value="1">Одно</option>
      <option value="2">Два</option>
      <option value="3" selected>Три</option>
      <option value="4">Четыре</option>
      <option value="5">Пять</option>
     </select>
   </p>
  </form>
 </div>

 <script type="text/javascript" src="treelib.js"></script>
 <script type="text/javascript">
  var width = 800;  
  var height = 400;
  var intervalId = 0;
 
  function init() {
   var canvas = document.getElementById('canvas');
   if (canvas.getContext('2d')) {
    document.getElementById('redrawItem').onclick = function() { 
     drawTree(); 
    } 
    canvas.width = width;
    canvas.height = height;
    ctx = canvas.getContext('2d');
    drawTree();
   } 
   else {
    document.getElementById('canvasContainer').innerHTML = 
     'Извините, Ваш браузер не поддерживает тег canvas';
   }
  };
 
  function drawTree() {
   var treeSpread = document.getElementById('spread').value;
   var leaveType  = parseInt(document.getElementById('leaveType').value);
   var treeCnt  = parseInt(document.getElementById('treeCnt').value);
   ctx.save();
   tree.draw(ctx,height,width,treeSpread,leaveType,treeCnt);
   ctx.restore();
  }

  init();
</script>
<noscript><div align="center">Извините, нужен Javascript для работы приложения</div></noscript>

 </body>
</html>
Файл treelib.js (из той же папки)
var tree = {
 canvas: '',
 ctx: '',
 width: 0,
 height: 0,
 spread: 0.6, //степень разрастания листьев, ]0,1[
 leavesColor: '',
 leaveType: 250, //ширина прямоугольников-листьев
 MAX_BRANCH_DEPTH: 12, //макс."глубина" ветви (уровень рекурсии)
 MAX_BRANCH_WIDTH: 16, //макс.ширина ветви (пикселы)
 BRANCH_ROTATE_COEFF: 0.125, //коэффициент для поворота ветвей, ]0,1[
    
 draw : function(ctx, h, w, spread, leaveType, treeCnt) { //рисуем дерево
  this.ctx = ctx;
  this.width = w;
  this.height = h;
  this.spread = spread;
  this.leaveType = leaveType;
  this.ctx.clearRect (0,0,this.width,this.height);
  for (var cnt = 1; cnt <= treeCnt; cnt++) {
   this.ctx.save();
   this.ctx.translate (this.width/(treeCnt+1)*cnt,this.height);
   this.leavesColor = '#'+(0x1000000+(Math.random())*0xffffff).toString(16).substr(1,6);
   this.ctx.lineWidth = 1 + Math.round (Math.random() * this.MAX_BRANCH_WIDTH);
   this.ctx.lineJoin = 'round';
   this.branch (0);
   this.ctx.restore();
  }
 },
    
 branch : function(depth) { //рисование ветки
  if (depth < this.MAX_BRANCH_DEPTH) {
   //В этйо ветке баловаться с числами аккуратней, красота - вещь хрупкая
   this.ctx.beginPath();
   this.ctx.moveTo (0,0);
   this.ctx.lineTo (0, -(this.height)/10);
   this.ctx.stroke ();
   this.ctx.translate (0,-this.height/10);
   var rand01 = - (Math.random() * this.BRANCH_ROTATE_COEFF) + this.BRANCH_ROTATE_COEFF;
   this.ctx.rotate (rand01); //поворот
   if (Math.random() < this.spread) { //вероятность выпустить ветку
    //Ветки слева:
    this.ctx.rotate (-0.35);
    this.ctx.scale (0.69,0.69);
    this.ctx.save();
    this.branch (depth+1);
    //Ветки справа:
    this.ctx.restore();  
    this.ctx.rotate (0.5);
    this.ctx.save();
    this.branch (depth + 1);   
    this.ctx.restore();        
   }
   else this.branch(depth);
  }
  else { //листья
   var lengthFactor = 100;
   if (this.leaveType === 1000) lengthFactor = 10; //если "узкие" листья
   this.ctx.fillStyle = this.leavesColor;
   this.ctx.fillRect(0, 0, this.leaveType, lengthFactor);
   this.ctx.stroke();
  }
 }
};

В IE младше 11 версии скрипт может и не работать вообще, а говнобраузер Chrome может блокировать всплывающие окна, и, соответственно, ссылку "Сохранить". Возможно, поможет добавление моего сайта в "Доверенные", или как там у них это называется. В "Огнелисе" всё работает :)

Зато девушки могут также погадать по деревцам, получающимся при первом открытии документа.

Если Ваши деревца сцепились кронами, быть Вам удачливой в любви.

А если деревце выросло выше верхнего края канвы, то богатой быть.

Ну, если толстое, значит, муж будет толстым... и т.д. 100500 раз.

P.S. Убрана функция "Сохранить" с кодом вида

<span id="saveItem">Сохранить</span>
//...
document.getElementById('saveItem').onclick = function() { 
 window.open ( canvas.toDataURL ('image/png'), '_blank'); 
}

вот из-за этого.

Для перерисовки в современных браузерах достаточно нажать правую кнопку мыши на канве и выбрать пункт меню "Сохранить картинку как..."

Зато стало работать и в Internet Explorer, по крайней мере, в 11-м :)


теги: javascript графика random

14.02.2019, 18:38; рейтинг: 223