example.js
· 18 KiB · JavaScript
原始文件
function generateSVG(grid) {
// Размер ячейки для каждого кружка (в пикселях) - как в первой версии
const cellSize = 22.5;
// Радиус кружка
const radius = 10;
// Ширина обводки для кружков
const strokeWidth = 2;
// Ширина и высота SVG
const width = grid[0].length * cellSize;
const height = grid.length * cellSize;
// Начало SVG
let svg = `<svg width="${width}" height="${height}" xmlns="http://www.w3.org/2000/svg">`;
// Проходим по 2D массиву (true - закрашенный, false - пустой)
for (let row = 0; row < grid.length; row++) {
for (let col = 0; col < grid[row].length; col++) {
// Центр кружка
const cx = col * cellSize + cellSize / 2;
const cy = row * cellSize + cellSize / 2;
// Длина окружности для stroke-dasharray
const circumference = 2 * Math.PI * radius;
// Направление: шахматное (чётная сумма row+col - по часовой, нечётная - против)
const isClockwise = (row + col) % 2 === 0;
const initialOffset = isClockwise ? circumference : -circumference;
// Квадрат для финальной анимации, начальный rx=ry=radius, opacity=0
const squareSize = 2 * radius;
const squareX = cx - radius;
const squareY = cy - radius;
svg += `<rect x="${squareX}" y="${squareY}" width="${squareSize}" height="${squareSize}" rx="${radius}" ry="${radius}" fill="black" opacity="0" id="square_${row}_${col}"></rect>`;
if (grid[row][col]) { // true - закрашенный
// Закрашенный кружок: дуга без заливки, затем внутренний чёрный кружок
svg += `<circle cx="${cx}" cy="${cy}" r="${radius}" fill="none" stroke="black" stroke-width="${strokeWidth}" stroke-dasharray="${circumference}" stroke-dashoffset="${initialOffset}" id="circle_${row}_${col}"></circle>`;
// Внутренний кружок для расширения и заполнения чёрным из центра, начальный r=0
svg += `<circle cx="${cx}" cy="${cy}" r="0" fill="black" id="inner_${row}_${col}"></circle>`;
} else { // false - пустой
// Пустой кружок: только дуга без заливки
svg += `<circle cx="${cx}" cy="${cy}" r="${radius}" fill="none" stroke="black" stroke-width="${strokeWidth}" stroke-dasharray="${circumference}" stroke-dashoffset="${initialOffset}" id="circle_${row}_${col}"></circle>`;
}
}
}
// Конец SVG
svg += '</svg>';
return svg;
}
// Функция для замены первого SVG на странице и запуска анимации
function replaceAndAnimate(grid) {
const svgString = generateSVG(grid);
const existingSVG = document.querySelector('svg');
if (existingSVG) {
existingSVG.outerHTML = svgString;
// Теперь запускаем анимацию
animateCircles(grid);
} else {
console.log('SVG не найден на странице');
}
}
// Функция анимации через JS
function animateCircles(grid) {
const radius = 10;
const arcDur = 500; // Длительность рисования дуги (мс)
const arcDelayStep = 100; // Задержка между кружками (мс)
const fillDur = 500; // Длительность расширения внутреннего (мс)
const fillDelayStep = 100; // Задержка для расширения (мс)
const squareDur = 2000; // Длительность превращения в квадрат (мс)
// Центр сетки
const centerRow = Math.floor(grid.length / 2);
const centerCol = Math.floor(grid[0].length / 2);
// Максимальная задержка для первого этапа (рисование дуг)
const maxDelayFirst = (grid.length + grid[0].length - 2) * arcDelayStep;
// Анимация рисования дуг для всех кружков
for (let row = 0; row < grid.length; row++) {
for (let col = 0; col < grid[row].length; col++) {
const delay = (row + col) * arcDelayStep;
const circle = document.getElementById(`circle_${row}_${col}`);
if (circle) {
const isClockwise = (row + col) % 2 === 0;
setTimeout(() => {
animateDashOffset(circle, isClockwise, 2 * Math.PI * radius, arcDur);
}, delay);
}
}
}
// Анимация расширения для закрашенных после первого этапа
setTimeout(() => {
for (let row = 0; row < grid.length; row++) {
for (let col = 0; col < grid[row].length; col++) {
if (grid[row][col]) { // true - закрашенный
const distance = Math.sqrt((row - centerRow) ** 2 + (col - centerCol) ** 2);
const delay = distance * fillDelayStep;
const innerCircle = document.getElementById(`inner_${row}_${col}`);
if (innerCircle) {
setTimeout(() => {
animateRadius(innerCircle, 0, radius, fillDur);
}, delay);
}
}
}
}
// Финальная анимация превращения в квадраты после расширения
const maxDelaySecond = Math.max(...grid.flatMap((row, r) => row.map((_, c) => Math.sqrt((r - centerRow) ** 2 + (c - centerCol) ** 2)))) * fillDelayStep;
setTimeout(() => {
for (let row = 0; row < grid.length; row++) {
for (let col = 0; col < grid[row].length; col++) {
const circle = document.getElementById(`circle_${row}_${col}`);
const square = document.getElementById(`square_${row}_${col}`);
if (grid[row][col]) { // Только для закрашенных
animateToSquare(circle, square, radius, squareDur);
} else { // Для незакрашенных - плавное исчезновение
animateFadeOut(circle, squareDur);
}
}
}
}, maxDelaySecond + fillDur);
}, maxDelayFirst + arcDur);
}
// Вспомогательная функция для анимации stroke-dashoffset (рисование дуги)
function animateDashOffset(element, isClockwise, circumference, duration) {
const startTime = performance.now();
const from = isClockwise ? circumference : -circumference;
const to = 0;
const step = () => {
const elapsed = performance.now() - startTime;
const progress = Math.min(elapsed / duration, 1);
const currentOffset = from + (to - from) * progress;
element.setAttribute('stroke-dashoffset', currentOffset);
if (progress < 1) {
requestAnimationFrame(step);
}
};
requestAnimationFrame(step);
}
// Вспомогательная функция для плавной анимации радиуса
function animateRadius(element, from, to, duration) {
const startTime = performance.now();
const step = () => {
const elapsed = performance.now() - startTime;
const progress = Math.min(elapsed / duration, 1);
const currentRadius = from + (to - from) * progress;
element.setAttribute('r', currentRadius);
if (progress < 1) {
requestAnimationFrame(step);
}
};
requestAnimationFrame(step);
}
// Вспомогательная функция для плавного превращения в квадрат (теперь с border-radius эффектом)
function animateToSquare(circle, square, radius, duration) {
const startTime = performance.now();
const step = () => {
const elapsed = performance.now() - startTime;
const progress = Math.min(elapsed / duration, 1);
const currentRxRy = radius * (1 - progress);
const currentOpacity = progress; // opacity от 0 до 1
square.setAttribute('rx', currentRxRy);
square.setAttribute('ry', currentRxRy);
square.setAttribute('opacity', currentOpacity);
// Скрываем круг, устанавливая opacity=0
circle.setAttribute('opacity', 1 - progress);
if (progress < 1) {
requestAnimationFrame(step);
}
};
requestAnimationFrame(step);
}
// Вспомогательная функция для плавного исчезновения круга
function animateFadeOut(element, duration) {
const startTime = performance.now();
const step = () => {
const elapsed = performance.now() - startTime;
const progress = Math.min(elapsed / duration, 1);
const currentOpacity = 1 - progress; // opacity от 1 до 0
element.setAttribute('opacity', currentOpacity);
if (progress < 1) {
requestAnimationFrame(step);
}
};
requestAnimationFrame(step);
}
// Пример использования:
replaceAndAnimate([[true, true, true, true, true, true, true, false, true, false, false, false, false, false, false, false, false, false, false, true, true, false, false, false, true, false, true, false, false, false, true, true, true, true, true, true, true], [true, false, false, false, false, false, true, false, false, false, true, false, false, true, true, true, true, true, false, false, true, true, false, true, true, false, false, false, true, false, true, false, false, false, false, false, true], [true, false, true, true, true, false, true, false, true, true, true, true, false, true, true, false, false, true, true, false, false, false, true, true, true, false, true, true, false, false, true, false, true, true, true, false, true], [true, false, true, true, true, false, true, false, true, false, false, false, true, true, false, false, false, false, true, false, true, false, false, true, true, true, false, false, true, false, true, false, true, true, true, false, true], [true, false, true, true, true, false, true, false, false, true, false, false, false, true, true, true, false, false, true, false, true, false, false, false, true, true, false, true, true, false, true, false, true, true, true, false, true], [true, false, false, false, false, false, true, false, true, false, false, true, false, false, false, true, true, false, false, true, false, true, false, false, true, true, true, true, false, false, true, false, false, false, false, false, true], [true, true, true, true, true, true, true, false, true, false, true, false, true, false, true, false, true, false, true, false, true, false, true, false, true, false, true, false, true, false, true, true, true, true, true, true, true], [false, false, false, false, false, false, false, false, true, false, false, true, true, true, true, false, true, true, false, false, false, true, false, true, false, false, true, true, true, false, false, false, false, false, false, false, false], [false, true, false, true, false, true, true, true, true, true, false, false, true, false, false, true, true, false, false, true, false, false, true, true, true, false, false, false, true, true, true, true, false, true, true, false, true], [true, false, false, false, false, false, false, true, true, false, false, true, true, true, false, false, true, true, false, true, true, false, true, true, true, true, true, true, true, false, false, true, false, false, true, true, false], [true, false, false, false, true, false, true, false, false, false, true, false, true, true, false, false, true, false, true, false, false, true, true, true, true, false, false, true, false, true, false, false, true, false, true, true, false], [false, true, false, true, true, false, false, true, true, false, true, true, false, true, true, true, false, false, false, true, true, false, false, true, true, true, false, false, true, false, false, true, true, false, true, false, true], [false, true, false, true, true, true, true, true, true, true, false, true, true, true, false, true, true, true, false, true, true, false, false, true, true, true, false, true, true, true, true, true, true, false, true, true, false], [true, false, false, false, true, true, false, true, false, false, true, false, false, true, false, false, false, true, true, false, false, false, true, false, true, false, false, true, false, true, true, false, false, true, false, false, false], [true, true, true, false, false, true, true, true, true, false, false, true, true, false, false, false, false, true, true, false, false, true, false, true, true, false, false, true, true, true, true, true, false, false, true, true, true], [true, false, true, true, true, true, false, true, true, false, true, false, false, false, true, true, false, true, false, true, true, false, false, true, true, true, true, false, true, false, false, true, false, false, false, false, false], [false, true, false, false, false, true, true, false, true, true, true, false, false, false, false, true, false, true, false, false, false, false, true, true, true, true, true, true, true, false, true, true, true, false, true, false, true], [false, false, true, true, false, false, false, true, true, false, false, false, true, false, false, true, false, false, true, false, false, true, false, false, true, false, false, true, false, true, false, false, false, false, true, false, false], [true, true, true, true, false, false, true, true, true, true, false, false, false, true, true, true, true, false, false, false, true, false, true, true, true, true, false, false, false, true, false, false, false, false, false, true, true], [false, true, false, false, true, true, false, false, false, true, false, false, false, true, true, true, true, true, true, false, false, true, false, false, true, true, false, true, true, true, true, true, true, false, false, false, false], [true, false, true, false, false, false, true, false, false, true, false, false, false, false, false, false, true, true, true, true, true, false, true, false, true, false, true, false, true, false, false, false, true, false, true, false, false], [false, true, true, false, true, false, false, true, false, true, false, true, true, false, false, false, true, false, false, false, true, false, false, true, true, false, false, false, false, true, false, false, false, true, false, false, false], [true, false, true, false, true, true, true, false, true, true, true, false, false, false, true, false, true, true, false, true, true, true, true, true, true, false, false, false, false, true, false, true, true, true, false, false, true], [false, false, false, true, true, false, false, true, true, false, true, true, false, false, false, false, false, true, false, true, true, false, false, true, true, false, true, true, true, false, true, false, false, true, false, true, false], [true, false, false, true, false, false, true, false, false, true, false, true, true, false, true, true, true, true, true, true, false, false, false, true, false, false, false, true, false, true, false, false, true, true, true, false, true], [false, false, false, true, true, false, false, true, true, false, false, true, true, true, false, true, true, true, false, false, true, true, true, true, false, true, false, true, true, true, false, true, true, true, true, false, false], [true, false, false, true, true, false, true, true, false, true, false, true, false, false, false, false, true, false, true, false, false, false, true, true, false, true, true, false, false, false, false, false, true, true, true, true, true], [false, true, false, false, false, false, false, false, true, true, false, true, true, true, true, true, false, false, false, false, false, true, true, true, false, true, true, true, false, false, true, false, true, true, false, false, false], [true, true, true, true, false, false, true, false, false, true, true, true, true, true, false, true, false, false, true, true, true, false, false, false, true, false, false, false, true, true, true, true, true, true, false, false, true], [false, false, false, false, false, false, false, false, true, false, true, false, false, false, false, true, false, false, true, true, true, true, true, true, true, false, false, false, true, false, false, false, true, false, false, false, false], [true, true, true, true, true, true, true, false, true, true, false, true, true, true, false, false, true, true, true, true, false, false, true, false, true, true, false, false, true, false, true, false, true, true, true, true, false], [true, false, false, false, false, false, true, false, true, true, true, false, true, false, true, true, true, false, false, false, false, true, false, false, false, true, false, true, true, false, false, false, true, false, true, true, true], [true, false, true, true, true, false, true, false, false, true, false, true, false, true, true, true, true, true, true, false, false, false, true, true, false, false, true, false, true, true, true, true, true, false, false, false, false], [true, false, true, true, true, false, true, false, true, true, true, true, true, true, true, false, false, true, true, true, true, false, true, true, false, true, false, false, false, true, false, true, false, true, false, true, false], [true, false, true, true, true, false, true, false, false, true, false, false, true, false, true, false, false, true, true, false, true, true, true, false, false, true, true, false, false, false, false, false, false, true, false, false, true], [true, false, false, false, false, false, true, false, true, true, true, true, false, true, true, true, true, false, false, false, false, false, false, false, false, true, false, true, false, true, true, true, false, true, false, false, false], [true, true, true, true, true, true, true, false, false, true, true, false, false, false, false, true, false, false, true, true, true, false, false, false, false, false, true, true, false, false, false, true, false, true, true, true, true]]);
| 1 | function generateSVG(grid) { |
| 2 | // Размер ячейки для каждого кружка (в пикселях) - как в первой версии |
| 3 | const cellSize = 22.5; |
| 4 | // Радиус кружка |
| 5 | const radius = 10; |
| 6 | // Ширина обводки для кружков |
| 7 | const strokeWidth = 2; |
| 8 | // Ширина и высота SVG |
| 9 | const width = grid[0].length * cellSize; |
| 10 | const height = grid.length * cellSize; |
| 11 | |
| 12 | // Начало SVG |
| 13 | let svg = `<svg width="${width}" height="${height}" xmlns="http://www.w3.org/2000/svg">`; |
| 14 | |
| 15 | // Проходим по 2D массиву (true - закрашенный, false - пустой) |
| 16 | for (let row = 0; row < grid.length; row++) { |
| 17 | for (let col = 0; col < grid[row].length; col++) { |
| 18 | // Центр кружка |
| 19 | const cx = col * cellSize + cellSize / 2; |
| 20 | const cy = row * cellSize + cellSize / 2; |
| 21 | |
| 22 | // Длина окружности для stroke-dasharray |
| 23 | const circumference = 2 * Math.PI * radius; |
| 24 | |
| 25 | // Направление: шахматное (чётная сумма row+col - по часовой, нечётная - против) |
| 26 | const isClockwise = (row + col) % 2 === 0; |
| 27 | const initialOffset = isClockwise ? circumference : -circumference; |
| 28 | |
| 29 | // Квадрат для финальной анимации, начальный rx=ry=radius, opacity=0 |
| 30 | const squareSize = 2 * radius; |
| 31 | const squareX = cx - radius; |
| 32 | const squareY = cy - radius; |
| 33 | svg += `<rect x="${squareX}" y="${squareY}" width="${squareSize}" height="${squareSize}" rx="${radius}" ry="${radius}" fill="black" opacity="0" id="square_${row}_${col}"></rect>`; |
| 34 | |
| 35 | if (grid[row][col]) { // true - закрашенный |
| 36 | // Закрашенный кружок: дуга без заливки, затем внутренний чёрный кружок |
| 37 | svg += `<circle cx="${cx}" cy="${cy}" r="${radius}" fill="none" stroke="black" stroke-width="${strokeWidth}" stroke-dasharray="${circumference}" stroke-dashoffset="${initialOffset}" id="circle_${row}_${col}"></circle>`; |
| 38 | |
| 39 | // Внутренний кружок для расширения и заполнения чёрным из центра, начальный r=0 |
| 40 | svg += `<circle cx="${cx}" cy="${cy}" r="0" fill="black" id="inner_${row}_${col}"></circle>`; |
| 41 | } else { // false - пустой |
| 42 | // Пустой кружок: только дуга без заливки |
| 43 | svg += `<circle cx="${cx}" cy="${cy}" r="${radius}" fill="none" stroke="black" stroke-width="${strokeWidth}" stroke-dasharray="${circumference}" stroke-dashoffset="${initialOffset}" id="circle_${row}_${col}"></circle>`; |
| 44 | } |
| 45 | } |
| 46 | } |
| 47 | |
| 48 | // Конец SVG |
| 49 | svg += '</svg>'; |
| 50 | return svg; |
| 51 | } |
| 52 | |
| 53 | // Функция для замены первого SVG на странице и запуска анимации |
| 54 | function replaceAndAnimate(grid) { |
| 55 | const svgString = generateSVG(grid); |
| 56 | const existingSVG = document.querySelector('svg'); |
| 57 | if (existingSVG) { |
| 58 | existingSVG.outerHTML = svgString; |
| 59 | // Теперь запускаем анимацию |
| 60 | animateCircles(grid); |
| 61 | } else { |
| 62 | console.log('SVG не найден на странице'); |
| 63 | } |
| 64 | } |
| 65 | |
| 66 | // Функция анимации через JS |
| 67 | function animateCircles(grid) { |
| 68 | const radius = 10; |
| 69 | const arcDur = 500; // Длительность рисования дуги (мс) |
| 70 | const arcDelayStep = 100; // Задержка между кружками (мс) |
| 71 | const fillDur = 500; // Длительность расширения внутреннего (мс) |
| 72 | const fillDelayStep = 100; // Задержка для расширения (мс) |
| 73 | const squareDur = 2000; // Длительность превращения в квадрат (мс) |
| 74 | |
| 75 | // Центр сетки |
| 76 | const centerRow = Math.floor(grid.length / 2); |
| 77 | const centerCol = Math.floor(grid[0].length / 2); |
| 78 | |
| 79 | // Максимальная задержка для первого этапа (рисование дуг) |
| 80 | const maxDelayFirst = (grid.length + grid[0].length - 2) * arcDelayStep; |
| 81 | |
| 82 | // Анимация рисования дуг для всех кружков |
| 83 | for (let row = 0; row < grid.length; row++) { |
| 84 | for (let col = 0; col < grid[row].length; col++) { |
| 85 | const delay = (row + col) * arcDelayStep; |
| 86 | const circle = document.getElementById(`circle_${row}_${col}`); |
| 87 | if (circle) { |
| 88 | const isClockwise = (row + col) % 2 === 0; |
| 89 | setTimeout(() => { |
| 90 | animateDashOffset(circle, isClockwise, 2 * Math.PI * radius, arcDur); |
| 91 | }, delay); |
| 92 | } |
| 93 | } |
| 94 | } |
| 95 | |
| 96 | // Анимация расширения для закрашенных после первого этапа |
| 97 | setTimeout(() => { |
| 98 | for (let row = 0; row < grid.length; row++) { |
| 99 | for (let col = 0; col < grid[row].length; col++) { |
| 100 | if (grid[row][col]) { // true - закрашенный |
| 101 | const distance = Math.sqrt((row - centerRow) ** 2 + (col - centerCol) ** 2); |
| 102 | const delay = distance * fillDelayStep; |
| 103 | const innerCircle = document.getElementById(`inner_${row}_${col}`); |
| 104 | if (innerCircle) { |
| 105 | setTimeout(() => { |
| 106 | animateRadius(innerCircle, 0, radius, fillDur); |
| 107 | }, delay); |
| 108 | } |
| 109 | } |
| 110 | } |
| 111 | } |
| 112 | |
| 113 | // Финальная анимация превращения в квадраты после расширения |
| 114 | const maxDelaySecond = Math.max(...grid.flatMap((row, r) => row.map((_, c) => Math.sqrt((r - centerRow) ** 2 + (c - centerCol) ** 2)))) * fillDelayStep; |
| 115 | setTimeout(() => { |
| 116 | for (let row = 0; row < grid.length; row++) { |
| 117 | for (let col = 0; col < grid[row].length; col++) { |
| 118 | const circle = document.getElementById(`circle_${row}_${col}`); |
| 119 | const square = document.getElementById(`square_${row}_${col}`); |
| 120 | if (grid[row][col]) { // Только для закрашенных |
| 121 | animateToSquare(circle, square, radius, squareDur); |
| 122 | } else { // Для незакрашенных - плавное исчезновение |
| 123 | animateFadeOut(circle, squareDur); |
| 124 | } |
| 125 | } |
| 126 | } |
| 127 | }, maxDelaySecond + fillDur); |
| 128 | }, maxDelayFirst + arcDur); |
| 129 | } |
| 130 | |
| 131 | // Вспомогательная функция для анимации stroke-dashoffset (рисование дуги) |
| 132 | function animateDashOffset(element, isClockwise, circumference, duration) { |
| 133 | const startTime = performance.now(); |
| 134 | const from = isClockwise ? circumference : -circumference; |
| 135 | const to = 0; |
| 136 | const step = () => { |
| 137 | const elapsed = performance.now() - startTime; |
| 138 | const progress = Math.min(elapsed / duration, 1); |
| 139 | const currentOffset = from + (to - from) * progress; |
| 140 | element.setAttribute('stroke-dashoffset', currentOffset); |
| 141 | if (progress < 1) { |
| 142 | requestAnimationFrame(step); |
| 143 | } |
| 144 | }; |
| 145 | requestAnimationFrame(step); |
| 146 | } |
| 147 | |
| 148 | // Вспомогательная функция для плавной анимации радиуса |
| 149 | function animateRadius(element, from, to, duration) { |
| 150 | const startTime = performance.now(); |
| 151 | const step = () => { |
| 152 | const elapsed = performance.now() - startTime; |
| 153 | const progress = Math.min(elapsed / duration, 1); |
| 154 | const currentRadius = from + (to - from) * progress; |
| 155 | element.setAttribute('r', currentRadius); |
| 156 | if (progress < 1) { |
| 157 | requestAnimationFrame(step); |
| 158 | } |
| 159 | }; |
| 160 | requestAnimationFrame(step); |
| 161 | } |
| 162 | |
| 163 | // Вспомогательная функция для плавного превращения в квадрат (теперь с border-radius эффектом) |
| 164 | function animateToSquare(circle, square, radius, duration) { |
| 165 | const startTime = performance.now(); |
| 166 | const step = () => { |
| 167 | const elapsed = performance.now() - startTime; |
| 168 | const progress = Math.min(elapsed / duration, 1); |
| 169 | const currentRxRy = radius * (1 - progress); |
| 170 | const currentOpacity = progress; // opacity от 0 до 1 |
| 171 | square.setAttribute('rx', currentRxRy); |
| 172 | square.setAttribute('ry', currentRxRy); |
| 173 | square.setAttribute('opacity', currentOpacity); |
| 174 | // Скрываем круг, устанавливая opacity=0 |
| 175 | circle.setAttribute('opacity', 1 - progress); |
| 176 | if (progress < 1) { |
| 177 | requestAnimationFrame(step); |
| 178 | } |
| 179 | }; |
| 180 | requestAnimationFrame(step); |
| 181 | } |
| 182 | |
| 183 | // Вспомогательная функция для плавного исчезновения круга |
| 184 | function animateFadeOut(element, duration) { |
| 185 | const startTime = performance.now(); |
| 186 | const step = () => { |
| 187 | const elapsed = performance.now() - startTime; |
| 188 | const progress = Math.min(elapsed / duration, 1); |
| 189 | const currentOpacity = 1 - progress; // opacity от 1 до 0 |
| 190 | element.setAttribute('opacity', currentOpacity); |
| 191 | if (progress < 1) { |
| 192 | requestAnimationFrame(step); |
| 193 | } |
| 194 | }; |
| 195 | requestAnimationFrame(step); |
| 196 | } |
| 197 | |
| 198 | // Пример использования: |
| 199 | replaceAndAnimate([[true, true, true, true, true, true, true, false, true, false, false, false, false, false, false, false, false, false, false, true, true, false, false, false, true, false, true, false, false, false, true, true, true, true, true, true, true], [true, false, false, false, false, false, true, false, false, false, true, false, false, true, true, true, true, true, false, false, true, true, false, true, true, false, false, false, true, false, true, false, false, false, false, false, true], [true, false, true, true, true, false, true, false, true, true, true, true, false, true, true, false, false, true, true, false, false, false, true, true, true, false, true, true, false, false, true, false, true, true, true, false, true], [true, false, true, true, true, false, true, false, true, false, false, false, true, true, false, false, false, false, true, false, true, false, false, true, true, true, false, false, true, false, true, false, true, true, true, false, true], [true, false, true, true, true, false, true, false, false, true, false, false, false, true, true, true, false, false, true, false, true, false, false, false, true, true, false, true, true, false, true, false, true, true, true, false, true], [true, false, false, false, false, false, true, false, true, false, false, true, false, false, false, true, true, false, false, true, false, true, false, false, true, true, true, true, false, false, true, false, false, false, false, false, true], [true, true, true, true, true, true, true, false, true, false, true, false, true, false, true, false, true, false, true, false, true, false, true, false, true, false, true, false, true, false, true, true, true, true, true, true, true], [false, false, false, false, false, false, false, false, true, false, false, true, true, true, true, false, true, true, false, false, false, true, false, true, false, false, true, true, true, false, false, false, false, false, false, false, false], [false, true, false, true, false, true, true, true, true, true, false, false, true, false, false, true, true, false, false, true, false, false, true, true, true, false, false, false, true, true, true, true, false, true, true, false, true], [true, false, false, false, false, false, false, true, true, false, false, true, true, true, false, false, true, true, false, true, true, false, true, true, true, true, true, true, true, false, false, true, false, false, true, true, false], [true, false, false, false, true, false, true, false, false, false, true, false, true, true, false, false, true, false, true, false, false, true, true, true, true, false, false, true, false, true, false, false, true, false, true, true, false], [false, true, false, true, true, false, false, true, true, false, true, true, false, true, true, true, false, false, false, true, true, false, false, true, true, true, false, false, true, false, false, true, true, false, true, false, true], [false, true, false, true, true, true, true, true, true, true, false, true, true, true, false, true, true, true, false, true, true, false, false, true, true, true, false, true, true, true, true, true, true, false, true, true, false], [true, false, false, false, true, true, false, true, false, false, true, false, false, true, false, false, false, true, true, false, false, false, true, false, true, false, false, true, false, true, true, false, false, true, false, false, false], [true, true, true, false, false, true, true, true, true, false, false, true, true, false, false, false, false, true, true, false, false, true, false, true, true, false, false, true, true, true, true, true, false, false, true, true, true], [true, false, true, true, true, true, false, true, true, false, true, false, false, false, true, true, false, true, false, true, true, false, false, true, true, true, true, false, true, false, false, true, false, false, false, false, false], [false, true, false, false, false, true, true, false, true, true, true, false, false, false, false, true, false, true, false, false, false, false, true, true, true, true, true, true, true, false, true, true, true, false, true, false, true], [false, false, true, true, false, false, false, true, true, false, false, false, true, false, false, true, false, false, true, false, false, true, false, false, true, false, false, true, false, true, false, false, false, false, true, false, false], [true, true, true, true, false, false, true, true, true, true, false, false, false, true, true, true, true, false, false, false, true, false, true, true, true, true, false, false, false, true, false, false, false, false, false, true, true], [false, true, false, false, true, true, false, false, false, true, false, false, false, true, true, true, true, true, true, false, false, true, false, false, true, true, false, true, true, true, true, true, true, false, false, false, false], [true, false, true, false, false, false, true, false, false, true, false, false, false, false, false, false, true, true, true, true, true, false, true, false, true, false, true, false, true, false, false, false, true, false, true, false, false], [false, true, true, false, true, false, false, true, false, true, false, true, true, false, false, false, true, false, false, false, true, false, false, true, true, false, false, false, false, true, false, false, false, true, false, false, false], [true, false, true, false, true, true, true, false, true, true, true, false, false, false, true, false, true, true, false, true, true, true, true, true, true, false, false, false, false, true, false, true, true, true, false, false, true], [false, false, false, true, true, false, false, true, true, false, true, true, false, false, false, false, false, true, false, true, true, false, false, true, true, false, true, true, true, false, true, false, false, true, false, true, false], [true, false, false, true, false, false, true, false, false, true, false, true, true, false, true, true, true, true, true, true, false, false, false, true, false, false, false, true, false, true, false, false, true, true, true, false, true], [false, false, false, true, true, false, false, true, true, false, false, true, true, true, false, true, true, true, false, false, true, true, true, true, false, true, false, true, true, true, false, true, true, true, true, false, false], [true, false, false, true, true, false, true, true, false, true, false, true, false, false, false, false, true, false, true, false, false, false, true, true, false, true, true, false, false, false, false, false, true, true, true, true, true], [false, true, false, false, false, false, false, false, true, true, false, true, true, true, true, true, false, false, false, false, false, true, true, true, false, true, true, true, false, false, true, false, true, true, false, false, false], [true, true, true, true, false, false, true, false, false, true, true, true, true, true, false, true, false, false, true, true, true, false, false, false, true, false, false, false, true, true, true, true, true, true, false, false, true], [false, false, false, false, false, false, false, false, true, false, true, false, false, false, false, true, false, false, true, true, true, true, true, true, true, false, false, false, true, false, false, false, true, false, false, false, false], [true, true, true, true, true, true, true, false, true, true, false, true, true, true, false, false, true, true, true, true, false, false, true, false, true, true, false, false, true, false, true, false, true, true, true, true, false], [true, false, false, false, false, false, true, false, true, true, true, false, true, false, true, true, true, false, false, false, false, true, false, false, false, true, false, true, true, false, false, false, true, false, true, true, true], [true, false, true, true, true, false, true, false, false, true, false, true, false, true, true, true, true, true, true, false, false, false, true, true, false, false, true, false, true, true, true, true, true, false, false, false, false], [true, false, true, true, true, false, true, false, true, true, true, true, true, true, true, false, false, true, true, true, true, false, true, true, false, true, false, false, false, true, false, true, false, true, false, true, false], [true, false, true, true, true, false, true, false, false, true, false, false, true, false, true, false, false, true, true, false, true, true, true, false, false, true, true, false, false, false, false, false, false, true, false, false, true], [true, false, false, false, false, false, true, false, true, true, true, true, false, true, true, true, true, false, false, false, false, false, false, false, false, true, false, true, false, true, true, true, false, true, false, false, false], [true, true, true, true, true, true, true, false, false, true, true, false, false, false, false, true, false, false, true, true, true, false, false, false, false, false, true, true, false, false, false, true, false, true, true, true, true]]); |
text2json_qr.py
· 1.7 KiB · Python
原始文件
import qrcode, json
def generate_qr_boolean_array(text):
"""
Generates a QR code for the given text using version 5 and error correction level Q,
then converts it to a 2D boolean array where each element represents a module (square):
- True for black (dark) modules
- False for white (light) modules
Note: QR version 5 has a fixed size of 37x37 modules (excluding borders).
If the text is too long, it may not fit; adjust version or error correction as needed.
"""
# Create QR code object with specified parameters
qr = qrcode.QRCode(
version=5, # Fixed to version 5
error_correction=qrcode.constants.ERROR_CORRECT_Q, # Q level error correction
box_size=1, # Each module is 1 pixel (not relevant for boolean array)
border=0, # No border to get raw 37x37 modules
)
# Add data and generate the QR code
qr.add_data(text)
qr.make(fit=True) # This will attempt to fit, but version is fixed to 5
# Generate the image (black and white)
img = qr.make_image(fill_color="black", back_color="white")
# Get image dimensions (should be 37x37 for version 5 with border=0)
width, height = img.size
# Convert to 2D boolean list
boolean_array = []
for y in range(height):
row = []
for x in range(width):
pixel = img.getpixel((x, y))
# Check if pixel is black (0 for grayscale, or (0,0,0) for RGB)
if pixel == 0 or pixel == (0, 0, 0):
row.append(True) # Black module
else:
row.append(False) # White module
boolean_array.append(row)
return boolean_array
# Example usage:
print(json.dumps(generate_qr_boolean_array("Hello, world!")))
| 1 | import qrcode, json |
| 2 | |
| 3 | def generate_qr_boolean_array(text): |
| 4 | """ |
| 5 | Generates a QR code for the given text using version 5 and error correction level Q, |
| 6 | then converts it to a 2D boolean array where each element represents a module (square): |
| 7 | - True for black (dark) modules |
| 8 | - False for white (light) modules |
| 9 | |
| 10 | Note: QR version 5 has a fixed size of 37x37 modules (excluding borders). |
| 11 | If the text is too long, it may not fit; adjust version or error correction as needed. |
| 12 | """ |
| 13 | # Create QR code object with specified parameters |
| 14 | qr = qrcode.QRCode( |
| 15 | version=5, # Fixed to version 5 |
| 16 | error_correction=qrcode.constants.ERROR_CORRECT_Q, # Q level error correction |
| 17 | box_size=1, # Each module is 1 pixel (not relevant for boolean array) |
| 18 | border=0, # No border to get raw 37x37 modules |
| 19 | ) |
| 20 | |
| 21 | # Add data and generate the QR code |
| 22 | qr.add_data(text) |
| 23 | qr.make(fit=True) # This will attempt to fit, but version is fixed to 5 |
| 24 | |
| 25 | # Generate the image (black and white) |
| 26 | img = qr.make_image(fill_color="black", back_color="white") |
| 27 | |
| 28 | # Get image dimensions (should be 37x37 for version 5 with border=0) |
| 29 | width, height = img.size |
| 30 | |
| 31 | # Convert to 2D boolean list |
| 32 | boolean_array = [] |
| 33 | for y in range(height): |
| 34 | row = [] |
| 35 | for x in range(width): |
| 36 | pixel = img.getpixel((x, y)) |
| 37 | # Check if pixel is black (0 for grayscale, or (0,0,0) for RGB) |
| 38 | if pixel == 0 or pixel == (0, 0, 0): |
| 39 | row.append(True) # Black module |
| 40 | else: |
| 41 | row.append(False) # White module |
| 42 | boolean_array.append(row) |
| 43 | |
| 44 | return boolean_array |
| 45 | |
| 46 | # Example usage: |
| 47 | print(json.dumps(generate_qr_boolean_array("Hello, world!"))) |