UNPKG

@adeelasif/awesome-editor

Version:

A full fledge web based photo editor

259 lines (236 loc) 7.11 kB
import React from "react"; import Modal from "react-modal"; import "semantic-ui-css/semantic.min.css"; import { Grid, Menu, Segment, Button } from "semantic-ui-react"; import Filters from "./Actions/Filters"; import Banner from "./Actions/Banner"; import Adjustments from "./Actions/Adjustments"; import ReactCrop from "react-image-crop"; import "react-image-crop/dist/ReactCrop.css"; import "./Editor.css"; const customStyles = { content: { top: "10%", left: "10%", right: "auto", bottom: "auto", width: "80%", height: "80%", }, }; // Make sure to bind modal to your appElement (http://reactcommunity.org/react-modal/accessibility/) Modal.setAppElement("body"); // const menuItems = ["Filter", "Adjustments", "Crop", "Mask", "Banner"]; const menuItems = ["Filter", "Adjustments"]; const getFilters = (activeItem, canvasId, imgURL, setActivePreset) => { switch (activeItem) { case "Filter": return ( <Filters canvasId={canvasId} image={imgURL} setActivePreset={setActivePreset} /> ); case "Banner": case "Mask": return ( <Banner canvasId={canvasId} image={imgURL} setActivePreset={setActivePreset} /> ); case "Adjustments": return ( <Adjustments canvasId={canvasId} image={imgURL} setActivePreset={setActivePreset} /> ); default: return null; } }; function download(canvas, filename) { var e; var lnk = document.createElement("a"); lnk.download = filename; lnk.href = canvas.toDataURL("image/jpeg", 0.8); if (document.createEvent) { e = document.createEvent("MouseEvents"); e.initMouseEvent( "click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null ); lnk.dispatchEvent(e); } else if (lnk.fireEvent) { lnk.fireEvent("onclick"); } } const saveImage = (canvas, image) => { const fileName = image.name; var fileExtension = fileName.slice(-4); if (fileExtension === ".jpg" || fileExtension === ".png") { var actualName = fileName.substring(0, fileName.length - 4); } download(canvas, actualName + "-edited.jpg"); }; const getImageDimensionsRelativeToCanvas = (canvas, img) => { const hRatio = canvas.width / img.width; const vRatio = canvas.height / img.height; const ratio = Math.min(hRatio, vRatio); const centerShift_x = (canvas.width - img.width * ratio) / 2; const centerShift_y = (canvas.height - img.height * ratio) / 2; return { width: img.width * ratio, height: img.height * ratio, }; }; export const Editor = (props) => { const { isOpen, image } = props; const [activeItem, setActiveItem] = React.useState(menuItems[0]); const [mainCanvas, setMainCanvas] = React.useState(); const [crop, setCrop] = React.useState({}); const [loadedImage, setLoadedImage] = React.useState(); const mainCanvasId = "mainCanvas"; const imgURL = image ? URL.createObjectURL(image) : ""; const revertCanvasChanges = (canvasId) => { global.Caman(`#${canvasId}`, imgURL, function () { this.revert(); this.render(); }); }; const getMainCanvas = () => document.getElementById(mainCanvasId); const canvasRef = React.useCallback((node) => { setMainCanvas(node); }, []); const handleItemClick = (e, { name }) => setActiveItem(name); React.useEffect(() => { if (isOpen && image && mainCanvas) { const reader = new FileReader(); const canvas = getMainCanvas(); if (canvas) { const ctx = canvas.getContext("2d"); const file = image; if (file) { reader.readAsDataURL(file); } reader.addEventListener( "load", function () { const img = new Image(); img.src = reader.result; img.onload = function () { const hRatio = canvas.width / img.width; const vRatio = canvas.height / img.height; const ratio = Math.min(hRatio, vRatio); const centerShift_x = (canvas.width - img.width * ratio) / 2; const centerShift_y = (canvas.height - img.height * ratio) / 2; ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.drawImage( img, 0, 0, img.width, img.height, centerShift_x, centerShift_y, img.width * ratio, img.height * ratio ); }; setLoadedImage(img); }, false ); } } }, [mainCanvas, isOpen, image]); const renderActions = () => { return ( <div> <Button onClick={() => revertCanvasChanges(mainCanvasId)}> Revert </Button> <Button onClick={() => saveImage(mainCanvas, image)}>Save</Button> </div> ); }; const setActivePreset = (preset) => {}; const renderFilters = () => { return getFilters(activeItem, mainCanvasId, imgURL, setActivePreset); }; return ( <div id="editor"> <Modal isOpen={props.isOpen} onAfterOpen={props.afterOpenModal} onRequestClose={props.onClose} style={customStyles} contentLabel="Example Modal" > <Grid className="main-container"> <Grid.Column width={4} className="full-height"> <Menu fluid vertical tabular className="left-menu"> {menuItems.map((item, index) => { return ( <Menu.Item key={index} name={item} active={activeItem === item} onClick={handleItemClick} /> ); })} </Menu> </Grid.Column> <Grid.Column stretched width={12} className="full-height"> <Grid className="full-height"> <Grid.Column width={10}> <Segment className="canvas-container"> {activeItem === "Crop" ? ( <ReactCrop src={imgURL} crop={crop} ruleOfThirds={true} height={300} width={300} onChange={(newCrop) => setCrop(newCrop)} /> ) : ( <canvas height={600} width={655} ref={canvasRef} id={mainCanvasId} ></canvas> )} </Segment> {renderActions()} </Grid.Column> <Grid.Column width={6} className="full-height"> {renderFilters()} </Grid.Column> </Grid> </Grid.Column> </Grid> </Modal> </div> ); }; export default Editor;