@adeelasif/awesome-editor
Version:
A full fledge web based photo editor
259 lines (236 loc) • 7.11 kB
JSX
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;