v1
詳細設計
- UI設計:
- 画像のダウンロード・コピーの横に「大」「中」「小」のボタンを配置。
- ボタンの選択に応じて、リサイズされた画像を表示する(プレビューは任意)。
tsx
コードをコピーする
const SizeOptions = ({ setSelectedSize }) => {
return (
<div>
<button onClick={() => setSelectedSize("large")}>大</button>
<button onClick={() => setSelectedSize("medium")}>中</button>
<button onClick={() => setSelectedSize("small")}>小</button>
</div>
);
};
- 画像リサイズ処理:
tsx
コードをコピーする
const resizeImage = async (src: string, size: "large" | "medium" | "small") => {
const response = await axios.get(src, { responseType: "blob" });
const blob = response.data;
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
const image = await createImageBitmap(blob);
const sizeMultiplier = size === "large" ? 1 : size === "medium" ? 0.5 : 0.25;
canvas.width = image.width * sizeMultiplier;
canvas.height = image.height * sizeMultiplier;
if (ctx) {
ctx.drawImage(image, 0, 0, canvas.width, canvas.height);
}
return new Promise<Blob | null>((resolve) => {
canvas.toBlob((newBlob) => resolve(newBlob), blob.type);
});
};
- ダウンロード時の処理:
tsx
コードをコピーする
export const downloadImage = async (src: string, size: "large" | "medium" | "small") => {
try {
const resizedBlob = await resizeImage(src, size);
if (resizedBlob) {
const fileName = src.substring(src.lastIndexOf("/") + 1);
saveAs(resizedBlob, fileName);
}
} catch (error) {
console.error("Image download failed", error);
}
};
- コピー時の処理:
tsx
コードをコピーする
export const copyImageToClipboard = async (
src: string,
size: "large" | "medium" | "small",
setIsCopied: React.Dispatch<React.SetStateAction<boolean>>
) => {
try {
const resizedBlob = await resizeImage(src, size);
if (resizedBlob) {
const clipboardItem = new ClipboardItem({ [resizedBlob.type]: resizedBlob });
await navigator.clipboard.write([clipboardItem]);
setIsCopied(true);
setTimeout(() => {
setIsCopied(false);
}, 3000); // 3秒後にテキストを戻す
}
} catch (err) {
console.error("Failed to copy on clipboard", err);
}
};
v2
詳細設計
- UI設計:
- スクロールバーと現在のサイズ(%)を表示する。
- サイズ調整時にリアルタイムでリサイズされた画像をプレビューとして表示する。
import { useState } from 'react';
const ImageResizer = ({ setImageSize }) => {
const [size, setSize] = useState(100); // 初期値は100%
const handleSliderChange = (e) => {
const newSize = e.target.value;
setSize(newSize);
setImageSize(newSize); // 親コンポーネントにサイズを伝える
};
return (
<div>
<label>{size}%</label>
<input
type="range"
min="10"
max="100"
value={size}
onChange={handleSliderChange}
/>
</div>
);
};
- 画像リサイズ処理:
const resizeImage = async (src: string, sizePercentage: number) => {
const response = await axios.get(src, { responseType: "blob" });
const blob = response.data;
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
const image = await createImageBitmap(blob);
const sizeMultiplier = sizePercentage / 100;
canvas.width = image.width * sizeMultiplier;
canvas.height = image.height * sizeMultiplier;
if (ctx) {
ctx.drawImage(image, 0, 0, canvas.width, canvas.height);
}
return new Promise<Blob | null>((resolve) => {
canvas.toBlob((newBlob) => resolve(newBlob), blob.type);
});
};
- ダウンロード時の処理:
export const downloadImage = async (src: string, sizePercentage: number) => {
try {
const resizedBlob = await resizeImage(src, sizePercentage);
if (resizedBlob) {
const fileName = src.substring(src.lastIndexOf("/") + 1);
saveAs(resizedBlob, fileName);
}
} catch (error) {
console.error("Image download failed", error);
}
};