Testing image copying
This commit is contained in:
parent
d80c99c6c0
commit
f8d1579cb2
|
|
@ -42,6 +42,9 @@ const dragStartTY = ref(0);
|
||||||
|
|
||||||
const MAX_SCALE = 8;
|
const MAX_SCALE = 8;
|
||||||
|
|
||||||
|
// Image context menu state
|
||||||
|
const contextMenu = ref({ visible: false, x: 0, y: 0 });
|
||||||
|
|
||||||
const imageCursorClass = computed(() => {
|
const imageCursorClass = computed(() => {
|
||||||
if (isDragging.value && hasMoved.value) return "cursor-grabbing";
|
if (isDragging.value && hasMoved.value) return "cursor-grabbing";
|
||||||
if (imageScale.value > fitScale.value + 0.01) return "cursor-grab";
|
if (imageScale.value > fitScale.value + 0.01) return "cursor-grab";
|
||||||
|
|
@ -56,7 +59,7 @@ const initImageView = () => {
|
||||||
const cH = container.clientHeight;
|
const cH = container.clientHeight;
|
||||||
const iW = img.naturalWidth || cW;
|
const iW = img.naturalWidth || cW;
|
||||||
const iH = img.naturalHeight || cH;
|
const iH = img.naturalHeight || cH;
|
||||||
const fs = Math.min(cW / iW, cH / iH);
|
const fs = Math.min(1, cW / iW, cH / iH);
|
||||||
fitScale.value = fs;
|
fitScale.value = fs;
|
||||||
imageScale.value = fs;
|
imageScale.value = fs;
|
||||||
translateX.value = (cW - iW * fs) / 2;
|
translateX.value = (cW - iW * fs) / 2;
|
||||||
|
|
@ -156,9 +159,42 @@ const handleMouseDown = (e) => {
|
||||||
window.addEventListener("mouseup", onMouseUp);
|
window.addEventListener("mouseup", onMouseUp);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const closeContextMenu = () => {
|
||||||
|
contextMenu.value.visible = false;
|
||||||
|
window.removeEventListener("click", closeContextMenu);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleContextMenu = (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
contextMenu.value = { visible: true, x: e.clientX, y: e.clientY };
|
||||||
|
setTimeout(() => window.addEventListener("click", closeContextMenu), 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
const copyImageToClipboard = async () => {
|
||||||
|
closeContextMenu();
|
||||||
|
const img = imageRef.value;
|
||||||
|
if (!img) return;
|
||||||
|
const displayW = Math.round(img.naturalWidth * fitScale.value);
|
||||||
|
const displayH = Math.round(img.naturalHeight * fitScale.value);
|
||||||
|
const canvas = document.createElement("canvas");
|
||||||
|
canvas.width = displayW;
|
||||||
|
canvas.height = displayH;
|
||||||
|
const ctx = canvas.getContext("2d");
|
||||||
|
ctx.drawImage(img, 0, 0, displayW, displayH);
|
||||||
|
canvas.toBlob(async (blob) => {
|
||||||
|
if (!blob) return;
|
||||||
|
try {
|
||||||
|
await navigator.clipboard.write([new ClipboardItem({ "image/png": blob })]);
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Copy failed", err);
|
||||||
|
}
|
||||||
|
}, "image/png");
|
||||||
|
};
|
||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
window.removeEventListener("mousemove", onMouseMove);
|
window.removeEventListener("mousemove", onMouseMove);
|
||||||
window.removeEventListener("mouseup", onMouseUp);
|
window.removeEventListener("mouseup", onMouseUp);
|
||||||
|
window.removeEventListener("click", closeContextMenu);
|
||||||
});
|
});
|
||||||
|
|
||||||
const fileExtension = computed(() => {
|
const fileExtension = computed(() => {
|
||||||
|
|
@ -337,6 +373,7 @@ watch(
|
||||||
transition: isDragging ? 'none' : 'transform 0.12s ease',
|
transition: isDragging ? 'none' : 'transform 0.12s ease',
|
||||||
}"
|
}"
|
||||||
@load="handleImageLoad"
|
@load="handleImageLoad"
|
||||||
|
@contextmenu.prevent="handleContextMenu"
|
||||||
/>
|
/>
|
||||||
<!-- Zoom level badge -->
|
<!-- Zoom level badge -->
|
||||||
<div
|
<div
|
||||||
|
|
@ -362,6 +399,21 @@ watch(
|
||||||
>
|
>
|
||||||
Kolesce za povečavo / pomanjšavo · Povleči za premik
|
Kolesce za povečavo / pomanjšavo · Povleči za premik
|
||||||
</div>
|
</div>
|
||||||
|
<!-- Custom context menu -->
|
||||||
|
<Teleport to="body">
|
||||||
|
<div
|
||||||
|
v-if="contextMenu.visible"
|
||||||
|
class="fixed z-[9999] min-w-36 rounded-md border bg-popover shadow-md py-1 text-sm text-popover-foreground"
|
||||||
|
:style="{ top: contextMenu.y + 'px', left: contextMenu.x + 'px' }"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
class="w-full text-left px-3 py-1.5 hover:bg-accent hover:text-accent-foreground rounded-sm"
|
||||||
|
@click.stop="copyImageToClipboard"
|
||||||
|
>
|
||||||
|
Kopiraj sliko
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</Teleport>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user