move * to apps/frontend
Main daploy / deploy (push) Successful in 43s

This commit is contained in:
2024-11-21 01:15:06 +02:00
parent 3ac451e5f3
commit 11bba7a275
89 changed files with 35 additions and 23 deletions
@@ -0,0 +1,53 @@
import { calculateFontSizeForText } from '@/utils/calculateFontSizeForText'
/**
* Добавление текста в SVG, прибитого к нижнему краю.
* @param svgText Исходный SVG в виде строки.
* @param label Надпись для добавления.
* @param color Цвет текста.
* @param marginMultiplier Множитель относительного отступа.
* @returns SVG с добавленным текстом.
*/
export function addLabelToSvg(
svgText: string,
label: string,
color: string,
marginMultiplier: number = 0.1,
): string {
if (!label) {
return svgText
}
const parser = new DOMParser()
const svgDoc = parser.parseFromString(svgText, '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, viewBox[2])
const textMargin = Math.min(fontSize, viewBox[3] * marginMultiplier)
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', '100%') // Устанавливаем Y на 100% высоты
textElement.setAttribute('text-anchor', 'middle')
textElement.setAttribute('alignment-baseline', 'baseline') // Привязываем к нижнему краю
textElement.setAttribute('dominant-baseline', 'text-after-edge') // Альтернативный способ
textElement.setAttribute('fill', color)
textElement.setAttribute('font-size', fontSize.toString())
textElement.setAttribute('font-family', 'Arial, sans-serif')
textElement.textContent = label
svgElement.appendChild(textElement)
}
}
const serializer = new XMLSerializer()
return serializer.serializeToString(svgDoc)
}
@@ -0,0 +1,25 @@
import { optimize } from 'svgo'
/**
* Оптимизация SVG с использованием SVGO.
* @param svgText string изображения SVG.
* @returns Строка оптимизированного SVG.
*/
export function optimizeSvg(svgText: string): string {
const optimizedSvg = optimize(svgText, {
plugins: [
{ name: 'removeDoctype' },
{ name: 'removeComments' },
{ name: 'removeDimensions' },
{ name: 'convertShapeToPath' },
{ name: 'convertPathData' },
{ name: 'mergePaths' },
],
})
if (!optimizedSvg.data) {
throw new Error('Ошибка оптимизации SVG')
}
return optimizedSvg.data
}
@@ -0,0 +1,20 @@
/**
* Заменяет атрибут `fill` в SVG-коде.
* @param svgText Исходный SVG в виде строки.
* @param fillColor Новый цвет для fill.
* @returns Измененный SVG-код.
*/
export function replaceFillInSvg(svgText: string, fillColor: string): string {
const parser = new DOMParser()
const svgDoc = parser.parseFromString(svgText, 'image/svg+xml')
const paths = svgDoc.querySelectorAll('path, rect, circle, polygon, ellipse')
paths.forEach((path) => {
if (path.hasAttribute('fill')) {
path.setAttribute('fill', fillColor)
}
})
const serializer = new XMLSerializer()
return serializer.serializeToString(svgDoc)
}