Фон из многоугольников

268
04 апреля 2018, 10:12

Необходимо сделать фон из многоугольников.

  1. Фон случайным образом заполняется многоугольниками
  2. Основа многоугольников это правильная фигура с равными рёбрами, но вершины должны случайным образом отходить от правильной фигуры. То есть к координатам каждой вершины прибавляем случайный вектор небольшого размера.
  3. Цвета многоугольников заранее заданы палитрой, массив цветов.
  4. При наведении мышкой на многоугольник запускается анимация смены цвета на заданный, увеличение размера, и возвращение в исходное состояние. Так же анимация случайного вращения вокруг центра во время трансформации цвета и размера.

Это Вопрос-Ответ в рамках обучающей инициативы нашего Ru.StackOverflow SVG чата.

Answer 1

Первое что мы сделаем это научимся генерировать равнобедренные многогранники.

Итак наш код:

function MakeIdealMnogogrannik(rad, n) {
    var angle = 2 * Math.PI / n;
    var points = [];
    for (var i = 0; i < n; i++) {
        points.push({
            x: rad * Math.cos(angle * i),
            y: rad * Math.sin(angle * i)
        });
    }
    return points;
}

Далее напишем функцию которая сгенерирует равнобедренные многогранники и сохранит во внешнюю переменную

var radius = 22;
var minGranNumber = 3;
var maxGranNumber = 6;
var mnogograniksIdeal = new Array(maxGranNumber - minGranNumber + 1);
function MakeIdeals() {
    var number = maxGranNumber - minGranNumber + 1;
    for (var i = 0; i < number; i++) {
        mnogograniksIdeal[i] = MakeIdealMnogogrannik(radius, i + minGranNumber);
    }
}

Генерируем кривоугольники на основе правильных многогранников.

/* палитра цветов */
var colors = ["rgb(187, 61, 255)","rgb(255, 194, 61)","rgb(255, 255, 61)","rgb(61, 155, 255)","rgb(226, 61, 255)"];
var svgNS = "http://www.w3.org/2000/svg";
/* передаём количество граней, расстояние на которое вершина может случайно отъехать в сторону, координаты кривоугольника */
function MakeRandomMnogogrannik(granNumber, distance, x, y) {
    var path = document.createElementNS(svgNS, "path");
    var points = new Array(mnogograniksIdeal[granNumber].length);
    /* случайно смещаем вершины равнобедренных многогранников что бы получить кривоугольник */
    for (var i = 0; i < points.length; i++) {
        points[i] = {
            x: mnogograniksIdeal[granNumber][i].x + randomMax(distance) + x,
            y: mnogograniksIdeal[granNumber][i].y + randomMax(distance) + y
        }
    }
    var d = `M ${points[0].x} ${points[0].y}`;
    for (var i = 1; i < points.length; i++) {
        d += ` L ${points[i].x} ${points[i].y}`;
    }
    d += " Z";
    path.setAttribute("stroke", "black");
    var color = colors[randomMax(colors.length - 1)];
    path.setAttribute("fill", color);
    /* запоминаем цвет в кастомную переменную, что бы во время анимации можно было вернуться к исходному цвету */
    path.setAttribute("mycolor", color);
    var rot = randomMax(360);
    path.setAttribute("transform", `rotate(${rot} ${x} ${y})`);
    path.setAttribute("d", d);
    path.addEventListener("mouseover", MouseOver1);
    return path;
}

Функция заполнения области

var svg = document.getElementById("svg1");
var width;
var height;
var distance = 4;
function FillArea() {
    /* получаем ширину и высоту окна */
    var style = window.getComputedStyle(svg);
    width = parseInt(style.width);
    height = parseInt(style.height);
    /* вычисляем количество кривоугольников на основе плотности - density */
    var elementsNumber = density * width * height / (100 * 100);
    for (var i = 0; i < elementsNumber; i++) {
        /* ставим на случайную точку */
        var x = randomMax(width);
        var y = randomMax(height);
        /* чередуем количество граней */
        var path = MakeRandomMnogogrannik(i % mnogograniksIdeal.length, distance, x, y);
        svg.appendChild(path);
    }
}

Анимация при наведении мыши с использованием SVG.js

function MouseOver1() {
    /* получаем объект SVG.js */
    var rect1 = SVG.adopt(this);
    /* прекращаем и фиксируем ранее идущую анимацию если есть */
    rect1.finish();
    var rot = (Math.random() - 0.5) * 90;
    /* помещаем фигуру на самый верх полотна, что бы была видна анимация */
    svg.append(this);
    /* цвет для восстановления из кастомного аттрибута */
    var color = this.getAttribute("mycolor");
    /* увеличиваем размер и делаем заданный цвет */
    rect1.fill("rgb(255, 0, 0)");
    rect1.scale(1.4);
    /* запускаем анимацию */
    rect1.animate(1100, "-")
        .rotate(rot)
        .scale(1)
        .attr({ fill: color });
}

Результирующий код

var svg = document.getElementById("svg1"); 
var minGranNumber = 3; 
var maxGranNumber = 6; 
var radius = 17; 
var distance = 4; 
var density = 60; 
 
 
var mnogograniksIdeal = new Array(maxGranNumber - minGranNumber + 1); 
 
var colors = ["rgb(187, 61, 255)", "rgb(255, 194, 61)", "rgb(255, 255, 61)", "rgb(61, 155, 255)", "rgb(226, 61, 255)"]; 
 
var svgNS = "http://www.w3.org/2000/svg"; 
 
function MakeIdeals() { 
  var number = maxGranNumber - minGranNumber + 1; 
  for (var i = 0; i < number; i++) { 
    mnogograniksIdeal[i] = MakeIdealMnogogrannik(radius, i + minGranNumber); 
  } 
} 
 
function MakeIdealMnogogrannik(rad, n) { 
  var angle = 2 * Math.PI / n; 
  var points = []; 
 
  for (var i = 0; i < n; i++) { 
    points.push({ 
      x: rad * Math.cos(angle * i), 
      y: rad * Math.sin(angle * i) 
    }); 
  } 
 
  return points; 
} 
 
function MakeRandomMnogogrannik(granNumber, distance, x, y) { 
  var path = document.createElementNS(svgNS, "path"); 
 
  var points = new Array(mnogograniksIdeal[granNumber].length); 
 
  for (var i = 0; i < points.length; i++) { 
    points[i] = { 
      x: mnogograniksIdeal[granNumber][i].x + randomMax(distance) + x, 
      y: mnogograniksIdeal[granNumber][i].y + randomMax(distance) + y 
    } 
  } 
 
  var d = `M ${points[0].x} ${points[0].y}`; 
  for (var i = 1; i < points.length; i++) { 
    d += ` L ${points[i].x} ${points[i].y}`; 
  } 
  d += " Z"; 
 
  path.setAttribute("stroke", "black"); 
 
  var color = colors[randomMax(colors.length - 1)]; 
  path.setAttribute("fill", color); 
  path.setAttribute("mycolor", color); 
 
  var rot = randomMax(360); 
 
  path.setAttribute("transform", `rotate(${rot} ${x} ${y})`); 
 
  path.setAttribute("d", d); 
 
  path.addEventListener("mouseover", MouseOver1); 
 
  return path; 
} 
 
var width; 
var height; 
 
function FillArea() { 
 
  var style = window.getComputedStyle(svg); 
 
  width = parseInt(style.width); 
  height = parseInt(style.height); 
 
  var elementsNumber = density * width * height / (100 * 100); 
 
  for (var i = 0; i < elementsNumber; i++) { 
    var x = randomMax(width); 
    var y = randomMax(height); 
    var path = MakeRandomMnogogrannik(i % mnogograniksIdeal.length, distance, x, y); 
    svg.appendChild(path); 
  } 
} 
 
function MouseOver1() { 
  var rect1 = SVG.adopt(this); 
 
  rect1.finish(); 
 
  var rot = (Math.random() - 0.5) * 90; 
 
  svg.append(this); 
 
  var color = this.getAttribute("mycolor"); 
 
  rect1.fill("rgb(255, 0, 0)"); 
  rect1.scale(1.4); 
 
  rect1.animate(1100, "-") 
    .rotate(rot) 
    .scale(1) 
    .attr({ 
      fill: color 
    }); 
} 
 
function randomBool() { 
  if (Math.random() > 0.5) { 
    return true; 
  } 
  return false; 
} 
 
function randomMinMax(min, max) { 
  return Math.floor(Math.random() * (max - min + 1) + min); 
} 
 
function randomMax(max) { 
  return Math.floor(Math.random() * (max + 1)); 
} 
 
 
MakeIdeals(); 
FillArea();
body { 
  margin: 0; 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/svg.js/2.6.4/svg.min.js"></script> 
<svg id="svg1" style="width:100%; height:400px; background: rgb(187, 61, 255);" version="1.1" xmlns="http://www.w3.org/2000/svg"> 
</svg>

Ссылка на Codepen.
Дополнения версия с мозаичным текстом.

READ ALSO
Как отправить данные по почте из формы?

Как отправить данные по почте из формы?

Как отправить данные на почту в вордрессе? По клику на странице выскакивает вот такое окно, после нажатия кнопки "Купить", не отправляет на почту...

190
Сформировать массив из ajax запроса

Сформировать массив из ajax запроса

Как сформировать массив из функции? Получаю данные ajax запросом и вывожу их в виде html:

182
Вернуть данные из mongodb без названия поля

Вернуть данные из mongodb без названия поля

Есть коллекция со списком сайтов:

190
React App - примеры профессионального кода

React App - примеры профессионального кода

Здравствуйте, работаю над проектом с использованием ReactПроект начал делать 2 месяца назад - после недели знакомства с React

210