UNPKG

@wordpress/block-editor

Version:
138 lines (137 loc) 3.89 kB
// packages/block-editor/src/components/image-editor/use-transform-image.js import { useCallback, useEffect, useMemo, useState } from "@wordpress/element"; import { applyFilters } from "@wordpress/hooks"; import { useImageCropper } from "@wordpress/image-cropper"; function useTransformImage({ url, naturalWidth, naturalHeight }) { const [editedUrl, setEditedUrl] = useState(); const { cropperState, setCropperState } = useImageCropper(); const { zoom, aspectRatio, crop, croppedArea } = cropperState; const setZoom = useCallback( (newZoom) => { setCropperState({ zoom: newZoom }); }, [setCropperState] ); const setAspectRatio = useCallback( (newAspect) => { setCropperState({ aspectRatio: newAspect }); }, [setCropperState] ); const defaultAspect = naturalWidth / naturalHeight; const rotatedAspect = naturalHeight / naturalWidth; useEffect(() => { setAspectRatio(defaultAspect); }, []); const [internalRotation, setInternalRotation] = useState(0); const rotateClockwise = useCallback(() => { const angle = (internalRotation + 90) % 360; let naturalAspectRatio = defaultAspect; const isDefaultAspect = defaultAspect === aspectRatio || rotatedAspect === aspectRatio; const shouldResetAspect = zoom !== 1 || !isDefaultAspect; if (internalRotation % 180 === 90) { naturalAspectRatio = 1 / defaultAspect; } if (angle === 0) { setEditedUrl(); setInternalRotation(angle); const newAspectRatio = shouldResetAspect ? aspectRatio : defaultAspect; setCropperState({ aspectRatio: newAspectRatio, crop: { x: -(crop.y * naturalAspectRatio), y: crop.x * naturalAspectRatio } }); return; } function editImage(event) { const canvas = document.createElement("canvas"); let translateX = 0; let translateY = 0; if (angle % 180) { canvas.width = event.target.height; canvas.height = event.target.width; } else { canvas.width = event.target.width; canvas.height = event.target.height; } if (angle === 90 || angle === 180) { translateX = canvas.width; } if (angle === 270 || angle === 180) { translateY = canvas.height; } const context = canvas.getContext("2d"); context.translate(translateX, translateY); context.rotate(angle * Math.PI / 180); context.drawImage(event.target, 0, 0); canvas.toBlob((blob) => { setEditedUrl(URL.createObjectURL(blob)); setInternalRotation(angle); const newAspectRatio = shouldResetAspect ? aspectRatio : canvas.width / canvas.height; setCropperState({ aspectRatio: newAspectRatio, crop: { x: -(crop.y * naturalAspectRatio), y: crop.x * naturalAspectRatio } }); }); } const el = new window.Image(); el.src = url; el.onload = editImage; const imgCrossOrigin = applyFilters( "media.crossOrigin", void 0, url ); if (typeof imgCrossOrigin === "string") { el.crossOrigin = imgCrossOrigin; } }, [ internalRotation, defaultAspect, url, setCropperState, crop, zoom, aspectRatio, rotatedAspect, setInternalRotation ]); return useMemo( () => ({ editedUrl, setEditedUrl, crop: croppedArea, zoom, setZoom, rotation: internalRotation, rotateClockwise, aspect: aspectRatio, setAspect: setAspectRatio, defaultAspect }), [ editedUrl, croppedArea, zoom, setZoom, internalRotation, rotateClockwise, aspectRatio, setAspectRatio, defaultAspect ] ); } export { useTransformImage as default }; //# sourceMappingURL=use-transform-image.js.map