Heim > Artikel > Web-Frontend > Erstellen eines Reaktionshakens zum Drehen von Bildern in einem beliebigen Winkel
Bei der Webentwicklung müssen Sie möglicherweise ein Bild drehen, was in CSS einfach zu bewerkstelligen ist. Einfacher Code wie diese Transformation: rotation(90deg);. Aber was ist, wenn wir es in JS machen wollen?
Zeichnet das Bild auf die Leinwand in der Browserumgebung und dreht es. Aber vorher müssen wir noch etwas rechnen, um das ursprüngliche Seitenverhältnis des Bildes beizubehalten.
Angenommen, wir haben das Bild geladen, kann die Berechnung des gedrehten Bildes wie folgt erfolgen:
const { PI, sin, cos, abs } = Math; const angle = (degree * PI) / 180; const sinAngle = sin(angle); const cosAngle = cos(angle); const rotatedWidth = abs(imageWidth * cosAngle) + abs(imageHeight * sinAngle); const rotatedHeight = abs(imageWidth * sinAngle) + abs(imageHeight * cosAngle);
Und als nächstes verwenden wir einige der Canvas-APIs, um die eigentliche Drehung durchzuführen:
const canvas = document.createElement('canvas'); const { width: canvasWidth, height: canvasHeight } = canvas; const canvasCtx2D = canvas.getContext('2d'); canvasCtx2D.clearRect(0, 0, canvasWidth, canvasHeight); canvasCtx2D.translate(canvasWidth / 2, canvasHeight / 2); canvasCtx2D.rotate(angle); canvasCtx2D.drawImage( image, -imageWidth / 2, -imageHeight / 2, imageWidth, imageHeight, ); return canvas.toDataURL('image/png');
Wenn der Kerncode vorhanden ist, können wir einige Optimierungen vornehmen und dedizierte React-Hooks schreiben, um ihn zu verwenden:
import { useEffect, useRef, useState } from 'react'; type RotatedImage = { src: string; width: number; height: number; } | null; let canvas: HTMLCanvasElement | null = null; let canvasCtx2D: CanvasRenderingContext2D | null = null; const getRotatedImage = ( image: HTMLImageElement | null, rotation: number, ): RotatedImage => { canvas ??= document.createElement('canvas'); canvasCtx2D ??= canvas.getContext('2d'); if (!image || !canvasCtx2D) return null; const { width: imageWidth, height: imageHeight, currentSrc } = image; const degree = rotation % 360; if (!degree) { return { src: currentSrc, width: imageWidth, height: imageHeight, }; } const { PI, sin, cos, abs } = Math; const angle = (degree * PI) / 180; const sinAngle = sin(angle); const cosAngle = cos(angle); canvas.width = abs(imageWidth * cosAngle) + abs(imageHeight * sinAngle); canvas.height = abs(imageWidth * sinAngle) + abs(imageHeight * cosAngle); // The width and height of the canvas will be automatically rounded. const { width: canvasWidth, height: canvasHeight } = canvas; canvasCtx2D.clearRect(0, 0, canvasWidth, canvasHeight); canvasCtx2D.translate(canvasWidth / 2, canvasHeight / 2); canvasCtx2D.rotate(angle); canvasCtx2D.drawImage( image, -imageWidth / 2, -imageHeight / 2, imageWidth, imageHeight, ); const src = canvas.toDataURL('image/png'); canvas.width = 0; canvas.height = 0; return { src, width: canvasWidth, height: canvasHeight, }; }; const useRotateImage = (imageSrc: string, rotation?: number): RotatedImage => { const imageEle = useRef<HTMLImageElement | null>(null); const [rotatedImage, setRotatedImage] = useState<RotatedImage>(null); useEffect(() => { if (typeof rotation === 'number') { let currImage = imageEle.current; if (currImage?.currentSrc !== imageSrc) { currImage = new Image(); imageEle.current = currImage; currImage.src = imageSrc; } currImage.decode().then( () => setRotatedImage(getRotatedImage(currImage, rotation)), () => setRotatedImage(null), ); } }, [imageSrc, rotation]); return rotatedImage; }; export default useRotateImage;
Hier verwende ich dasselbe Canvas-Element wieder, um wiederholte Erstellungen zu reduzieren. Zweitens sollte beachtet werden, dass ich seine Breite und Höhe nach jeder Drehung auf 0 setze, um den Speicherverbrauch zu reduzieren. Übrigens habe ich auch die Reinigung der Leinwand durchgeführt. Dies liegt daran, dass in der HTML-Spezifikation, wenn Sie die Breite und Höhe der Leinwand ändern (unabhängig davon, ob sie dieselben wie zuvor sind), die Leinwand gelöscht wird, was mit „canvasCtx2D.clearRect(0, 0, canvasWidth, canvasHeight)“ identisch ist wird von modernen Browsern unterstützt.
In useRotateImage behalte ich einen Verweis auf das Bildelement und lege den gedrehten Bildstatus nach image.decode() fest, der aufgelöst wird, nachdem die Bilddaten bereit sind.
Unten finden Sie einen Online-Anwendungsfall:
Wenn Sie dies hilfreich fanden, denken Sie bitte darüber nach Abonnieren Sie meinen Newsletter für weitere nützliche Artikel und Tools zur Webentwicklung. Danke fürs Lesen!
Das obige ist der detaillierte Inhalt vonErstellen eines Reaktionshakens zum Drehen von Bildern in einem beliebigen Winkel. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!