Pull to refresh

Создаём сложный лабиринт в фоне веб-страницы (на клиенте)

Reading time2 min
Views17K
Мне показалось немного странным, желание автора этого поста, генерировать изображения на сервере, в то время как современные браузеры позволяют делать это на клиенте. Поэтому хочу предложить другой, а точнее даже два других способа генерации фона.

Сразу оговорюсь что, скорее всего, без доработки они будут работать не во всех современных браузерах (тестировал только в Chrome 24 и FF 16 под Linux).

background-image


Как известно у background-image в CSS3 можно указывать несколько файлов фонового изображения, а в background-position их координаты. Следовательно, «смещая» всего две небольших картинки можно сгенерировать случайный лабиринт, например таким кодом:

  var images = [];	// имена файлов картинок
  var positions = [];	// координаты
  var l = 26;		// размер картинок (для простоты квадратные)
  var src = ['1.png', '2.png'];
  
  var body = document.getElementsByTagName('body')[0];
  var w = body.scrollWidth/l;
  var h = body.scrollHeight/l;

  for(var i=0;i<h;i++){
    for(var j=0;j<w;j++){
      images.push('url('+src[Math.round(Math.random())]+')'); // выбираем случайную картинку
      positions.push(j*l+'px '+i*l+'px');  // и её координаты
    }
  }

  // склеиваем и присваиваем
  body.style.backgroundImage = images.join(', ');
  body.style.backgroundPosition = positions.join(', ');
  body.style.backgroundRepeat = "no-repeat";


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

  for(var i=0;i<images.length*0.05;i++){
    images[Math.floor(images.length*Math.random())]=('url('+src[Math.round(Math.random())]+')');
  }
  body.style.backgroundImage = images.join(', ');
  body.style.backgroundPosition = positions.join(', ');
  body.style.backgroundRepeat = "no-repeat";


Серьёзный минус этого способа в том, что он раздувает элемент до неприличных размеров, кроме того он довольно медленный (похоже по той же причине).

Canvas+Blob


Немного подумав, я решил, что можно сделать реализацию на Canvas+Blob. Суть примерно такая:
  • создаём холст и устанавливаем у него размер равный размеру элемента, для которого создаём фон;
  • заполняем холст рисунком;
  • с помощью JavaScript-Canvas-to-Blob конвертируем содержимое в Blob;
  • и с помощью URL.createObjectURL получаем URL блоба.

Полученный URL присваиваем свойству body.style.backgroundImage:

  var body = document.getElementsByTagName('body')[0];
  canvas.toBlob(function(blob){
    var url = URL.createObjectURL(blob);
    body.style.backgroundImage = "url('" + url + "')";
  })


Правда и здесь не обошлось без недостатка. При обновлении значения backgroundImage фон на мгновение исчезает. Хотя это довольно легко устраняется, например наложением картинок на время подгруздки:

    var url = URL.createObjectURL(blob);
    body.style.backgroundImage += ", url('" + url + "')";
    body.style.backgroundRepeat = "no-repeat";
    setTimeout(function(){
      body.style.backgroundImage = "url('" + url + "')";
    },200);


Пример 1 (background-image)
Пример 2 (Canvas+Blob)

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

p.s. Опыта написания статей почти не имею, так что сильно не ругайтесь, ежели чего не так.
Tags:
Hubs:
Total votes 42: ↑36 and ↓6+30
Comments28

Articles