@@ -60,14 +60,20 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { computed, ref } from 'vue'
|
||||
import { useQuery } from '@tanstack/vue-query'
|
||||
import QRCodeStyling from 'qr-code-styling'
|
||||
import { optimize } from 'svgo'
|
||||
import { getQrCodeDocument } from '@/api/qrCode'
|
||||
import { type QRCodeDocument } from '@/types/DBDocumentTypes'
|
||||
import { calculateFontSizeForText } from '@/utils/images/calculateFontSizeForText'
|
||||
import { downloadImage } from '@/utils/images/downloadImage'
|
||||
|
||||
const { qr_code_uri } = defineProps<{ qr_code_uri: QRCodeDocument['uri'] }>()
|
||||
const color = ref('#f43f5e')
|
||||
const label = ref('Сообщите о проблеме или задайте вопрос')
|
||||
const width = ref(256 * 4)
|
||||
const height = ref(width.value)
|
||||
|
||||
// Хук для загрузки данных QR‑кода
|
||||
const {
|
||||
@@ -81,12 +87,28 @@ const {
|
||||
|
||||
// Инициализация QRCodeStyling
|
||||
const qrCode = new QRCodeStyling({
|
||||
width: 256 * 4,
|
||||
height: 256 * 4,
|
||||
width: width.value,
|
||||
height: height.value,
|
||||
data: '',
|
||||
image: '/images/logo.svg',
|
||||
imageOptions: {
|
||||
margin: 20,
|
||||
// hideBackgroundDots: false,
|
||||
imageSize: 0.45,
|
||||
},
|
||||
type: 'svg',
|
||||
backgroundOptions: {
|
||||
color: '#ffffff',
|
||||
color: 'transparent',
|
||||
},
|
||||
cornersSquareOptions: {
|
||||
type: 'extra-rounded',
|
||||
},
|
||||
cornersDotOptions: {
|
||||
type: 'dot',
|
||||
},
|
||||
dotsOptions: {
|
||||
color: color.value,
|
||||
type: 'classy-rounded',
|
||||
},
|
||||
})
|
||||
|
||||
@@ -126,7 +148,48 @@ const {
|
||||
})
|
||||
|
||||
if (optimizedSvg.data) {
|
||||
return URL.createObjectURL(new Blob([optimizedSvg.data], { type: 'image/svg+xml' }))
|
||||
if (!label.value) {
|
||||
// Если label пуст, возвращаем SVG без изменений
|
||||
return URL.createObjectURL(new Blob([optimizedSvg.data], { type: 'image/svg+xml' }))
|
||||
}
|
||||
|
||||
// Добавляем надпись и увеличиваем viewBox
|
||||
const parser = new DOMParser()
|
||||
const svgDoc = parser.parseFromString(optimizedSvg.data, 'image/svg+xml')
|
||||
const svgElement = svgDoc.querySelector('svg')
|
||||
|
||||
if (svgElement) {
|
||||
// Увеличиваем viewBox
|
||||
const viewBox = svgElement.getAttribute('viewBox')?.split(' ').map(Number)
|
||||
if (viewBox) {
|
||||
// Расчет реального размера шрифта
|
||||
const fontSize = calculateFontSizeForText(label.value, viewBox[2])
|
||||
|
||||
// Рассчитываем вертикальное расстояние между QR-кодом и текстом
|
||||
const textMargin = Math.min(fontSize, viewBox[3] * 0.1) // Максимум 10% от высоты QR-кода
|
||||
|
||||
viewBox[3] += fontSize + textMargin // Увеличиваем высоту для текста
|
||||
svgElement.setAttribute('viewBox', viewBox.join(' '))
|
||||
|
||||
// Добавляем текст
|
||||
const textElement = svgDoc.createElementNS('http://www.w3.org/2000/svg', 'text')
|
||||
textElement.setAttribute('x', '50%')
|
||||
textElement.setAttribute('y', viewBox[3] - fontSize / 2) // Уменьшаем нижний отступ
|
||||
textElement.setAttribute('text-anchor', 'middle')
|
||||
textElement.setAttribute('fill', color.value)
|
||||
textElement.setAttribute('font-size', fontSize.toString())
|
||||
textElement.setAttribute('font-family', 'Arial, sans-serif')
|
||||
textElement.textContent = label.value
|
||||
|
||||
svgElement.appendChild(textElement)
|
||||
}
|
||||
}
|
||||
|
||||
// Сериализуем обратно в строку
|
||||
const serializer = new XMLSerializer()
|
||||
const updatedSvg = serializer.serializeToString(svgDoc)
|
||||
|
||||
return URL.createObjectURL(new Blob([updatedSvg], { type: 'image/svg+xml' }))
|
||||
} else {
|
||||
throw new Error('Ошибка оптимизации SVG')
|
||||
}
|
||||
@@ -144,9 +207,14 @@ const {
|
||||
// Скачивание PNG
|
||||
async function downloadPng() {
|
||||
try {
|
||||
await qrCode.download({
|
||||
name: sanitizedFileName.value,
|
||||
extension: 'png',
|
||||
if (!svgQueryData.value) {
|
||||
throw new Error('SVG не загружен')
|
||||
}
|
||||
await downloadImage({
|
||||
type: 'image/png',
|
||||
filename: `${sanitizedFileName.value}.png`,
|
||||
width: width.value,
|
||||
url: svgQueryData.value,
|
||||
})
|
||||
} catch (err) {
|
||||
console.error('Ошибка скачивания PNG:', err)
|
||||
|
||||
Reference in New Issue
Block a user