codepens/a-generative-svg-using-a-te.../dist/script.js

197 lines
4.2 KiB
JavaScript
Raw Normal View History

2023-10-06 23:12:53 +02:00
const settings = {
colors: {
decor: ["#432ee6", "#e62e74", "#d0e62e", "#2ee69f"],
main: ["#dddddd", "#222222"]
},
decor: {
count: 25,
minWidth: 1,
maxWidth: 2,
minHeight: 3,
maxHeight: 12
},
sizes: {
columns: 35,
rows: 50,
maxColumnPart: 4
}
};
const utils = {
getRandFromRange: function (min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
},
count: function (array) {
return array.length
? array.reduce(function (previous, current) {
return previous + current;
})
: 0;
}
};
class Illustration {
baseHeight;
baseWidth;
columns;
columnCount;
rowCount;
maxColumnPart;
decor;
colors;
screen = { width: 0, height: 0 };
svg;
constructor(selector, colors, decor, sizes) {
this.screen = {
width: window.innerWidth,
height: window.innerHeight
};
this.setSVG(selector);
this.columns = [];
this.decor = decor;
this.colors = colors;
this.columnCount = sizes.columns;
this.rowCount = sizes.rows;
this.maxColumnPart = sizes.maxColumnPart;
this.baseHeight = this.screen.height / this.rowCount;
this.baseWidth = this.screen.width / this.columnCount;
this.draw();
}
setSVG(selector) {
this.svg = document.querySelector(selector);
this.svg.addEventListener("click", this.draw.bind(this));
this.svg.setAttribute(
"viewBox",
`0 0 ${this.screen.width} ${this.screen.height}`
);
}
reset() {
this.columns = [];
this.svg.innerHTML = "";
}
setColumns() {
for (let i = 0; i < this.columnCount; ) {
const maxSize = this.columnCount - i;
const size = utils.getRandFromRange(
1,
maxSize < this.maxColumnPart ? maxSize : this.maxColumnPart
);
this.columns.push(size);
i += size;
}
}
draw() {
this.reset();
this.setColumns();
this.drawBase();
this.drawDecor();
}
drawBase() {
for (let i = 0; i < this.rowCount; i++) {
let x = 0;
for (let j = 0; j < this.columns.length; j++) {
const width = this.baseWidth * this.columns[j];
const rect = new Rect(
x,
i * this.baseHeight,
width,
this.baseHeight,
this.colors.main[(i + j) % 2]
);
x += width;
this.svg.appendChild(rect.getDOMElement());
}
}
}
drawDecor() {
for (let i = 0; i < this.decor.count; i++) {
const x = utils.getRandFromRange(0, this.columns.length - 1);
const y = utils.getRandFromRange(0, this.rowCount - 1);
const height = utils.getRandFromRange(
this.decor.minHeight,
this.rowCount - y > this.decor.maxHeight
? this.decor.maxHeight
: this.rowCount - y
);
const width = utils.getRandFromRange(
this.decor.minWidth,
height > this.decor.maxWidth + 1
? this.decor.minWidth
: this.decor.maxWidth
);
const columnOffset = utils.count(this.columns.slice(0, x));
const columnSpan = utils.count(this.columns.slice(x, x + width));
const rect = new Rect(
columnOffset * this.baseWidth,
y * this.baseHeight,
this.baseWidth * columnSpan,
this.baseHeight * height,
this.colors.decor[
utils.getRandFromRange(0, this.colors.decor.length - 1)
]
);
this.svg.appendChild(rect.getDOMElement());
}
}
}
class Rect {
x;
y;
width;
height;
fill;
element;
constructor(x, y, width, height, fill) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.fill = fill;
this.setDOMElement();
}
getDOMElement() {
return this.element;
}
setDOMElement(x, y, width, height, fill) {
this.element = document.createElementNS(
"http://www.w3.org/2000/svg",
"rect"
);
this.element.setAttribute("x", x ? x : this.x);
this.element.setAttribute("y", y ? y : this.y);
this.element.setAttribute("width", width ? width : this.width);
this.element.setAttribute("height", height ? height : this.height);
this.element.style.fill = fill ? fill : this.fill;
}
}
const illustration = new Illustration(
"#illustration",
settings.colors,
settings.decor,
settings.sizes
);