v1

詳細設計

  1. UI設計:
tsx
コードをコピーする
const SizeOptions = ({ setSelectedSize }) => {
  return (
    <div>
      <button onClick={() => setSelectedSize("large")}>大</button>
      <button onClick={() => setSelectedSize("medium")}>中</button>
      <button onClick={() => setSelectedSize("small")}>小</button>
    </div>
  );
};

  1. 画像リサイズ処理:
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);
  });
};

  1. ダウンロード時の処理:
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);
  }
};

  1. コピー時の処理:
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

詳細設計

  1. 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>
  );
};

  1. 画像リサイズ処理:

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);
  });
};

  1. ダウンロード時の処理:

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);
  }
};