add new version
This commit is contained in:
@@ -9,7 +9,7 @@
|
||||
let minZoom = 1;
|
||||
let restrictPosition = true;
|
||||
let showGrid = false;
|
||||
let croppedImage = null; // хранение вырезанного изображения
|
||||
let croppedImage = null;
|
||||
|
||||
let image: string;
|
||||
let incorrectImage: string;
|
||||
@@ -18,7 +18,6 @@
|
||||
let isDragging: boolean = false;
|
||||
let isModalOpen: boolean = false;
|
||||
|
||||
// Проверка и загрузка изображения
|
||||
async function validateAndLoadImage(file: File): Promise<void> {
|
||||
error = "";
|
||||
const img = new Image();
|
||||
@@ -38,11 +37,10 @@
|
||||
reader.readAsDataURL(file);
|
||||
}
|
||||
|
||||
// Обработка Drag and Drop
|
||||
function handleDrop(e: DragEvent): void {
|
||||
e.preventDefault();
|
||||
isDragging = false;
|
||||
const file = (e.dataTransfer as DataTransfer).files[0]; // Explicitly casting to DataTransfer
|
||||
const file = (e.dataTransfer as DataTransfer).files[0];
|
||||
if (file && file.type.startsWith("image/")) {
|
||||
validateAndLoadImage(file);
|
||||
}
|
||||
@@ -62,35 +60,25 @@
|
||||
|
||||
let node = document.getElementById("result");
|
||||
|
||||
// Убираем лишние стили
|
||||
if (node) {
|
||||
domtoimage
|
||||
.toPng(node, {
|
||||
style: {
|
||||
border: "none", // Убираем рамки
|
||||
padding: "0", // Убираем отступы
|
||||
margin: "0", // Убираем маргины
|
||||
outline: "none", // Убираем outline
|
||||
border: "none",
|
||||
padding: "0",
|
||||
margin: "0",
|
||||
outline: "none",
|
||||
},
|
||||
})
|
||||
.then((dataUrl: string) => {
|
||||
var link = document.createElement("a");
|
||||
link.download = "avatar.png";
|
||||
link.href = dataUrl;
|
||||
link.click(); // Скачать изображение
|
||||
link.click();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const openModal = (): void => {
|
||||
isModalOpen = true;
|
||||
};
|
||||
|
||||
// Закрыть модальное окно
|
||||
const closeModal = (): void => {
|
||||
isModalOpen = false;
|
||||
};
|
||||
|
||||
function cropImage(x: number, y: number, width: number, height: number) {
|
||||
const img = new Image();
|
||||
img.src = incorrectImage;
|
||||
@@ -101,10 +89,8 @@
|
||||
canvas.width = 512;
|
||||
canvas.height = 512;
|
||||
|
||||
// Обрезаем изображение с помощью canvas
|
||||
ctx.drawImage(img, x, y, width, height, 0, 0, 512, 512);
|
||||
|
||||
// Получаем обрезанное изображение в формате base64
|
||||
croppedImage = canvas.toDataURL("image/png");
|
||||
};
|
||||
}
|
||||
@@ -115,7 +101,7 @@
|
||||
};
|
||||
|
||||
function saveToMainImage() {
|
||||
image = croppedImage; // Ссылка на обрезанное изображение
|
||||
image = croppedImage;
|
||||
isModalOpen = false;
|
||||
}
|
||||
</script>
|
||||
@@ -140,16 +126,16 @@
|
||||
|
||||
<button
|
||||
onclick={saveToMainImage}
|
||||
class="px-6 py-3 bg-gradient-to-r from-purple-600 to-blue-600 text-white font-medium rounded-lg hover:opacity-90 transition-opacity disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
class="px-6 py-3 bg-gradient-to-r from-purple-600 to-blue-600 text-white font-medium rounded-lg hover:opacity-90 transition-opacity disabled:opacity-50 disabled:cursor-not-allowed mt-3"
|
||||
>
|
||||
Сохранить
|
||||
Обрезать
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="bg-white rounded-xl shadow-lg p-6">
|
||||
<div
|
||||
class="preview-container relative bg-gray-50 rounded-lg mb-4 overflow-hidden border-2 transition-colors h-[512px]"
|
||||
class="preview-container relative bg-gray-50 mb-4 overflow-hidden border-2 transition-colors h-[512px] w-[512px] rounded-full"
|
||||
ondrop={handleDrop}
|
||||
ondragover={handleDragOver}
|
||||
ondragleave={handleDragLeave}
|
||||
@@ -179,22 +165,34 @@
|
||||
|
||||
<!-- Загруженное изображение -->
|
||||
{#if image}
|
||||
<div id="result" class="relative">
|
||||
<img src={image} class="object-cover" />
|
||||
<!-- Текст -->
|
||||
<div id="result" class="w-full h-full">
|
||||
<svg viewBox="0 0 512 512" class="w-full h-full">
|
||||
<defs>
|
||||
<clipPath id="circle-clip">
|
||||
<circle cx="256" cy="256" r="256" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
<image href={image} width="512" height="512" clip-path="url(#circle-clip)" />
|
||||
<!-- Текст -->
|
||||
{#if text}
|
||||
<div
|
||||
id="text-frame"
|
||||
class="absolute bottom-0 left-0 right-0 py-5 bg-black/70 rounded-t-4xl"
|
||||
>
|
||||
<h1
|
||||
class="text-center text-5xl font-bold text-transparent bg-clip-text bg-cover bg-right leading-17 tracking-tight"
|
||||
style="background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAgAAAADICAYAAACeXFkKAAAACXBIWXMAAA7EAAAOxAGVKw4bAAADs0lEQVR42u3WTU7DMBCA0RkOySU4HScMi4bW/06zYcF7EhKV09SeptKXn1/fR0RExhEREZkR8ft/RFRrERFZrh3Pax7vna2d/+drrbsu6/d098ij20+5p/Faeab2/vvzjs7UXbc9UzO/6Zmae+RgfuU9Fmcq97Q/U3NdDuZ34UzlLG+dafLsrM5UP1d3zrQ+b/nsDJ+r7kzXfivP++fN30q37/1vpbp/c6bjuXL+Zdavu/XXTofr5wcexe67e+Xo3lm/zv7e1edmrPd5DnG+/viCp2vVPt6byWoet2eSq31enEnz3Q6v3c0ki/kuZjb9Xqf7zM3Mms/NzTkiNzO78Kw/93FvJvNn+f2ZrJ/lizNpvtuPAAD+HQEAAAIAABAAAIAAAAAEAAAgAAAAAQAACAAAQAAAAAIAABAAAIAAAAAEAAAgAAAAAQAACAAAQAAAAAIAAAQAACAAAAABAAAIAABAAAAAAgAAEAAAgAAAAAQAACAAAAABAAAIAABAAAAAAgAAEAAAgAAAAAQAAAgAAEAAAAACAAAQAACAAAAABAAAIAAAAAEAAAgAAEAAAAACAAAQAACAAAAABAAAIAAAAAEAAAgAABAAAIAAAAAEAAAgAAAAAQAACAAAQAAAAAIAABAAAIAAAAAEAAAgAAAAAQAACAAAQAAAAAIAABAAACAAAAABAAAIAABAAAAAAgAAEAAAgAAAAAQAACAAAAABAAAIAABAAAAAAgAAEAAAgAAAAAQAACAAAAABAAACAAAQAACAAAAABAAAIAAAAAEAAAgAAEAAAAACAAAQAACAAAAABAAAIAAAAAEAAAgAAEAAAAACAAAEAAAgAAAAAQAACAAAQAAAAAIAABAAAIAAAAAEAAAgAAAAAQAACAAAQAAAAAIAABAAAIAAAAAEAAAIAABAAAAAAgAAEAAAgAAAAAQAACAAAAABAAAIAABAAAAAAgAAEAAAgAAAAAQAACAAAAABAAAIAAAQAACAAAAABAAAIAAAAAEAAAgAAEAAAAACAAAQAACAAAAABAAAIAAAAAEAAAgAAEAAAAACAAAQAAAgAAAAAQAACAAAQAAAAAIAABAAAIAAAAAEAAAgAAAAAQAACAAAQAAAAAIAABAAAIAAAAAEAAAgAAAAAQAAAgAAEAAAgAAAAAQAACAAAAABAAAIAABAAAAAAgAAEAAAgAAAAAQAACAAAAABAAAIAABAAAAAAgAABAAAIAAAAAEAAAgAAEAAAAACAAAQAACAAAAA/tYPVhsMy8Jj9qoAAAAASUVORK5CYII=');"
|
||||
>
|
||||
{text}
|
||||
</h1>
|
||||
</div>
|
||||
<path
|
||||
id="text-path"
|
||||
d="M 26,256 a 230,230 0 1,0 460,0 a 230,230 0 1,1 -460,0"
|
||||
fill="none"
|
||||
/>
|
||||
<linearGradient id="text-gradient" x1="0%" y1="0%" x2="100%" y2="0%">
|
||||
<stop offset="0%" style="stop-color:rgb(124, 58, 237);stop-opacity:1" />
|
||||
<stop offset="100%" style="stop-color:rgb(37, 99, 235);stop-opacity:1" />
|
||||
</linearGradient>
|
||||
|
||||
<text class="circle-text-bg">
|
||||
<textPath href="#text-path" startOffset="25%" text-anchor="middle">{text}</textPath>
|
||||
</text>
|
||||
<text class="circle-text">
|
||||
<textPath href="#text-path" startOffset="25%" text-anchor="middle">{text}</textPath>
|
||||
</text>
|
||||
{/if}
|
||||
</svg>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
@@ -208,12 +206,10 @@
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Сообщение об ошибке -->
|
||||
{#if error}
|
||||
<p class="text-red-500 text-sm mb-4 text-center">{error}</p>
|
||||
{/if}
|
||||
|
||||
<!-- Поле ввода текста -->
|
||||
<div class="flex flex-col sm:flex-row gap-3 mb-4">
|
||||
<input
|
||||
type="text"
|
||||
@@ -235,3 +231,27 @@
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.circle-text-bg {
|
||||
fill: none;
|
||||
stroke: rgb(0, 0, 0, 0.7);
|
||||
stroke-width: 5px;
|
||||
stroke-linejoin:round;
|
||||
stroke-linecap:round;
|
||||
paint-order: stroke;
|
||||
font-size: 2.5rem;
|
||||
font-weight: 700;
|
||||
letter-spacing: 3px;
|
||||
}
|
||||
|
||||
.circle-text {
|
||||
fill: url(#text-gradient);
|
||||
stroke: #000;
|
||||
stroke-width: 1.5px;
|
||||
paint-order: stroke;
|
||||
letter-spacing: 3px;
|
||||
font-size: 2.5rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user