canvas-backend/src/components/EachComponent/Customization/ImageCustomization.jsx
2024-12-25 18:13:00 +06:00

226 lines
9 KiB
JavaScript

import { useContext, useState } from 'react'
import { ImageIcon, Wand2 } from 'lucide-react'
import { fabric } from 'fabric'
import CanvasContext from '@/components/Context/canvasContext/CanvasContext'
import { Label } from '@/components/ui/label'
import { Input } from '@/components/ui/input'
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'
import { Button } from '@/components/ui/button'
import { Slider } from '@/components/ui/slider'
import { Separator } from '@/components/ui/separator'
const ImageCustomization = () => {
const { canvas } = useContext(CanvasContext)
const [shadowColor, setShadowColor] = useState("#000000")
const [highlightColor, setHighlightColor] = useState("#ffffff")
const [blendMode, setBlendMode] = useState("multiply")
const [filterType, setFilterType] = useState("sepia")
const [filterIntensity, setFilterIntensity] = useState(0.5)
const applyDuotoneFilter = () => {
if (!canvas) return
const activeObject = canvas.getActiveObject()
if (!activeObject || activeObject.type !== "image") {
console.warn("No active image object selected.")
return
}
activeObject.filters = [
new fabric.Image.filters.BlendColor({
color: shadowColor,
mode: blendMode,
}),
new fabric.Image.filters.BlendColor({
color: highlightColor,
mode: "screen",
}),
]
activeObject.applyFilters()
canvas.renderAll()
}
const createFilter = (value) => {
let effect
switch (value) {
case 'sepia':
effect = new fabric.Image.filters.Sepia()
break
case 'contrast':
effect = new fabric.Image.filters.Contrast({ contrast: filterIntensity })
break
case 'brightness':
effect = new fabric.Image.filters.Brightness({ brightness: filterIntensity })
break
case 'grayscale':
effect = new fabric.Image.filters.Grayscale()
break
case 'invert':
effect = new fabric.Image.filters.Invert()
break
case 'blur':
effect = new fabric.Image.filters.Blur({
blur: filterIntensity,
})
break
case 'pixelate':
effect = new fabric.Image.filters.Pixelate({
blocksize: filterIntensity * 10,
})
break
case 'huerotation':
effect = new fabric.Image.filters.HueRotation({
rotation: filterIntensity * 360,
})
break
case 'noise':
effect = new fabric.Image.filters.Noise({
noise: filterIntensity * 100,
})
break
default:
effect = null
}
return effect
}
const applyFilter = () => {
if (!canvas) return
const activeObject = canvas.getActiveObject()
if (!activeObject || activeObject.type !== "image") {
console.warn("No active image object selected.")
return
}
const filter = createFilter(filterType)
if (filter) {
activeObject.filters = [filter]
activeObject.applyFilters()
canvas.renderAll()
}
}
const revertFilters = () => {
if (!canvas) return
const image = canvas.getActiveObject()
if (image) {
image.filters = []
image.applyFilters()
canvas.renderAll()
}
}
return (
<div className="space-y-2">
<h2 className="font-semibold my-2">Blend filter</h2>
<div className="grid grid-cols-1 gap-4">
<div className="space-y-2">
<Label>Shadow Color</Label>
<div className="flex items-center space-x-2">
<Input
type="color"
value={shadowColor}
onChange={(e) => setShadowColor(e.target.value)}
className="w-12 h-12 p-1 rounded-md"
/>
<Input
type="text"
value={shadowColor}
onChange={(e) => setShadowColor(e.target.value)}
className="flex-grow"
/>
</div>
</div>
<div className="space-y-2">
<Label>Highlight Color</Label>
<div className="flex items-center space-x-2">
<Input
type="color"
value={highlightColor}
onChange={(e) => setHighlightColor(e.target.value)}
className="w-12 h-12 p-1 rounded-md"
/>
<Input
type="text"
value={highlightColor}
onChange={(e) => setHighlightColor(e.target.value)}
className="flex-grow"
/>
</div>
</div>
</div>
<div className="space-y-2">
<Label>Blend Mode</Label>
<Select value={blendMode} onValueChange={setBlendMode}>
<SelectTrigger>
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="multiply">Multiply</SelectItem>
<SelectItem value="screen">Screen</SelectItem>
<SelectItem value="overlay">Overlay</SelectItem>
<SelectItem value="darken">Darken</SelectItem>
<SelectItem value="lighten">Lighten</SelectItem>
</SelectContent>
</Select>
</div>
<div className="grid gap-2">
<Button onClick={applyDuotoneFilter} className="flex-1">
<Wand2 className="mr-2" />
Apply Duotone
</Button>
<Button variant="outline" onClick={revertFilters} className="flex-1">
<ImageIcon className="mr-2" />
Revert Filters
</Button>
</div>
<div>
<Separator className="mt-4" />
<h2 className="font-semibold my-2">Apply filter</h2>
<div className='grid gap-4'>
<div className="space-y-2">
<Label>Filter Type</Label>
<Select value={filterType} onValueChange={setFilterType}>
<SelectTrigger>
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="sepia">Sepia</SelectItem>
<SelectItem value="contrast">Contrast</SelectItem>
<SelectItem value="brightness">Brightness</SelectItem>
<SelectItem value="grayscale">Grayscale</SelectItem>
<SelectItem value="invert">Invert</SelectItem>
<SelectItem value="blur">Blur</SelectItem>
<SelectItem value="pixelate">Pixelate</SelectItem>
<SelectItem value="huerotation">Hue Rotation</SelectItem>
<SelectItem value="noise">Noise</SelectItem>
</SelectContent>
</Select>
</div>
<div className="space-y-2">
<Label>Filter Intensity</Label>
<Slider
min={0}
max={1}
step={0.01}
value={[filterIntensity]}
onValueChange={([value]) => setFilterIntensity(value)}
/>
</div>
<div className="grid gap-2">
<Button onClick={applyFilter} className="flex-1">
<Wand2 className="mr-2" />
Apply Filter
</Button>
<Button variant="outline" onClick={revertFilters} className="flex-1">
<ImageIcon className="mr-2" />
Revert Filters
</Button>
</div>
</div>
</div>
</div>
)
}
export default ImageCustomization