簡體   English   中英

如何使用 react-image-crop 顯示裁剪部分 - 它顯示為裁剪部分的黑色圖像

[英]How do I display the cropped part using react-image-crop- It appears as a black image of the cropped portion

function getCroppedImg(){
        
        console.log('inside getCroppedImg')
        const canvas = document.createElement("canvas");
        const image = document.createElement("image");
        const scaleX = image.naturalWidth / image.width;
        const scaleY = image.naturalHeight / image.height;
        canvas.width = crop.width;
        canvas.height = crop.height;
        const ctx = canvas.getContext("2d");
        ctx.drawImage(
            image,
            crop.x * scaleX,
            crop.y * scaleY,
            crop.width * scaleX,
            crop.height * scaleY,
            0,
            0,
            crop.width,
            crop.height
            );
            const base64Image = canvas.toDataURL("image/jpeg", 1);
            setResult(base64Image);
          
    };
const [srcImg, setSrcImg] = useState(null);
    const [image, setImage] = useState(null);
    const [crop, setCrop] = useState({aspect: 16 / 9});
    const [result, setResult] = useState(null);

    const handleImage = event => {
        setSrcImg(URL.createObjectURL(event.target.files[0]));
        console.log(event.target.files[0]);
    };
return (
<div>
{srcImg && (
 <div>
<ReactCrop src={srcImg} onLoad={setImage} crop={crop} onChange={(crop) => setCrop(crop)}>
<img src={srcImg}/>
</ReactCrop>
<button className="cropButton" onClick={getCroppedImg}>crop</button>
</div>)}
{result && (
<div>
<img src={result} alt="cropped image"/>
</div>
=)}
</div>)

上面是點擊裁剪按鈕時調用的 function。 但它返回的是黑色圖像。 我想用“結果”來顯示它。 基本上我正在嘗試輸入圖像,點擊裁剪按鈕裁剪的部分應該顯示在{result}中。 我不介意它是否也作為預覽出現,比如動態裁剪預覽。

編輯:我已經更新了代碼。 這就是我現在得到的在此處輸入圖像描述 .

顯示為黑色圖像。 我該如何解決?

處理圖像的不錯的庫

因此,根據他們的官方文檔https://www.npmjs.com/package/react-image-crop沒有內置的方式來顯示裁剪區域“我如何在瀏覽器中生成裁剪預覽?這不是圖書館的一部分”

另一方面,他們提供了帶有“裁剪預覽”實現的實例: https://codesandbox.io/s/react-image-crop-demo-with-react-hooks-y831o?file=/src/App.tsx: 3989-4188

在我這邊,我決定使用 crop preview-s 來簡化一些工作,並為此實現了額外的組件。 我使用上面的代碼示例作為參考。

import { useEffect, useRef } from 'react';

import { canvasPreview } from './canvasPreview';

export default function CropPreview({ img, crop }) {
    const canvasRef = useRef(null);

    useEffect(() => {
        if (!crop?.width || !crop?.height || !img || !canvasRef.current) {
            return;
        }

        canvasPreview(img, canvasRef.current, crop, 1, 0);
    }, [img, crop]);

    if (!!crop && !!img) {
        return <canvas ref={canvasRef} />;
    }
}

它的用法:

import { useRef, useState } from 'react';

import CropPreview from './CropPreview';
import ReactCrop from 'react-image-crop';

function App() {
    const imgRef = useRef(null);
    const [crop, setCrop] = useState();
    const [completedCrop, setCompletedCrop] = useState();

    return (
        <>
            <div style={{ maxWidth: '500px' }}>
                <ReactCrop
                    crop={crop}
                    onChange={setCrop}
                    onComplete={(c) => setCompletedCrop(c)}
                >
                    <img
                        crossOrigin="anonymous"
                        ref={imgRef}
                        src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/b6/Image_created_with_a_mobile_phone.png/1024px-Image_created_with_a_mobile_phone.png"
                    />
                </ReactCrop>
            </div>

            <CropPreview img={imgRef.current} crop={completedCrop} />
        </>
    );
}

export default App;

canvasPreview.js 是從上面的實例中“按原樣”獲取的,只刪除了一些特定於打字稿的代碼片段(我在沒有 TS 的情況下創建了這個組件):

const TO_RADIANS = Math.PI / 180;

export async function canvasPreview(
    image,
    canvas,
    crop,
    scale = 1,
    rotate = 0
) {
    const ctx = canvas.getContext('2d');

    if (!ctx) {
        throw new Error('No 2d context');
    }

    const scaleX = image.naturalWidth / image.width;
    const scaleY = image.naturalHeight / image.height;
    // devicePixelRatio slightly increases sharpness on retina devices
    // at the expense of slightly slower render times and needing to
    // size the image back down if you want to download/upload and be
    // true to the images natural size.
    const pixelRatio = window.devicePixelRatio;
    // const pixelRatio = 1

    canvas.width = Math.floor(crop.width * scaleX * pixelRatio);
    canvas.height = Math.floor(crop.height * scaleY * pixelRatio);

    ctx.scale(pixelRatio, pixelRatio);
    ctx.imageSmoothingQuality = 'high';

    const cropX = crop.x * scaleX;
    const cropY = crop.y * scaleY;

    const rotateRads = rotate * TO_RADIANS;
    const centerX = image.naturalWidth / 2;
    const centerY = image.naturalHeight / 2;

    ctx.save();

    // 5) Move the crop origin to the canvas origin (0,0)
    ctx.translate(-cropX, -cropY);
    // 4) Move the origin to the center of the original position
    ctx.translate(centerX, centerY);
    // 3) Rotate around the origin
    ctx.rotate(rotateRads);
    // 2) Scale the image
    ctx.scale(scale, scale);
    // 1) Move the center of the image to the origin (0,0)
    ctx.translate(-centerX, -centerY);
    ctx.drawImage(
        image,
        0,
        0,
        image.naturalWidth,
        image.naturalHeight,
        0,
        0,
        image.naturalWidth,
        image.naturalHeight
    );

    ctx.restore();
}

使用此解決方案,您將能夠在 canvas 上顯示當前裁剪。

我不太清楚為什么您最初嘗試在 canvas 上繪制當前作物,然后在圖像上從 canvas 繪制當前作物。 但是,如果出於某種原因這很重要——像下面這樣的代碼片段會將裁剪從 canvas“轉移”到圖像:

canvasRef.current.toBlob((blob) => {
    const url = URL.createObjectURL(blob);
    const image = document.createElement('img');
    document.body.appendChild(image);
    image.onload = function () {
        URL.revokeObjectURL(url);
    };
    image.src = url;
});

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM