add new version
This commit is contained in:
@@ -9,7 +9,7 @@
|
|||||||
let minZoom = 1;
|
let minZoom = 1;
|
||||||
let restrictPosition = true;
|
let restrictPosition = true;
|
||||||
let showGrid = false;
|
let showGrid = false;
|
||||||
let croppedImage = null; // хранение вырезанного изображения
|
let croppedImage = null;
|
||||||
|
|
||||||
let image: string;
|
let image: string;
|
||||||
let incorrectImage: string;
|
let incorrectImage: string;
|
||||||
@@ -18,7 +18,6 @@
|
|||||||
let isDragging: boolean = false;
|
let isDragging: boolean = false;
|
||||||
let isModalOpen: boolean = false;
|
let isModalOpen: boolean = false;
|
||||||
|
|
||||||
// Проверка и загрузка изображения
|
|
||||||
async function validateAndLoadImage(file: File): Promise<void> {
|
async function validateAndLoadImage(file: File): Promise<void> {
|
||||||
error = "";
|
error = "";
|
||||||
const img = new Image();
|
const img = new Image();
|
||||||
@@ -38,11 +37,10 @@
|
|||||||
reader.readAsDataURL(file);
|
reader.readAsDataURL(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Обработка Drag and Drop
|
|
||||||
function handleDrop(e: DragEvent): void {
|
function handleDrop(e: DragEvent): void {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
isDragging = false;
|
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/")) {
|
if (file && file.type.startsWith("image/")) {
|
||||||
validateAndLoadImage(file);
|
validateAndLoadImage(file);
|
||||||
}
|
}
|
||||||
@@ -62,35 +60,25 @@
|
|||||||
|
|
||||||
let node = document.getElementById("result");
|
let node = document.getElementById("result");
|
||||||
|
|
||||||
// Убираем лишние стили
|
|
||||||
if (node) {
|
if (node) {
|
||||||
domtoimage
|
domtoimage
|
||||||
.toPng(node, {
|
.toPng(node, {
|
||||||
style: {
|
style: {
|
||||||
border: "none", // Убираем рамки
|
border: "none",
|
||||||
padding: "0", // Убираем отступы
|
padding: "0",
|
||||||
margin: "0", // Убираем маргины
|
margin: "0",
|
||||||
outline: "none", // Убираем outline
|
outline: "none",
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.then((dataUrl: string) => {
|
.then((dataUrl: string) => {
|
||||||
var link = document.createElement("a");
|
var link = document.createElement("a");
|
||||||
link.download = "avatar.png";
|
link.download = "avatar.png";
|
||||||
link.href = dataUrl;
|
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) {
|
function cropImage(x: number, y: number, width: number, height: number) {
|
||||||
const img = new Image();
|
const img = new Image();
|
||||||
img.src = incorrectImage;
|
img.src = incorrectImage;
|
||||||
@@ -101,10 +89,8 @@
|
|||||||
canvas.width = 512;
|
canvas.width = 512;
|
||||||
canvas.height = 512;
|
canvas.height = 512;
|
||||||
|
|
||||||
// Обрезаем изображение с помощью canvas
|
|
||||||
ctx.drawImage(img, x, y, width, height, 0, 0, 512, 512);
|
ctx.drawImage(img, x, y, width, height, 0, 0, 512, 512);
|
||||||
|
|
||||||
// Получаем обрезанное изображение в формате base64
|
|
||||||
croppedImage = canvas.toDataURL("image/png");
|
croppedImage = canvas.toDataURL("image/png");
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -115,7 +101,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
function saveToMainImage() {
|
function saveToMainImage() {
|
||||||
image = croppedImage; // Ссылка на обрезанное изображение
|
image = croppedImage;
|
||||||
isModalOpen = false;
|
isModalOpen = false;
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@@ -140,16 +126,16 @@
|
|||||||
|
|
||||||
<button
|
<button
|
||||||
onclick={saveToMainImage}
|
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>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<div class="bg-white rounded-xl shadow-lg p-6">
|
<div class="bg-white rounded-xl shadow-lg p-6">
|
||||||
<div
|
<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}
|
ondrop={handleDrop}
|
||||||
ondragover={handleDragOver}
|
ondragover={handleDragOver}
|
||||||
ondragleave={handleDragLeave}
|
ondragleave={handleDragLeave}
|
||||||
@@ -179,22 +165,34 @@
|
|||||||
|
|
||||||
<!-- Загруженное изображение -->
|
<!-- Загруженное изображение -->
|
||||||
{#if image}
|
{#if image}
|
||||||
<div id="result" class="relative">
|
<div id="result" class="w-full h-full">
|
||||||
<img src={image} class="object-cover" />
|
<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}
|
{#if text}
|
||||||
<div
|
<path
|
||||||
id="text-frame"
|
id="text-path"
|
||||||
class="absolute bottom-0 left-0 right-0 py-5 bg-black/70 rounded-t-4xl"
|
d="M 26,256 a 230,230 0 1,0 460,0 a 230,230 0 1,1 -460,0"
|
||||||
>
|
fill="none"
|
||||||
<h1
|
/>
|
||||||
class="text-center text-5xl font-bold text-transparent bg-clip-text bg-cover bg-right leading-17 tracking-tight"
|
<linearGradient id="text-gradient" x1="0%" y1="0%" x2="100%" y2="0%">
|
||||||
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=');"
|
<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" />
|
||||||
{text}
|
</linearGradient>
|
||||||
</h1>
|
|
||||||
</div>
|
<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}
|
{/if}
|
||||||
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
@@ -208,12 +206,10 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Сообщение об ошибке -->
|
|
||||||
{#if error}
|
{#if error}
|
||||||
<p class="text-red-500 text-sm mb-4 text-center">{error}</p>
|
<p class="text-red-500 text-sm mb-4 text-center">{error}</p>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<!-- Поле ввода текста -->
|
|
||||||
<div class="flex flex-col sm:flex-row gap-3 mb-4">
|
<div class="flex flex-col sm:flex-row gap-3 mb-4">
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
@@ -235,3 +231,27 @@
|
|||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</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