开发者们大家好,
今天,我将向您展示如何使用 ReactJS 创建图像生成器,并且完全可以免费使用,这要感谢黑森林实验室和 Together AI。
在本教程中,我们将使用 Vite 来初始化应用程序并使用 Shadcn 来初始化 UI。我假设您已经设置了项目并安装了 Shadcn。
我们需要安装 Together AI 包才能访问免费的 Flux 模型来生成图像。
在终端中运行以下命令
npm i together-ai
现在,让我们为我们的应用程序创建 UI。以下是图像生成器组件的完整代码。它包括提示文本输入。用于选择宽高比的下拉菜单。
请记住,我们需要使用“black-forest-labs/FLUX.1-schnell-Free”,因为它是免费的。
import { useRef, useState } from "react"; import Together from "together-ai"; import { ImagesResponse } from "together-ai"; import { Button } from "@/components/ui/button"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { Textarea } from "@/components/ui/textarea"; import { motion } from "framer-motion"; import { Separator } from "@/components/ui/separator"; import { DownloadIcon } from "@radix-ui/react-icons"; import { save } from "@tauri-apps/plugin-dialog"; import { writeFile } from "@tauri-apps/plugin-fs"; function App() { const [input, setInput] = useState(""); const [imageUrl, setImageUrl] = useState(""); const [ratio, setRatio] = useState("9:16"); const [isLoading, setIsLoading] = useState(false); const [downloading, setDownloading] = useState(false); const imageRef = useRef<HTMLImageElement>(null); const hRatio = ratio.split(":").map(Number)[0]; const vRatio = ratio.split(":").map(Number)[1]; const width = hRatio === 1 ? 512 : hRatio * 64; const height = vRatio === 1 ? 512 : vRatio * 64; const together = new Together({ apiKey: import.meta.env.VITE_TOGETHER_API_KEY, }); const handleGenerateImage = async () => { setIsLoading(true); try { console.log(width, height); const response: ImagesResponse = await together.images.create({ model: "black-forest-labs/FLUX.1-schnell-Free", prompt: input, width: width, height: height, // @ts-expect-error response_format is not defined in the type response_format: "b64_json", }); const base64Image = response.data[0].b64_json; const dataUrl = `data:image/png;base64,${base64Image}`; setImageUrl(dataUrl); } catch (error) { console.error("Error generating image:", error); // You might want to add some error handling UI here } finally { setIsLoading(false); } }; const handleDownloadImage = async () => { if (imageUrl) { setDownloading(true); try { // Remove the data URL prefix const base64Data = imageUrl.replace(/^data:image\/\w+;base64,/, ""); // Convert base64 to binary const imageBuffer = Uint8Array.from(atob(base64Data), (c) => c.charCodeAt(0) ); // Open a save dialog const filePath = await save({ filters: [ { name: "Image", extensions: ["png"], }, ], }); if (filePath) { // Write the file await writeFile(filePath, imageBuffer); console.log("File saved successfully"); } } catch (error) { console.error("Error saving image:", error); } finally { setDownloading(false); } } }; return ( <div className="bg-gradient-to-br from-indigo-100 via-purple-100 to-pink-100 p-10 md:p-8"> <motion.div initial={{ opacity: 0, y: 20 }} animate={{ opacity: 1, y: 0 }} transition={{ duration: 0.5 }} className="max-w-7xl mx-auto bg-white/80 backdrop-blur-sm rounded-3xl shadow-2xl overflow-y-auto" > <div className="flex flex-col md:flex-row h-[calc(100vh-4rem)]"> <div className="w-full md:w-1/2 p-6 flex flex-col"> <h2 className="text-3xl font-bold mb-6 text-gray-800 bg-clip-text text-transparent bg-gradient-to-r from-indigo-500 to-purple-600"> AI Image Generator for "Thảo" </h2> <div className="flex-grow flex flex-col justify-center"> <Textarea value={input} onChange={(e) => setInput(e.target.value)} placeholder="Describe the image you want to create..." className="mb-4 resize-none rounded-2xl border-2 border-indigo-200 focus:border-indigo-500 transition-colors" rows={5} /> <div className="flex items-center space-x-4 mb-6"> <Select value={ratio} onValueChange={setRatio}> <SelectTrigger className="w-full rounded-full border-2 border-purple-200 focus:border-purple-500 transition-colors"> <SelectValue placeholder="Select ratio" /> </SelectTrigger> <SelectContent> <SelectItem value="1:1">1:1</SelectItem> <SelectItem value="4:3">4:3</SelectItem> <SelectItem value="16:9">16:9</SelectItem> <SelectItem value="3:4">3:4</SelectItem> <SelectItem value="9:16">9:16</SelectItem> </SelectContent> </Select> <Button onClick={handleGenerateImage} disabled={isLoading} className="flex-shrink-0 bg-gradient-to-r from-indigo-500 to-purple-600 hover:from-indigo-600 hover:to-purple-700 text-white font-semibold py-2 px-4 rounded-full transition-all duration-300 ease-in-out transform hover:scale-105" > {isLoading ? "Generating..." : "Generate Image"} </Button> </div> </div> </div> <Separator orientation="vertical" className="hidden md:block" /> <div className="w-full md:w-1/2 p-6 bg-gray-50/50 flex flex-col"> <h2 className="text-3xl font-bold mb-6 text-gray-800 bg-clip-text text-transparent bg-gradient-to-r from-purple-500 to-pink-600"> Generated Image </h2> {imageUrl ? ( <motion.div initial={{ opacity: 0, scale: 0.9 }} animate={{ opacity: 1, scale: 1 }} transition={{ duration: 0.5 }} className="flex-grow flex flex-col items-center justify-center" > <img ref={imageRef} src={imageUrl} alt="Generated" className="max-w-full max-h-[60vh] object-contain rounded-lg shadow-lg mb-6" /> <div className="flex space-x-4"> <Button onClick={handleDownloadImage} className="rounded-full bg-gradient-to-r from-purple-500 to-pink-600 hover:from-purple-600 hover:to-pink-700 text-white font-semibold py-2 px-4 transition-all duration-300 ease-in-out transform hover:scale-105 flex items-center space-x-2" > {downloading ? "Downloading..." : <DownloadIcon />} <span>Download</span> </Button> </div> </motion.div> ) : ( <div className="flex-grow flex items-center justify-center text-gray-400"> <p className="text-lg italic"> Your generated image will appear here </p> </div> )} </div> </div> </motion.div> </div> ); } export default App;
通过此设置,您现在拥有一个简单的 ReactJS 应用程序,可以生成和下载 AI 生成的图像。
感谢您的阅读!如果您觉得这篇文章有趣,请不要犹豫,点个赞。快乐编码!
以上是使用 ReactJS 构建免费的 AI 图像生成器的详细内容。更多信息请关注PHP中文网其他相关文章!