flip image buttons added with - bug present

This commit is contained in:
Artur AGH
2023-11-01 12:14:00 +01:00
parent 53e8e16191
commit df33d4a3b8
4 changed files with 120 additions and 16 deletions

View File

@@ -0,0 +1,59 @@
import React from "react";
import { Label } from "@/components/ui/label";
import { Slider } from "@/components/ui/slider";
import { useAppDispatch } from "@/hooks";
import { updateImage, updateText } from "@/store/app.slice";
import { HoverCard, HoverCardTrigger } from "@/components/ui/hover-card";
import { type ImageConfig } from "konva/lib/shapes/Image";
import { TransformableImageProps } from "@/components/transformable-image";
type Props = {
currentImage: ImageConfig;
selectedItemId: string;
};
export default function ImageOpacityTool({
selectedItemId,
currentImage,
}: Props) {
const dispatch = useAppDispatch();
const value = currentImage.opacity ?? 1;
const handleOpacityChange = (e) => {
if (!selectedItemId) return;
dispatch(
updateImage({
id: selectedItemId,
opacity: e,
}),
);
};
return (
<HoverCard openDelay={200}>
<HoverCardTrigger asChild>
<div className="grid gap-4">
<div className="flex items-center justify-between">
<Label htmlFor="fontSize">Opacity</Label>
<span className="w-12 rounded-md border border-transparent px-2 py-0.5 text-right text-sm text-muted-foreground hover:border-border">
{value}
</span>
</div>
<Slider
id="fontSize"
min={0}
max={1}
defaultValue={[currentImage.opacity ?? 16]}
step={0.1}
onValueChange={(e) => {
handleOpacityChange(e[0]);
}}
className="[&_[role=slider]]:h-4 [&_[role=slider]]:w-4"
aria-label="opacity"
/>
</div>
</HoverCardTrigger>
</HoverCard>
);
}

View File

@@ -1,32 +1,49 @@
import React from "react"; import React from "react";
import { DeleteShapeButton } from "@/components/delete-shape-button";
import { Button } from "@/components/ui/button";
import { TbFlipHorizontal, TbFlipVertical } from "react-icons/tb"; import { TbFlipHorizontal, TbFlipVertical } from "react-icons/tb";
import { Toggle } from "@/components/ui/toggle"; import { Toggle } from "@/components/ui/toggle";
import { useAppDispatch } from "@/hooks"; import { useAppDispatch } from "@/hooks";
import { updateImage } from "@/store/app.slice"; import { updateImage } from "@/store/app.slice";
import ImageOpacityTool from "@/components/image-editing-tools/image-opacity-tool";
import { Separator } from "@/components/ui/separator";
export function ImageToolbar({ selectedItemId, currentImage }) { export function ImageToolbar({ selectedItemId, currentImage }) {
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
const flipImageVerticaly = (selectedItemId) => { const flipImageVerticaly = () => {
const editOffsetY = currentImage.height / 2;
const editScaleY = -1 * currentImage.scaleY;
dispatch( dispatch(
updateImage({ updateImage({
id: selectedItemId, id: selectedItemId,
offsetY: editOffsetY,
scaleY: editScaleY,
}), }),
); );
}; };
const flipImageHorizontaly = () => { const flipImageHorizontaly = () => {
console.log("Horizontal Flip"); const editOffsetX = currentImage.width / 2;
const editScaleX = -1 * currentImage.scaleX;
dispatch(
updateImage({
id: selectedItemId,
offsetX: editOffsetX,
scaleX: editScaleX,
}),
);
}; };
return ( return (
<> <>
<Toggle onClick={flipImageVerticaly}> <Toggle onClick={() => flipImageHorizontaly()}>
<TbFlipVertical /> <TbFlipVertical />
</Toggle> </Toggle>
<Toggle> <Toggle>
<TbFlipHorizontal onClick={flipImageHorizontaly} /> <TbFlipHorizontal onClick={() => flipImageVerticaly()} />
</Toggle> </Toggle>
<Separator orientation="vertical" />
<ImageOpacityTool
selectedItemId={selectedItemId}
currentImage={currentImage}
/>
</> </>
); );
} }

View File

@@ -1,4 +1,4 @@
import React, { ChangeEvent } from "react"; import React, { type ChangeEvent } from "react";
import { import {
Popover, Popover,
PopoverContent, PopoverContent,
@@ -16,7 +16,17 @@ function ImageInput() {
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
const handleImageUploaded = (e: ChangeEvent<HTMLInputElement>) => { const handleImageUploaded = (e: ChangeEvent<HTMLInputElement>) => {
dispatch(addImage(e)); const file = e.target.files?.[0];
if (!file) return;
const img = document.createElement("img");
const imageUrl = URL.createObjectURL(file);
img.onload = () => {
dispatch(addImage({ imageUrl, width: img.width, height: img.height }));
img.remove();
};
img.src = imageUrl;
img.style.cssText = "display: none;";
document.body.appendChild(img);
}; };
return ( return (

View File

@@ -22,7 +22,15 @@ const defaultTextConfig = {
fontFamily: "Roboto", fontFamily: "Roboto",
}; };
const defaultImageConfig = {}; const defaultImageConfig = {
x: 50,
y: 50,
opacity: 1,
offsetX: 0,
offsetY: 0,
scaleX: 1,
scaleY: 1,
};
export const appSlice = createSlice({ export const appSlice = createSlice({
name: "app", name: "app",
@@ -35,17 +43,27 @@ export const appSlice = createSlice({
id: textId, id: textId,
...defaultTextConfig, ...defaultTextConfig,
}); });
console.log(current(state.texts));
}, },
addImage: (state, action: PayloadAction<ChangeEvent<HTMLInputElement>>) => { addImage: (
const file = action.payload.target.files?.[0]; state,
action: PayloadAction<{
imageUrl: string;
width: number;
height: number;
}>,
) => {
const file = action.payload;
if (!file) return; if (!file) return;
const imageId = v1(); const imageId = v1();
const imageUrl = URL.createObjectURL(file);
state.images.push({ imageUrl, id: imageId }); state.images.push({
console.log(current(state.images)); imageUrl: action.payload.imageUrl,
id: imageId,
width: action.payload.width,
height: action.payload.height,
...defaultImageConfig,
});
}, },
selectItem: (state, action: PayloadAction<string>) => { selectItem: (state, action: PayloadAction<string>) => {