feat: Change square2 view
- Fill is now determined by max size, steps and percentage - Steps reduce size by half - Percentages are given for every but the last step
This commit is contained in:
parent
c73f4fbdb3
commit
04072e7706
1 changed files with 77 additions and 39 deletions
|
|
@ -17,7 +17,7 @@ tags:
|
|||
|
||||
{% block script %}
|
||||
<script>
|
||||
function fillCanvasWithSquares(maxSquareSize = 128, minSquareSize = 8, largeSquarePercentage = 40) {
|
||||
function fillCanvasWithSquares(maxSquareSize = 128, steps = 3, percentages = [40, 30, 20]) {
|
||||
const canvas = document.createElement('canvas');
|
||||
canvas.width = window.innerWidth;
|
||||
canvas.height = window.innerHeight;
|
||||
|
|
@ -25,22 +25,56 @@ tags:
|
|||
|
||||
const ctx = canvas.getContext('2d');
|
||||
const colors = [
|
||||
'#fad803', '#d30a51', '#273f8b',
|
||||
'#b7e0f0', '#52bed1', '#0c85ff'
|
||||
'#e1d170',
|
||||
'#cfb16a',
|
||||
'#8b3050',
|
||||
'#683657',
|
||||
'#354063',
|
||||
'#4b5776',
|
||||
'#c8dbe2',
|
||||
'#90bac2',
|
||||
'#7daeb7'
|
||||
];
|
||||
|
||||
function isPowerOfTwo(n) {
|
||||
return n > 0 && (n & (n - 1)) === 0;
|
||||
}
|
||||
|
||||
if (!isPowerOfTwo(maxSquareSize) || !isPowerOfTwo(minSquareSize)) {
|
||||
console.error('Both sizes must be powers of 2');
|
||||
if (!isPowerOfTwo(maxSquareSize)) {
|
||||
console.error('maxSquareSize must be a power of 2');
|
||||
return;
|
||||
}
|
||||
|
||||
let grid = Array(Math.ceil(canvas.height / minSquareSize))
|
||||
if (steps < 1) {
|
||||
console.error('steps must be at least 1');
|
||||
return;
|
||||
}
|
||||
|
||||
// Generate sizes by halving for each step
|
||||
const sizes = [];
|
||||
for (let i = 0; i < steps; i++) {
|
||||
sizes.push(maxSquareSize / Math.pow(2, i));
|
||||
}
|
||||
|
||||
// Validate percentages array
|
||||
if (!Array.isArray(percentages)) {
|
||||
console.error('percentages must be an array');
|
||||
return;
|
||||
}
|
||||
|
||||
if (percentages.length !== sizes.length - 1) {
|
||||
console.warn(`percentages array should have ${sizes.length - 1} elements. Adjusting...`);
|
||||
percentages = percentages.slice(0, sizes.length - 1);
|
||||
while (percentages.length < sizes.length - 1) {
|
||||
percentages.push(50);
|
||||
}
|
||||
}
|
||||
|
||||
const minSize = sizes[sizes.length - 1];
|
||||
|
||||
let grid = Array(Math.ceil(canvas.height / minSize))
|
||||
.fill(null)
|
||||
.map(() => Array(Math.ceil(canvas.width / minSquareSize)).fill(false));
|
||||
.map(() => Array(Math.ceil(canvas.width / minSize)).fill(false));
|
||||
|
||||
function canPlace(gridX, gridY, sizeInCells) {
|
||||
if (gridY + sizeInCells > grid.length || gridX + sizeInCells > grid[0].length) return false;
|
||||
|
|
@ -61,8 +95,9 @@ tags:
|
|||
}
|
||||
|
||||
function draw(gridX, gridY, sizeInPixels) {
|
||||
const x = gridX * minSquareSize;
|
||||
const y = gridY * minSquareSize;
|
||||
const x = gridX * minSize;
|
||||
const y = gridY * minSize;
|
||||
|
||||
ctx.fillStyle = colors[Math.floor(Math.random() * colors.length)];
|
||||
ctx.fillRect(x, y, sizeInPixels, sizeInPixels);
|
||||
ctx.strokeStyle = '#333';
|
||||
|
|
@ -71,39 +106,42 @@ tags:
|
|||
}
|
||||
|
||||
function fill() {
|
||||
const largestSizeInCells = maxSquareSize / minSquareSize;
|
||||
// Process each size with its corresponding percentage
|
||||
for (let sizeIndex = 0; sizeIndex < sizes.length; sizeIndex++) {
|
||||
const size = sizes[sizeIndex];
|
||||
const sizeInCells = size / minSize;
|
||||
const percentage = sizeIndex < percentages.length ? percentages[sizeIndex] : 0;
|
||||
|
||||
// Collect and shuffle positions for largest squares
|
||||
const positions = [];
|
||||
for (let gridY = 0; gridY < grid.length; gridY++) {
|
||||
for (let gridX = 0; gridX < grid[0].length; gridX++) {
|
||||
if (canPlace(gridX, gridY, largestSizeInCells)) {
|
||||
positions.push({ gridX, gridY });
|
||||
if (sizeIndex < sizes.length - 1) {
|
||||
// For all sizes except the last, apply percentage
|
||||
const positions = [];
|
||||
for (let gridY = 0; gridY < grid.length; gridY++) {
|
||||
for (let gridX = 0; gridX < grid[0].length; gridX++) {
|
||||
if (canPlace(gridX, gridY, sizeInCells)) {
|
||||
positions.push({ gridX, gridY });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
positions.sort(() => Math.random() - 0.5);
|
||||
positions.sort(() => Math.random() - 0.5);
|
||||
|
||||
// Place largest squares up to percentage
|
||||
const target = Math.floor(positions.length * largeSquarePercentage / 100);
|
||||
for (let i = 0; i < target; i++) {
|
||||
const { gridX, gridY } = positions[i];
|
||||
if (canPlace(gridX, gridY, largestSizeInCells)) {
|
||||
markOccupied(gridX, gridY, largestSizeInCells);
|
||||
draw(gridX, gridY, maxSquareSize);
|
||||
}
|
||||
}
|
||||
|
||||
// Fill remaining space with smaller sizes
|
||||
for (let size = maxSquareSize / 2; size >= minSquareSize; size /= 2) {
|
||||
const cellSize = size / minSquareSize;
|
||||
for (let gridY = 0; gridY < grid.length; gridY++) {
|
||||
for (let gridX = 0; gridX < grid[0].length; gridX++) {
|
||||
if (canPlace(gridX, gridY, cellSize)) {
|
||||
markOccupied(gridX, gridY, cellSize);
|
||||
const target = Math.floor(positions.length * percentage / 100);
|
||||
for (let i = 0; i < target; i++) {
|
||||
const { gridX, gridY } = positions[i];
|
||||
if (canPlace(gridX, gridY, sizeInCells)) {
|
||||
markOccupied(gridX, gridY, sizeInCells);
|
||||
draw(gridX, gridY, size);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Fill remaining space with the smallest size
|
||||
for (let gridY = 0; gridY < grid.length; gridY++) {
|
||||
for (let gridX = 0; gridX < grid[0].length; gridX++) {
|
||||
if (canPlace(gridX, gridY, sizeInCells)) {
|
||||
markOccupied(gridX, gridY, sizeInCells);
|
||||
draw(gridX, gridY, size);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -113,14 +151,14 @@ tags:
|
|||
window.addEventListener('resize', () => {
|
||||
canvas.width = window.innerWidth;
|
||||
canvas.height = window.innerHeight;
|
||||
grid = Array(Math.ceil(canvas.height / minSquareSize))
|
||||
grid = Array(Math.ceil(canvas.height / minSize))
|
||||
.fill(null)
|
||||
.map(() => Array(Math.ceil(canvas.width / minSquareSize)).fill(false));
|
||||
.map(() => Array(Math.ceil(canvas.width / minSize)).fill(false));
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
fill();
|
||||
});
|
||||
}
|
||||
|
||||
fillCanvasWithSquares(128, 8, 10);
|
||||
fillCanvasWithSquares(128, 4, [2, 24, 64]);
|
||||
</script>
|
||||
{% endblock %}
|
||||
Loading…
Add table
Add a link
Reference in a new issue