Skip to content

Commit 3cddb9c

Browse files
committed
feat: Initial commit for export as Image
1 parent 4049c6c commit 3cddb9c

5 files changed

Lines changed: 162 additions & 33 deletions

File tree

components/core/App.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ const App = (props) => {
6464
width={300}
6565
/>
6666
) : (
67-
<ShapeList data={ data } />
67+
<ShapeList {...props} data={ data } />
6868
)}
6969
</>
7070
);

components/core/ExportShape.js

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
import React, { useState } from "react";
2+
3+
// dynamic from Next.js
4+
import dynamic from "next/dynamic";
5+
6+
// modal
7+
import Modal from "react-bootstrap/Modal";
8+
9+
// button
10+
import Button from "react-bootstrap/Button";
11+
12+
// Clip-Path
13+
const Shape = dynamic(import("react-clip-path"), { ssr: false });
14+
15+
// Toast
16+
import toast from "react-hot-toast";
17+
18+
// html-to-image
19+
import { toPng, toJpeg, toSvg, toCanvas } from "html-to-image";
20+
21+
// downloadjs
22+
import download from "downloadjs";
23+
24+
// misc utilities
25+
import { getShapeId } from "../../utils/misc";
26+
27+
const ExportShape = ({ show, setShow, shape }) => {
28+
console.log({ shape });
29+
const [exportType, setExportType] = useState('png');
30+
31+
const doExport = (id, name) => {
32+
console.log("Save as Png");
33+
switch(exportType) {
34+
case "png":
35+
exportAsPNG(id, name);
36+
break;
37+
case "jpeg":
38+
exportAsJPEG(id, name);
39+
break;
40+
case "svg":
41+
exportAsSVG(id, name);
42+
break;
43+
case "canvas":
44+
exportAsCanvas(id, name);
45+
break;
46+
default:
47+
exportAsPNG(id, name);
48+
break;
49+
}
50+
51+
};
52+
53+
const exportAsPNG = (id, name) => {
54+
toPng(document.getElementById(id)).then(function (dataUrl) {
55+
console.log(dataUrl);
56+
download(dataUrl, `${name}.png`);
57+
toast.success(`${name}.png has been exported sucessfully!`);
58+
});
59+
}
60+
const exportAsCanvas = (id, name) => {
61+
toCanvas(document.getElementById(id)).then(function (dataUrl) {
62+
console.log(dataUrl);
63+
download(dataUrl, `${name}.png`);
64+
toast.success(`${name}.png has been exported sucessfully!`);
65+
});
66+
}
67+
const exportAsJPEG = (id, name) => {
68+
toJpeg(document.getElementById(id)).then(function (dataUrl) {
69+
console.log(dataUrl);
70+
download(dataUrl, `${name}.png`);
71+
toast.success(`${name}.png has been exported sucessfully!`);
72+
});
73+
}
74+
const exportAsSVG = (id, name) => {
75+
toSvg(document.getElementById(id)).then(function (dataUrl) {
76+
console.log(dataUrl);
77+
download(dataUrl, `${name}.png`);
78+
toast.success(`${name}.png has been exported sucessfully!`);
79+
});
80+
}
81+
return (
82+
<>
83+
{shape &&
84+
<Modal
85+
size="lg"
86+
aria-labelledby="contained-modal-title-vcenter"
87+
show={show}
88+
onHide={() => setShow(false)}
89+
centered
90+
>
91+
<Modal.Header closeButton>
92+
<Modal.Title>Export {shape.name} </Modal.Title>
93+
</Modal.Header>
94+
<Modal.Body>
95+
<div>
96+
<Shape
97+
name={shape.name}
98+
formula={shape.formula}
99+
width="300px"
100+
height="300px"
101+
backgroundColor={shape.backgroundColor}
102+
id={getShapeId(shape.name, true)}
103+
/>
104+
</div>
105+
<div>
106+
107+
</div>
108+
</Modal.Body>
109+
110+
<Modal.Footer>
111+
<Button
112+
onClick={() => doExport(getShapeId(shape.name, true), shape.name)}
113+
>
114+
Export
115+
</Button>
116+
</Modal.Footer>
117+
</Modal>}
118+
</>
119+
);
120+
};
121+
122+
export default ExportShape;

components/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
export { default as App } from "./core/App";
33
export { default as Landing } from "./core/Landing";
44
export { default as SignInModal } from "./core/SignInModal";
5+
export { default as ExportShape } from "./core/ExportShape";
56

67
// utils
78
export { default as Header } from "./utils/Header";

components/utils/ShapeList.js

Lines changed: 28 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,15 @@ const Shape = dynamic(import("react-clip-path"), { ssr: false });
1515
// Switch
1616
import Switch from "react-switch";
1717

18-
// html-to-image
19-
import { toPng } from 'html-to-image';
20-
21-
// downloadjs
22-
import download from 'downloadjs';
23-
2418
// icons
2519
import { FiCopy, FiDownload, FiHeart, FiLock } from 'react-icons/fi';
20+
import { BiExport } from "react-icons/bi";
21+
22+
// Export Shape
23+
import { ExportShape } from '..';
24+
25+
// misc unitless
26+
import { getShapeFileName, getShapeId } from '../../utils/misc';
2627

2728
// Shape Listing Styled-Componentns
2829
const ShapeCards = styled.div`
@@ -86,7 +87,7 @@ const CopyIcon = styled(FiCopy)`
8687
}
8788
`;
8889

89-
const DownloadIcon = styled(FiDownload)`
90+
const ExportIcon = styled(BiExport)`
9091
cursor: pointer;
9192
&:hover {
9293
color: #f71b76;
@@ -100,9 +101,11 @@ const LikeIcon = styled(FiHeart)`
100101
}
101102
`;
102103

103-
const ShapeList = ({ data }) => {
104+
const ShapeList = ({ setOpen, user, data }) => {
104105

105106
const [shapes, setShapes] = useState(data);
107+
const [showExportModal, setShowExportModal] = useState(false);
108+
const [shapeToExport, setShapeToExport] = useState();
106109

107110
const handleSwicth = (shapeName) => {
108111

@@ -118,20 +121,6 @@ const ShapeList = ({ data }) => {
118121
setShapes(...[modifiedShapes]);
119122
};
120123

121-
const getShapeFileName = (name) => {
122-
return name.split(" ").join("-");
123-
};
124-
125-
const saveAsPng = (event, id, name) => {
126-
console.log('Save as Png');
127-
128-
toPng(document.getElementById(id)).then(function (dataUrl) {
129-
console.log(dataUrl);
130-
download(dataUrl, `${name}.png`);
131-
toast.success(`${name}.png has been exported sucessfully!`);
132-
});
133-
}
134-
135124
async function performCopy(event, formula) {
136125
event.preventDefault();
137126
try {
@@ -143,9 +132,22 @@ const ShapeList = ({ data }) => {
143132
}
144133
}
145134

135+
const performExport = shape => {
136+
if (user.length === 0) {
137+
setOpen(true);
138+
} else {
139+
setShapeToExport(shape);
140+
setShowExportModal(true);
141+
}
142+
}
143+
146144
return (
147145
<ShapePallete>
148146
<ShapeCards>
147+
<ExportShape
148+
show={ showExportModal }
149+
setShow={ setShowExportModal }
150+
shape = { shapeToExport } />
149151
{shapes.map((shape, index) => (
150152
<React.Fragment key={index}>
151153
<ShapeCard>
@@ -156,16 +158,10 @@ const ShapeList = ({ data }) => {
156158
<span title="Like">
157159
<LikeIcon size={24} />
158160
</span>{" "}
159-
<span title="Download">
160-
<DownloadIcon
161+
<span title="Export">
162+
<ExportIcon
161163
size={24}
162-
onClick={(event) =>
163-
saveAsPng(
164-
event,
165-
`${getShapeFileName(shape.name)}-id`,
166-
getShapeFileName(shape.name)
167-
)
168-
}
164+
onClick={() => performExport(shape)}
169165
/>
170166
</span>
171167
</ShapeActions>
@@ -174,7 +170,7 @@ const ShapeList = ({ data }) => {
174170
width="300px"
175171
height="300px"
176172
name={shape.name}
177-
id={`${getShapeFileName(shape.name)}-id`}
173+
id={getShapeId(shape.name)}
178174
backgroundColor="#eb3d86"
179175
showShadow={shape.showAdvanced}
180176
/>

utils/misc.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
2+
export const getShapeFileName = name => {
3+
return name.split(" ").join("-");
4+
};
5+
6+
export const getShapeId = (name, isExport) => {
7+
return isExport ?
8+
`${getShapeFileName(name)}-export-id` :
9+
`${getShapeFileName(name)}-id`;
10+
}

0 commit comments

Comments
 (0)