本專案將使用 React 框架,利用一個名為 "react-easy-crop" 的 npm 套件來實現圖片裁剪的功能。我們將建立一個能夠顯示圖片列表的應用程式,並提供圖片裁剪的功能,使用者可以選擇圖片進行裁剪,並儲存裁剪後的圖片。
安裝所需套件
在開始之前,我們需要先安裝所需的套件。請執行以下指令來安裝 "react-easy-crop" 套件:
npm install react-easy-crop
安裝完成後,我們可以開始進行專案的設置。
開始設定 React App
首先,我們需要使用 Create React App 工具來建立一個新的 React 專案。請執行以下指令:
npx create-react-app image-cropping-with-react-easy-crop
這將會建立一個名為 "image-cropping-with-react-easy-crop" 的專案目錄,並自動安裝所有必要的相依套件。
建立完成後,請使用以下指令切換至專案目錄並開啟程式碼編輯器:
cd image-cropping-with-react-easy-crop
code .
透過這些步驟,我們已經建立好了一個新的 React 專案並準備開始編寫程式碼。
建立圖片列表
我們首先要建立一個能夠顯示圖片的列表。在專案目錄中,打開 src/App.js 檔案,並將原始內容刪除,然後新增以下程式碼:
import React from 'react';
function App() {
const images = [
{ id: 1, imageUrl: 'images/r1.png' },
{ id: 2, imageUrl: 'images/r2.png' },
{ id: 3, imageUrl: 'images/r3.png' },
// 其他圖片資料...
return (
<div className="App">
{images.map((image) => (
<div key={image.id} className="image-card">
<img src={image.imageUrl} alt="Image" />
export default App;
這段程式碼定義了一個名為
App
的 React 函式元件,並在其中建立了一個
images
陣列,用來儲存圖片資訊。然後,我們使用
Array.map()
方法將
images
陣列中的每一個元素轉換為一個圖片卡片,並顯示在畫面上。
請確保在專案目錄下建立一個名為 "public" 的資料夾,並在其中建立一個名為 "images" 的子資料夾。將所需的圖片檔案存放在 "public/images" 資料夾中,並確保圖片檔案路徑正確。
完成後,請執行以下指令來啟動 React 應用程式:
npm start
這將會在瀏覽器中打開應用程式,您應該能夠看到顯示出來的圖片列表。
實作圖片裁剪功能
接下來,我們要為圖片裁剪的功能提供支援。我們將使用 "react-easy-crop" 套件來實現這一功能。
首先,讓我們先安裝所需的套件。在專案目錄中,執行以下指令:
npm install react-easy-crop
安裝完成後,讓我們回到 src/App.js 檔案,並更新程式碼如下:
import React, { useState } from 'react';
import ImageCropDialog from './ImageCropDialog';
function App() {
const [selectedImage, setSelectedImage] = useState(null);
const images = [
{ id: 1, imageUrl: 'images/r1.png' },
{ id: 2, imageUrl: 'images/r2.png' },
{ id: 3, imageUrl: 'images/r3.png' },
// 其他圖片資料...
const handleImageClick = (image) => {
setSelectedImage(image);
const handleCancelCrop = () => {
setSelectedImage(null);
const handleSaveCrop = (cropData) => {
// 儲存裁剪後圖片的邏輯...
console.log(cropData);
return (
<div className="App">
{images.map((image) => (
<div key={image.id} className="image-card">
src={image.imageUrl}
alt="Image"
onClick={() => handleImageClick(image)}
{selectedImage && (
<ImageCropDialog
imageUrl={selectedImage.imageUrl}
onCancel={handleCancelCrop}
onSave={handleSaveCrop}
export default App;
在這段程式碼中,我們使用
useState
鉤子來建立一個名為
selectedImage
的狀態變數,用於追蹤被選中的圖片。
handleImageClick
函數用於處理圖片的點擊事件,當使用者點擊某一張圖片時,我們將該圖片設定為選中的圖片。
接著,我們定義了
handleCancelCrop
函數和
handleSaveCrop
函數,用於取消裁剪和儲存裁剪後的圖片。
最後,我們使用三元運算子來條件渲染
ImageCropDialog
元件。當有選中的圖片時,我們將顯示該圖片對應的裁剪對話框。
現在,我們需要建立一個新的 React 元件來實現圖片裁剪對話框。在專案目錄中,建立一個新的檔案,並命名為 "ImageCropDialog.js",然後將下面的程式碼貼入該檔案中:
import React, { useState } from 'react';
import { Cropper } from 'react-easy-crop';
function ImageCropDialog({ imageUrl, onCancel, onSave }) {
const [crop, setCrop] = useState({ x: 0, y: 0 });
const [zoom, setZoom] = useState(1);
const [aspect, setAspect] = useState(4 / 3);
const handleCropChange = (crop) => {
setCrop(crop);
const handleZoomChange = (zoom) => {
setZoom(zoom);
const handleAspectChange = (e) => {
const value = e.target.value;
const ratio = aspectRatios.find((ratio) => ratio.value === value);
setAspect(ratio.value);
const handleCancel = () => {
onCancel();
const handleSave = () => {
const cropData = { crop, zoom, aspect };
onSave(cropData);
const aspectRatios = [
{ value: '4/3', label: '4:3' },
{ value: '16/9', label: '16:9' },
{ value: '1/2', label: '1:2' },
// 其他比例設定...
return (
<div className="image-crop-dialog">
<div className="backdrop" onClick={handleCancel} />
<div className="crop-container">
<Cropper
image={imageUrl}
crop={crop}
zoom={zoom}
aspect={aspect}
onCropChange={handleCropChange}
onZoomChange={handleZoomChange}
<div className="controls">
<div className="slider">
<input
type="range"
min="1"
max="3"
step="0.1"
value={zoom}
onChange={(e) => handleZoomChange(parseFloat(e.target.value))}
<div className="aspect-ratio">
<select value={aspect} onChange={handleAspectChange}>
{aspectRatios.map((ratio) => (
<option key={ratio.value} value={ratio.value}>
{ratio.label}
</option>
</select>
<div className="buttons">
<button onClick={handleCancel}>Cancel</button>
<button onClick={handleSave}>Crop</button>
export default ImageCropDialog;
在這段程式碼中,我們定義了一個名為
ImageCropDialog
的 React 函數元件,該元件用於顯示圖片裁剪對話框。這個元件接收三個屬性:
imageUrl
(圖片 URL)、
onCancel
(取消裁剪事件)和
onSave
(儲存裁剪圖片事件)。
在元件中,我們使用
useState
鉤子來建立三個狀態變數
crop
、
zoom
和
aspect
,分別用於追蹤裁剪區域、縮放比例和圖片比例。
我們定義了一些處理函數,例如
handleCropChange
、
handleZoomChange
和
handleAspectChange
,用於追蹤裁剪區域、縮放比例和圖片比例的變化。
在
return
區塊中,我們使用
Cropper
元件來顯示圖片並提供裁剪功能。我們還添加了一個滑桿和一個下拉選單,用於調整縮放比例和圖片比例。
最後,我們添加了兩個按鈕用於取消和儲存裁剪結果。
現在,我們的應用程式已經具備了圖片裁剪的功能。您可以點擊圖片,開啟裁剪對話框,並選擇所需的裁剪區域,然後點擊 "Crop" 按鈕進行裁剪。
設定圖片裁剪參數
在上一節,我們為裁剪圖片設定了一些預設值,例如裁剪區域坐標、縮放比例和圖片比例。然而,這些值在每次點擊圖片並打開裁剪對話框時,都會重置為預設值。
要記住用戶在上一次裁剪的結果,並在下一次打開同一張圖片時應用這些值,我們需要將這些值存儲在
selectedImage
的對象中。在
handleSaveCrop
函數中,我們可以獲取這些值並將它們存儲在
selectedImage
對象中。
首先,在
useState
鉤子中為
selectedImage
狀態變數添加
crop
、
zoom
和
aspect
屬性:
const [selectedImage, setSelectedImage] = useState({ crop: { x: 0, y: 0 }, zoom: 1, aspect: 4 / 3 });
然後,在
handleSaveCrop
函數中更新
selectedImage
的值:
const handleSaveCrop = (cropData) => {
setSelectedImage((prevImage) => ({
...prevImage,
...cropData,
現在,在下一次點擊圖片並打開裁剪對話框時,先從 selectedImage
中檢查是否有存儲的裁剪值。如果有,將這些值傳遞給裁剪對話框,以便在打開時恢復這些值。
要實現這一點,在 ImageCropDialog
元件內部,首先將 crop
、zoom
和 aspect
的預設值設置為來自 selectedImage
的值:
const [crop, setCrop] = useState(selectedImage.crop);
const [zoom, setZoom] = useState(selectedImage.zoom);
const [aspect, setAspect] = useState(selectedImage.aspect);
然後,在 Cropper
元件中將 crop
、zoom
和 aspect
屬性更新為對應的狀態:
<Cropper
image={imageUrl}
crop={crop}
zoom={zoom}
aspect={aspect}
onCropChange={handleCropChange}
onZoomChange={handleZoomChange}
現在,當您點擊圖片並再次打開裁剪對話框時,它將恢復上一次裁剪的結果。
顯示圖片裁剪對話框
為了實現將圖片裁剪結果顯示在畫面上,我們需要將裁剪後的圖片 URL 傳遞回 App
元件,並使用它來更新相應圖片的狀態。
首先,在 App
元件中為裁剪結果建立一個狀態變數:
const [croppedImages, setCroppedImages] = useState([]);
然後,定義一個函數來處理屬性的更新:
const handleSetCroppedImage = (imageId, cropData) => {
setCroppedImages((prevImages) =>
prevImages.map((image) =>
image.id === imageId ? { ...image, ...cropData } : image
在 handleSaveCrop
函數中,呼叫 handleSetCroppedImage
函數並傳遞圖片的標識符和裁剪數據:
const handleSaveCrop = (cropData) => {
const imageId = selectedImage.id;
handleSetCroppedImage(imageId, cropData);
setSelectedImage(null);
接下來,讓我們更新 ImageCropDialog
元件:
function ImageCropDialog({ imageUrl, onCancel, onSave }) {
// 狀態變數...
const handleSave = () => {
const cropData = { crop, zoom, aspect };
onSave(cropData);
// 其他程式碼...
return (
<div className="image-crop-dialog">
{/* 其他元素... */}
<div className="buttons">
{/* 之前的按鈕... */}
<button onClick={handleSave}>Crop</button>
在 handleSave
函數中,我們將 crop
、zoom
和 aspect
的值傳遞給 onSave
屬性,以將裁剪數據返回給 App
元件。
在 App
元件中,稍微修改一下對應的函數 handleSetCroppedImage
:
const handleSetCroppedImage = (imageId, cropData) => {
setCroppedImages((prevImages) =>
prevImages.map((image) =>
image.id === imageId ? { ...image, croppedData: cropData } : image
我們將裁剪數據保存在 croppedData
中,以便在需要時能夠顯示它。
現在,當您點擊 "Crop" 按鈕並儲存裁剪的結果時,該結果將顯示在對應的圖片上。
最後,我們將增加重置圖片的功能。這將允許使用者將圖片的裁剪狀態重置為預設值。
首先,在 ImageCropDialog
元件中將取消和重置兩個按鈕的 onClick
屬性更新如下:
<button onClick={handleCancel}>Cancel</button>
<button onClick={handleReset}>Reset</button>
然後,添加 handleReset
函數:
const handleReset = () => {
const crop = { x: 0, y: 0 };
const zoom = 1;
const aspect = 4 / 3;
setCrop(crop);
setZoom(zoom);
setAspect(aspect);
在這個函數中,我們將裁剪區域 (crop
)、縮放比例 (zoom
) 和圖片比例 (aspect
) 的值重置為預設值。
現在,當您點擊 "Reset" 按鈕時,圖片的裁剪狀態將被重置為預設值。
恭喜!您已經成功實現了使用 "react-easy-crop" 套件進行圖片裁剪的功能。您的應用程序現在能夠顯示圖片列表並提供裁剪功能,使用者可以選擇圖片,裁剪圖片,並將裁剪後的圖片儲存下來。
如有任何問題,請隨時向我們詢問。祝您使用愉快!