Страницы

Поиск по вопросам

пятница, 14 февраля 2020 г.

Как сделать фон из случайно расположенных фигур SVG?

#javascript #html #css #svg


Есть сайт с разметкой, на сайте есть некоторые элементы div с заданным id и определённым
цветом фона.

Some content
Необходимо написать скрипт, который между содержанием блока и его фоном разместит случайным образом набор фигур SVG. Сами фигуры задаются заранее, скрипт располагает клоны фигур в разные места фона случайным образом, при этом немного варьируется угол поворота и масштаб фигуры. Сами фигуры должны не сильно выделяться на фоне div но при этом что бы были видны. Зачем это нужно - разнообразить и сделать более живыми фоны на уже имеющемся сайте. Так как сайт уже есть, то нужно сделать так что бы работа скрипта не нарушала существующую разметку сайта.


Ответы

Ответ 1



/* Сначала создаём шаблоны фигур, которые мы будем клонировать в разные места холста */ var figures = ` `; /* Эту разметку мы добавим в результирующий SVG код в раздел defs. Используем кастомный атрибут density у этих фигур, через него будет рассчитываться плотность (количество) фигур на выходе. Величина density это количество фигур на квадратные 100 пикселей.*/ /* основная функция выполняющая обработку */ function GenerateBack(elementId, figures) { var element = document.getElementById(elementId); var width = element.clientWidth; var height = element.clientHeight; space = width * height; var svg = document.createElement("svg"); svg.setAttribute("xmlns", "http://www.w3.org/2000/svg"); svg.setAttribute("xmlns:xlink", "http://www.w3.org/1999/xlink"); svg.style.width = width + "px"; svg.style.height = height + "px"; svg.setAttribute("width", width); svg.setAttribute("height", height); svg.setAttribute("viewBox", `0 0 ${width} ${height}`); /* получаем цвет блока */ var computedStyle = getComputedStyle(element); svg.style.backgroundColor = computedStyle.backgroundColor; /* Вычисляем слабо контрасный цвет для контуров фигур */ var color = MoveColor(computedStyle.backgroundColor); /* вставляем в SVG полотно блок определения фигур */ var defs = document.createElement("defs"); defs.innerHTML = figures; svg.appendChild(defs); /* получаем список всех фигур */ var figuresAll = Array.from(defs.children); /* Располагаем элементы `use` (клоны) по полотну `SVG` случайным образом, генерирую случайный `scale` и `rotate`. */ for (var figure of figuresAll) { /* вычисляем количество фигур для конкретного шаблона */ var number = (space * figure.getAttribute("density")) / (100 * 100); for (var i = 0; i < number; i++) { var use = document.createElement("use"); var x = random(0, width); var y = random(0, height); use.setAttribute("x", x); use.setAttribute("y", y); use.setAttribute("xlink:href", "#" + figure.id); use.setAttribute("stroke", color); use.setAttribute("fill", "transparent"); var rotate = random(-12, 12); var scale = randomFloat(0.8, 1.6); use.setAttribute("transform", `scale(${scale}) rotate(${rotate})`); svg.appendChild(use); } } SetSVGBackground(svg, element); } /* Вставляем SVG как inline фон для блока */ function SetSVGBackground(svg, element) { var svgCode = svg.outerHTML.replace(/\"/g, "'").replace(/\n/g, ""); var backURL = `url("data:image/svg+xml;utf8, ${svgCode}")`; element.style.background = backURL; } /* генерируем случайное целое число */ function random(min, max) { return Math.floor(Math.random() * (max - min + 1) + min); } /* генерируем случайное число дробного значения */ function randomFloat(min, max) { return Math.random() * (max - min) + min; } /* Получаем из строки цвета CSS R,G и B компоненты */ function GetComponentsFromRGB(colorString) { var matches = colorString.match(/[0-9]+/g); return [+matches[0], +matches[1], +matches[2]]; } /* Вычисляем слабо контрасный цвет для контуров фигур */ function MoveColor(colorString) { var components = GetComponentsFromRGB(colorString); var hsl = rgbToHsl(components[0], components[1], components[2]); var h = (hsl[0] * 360 + 20) % 360; var s = hsl[1] * 100; var l = (hsl[2] * 100 + 10); if (l > 100) l = 100; var rez = `hsl(${Math.floor(h)},${Math.floor(s)}%,${Math.floor(l)}%)`; return rez; } /* переводим цвет в формат HTL */ function rgbToHsl(r, g, b) { r /= 255, g /= 255, b /= 255; var max = Math.max(r, g, b), min = Math.min(r, g, b); var h, s, l = (max + min) / 2; if (max == min) { h = s = 0; // achromatic } else { var d = max - min; s = l > 0.5 ? d / (2 - max - min) : d / (max + min); switch (max) { case r: h = (g - b) / d + (g < b ? 6 : 0); break; case g: h = (b - r) / d + 2; break; case b: h = (r - g) / d + 4; break; } h /= 6; } return [h, s, l]; } /* запускаем */ GenerateBack("d1", figures); GenerateBack("d2", figures); GenerateBack("d3", figures); #d1 { background-color: blanchedalmond } #d2 { background-color: blue; color: white } #d3 { background-color: green; color: white } .d { margin-bottom: 15px; padding: 15px; width: 500px; }

Заголовок

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

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

Заголовок

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

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

Заголовок

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

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

Скрипт после подключения на сайт легко вызывается. GenerateBack("blockId", figures); figures - текстовое задание фигур SVG - шаблонов для генерации. Так как результирующий SVG вставляется за место фона блока, существующая разметка не ломается. Что можно ещё улучшить: Сделать перерисовку при масштабировании Анимировать фигуры, движение по путям Сделать так что бы фигуры не пересекались Попробую эти функции реализовать в новой версии скрипта.

Комментариев нет:

Отправить комментарий