react-image-crop kütüphanesiyle croplanmış olan resmin kaydedilmesi
react-image-crop kütüphanesini kullanarak müşteri için ürünlerini yükleyebildiği ve ürün resimlerini boyutlandırabileceği bir cms yazmakla uğraşıyordum. 2 gündür deniyorum olmuyor. Sorum biraz frontend i kapsıyor.
const handleOnCropComplete = (crop, pixelCrop) => {
const croppedImg = getCroppedImg(productImage, crop, 'test');
console.log(croppedImg);
}
resim crop işlemi yapıldıktan sonra bu üste gördüğümüz fonksiyon çalışyor ve bunun ardından getCroppedImg isimli farklı bir fonksiyona :
state de bulunan productImage (file inputtan alınan resmin blob u)
crop parametresi kütüphanenın sagladıgı bir parametre kesılen alanın verısını verıyor
test yazdıgım kısımda fıleName kısmı oda resmımızın ısmı oluyor.
hatam ctx.drawImage ... kısmında oluşuyor hata kodu şu şekilde:
TypeError: Failed to execute 'drawImage'
on 'CanvasRenderingContext2D':
The provided value is not of type '(CSSImageValue or HTMLImageElement
or SVGImageElement or HTMLVideoElement or HTMLCanvasElement or
ImageBitmap or OffscreenCanvas or VideoFrame)'
blob oldugundan bende mantıklı olarak new Image() kullanarak HTML elementı olusturdum fakat olmadı
AddProductScreen.js
import React, { useState, useEffect } from 'react'
import { RiAddFill } from 'react-icons/ri';
import 'react-image-crop/dist/ReactCrop.css';
import ReactCrop from 'react-image-crop';
function AddProductScreen() {
const [productImage, setproductImage] = useState(null);
const [crop, setCrop] = useState({ aspect: 16 / 9 });
const [OnImageLoaded, setOnImageLoaded] = useState(null);
const SelectImageHandler = async (e) => {
const objectURL = URL.createObjectURL(e.target.files[0])
setproductImage(objectURL);
}
const handleOnCropComplete = (crop, pixelCrop) => {
const croppedImg = getCroppedImg(productImage, crop, 'test');
console.log(croppedImg);
}
function getCroppedImg(image, crop, fileName) {
const canvas = document.createElement('canvas');
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,
);
// As Base64 string
// const base64Image = canvas.toDataURL('image/jpeg');
// As a blob
return new Promise((resolve, reject) => {
canvas.toBlob(blob => {
blob.name = fileName;
resolve(blob);
}, 'image/jpeg', 1);
});
}
function CropDemo({ src }) {
return <ReactCrop src={src} crop={crop}
onChange={newCrop => setCrop(newCrop)}
onComplete={handleOnCropComplete}
onImageLoaded={image => setOnImageLoaded(setOnImageLoaded({ crop: { width: image.width, height: image.height } }))}
/>;
}
return (
<div className="inner-container flex-row">
<form>
<div>
<label for="">Ürün Adı</label>
<input type="text" />
</div>
<div>
<label for="">Ürün Kategorisi</label>
<select>
<option value="">Anadolu Halısı</option>
<option value="">A Halısı</option>
<option value="">B Halısı</option>
</select>
</div>
<div>
<label for="">Ürün Resmi</label>
<input onChange={(e) => SelectImageHandler(e)} type="file" />
{CropDemo({ src: productImage })}
</div>
<button className="add-btn"><RiAddFill />Ürünü Ekle</button>
</form>
<div className="addProduct-preview">
<div className="preview-box">
<div className="productHeader">
<span>Ürün Adı</span>
<small>Ürün Kategorisi</small>
</div>
<div className="preview-image-box">
</div>
</div>
</div>
</div>
)
}
export default AddProductScreen
package.json
{
"name": "saricalar-stok-yonetimi",
"version": "0.1.0",
"private": true,
"dependencies": {
"@testing-library/jest-dom": "^5.11.4",
"@testing-library/react": "^11.1.0",
"@testing-library/user-event": "^12.1.10",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-icons": "^4.2.0",
"react-image-crop": "^8.6.12",
"react-router-dom": "^5.2.0",
"react-scripts": "4.0.3",
"web-vitals": "^1.0.1"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
yardımcı olabilirseniz mutlu olurum :) iyi calismalar diliyorum
Soru hatalı mı? 👎
Eğer sorunun kurallara aykırı olduğunu düşünüyorsanız lütfen bize bildirin!
Cevaplar (3)
getCroppedImg bu fonksiyona dikkatli bakarsan bir Promise
döndürüyorsun hata alman çok normal onun yerine şunu mantıkda ilerleyebilirsin
yazılan method'un resolvunun yerine direk olarak blob olarak gönderebilirsin belki ?
const myimage = new Image();
myimage.src = image;
console.log(myimage.naturalWidth, myimage.naturalHeight, crop.width, crop.height)
const canvas = document.createElement('canvas');
const scaleX = myimage.naturalWidth / onImageLoaded.crop.width;
const scaleY = myimage.naturalHeight / onImageLoaded.crop.height;
canvas.width = crop.width;
canvas.height = crop.height;
const ctx = canvas.getContext('2d');
ctx.drawImage(
myimage,
crop.x * scaleX,
crop.y * scaleY,
crop.width * scaleX,
crop.height * scaleY,
0,
0,
crop.width,
crop.height,
);
// As Base64 string
return canvas.toDataURL('image/jpeg');
// As a blob
/*
return new Promise((resolve, reject) => {
canvas.toBlob(blob => {
blob.name = fileName;
resolve(blob);
}, 'image/jpeg', 1);
});*/
çözümü bu şekilde takılan arkadaşlara destek olsun cok ugrastırdı. Burada öğrendiğim şey canvasa bir resim cizmek istediğimizde HTML ımage olarak yenı bır element olusturmak sonrasında da tabi farklı sorunlarlada karşılastım mesela cropladıgım alanın degerleri tam optimize olmuyordu suan sorunsuz calısıyor teşekkürler kardeşim herkese iyi çalışmalar
dedigini dikkate alarak tekrar bi deneme yaptıp canvasta blob kullanamıyor muyuz acaba cünkü ben normalde canvasa resim cizdirmek istediğimde new Image() dıyerek HTML ımage elementı olusturarak onu draw edıyordum. bi kez daha deniyim insallah olur bu sefer