|
@@ -1,44 +1,43 @@
|
|
<script lang="ts">
|
|
<script lang="ts">
|
|
|
|
+ import { mdiContrastCircle } from '@mdi/js'; // Contrast
|
|
|
|
+ import { mdiBrightness6 } from '@mdi/js'; // Brightness
|
|
|
|
+ import { mdiInvertColors } from '@mdi/js'; // Invert
|
|
|
|
+ import { mdiBlur } from '@mdi/js'; // Blur
|
|
|
|
+ import { mdiCircleHalfFull } from '@mdi/js'; // Vignette
|
|
|
|
+ import { mdiDotsCircle } from '@mdi/js'; // Tilt-shift
|
|
|
|
+ import { mdiSelectInverse } from '@mdi/js'; // Selective
|
|
|
|
+ import { mdiPillar } from '@mdi/js'; // Pillarbox
|
|
|
|
+
|
|
import { onMount, SvelteComponent } from 'svelte';
|
|
import { onMount, SvelteComponent } from 'svelte';
|
|
import { api, AssetResponseDto } from '@api';
|
|
import { api, AssetResponseDto } from '@api';
|
|
import { handleError } from '$lib/utils/handle-error';
|
|
import { handleError } from '$lib/utils/handle-error';
|
|
|
|
|
|
import Icon from '$lib/components/elements/icon.svelte';
|
|
import Icon from '$lib/components/elements/icon.svelte';
|
|
|
|
|
|
- import { mdiAutoFix } from '@mdi/js';
|
|
|
|
- import { mdiImageFilterHdr } from '@mdi/js';
|
|
|
|
- import { mdiWeatherSunny } from '@mdi/js';
|
|
|
|
- import { mdiWeatherCloudy } from '@mdi/js';
|
|
|
|
- import { mdiCropRotate } from '@mdi/js';
|
|
|
|
- import { mdiTune } from '@mdi/js';
|
|
|
|
- import { mdiImageAutoAdjust } from '@mdi/js';
|
|
|
|
- import { mdiFullscreen } from '@mdi/js';
|
|
|
|
- import { mdiRelativeScale } from '@mdi/js';
|
|
|
|
- import { mdiRectangleOutline } from '@mdi/js';
|
|
|
|
- import { mdiSquareOutline } from '@mdi/js';
|
|
|
|
-
|
|
|
|
- import { mdiClose } from '@mdi/js';
|
|
|
|
- import { mdiDotsVertical } from '@mdi/js';
|
|
|
|
- import { mdiFlipHorizontal } from '@mdi/js';
|
|
|
|
- import { mdiFlipVertical } from '@mdi/js';
|
|
|
|
- import { mdiFormatRotate90 } from '@mdi/js';
|
|
|
|
- import { mdiTriangleSmallUp } from '@mdi/js';
|
|
|
|
|
|
+ import { mdiAutoFix } from '@mdi/js'; // Auto
|
|
|
|
+ import { mdiImageFilterHdr } from '@mdi/js'; // HDR
|
|
|
|
+ import { mdiWeatherSunny } from '@mdi/js'; // Exposure
|
|
|
|
+ import { mdiWeatherCloudy } from '@mdi/js'; // Contrast
|
|
|
|
+ import { mdiCropRotate } from '@mdi/js'; // Rotate
|
|
|
|
+ import { mdiTune } from '@mdi/js'; // Adjust
|
|
|
|
+ import { mdiImageAutoAdjust } from '@mdi/js'; // Auto Adjust
|
|
|
|
+ import { mdiFullscreen } from '@mdi/js'; // Fullscreen
|
|
|
|
+ import { mdiRelativeScale } from '@mdi/js'; // Ratio
|
|
|
|
+ import { mdiRectangleOutline } from '@mdi/js'; // Rectangle
|
|
|
|
+ import { mdiSquareOutline } from '@mdi/js'; // Square
|
|
|
|
+
|
|
|
|
+ import { mdiClose } from '@mdi/js'; // Close
|
|
|
|
+ import { mdiDotsVertical } from '@mdi/js'; // More
|
|
|
|
+ import { mdiFlipHorizontal } from '@mdi/js'; // Flip horizontal
|
|
|
|
+ import { mdiFlipVertical } from '@mdi/js'; // Flip vertical
|
|
|
|
+ import { mdiFormatRotate90 } from '@mdi/js'; // Rotate
|
|
|
|
+ import { mdiTriangleSmallUp } from '@mdi/js'; // Triangle
|
|
|
|
|
|
import SuggestionsButton from './suggestions-button.svelte';
|
|
import SuggestionsButton from './suggestions-button.svelte';
|
|
import AspectRatioButton from './aspect-ratio-button.svelte';
|
|
import AspectRatioButton from './aspect-ratio-button.svelte';
|
|
import AdjustElement from './adjust-element.svelte';
|
|
import AdjustElement from './adjust-element.svelte';
|
|
import FilterCard from './filter-card.svelte';
|
|
import FilterCard from './filter-card.svelte';
|
|
|
|
|
|
- //Filter icons
|
|
|
|
- import { mdiContrastCircle } from '@mdi/js';
|
|
|
|
- import { mdiBrightness6 } from '@mdi/js';
|
|
|
|
- import { mdiInvertColors } from '@mdi/js';
|
|
|
|
- import { mdiBlur } from '@mdi/js';
|
|
|
|
- import { mdiCircleHalfFull } from '@mdi/js';
|
|
|
|
- import { mdiDotsCircle } from '@mdi/js';
|
|
|
|
- import { mdiSelectInverse } from '@mdi/js';
|
|
|
|
- import { mdiPillar } from '@mdi/js';
|
|
|
|
-
|
|
|
|
import Render from './render.svelte';
|
|
import Render from './render.svelte';
|
|
import { presets as presetsObject } from './filter.js';
|
|
import { presets as presetsObject } from './filter.js';
|
|
|
|
|
|
@@ -57,6 +56,7 @@
|
|
};
|
|
};
|
|
|
|
|
|
import { createEventDispatcher } from 'svelte';
|
|
import { createEventDispatcher } from 'svelte';
|
|
|
|
+ import LoadingSpinner from '$lib/components/shared-components/loading-spinner.svelte';
|
|
|
|
|
|
const dispatch = createEventDispatcher();
|
|
const dispatch = createEventDispatcher();
|
|
|
|
|
|
@@ -81,6 +81,7 @@
|
|
let imageElement: HTMLImageElement;
|
|
let imageElement: HTMLImageElement;
|
|
|
|
|
|
let originalImage: HTMLImageElement;
|
|
let originalImage: HTMLImageElement;
|
|
|
|
+ let isLoaded = false;
|
|
|
|
|
|
let imageWrapper: HTMLDivElement;
|
|
let imageWrapper: HTMLDivElement;
|
|
let cropElement: HTMLDivElement;
|
|
let cropElement: HTMLDivElement;
|
|
@@ -160,23 +161,24 @@
|
|
|
|
|
|
const applyFilter = () => {
|
|
const applyFilter = () => {
|
|
if (!isFilter(presets[currentFilter] as Preset)) {
|
|
if (!isFilter(presets[currentFilter] as Preset)) {
|
|
- console.log(currentFilter);
|
|
|
|
- console.log(presets[currentFilter]);
|
|
|
|
- console.log(filter);
|
|
|
|
|
|
+ // console.log(currentFilter);
|
|
|
|
+ // console.log(presets[currentFilter]);
|
|
|
|
+ // console.log(filter);
|
|
currentFilter = 'custom';
|
|
currentFilter = 'custom';
|
|
}
|
|
}
|
|
|
|
|
|
- console.log('apply filter');
|
|
|
|
- console.log(filter);
|
|
|
|
- (imageElement.style.filter = `blur(${filter.blur * 10}px) brightness(${filter.brightness}) contrast(${
|
|
|
|
|
|
+ // console.log('apply filter');
|
|
|
|
+ // console.log(filter);
|
|
|
|
+ imageElement.style.filter = `blur(${filter.blur * 10}px) brightness(${filter.brightness}) contrast(${
|
|
filter.contrast
|
|
filter.contrast
|
|
}) grayscale(${filter.grayscale}) hue-rotate(${(filter.hueRotate - 1) * 180}deg) invert(${filter.invert}) opacity(${
|
|
}) grayscale(${filter.grayscale}) hue-rotate(${(filter.hueRotate - 1) * 180}deg) invert(${filter.invert}) opacity(${
|
|
filter.opacity
|
|
filter.opacity
|
|
- }) saturate(${filter.saturation}) sepia(${filter.sepia})`),
|
|
|
|
- console.log('applied filter');
|
|
|
|
|
|
+ }) saturate(${filter.saturation}) sepia(${filter.sepia})`;
|
|
|
|
+ //console.log('applied filter');
|
|
};
|
|
};
|
|
|
|
|
|
onMount(async () => {
|
|
onMount(async () => {
|
|
|
|
+ isLoaded = false;
|
|
try {
|
|
try {
|
|
await loadThumbData();
|
|
await loadThumbData();
|
|
await loadAssetData();
|
|
await loadAssetData();
|
|
@@ -186,16 +188,13 @@
|
|
}
|
|
}
|
|
imageElement.src = thumbData || assetData;
|
|
imageElement.src = thumbData || assetData;
|
|
imageElement.onload = () => {
|
|
imageElement.onload = () => {
|
|
- console.log('imageElement.onload');
|
|
|
|
- initAngleSlider();
|
|
|
|
- initAssetDrag();
|
|
|
|
- initZoom();
|
|
|
|
|
|
+ isLoaded = true;
|
|
setAspectRatio('original');
|
|
setAspectRatio('original');
|
|
};
|
|
};
|
|
});
|
|
});
|
|
|
|
|
|
const initZoom = () => {
|
|
const initZoom = () => {
|
|
- document.addEventListener('wheel', function (e) {
|
|
|
|
|
|
+ document.onwheel = (e: WheelEvent) => {
|
|
if (e.deltaY > 0) {
|
|
if (e.deltaY > 0) {
|
|
if (currentZoom <= 5) {
|
|
if (currentZoom <= 5) {
|
|
currentZoom += zoomSpeed;
|
|
currentZoom += zoomSpeed;
|
|
@@ -206,12 +205,12 @@
|
|
}
|
|
}
|
|
}
|
|
}
|
|
setImageWrapperTransform();
|
|
setImageWrapperTransform();
|
|
- });
|
|
|
|
|
|
+ };
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+ // Sets the filter to the preset passed in by the event
|
|
const setPreset = (event: CustomEvent<string>) => {
|
|
const setPreset = (event: CustomEvent<string>) => {
|
|
const preset = event.detail;
|
|
const preset = event.detail;
|
|
- console.log(presets);
|
|
|
|
filter.blur = presets[preset].blur;
|
|
filter.blur = presets[preset].blur;
|
|
filter.brightness = presets[preset].brightness;
|
|
filter.brightness = presets[preset].brightness;
|
|
filter.contrast = presets[preset].contrast;
|
|
filter.contrast = presets[preset].contrast;
|
|
@@ -221,14 +220,12 @@
|
|
filter.opacity = presets[preset].opacity;
|
|
filter.opacity = presets[preset].opacity;
|
|
filter.saturation = presets[preset].saturation;
|
|
filter.saturation = presets[preset].saturation;
|
|
filter.sepia = presets[preset].sepia;
|
|
filter.sepia = presets[preset].sepia;
|
|
-
|
|
|
|
- console.log(presets);
|
|
|
|
- console.log(preset);
|
|
|
|
applyFilter();
|
|
applyFilter();
|
|
currentFilter = preset;
|
|
currentFilter = preset;
|
|
};
|
|
};
|
|
|
|
|
|
const loadAssetData = async () => {
|
|
const loadAssetData = async () => {
|
|
|
|
+ // Load original image
|
|
try {
|
|
try {
|
|
const { data } = await api.assetApi.serveFile(
|
|
const { data } = await api.assetApi.serveFile(
|
|
{ id: asset.id, isThumb: false, isWeb: false, key: publicSharedKey },
|
|
{ id: asset.id, isThumb: false, isWeb: false, key: publicSharedKey },
|
|
@@ -277,6 +274,10 @@
|
|
activeButton = button;
|
|
activeButton = button;
|
|
const cropWrapperParent = cropElementWrapper.parentElement;
|
|
const cropWrapperParent = cropElementWrapper.parentElement;
|
|
|
|
|
|
|
|
+ removeAngleSlider();
|
|
|
|
+ removeAssetDrag();
|
|
|
|
+ removeZoom();
|
|
|
|
+
|
|
//TODO: better solution
|
|
//TODO: better solution
|
|
if (!cropWrapperParent) {
|
|
if (!cropWrapperParent) {
|
|
return;
|
|
return;
|
|
@@ -288,6 +289,9 @@
|
|
setAspectRatio(currentAspectRatio);
|
|
setAspectRatio(currentAspectRatio);
|
|
break;
|
|
break;
|
|
case 'crop':
|
|
case 'crop':
|
|
|
|
+ initAngleSlider();
|
|
|
|
+ initAssetDrag();
|
|
|
|
+ initZoom();
|
|
if (!cropWrapperParent.classList.contains('p-24')) {
|
|
if (!cropWrapperParent.classList.contains('p-24')) {
|
|
cropWrapperParent.classList.add('p-24');
|
|
cropWrapperParent.classList.add('p-24');
|
|
cropWrapperParent.classList.add('pb-52');
|
|
cropWrapperParent.classList.add('pb-52');
|
|
@@ -318,13 +322,13 @@
|
|
aspectRatio = strings[1] + '_' + strings[0];
|
|
aspectRatio = strings[1] + '_' + strings[0];
|
|
}
|
|
}
|
|
if (currentAngleOffset % 180 == 0) {
|
|
if (currentAngleOffset % 180 == 0) {
|
|
- console.log('currentAngleOffset', currentAngleOffset);
|
|
|
|
- console.log('isRotate', isRotate);
|
|
|
|
|
|
+ //console.log('currentAngleOffset', currentAngleOffset);
|
|
|
|
+ //console.log('isRotate', isRotate);
|
|
isRotate = false;
|
|
isRotate = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- console.log('isRotate', isRotate);
|
|
|
|
|
|
+ //console.log('isRotate', isRotate);
|
|
|
|
|
|
currentAspectRatio = aspectRatio;
|
|
currentAspectRatio = aspectRatio;
|
|
|
|
|
|
@@ -374,8 +378,8 @@
|
|
cropElement.style.aspectRatio = '' + aspectRatioNum;
|
|
cropElement.style.aspectRatio = '' + aspectRatioNum;
|
|
const cropElementWrapperAspectRatio = cropElementWrapper.offsetWidth / cropElementWrapper.offsetHeight;
|
|
const cropElementWrapperAspectRatio = cropElementWrapper.offsetWidth / cropElementWrapper.offsetHeight;
|
|
|
|
|
|
- console.log('aspectRatioNum', aspectRatioNum);
|
|
|
|
- console.log('cropElementWrapperAspectRatio', cropElementWrapperAspectRatio);
|
|
|
|
|
|
+ //console.log('aspectRatioNum', aspectRatioNum);
|
|
|
|
+ //console.log('cropElementWrapperAspectRatio', cropElementWrapperAspectRatio);
|
|
|
|
|
|
if (aspectRatioNum >= 1 && cropElementWrapperAspectRatio >= 1 && aspectRatioNum < cropElementWrapperAspectRatio) {
|
|
if (aspectRatioNum >= 1 && cropElementWrapperAspectRatio >= 1 && aspectRatioNum < cropElementWrapperAspectRatio) {
|
|
cropElement.style.width = 'auto';
|
|
cropElement.style.width = 'auto';
|
|
@@ -408,8 +412,8 @@
|
|
//cropElement.style.maxWidth = '100%';
|
|
//cropElement.style.maxWidth = '100%';
|
|
}
|
|
}
|
|
|
|
|
|
- console.log('cropElement.offsetWidth', cropElement.offsetWidth);
|
|
|
|
- console.log('cropElement.offsetHeight', cropElement.offsetHeight);
|
|
|
|
|
|
+ //console.log('cropElement.offsetWidth', cropElement.offsetWidth);
|
|
|
|
+ //console.log('cropElement.offsetHeight', cropElement.offsetHeight);
|
|
|
|
|
|
currentTranslate = { x: 0, y: 0 };
|
|
currentTranslate = { x: 0, y: 0 };
|
|
calcImageElement(currentAngle);
|
|
calcImageElement(currentAngle);
|
|
@@ -443,7 +447,7 @@
|
|
a = Math.min(a, (125 / 49) * 45);
|
|
a = Math.min(a, (125 / 49) * 45);
|
|
}
|
|
}
|
|
|
|
|
|
- console.log('a', a);
|
|
|
|
|
|
+ //console.log('a', a);
|
|
|
|
|
|
let angle = Math.round((a / 125) * 49);
|
|
let angle = Math.round((a / 125) * 49);
|
|
angle = angle * -1;
|
|
angle = angle * -1;
|
|
@@ -459,7 +463,7 @@
|
|
// set the element's new position:
|
|
// set the element's new position:
|
|
let a = angleSlider.offsetLeft - pos1;
|
|
let a = angleSlider.offsetLeft - pos1;
|
|
|
|
|
|
- console.log('a', a);
|
|
|
|
|
|
+ //console.log('a', a);
|
|
if (a < 0) {
|
|
if (a < 0) {
|
|
a = Math.max(a, (-125 / 49) * 45);
|
|
a = Math.max(a, (-125 / 49) * 45);
|
|
} else {
|
|
} else {
|
|
@@ -485,7 +489,7 @@
|
|
|
|
|
|
const dragTouchStart = (e: TouchEvent) => {
|
|
const dragTouchStart = (e: TouchEvent) => {
|
|
e.preventDefault();
|
|
e.preventDefault();
|
|
- console.log('dragTouchStart');
|
|
|
|
|
|
+ //console.log('dragTouchStart');
|
|
// get the mouse cursor position at startup:
|
|
// get the mouse cursor position at startup:
|
|
pos2 = e.touches[0].clientX;
|
|
pos2 = e.touches[0].clientX;
|
|
document.ontouchend = closeDragElement;
|
|
document.ontouchend = closeDragElement;
|
|
@@ -556,17 +560,17 @@
|
|
|
|
|
|
maxY = maxY / currentZoom;
|
|
maxY = maxY / currentZoom;
|
|
|
|
|
|
- console.log('currentZoom', currentZoom);
|
|
|
|
- console.log('offsetHeight', imageWrapper.offsetHeight);
|
|
|
|
- console.log('realHight', imageWrapper.offsetHeight * currentZoom);
|
|
|
|
- console.log('maxY', maxY);
|
|
|
|
|
|
+ // console.log('currentZoom', currentZoom);
|
|
|
|
+ // console.log('offsetHeight', imageWrapper.offsetHeight);
|
|
|
|
+ // console.log('realHight', imageWrapper.offsetHeight * currentZoom);
|
|
|
|
+ // console.log('maxY', maxY);
|
|
|
|
|
|
// Calc max x translation
|
|
// Calc max x translation
|
|
const h3 = Math.sin((Math.abs(currentAngle) * Math.PI) / 180) * h1;
|
|
const h3 = Math.sin((Math.abs(currentAngle) * Math.PI) / 180) * h1;
|
|
const h4 = Math.cos((Math.abs(currentAngle) * Math.PI) / 180) * w1;
|
|
const h4 = Math.cos((Math.abs(currentAngle) * Math.PI) / 180) * w1;
|
|
let maxX = (imageWrapper.offsetWidth * currentZoom - h3 - h4) / 2;
|
|
let maxX = (imageWrapper.offsetWidth * currentZoom - h3 - h4) / 2;
|
|
maxX = maxX / currentZoom;
|
|
maxX = maxX / currentZoom;
|
|
- console.log('maxX', maxX);
|
|
|
|
|
|
+ //console.log('maxX', maxX);
|
|
|
|
|
|
if (currentTranslate.x - pos1 > maxX) {
|
|
if (currentTranslate.x - pos1 > maxX) {
|
|
x = maxX;
|
|
x = maxX;
|
|
@@ -584,8 +588,8 @@
|
|
y = currentTranslate.y - pos2;
|
|
y = currentTranslate.y - pos2;
|
|
}
|
|
}
|
|
|
|
|
|
- console.log('y:', Math.round(y));
|
|
|
|
- console.log('x:', Math.round(x));
|
|
|
|
|
|
+ // console.log('y:', Math.round(y));
|
|
|
|
+ // console.log('x:', Math.round(x));
|
|
|
|
|
|
// Decide which direction to translate
|
|
// Decide which direction to translate
|
|
// if (currentTranslateDirection === 'y') {
|
|
// if (currentTranslateDirection === 'y') {
|
|
@@ -608,14 +612,14 @@
|
|
x: x,
|
|
x: x,
|
|
y: y,
|
|
y: y,
|
|
};
|
|
};
|
|
- console.log('currentTranslateBefore', currentTranslate);
|
|
|
|
|
|
+ // console.log('currentTranslateBefore', currentTranslate);
|
|
|
|
|
|
- console.log('currentTranslate', currentTranslate);
|
|
|
|
|
|
+ // console.log('currentTranslate', currentTranslate);
|
|
setImageWrapperTransform();
|
|
setImageWrapperTransform();
|
|
};
|
|
};
|
|
|
|
|
|
const dragMouseDown = (e: MouseEvent) => {
|
|
const dragMouseDown = (e: MouseEvent) => {
|
|
- console.log('dragMouseDown');
|
|
|
|
|
|
+ //console.log('dragMouseDown');
|
|
|
|
|
|
e.preventDefault();
|
|
e.preventDefault();
|
|
// get the mouse cursor position at startup:
|
|
// get the mouse cursor position at startup:
|
|
@@ -628,6 +632,25 @@
|
|
assetDragHandle.onmousedown = dragMouseDown;
|
|
assetDragHandle.onmousedown = dragMouseDown;
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+ const removeAssetDrag = () => {
|
|
|
|
+ assetDragHandle.onmousedown = null;
|
|
|
|
+ document.onmouseup = null;
|
|
|
|
+ document.onmousemove = null;
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ const removeAngleSlider = () => {
|
|
|
|
+ angleSliderHandle.onmousedown = null;
|
|
|
|
+ document.onmouseup = null;
|
|
|
|
+ document.onmousemove = null;
|
|
|
|
+ document.ontouchmove = null;
|
|
|
|
+ document.ontouchend = null;
|
|
|
|
+ angleSliderHandle.ontouchstart = null;
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ const removeZoom = () => {
|
|
|
|
+ document.onwheel = null;
|
|
|
|
+ };
|
|
|
|
+
|
|
const calcImageElement = (angle: number) => {
|
|
const calcImageElement = (angle: number) => {
|
|
// Get image wrapper width and height
|
|
// Get image wrapper width and height
|
|
|
|
|
|
@@ -644,8 +667,8 @@
|
|
const cropElementWidth = cropElement.offsetWidth;
|
|
const cropElementWidth = cropElement.offsetWidth;
|
|
const cropElementHeight = cropElement.offsetHeight;
|
|
const cropElementHeight = cropElement.offsetHeight;
|
|
|
|
|
|
- console.log('cropElementWidth', cropElementWidth);
|
|
|
|
- console.log('cropElementHeight', cropElementHeight);
|
|
|
|
|
|
+ // console.log('cropElementWidth', cropElementWidth);
|
|
|
|
+ // console.log('cropElementHeight', cropElementHeight);
|
|
|
|
|
|
const x1 = Math.cos((Math.abs(angle) * Math.PI) / 180) * cropElementWidth;
|
|
const x1 = Math.cos((Math.abs(angle) * Math.PI) / 180) * cropElementWidth;
|
|
const x2 = Math.cos(((90 - Math.abs(angle)) * Math.PI) / 180) * cropElementHeight;
|
|
const x2 = Math.cos(((90 - Math.abs(angle)) * Math.PI) / 180) * cropElementHeight;
|
|
@@ -656,29 +679,29 @@
|
|
if ((x1 + x2) / (y1 + y2) > originalAspect) {
|
|
if ((x1 + x2) / (y1 + y2) > originalAspect) {
|
|
newWidth = `${x1 + x2}px`;
|
|
newWidth = `${x1 + x2}px`;
|
|
newHeight = `${(x1 + x2) / originalAspect}px`;
|
|
newHeight = `${(x1 + x2) / originalAspect}px`;
|
|
- console.log('Translation in Y possible');
|
|
|
|
- console.log('case4');
|
|
|
|
|
|
+ // console.log('Translation in Y possible');
|
|
|
|
+ // console.log('case4');
|
|
currentTranslateDirection = 'y';
|
|
currentTranslateDirection = 'y';
|
|
} else if ((x1 + x2) / (y1 + y2) < originalAspect) {
|
|
} else if ((x1 + x2) / (y1 + y2) < originalAspect) {
|
|
newHeight = `${y1 + y2}px`;
|
|
newHeight = `${y1 + y2}px`;
|
|
newWidth = `${(y1 + y2) / (1 / originalAspect)}px`;
|
|
newWidth = `${(y1 + y2) / (1 / originalAspect)}px`;
|
|
- console.log('Translation in X possible');
|
|
|
|
|
|
+ // console.log('Translation in X possible');
|
|
currentTranslateDirection = 'x';
|
|
currentTranslateDirection = 'x';
|
|
- console.log('case5');
|
|
|
|
|
|
+ // console.log('case5');
|
|
} else {
|
|
} else {
|
|
newHeight = `${y1 + y2}px`;
|
|
newHeight = `${y1 + y2}px`;
|
|
newWidth = `${(y1 + y2) / (1 / originalAspect)}px`;
|
|
newWidth = `${(y1 + y2) / (1 / originalAspect)}px`;
|
|
currentTranslateDirection = '';
|
|
currentTranslateDirection = '';
|
|
- console.log('case6');
|
|
|
|
|
|
+ // console.log('case6');
|
|
}
|
|
}
|
|
|
|
|
|
// Set image element width and height
|
|
// Set image element width and height
|
|
- console.log('newWidth', newWidth);
|
|
|
|
- console.log('newHeight', newHeight);
|
|
|
|
- console.log('currentAngleOffset', currentAngleOffset);
|
|
|
|
- console.log('currentTranslateDirection', currentTranslateDirection);
|
|
|
|
- console.log('currentTranslate', currentTranslate);
|
|
|
|
- console.log('currentAngle', currentAngle);
|
|
|
|
|
|
+ // console.log('newWidth', newWidth);
|
|
|
|
+ // console.log('newHeight', newHeight);
|
|
|
|
+ // console.log('currentAngleOffset', currentAngleOffset);
|
|
|
|
+ // console.log('currentTranslateDirection', currentTranslateDirection);
|
|
|
|
+ // console.log('currentTranslate', currentTranslate);
|
|
|
|
+ // console.log('currentAngle', currentAngle);
|
|
|
|
|
|
if (currentAngleOffset === 90 || currentAngleOffset === 270) {
|
|
if (currentAngleOffset === 90 || currentAngleOffset === 270) {
|
|
imageWrapper.style.height = newWidth;
|
|
imageWrapper.style.height = newWidth;
|
|
@@ -695,7 +718,7 @@
|
|
};
|
|
};
|
|
|
|
|
|
const navigateEdit = (edit: activeEdit) => {
|
|
const navigateEdit = (edit: activeEdit) => {
|
|
- console.log('navigateEdit');
|
|
|
|
|
|
+ // console.log('navigateEdit');
|
|
let revert = false;
|
|
let revert = false;
|
|
if (activeEdit === edit) {
|
|
if (activeEdit === edit) {
|
|
revert = true;
|
|
revert = true;
|
|
@@ -719,61 +742,73 @@
|
|
};
|
|
};
|
|
|
|
|
|
const resetCropAndRotate = async () => {
|
|
const resetCropAndRotate = async () => {
|
|
|
|
+ // Reset the image orientation.
|
|
currentFlipX = false;
|
|
currentFlipX = false;
|
|
currentFlipY = false;
|
|
currentFlipY = false;
|
|
currentZoom = 1;
|
|
currentZoom = 1;
|
|
rotate(0, 0);
|
|
rotate(0, 0);
|
|
|
|
+
|
|
|
|
+ // Reset the aspect ratio.
|
|
await setAspectRatio('original');
|
|
await setAspectRatio('original');
|
|
};
|
|
};
|
|
|
|
|
|
const flipVertical = async () => {
|
|
const flipVertical = async () => {
|
|
currentFlipY = !currentFlipY;
|
|
currentFlipY = !currentFlipY;
|
|
- console.log('flipVertical');
|
|
|
|
rotate(currentAngle, currentAngleOffset);
|
|
rotate(currentAngle, currentAngleOffset);
|
|
};
|
|
};
|
|
const flipHorizontal = async () => {
|
|
const flipHorizontal = async () => {
|
|
currentFlipX = !currentFlipX;
|
|
currentFlipX = !currentFlipX;
|
|
- console.log('flipHorizontal');
|
|
|
|
rotate(currentAngle, currentAngleOffset);
|
|
rotate(currentAngle, currentAngleOffset);
|
|
};
|
|
};
|
|
|
|
|
|
const rotate = async (angle: number, angleOffset: number, isRotate?: boolean) => {
|
|
const rotate = async (angle: number, angleOffset: number, isRotate?: boolean) => {
|
|
|
|
+ // If the angle offset is greater than 360 degrees, reset it back to 0
|
|
if (angleOffset > 360) {
|
|
if (angleOffset > 360) {
|
|
angleOffset = angleOffset - 360;
|
|
angleOffset = angleOffset - 360;
|
|
}
|
|
}
|
|
- console.log('isRotate', isRotate);
|
|
|
|
|
|
|
|
|
|
+ // Set current angle and angle offset
|
|
currentAngle = angle;
|
|
currentAngle = angle;
|
|
currentAngleOffset = angleOffset;
|
|
currentAngleOffset = angleOffset;
|
|
|
|
|
|
|
|
+ // Set aspect ratio
|
|
setAspectRatio(currentAspectRatio, isRotate ? true : false);
|
|
setAspectRatio(currentAspectRatio, isRotate ? true : false);
|
|
|
|
|
|
|
|
+ // Set slider handle position
|
|
let a = -1 * angle * (125 / 49);
|
|
let a = -1 * angle * (125 / 49);
|
|
- let b = a + 'px';
|
|
|
|
- angleSliderHandle.style.left = b;
|
|
|
|
- angleSlider.style.left = b;
|
|
|
|
|
|
+ angleSliderHandle.style.left = a + 'px';
|
|
|
|
+ angleSlider.style.left = a + 'px';
|
|
};
|
|
};
|
|
|
|
|
|
- // Temporary function
|
|
|
|
const save = async () => {
|
|
const save = async () => {
|
|
- // TBD
|
|
|
|
|
|
+ // Save element
|
|
if (isRendering) {
|
|
if (isRendering) {
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
await renderElement.start();
|
|
await renderElement.start();
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+ // Set the transform of the image wrapper, which includes the rotation, translation, and scale.
|
|
const setImageWrapperTransform = () => {
|
|
const setImageWrapperTransform = () => {
|
|
let transformString = '';
|
|
let transformString = '';
|
|
|
|
|
|
|
|
+ // Add rotation to the transform string.
|
|
transformString += `rotate(${currentAngle - currentAngleOffset}deg)`;
|
|
transformString += `rotate(${currentAngle - currentAngleOffset}deg)`;
|
|
|
|
+
|
|
|
|
+ // If translation is non-zero, add it to the transform string.
|
|
if (currentTranslate.x || currentTranslate.y) {
|
|
if (currentTranslate.x || currentTranslate.y) {
|
|
transformString += ` translate(${currentTranslate.x * currentZoom}px, ${currentTranslate.y * currentZoom}px)`;
|
|
transformString += ` translate(${currentTranslate.x * currentZoom}px, ${currentTranslate.y * currentZoom}px)`;
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ // Add scale to the transform string.
|
|
transformString += ` scaleX(${(currentFlipX ? -1 : 1) * currentZoom}) scaleY(${
|
|
transformString += ` scaleX(${(currentFlipX ? -1 : 1) * currentZoom}) scaleY(${
|
|
(currentFlipY ? -1 : 1) * currentZoom
|
|
(currentFlipY ? -1 : 1) * currentZoom
|
|
})`;
|
|
})`;
|
|
- imageWrapper.style.transform = transformString;
|
|
|
|
|
|
+ // Set the transform of the image wrapper.
|
|
|
|
+
|
|
|
|
+ if (imageWrapper && imageWrapper.style) {
|
|
|
|
+ imageWrapper.style.transform = transformString;
|
|
|
|
+ }
|
|
};
|
|
};
|
|
</script>
|
|
</script>
|
|
|
|
|
|
@@ -820,8 +855,16 @@
|
|
<div class="-z-10 flex h-full w-full items-center justify-center">
|
|
<div class="-z-10 flex h-full w-full items-center justify-center">
|
|
<div bind:this={cropElementWrapper} class="relative flex h-full w-full items-center justify-center">
|
|
<div bind:this={cropElementWrapper} class="relative flex h-full w-full items-center justify-center">
|
|
<div>
|
|
<div>
|
|
- <div bind:this={imageWrapper} class="">
|
|
|
|
- <img class="h-full w-full" bind:this={imageElement} src="" alt="" />
|
|
|
|
|
|
+ <div bind:this={imageWrapper}>
|
|
|
|
+ <div
|
|
|
|
+ class="{isLoaded
|
|
|
|
+ ? 'hidden'
|
|
|
|
+ : 'flex'} absolute z-[1001] left-0 top-0 w-full h-full bg-black justify-center items-center gap-1"
|
|
|
|
+ >
|
|
|
|
+ <span>Loading</span>
|
|
|
|
+ <LoadingSpinner />
|
|
|
|
+ </div>
|
|
|
|
+ <img class="h-full w-full {isLoaded ? '' : 'hidden'}" bind:this={imageElement} src="" alt="" />
|
|
</div>
|
|
</div>
|
|
<div
|
|
<div
|
|
bind:this={cropElement}
|
|
bind:this={cropElement}
|