244 lines
10 KiB
JavaScript
244 lines
10 KiB
JavaScript
import { useContext, useEffect, useState } from 'react'
|
|
import { Label } from '@/components/ui/label'
|
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'
|
|
import { Input } from '@/components/ui/input'
|
|
import { Button } from '@/components/ui/button'
|
|
import ColorContext from './Context/colorContext/ColorContext'
|
|
import CanvasContext from './Context/canvasContext/CanvasContext'
|
|
import { fabric } from 'fabric'
|
|
|
|
const ColorComponent = () => {
|
|
const { canvas } = useContext(CanvasContext)
|
|
const { backgroundType, setBackgroundType, solidColor, gradientColors, setSolidColor, setGradientColors, gradientDirection, setGradientDirection, setDirectionCoords,
|
|
} = useContext(ColorContext)
|
|
|
|
const [previewBackgroundType, setPreviewBackgroundType] = useState(backgroundType)
|
|
const [previewSolidColor, setPreviewSolidColor] = useState(solidColor)
|
|
const [previewGradientColors, setPreviewGradientColors] = useState(gradientColors)
|
|
const [previewGradientDirection, setPreviewGradientDirection] = useState(gradientDirection)
|
|
|
|
useEffect(() => {
|
|
setPreviewBackgroundType(backgroundType)
|
|
setPreviewSolidColor(solidColor)
|
|
setPreviewGradientColors(gradientColors)
|
|
setPreviewGradientDirection(gradientDirection)
|
|
}, [backgroundType, solidColor, gradientColors, gradientDirection])
|
|
|
|
useEffect(() => {
|
|
if (previewBackgroundType === "gradient" && canvas) {
|
|
const width = canvas.width || 0
|
|
const height = canvas.height || 0
|
|
|
|
const linearCoords = {
|
|
"top-to-bottom": { x1: 0, y1: 0, x2: 0, y2: height },
|
|
"bottom-to-top": { x1: 0, y1: height, x2: 0, y2: 0 },
|
|
"left-to-right": { x1: 0, y1: 0, x2: width, y2: 0 },
|
|
"right-to-left": { x1: width, y1: 0, x2: 0, y2: 0 },
|
|
}
|
|
|
|
const coords = linearCoords[previewGradientDirection]
|
|
if (coords) {
|
|
setDirectionCoords(coords)
|
|
}
|
|
}
|
|
}, [previewBackgroundType, previewGradientDirection, canvas, setDirectionCoords])
|
|
|
|
const applyChanges = () => {
|
|
setBackgroundType(previewBackgroundType)
|
|
setSolidColor(previewSolidColor)
|
|
setGradientColors(previewGradientColors)
|
|
setGradientDirection(previewGradientDirection)
|
|
applyToCanvas()
|
|
}
|
|
|
|
const applyToCanvas = () => {
|
|
if (!canvas) return
|
|
|
|
if (previewBackgroundType === "color") {
|
|
canvas.backgroundColor = previewSolidColor
|
|
} else if (previewBackgroundType === "gradient") {
|
|
const width = canvas.width || 0
|
|
const height = canvas.height || 0
|
|
|
|
const linearCoords = {
|
|
"top-to-bottom": { x1: 0, y1: 0, x2: 0, y2: height },
|
|
"bottom-to-top": { x1: 0, y1: height, x2: 0, y2: 0 },
|
|
"left-to-right": { x1: 0, y1: 0, x2: width, y2: 0 },
|
|
"right-to-left": { x1: width, y1: 0, x2: 0, y2: 0 },
|
|
}
|
|
|
|
const coords = linearCoords[previewGradientDirection]
|
|
if (coords) {
|
|
setDirectionCoords(coords)
|
|
const gradient = new fabric.Gradient({
|
|
type: "linear",
|
|
gradientUnits: "pixels",
|
|
coords: coords,
|
|
colorStops: [
|
|
{ offset: 0, color: previewGradientColors.color1 },
|
|
{ offset: 1, color: previewGradientColors.color2 },
|
|
],
|
|
})
|
|
canvas.backgroundColor = gradient
|
|
}
|
|
} else if (previewBackgroundType === "radial") {
|
|
const gradient = new fabric.Gradient({
|
|
type: "radial",
|
|
gradientUnits: "pixels",
|
|
coords: {
|
|
x1: canvas.width / 2,
|
|
y1: canvas.height / 2,
|
|
r1: 0,
|
|
x2: canvas.width / 2,
|
|
y2: canvas.height / 2,
|
|
r2: Math.min(canvas.width, canvas.height) / 2,
|
|
},
|
|
colorStops: [
|
|
{ offset: 0, color: previewGradientColors.color1 },
|
|
{ offset: 1, color: previewGradientColors.color2 },
|
|
],
|
|
})
|
|
canvas.backgroundColor = gradient
|
|
}
|
|
|
|
canvas.renderAll()
|
|
}
|
|
|
|
const getPreviewStyle = () => {
|
|
if (previewBackgroundType === "color") {
|
|
return { backgroundColor: previewSolidColor }
|
|
} else if (previewBackgroundType === "gradient") {
|
|
const direction = {
|
|
'top-to-bottom': '180deg',
|
|
'bottom-to-top': '0deg',
|
|
'left-to-right': '90deg',
|
|
'right-to-left': '270deg'
|
|
}[previewGradientDirection]
|
|
return {
|
|
backgroundImage: `linear-gradient(${direction}, ${previewGradientColors.color1}, ${previewGradientColors.color2})`
|
|
}
|
|
} else if (previewBackgroundType === "radial") {
|
|
return {
|
|
backgroundImage: `radial-gradient(circle, ${previewGradientColors.color1}, ${previewGradientColors.color2})`
|
|
}
|
|
}
|
|
}
|
|
|
|
return (
|
|
<div className='flex flex-col gap-4 p-1'>
|
|
<div className='flex flex-col gap-2'>
|
|
<Label>Background Type:</Label>
|
|
<Select value={previewBackgroundType} onValueChange={setPreviewBackgroundType}>
|
|
<SelectTrigger>
|
|
<SelectValue placeholder="Select background type" />
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
<SelectItem value="color">Solid Color</SelectItem>
|
|
<SelectItem value="gradient">Linear Gradient</SelectItem>
|
|
<SelectItem value="radial">Radial Gradient</SelectItem>
|
|
</SelectContent>
|
|
</Select>
|
|
</div>
|
|
|
|
{previewBackgroundType === "color" ? (
|
|
<div className='flex flex-col gap-2'>
|
|
<Label>Solid Color:</Label>
|
|
<Input
|
|
type="color"
|
|
value={previewSolidColor}
|
|
onChange={(e) => setPreviewSolidColor(e.target.value)}
|
|
/>
|
|
</div>
|
|
) : previewBackgroundType === "gradient" ? (
|
|
<div className='grid grid-cols-1 gap-2'>
|
|
<div className='flex flex-col gap-2'>
|
|
<Label>Direction:</Label>
|
|
<Select
|
|
value={previewGradientDirection}
|
|
onValueChange={setPreviewGradientDirection}
|
|
>
|
|
<SelectTrigger>
|
|
<SelectValue placeholder="Select direction" />
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
<SelectItem value="top-to-bottom">Top to Bottom</SelectItem>
|
|
<SelectItem value="bottom-to-top">Bottom to Top</SelectItem>
|
|
<SelectItem value="left-to-right">Left to Right</SelectItem>
|
|
<SelectItem value="right-to-left">Right to Left</SelectItem>
|
|
</SelectContent>
|
|
</Select>
|
|
</div>
|
|
|
|
<div className='flex flex-col gap-2'>
|
|
<Label>Color 1:</Label>
|
|
<Input
|
|
type="color"
|
|
value={previewGradientColors.color1}
|
|
onChange={(e) =>
|
|
setPreviewGradientColors((prev) => ({
|
|
...prev,
|
|
color1: e.target.value,
|
|
}))}
|
|
/>
|
|
</div>
|
|
|
|
<div className='flex flex-col gap-2'>
|
|
<Label>Color 2:</Label>
|
|
<Input
|
|
type="color"
|
|
value={previewGradientColors.color2}
|
|
onChange={(e) =>
|
|
setPreviewGradientColors((prev) => ({
|
|
...prev,
|
|
color2: e.target.value,
|
|
}))}
|
|
/>
|
|
</div>
|
|
</div>
|
|
) : (
|
|
<div className='grid grid-cols-1 gap-2'>
|
|
<div className='flex flex-col gap-2'>
|
|
<Label>Color 1:</Label>
|
|
<Input
|
|
type="color"
|
|
value={previewGradientColors.color1}
|
|
onChange={(e) =>
|
|
setPreviewGradientColors((prev) => ({
|
|
...prev,
|
|
color1: e.target.value,
|
|
}))}
|
|
/>
|
|
</div>
|
|
|
|
<div className='flex flex-col gap-2'>
|
|
<Label>Color 2:</Label>
|
|
<Input
|
|
type="color"
|
|
value={previewGradientColors.color2}
|
|
onChange={(e) =>
|
|
setPreviewGradientColors((prev) => ({
|
|
...prev,
|
|
color2: e.target.value,
|
|
}))}
|
|
/>
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
<div>
|
|
<Label>Preview:</Label>
|
|
<div
|
|
className='w-full h-24 rounded-md mt-2'
|
|
style={getPreviewStyle()}
|
|
></div>
|
|
</div>
|
|
|
|
<Button onClick={applyChanges}>
|
|
Apply Changes
|
|
</Button>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export default ColorComponent
|
|
|