mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-05-03 10:00:07 -04:00
parent
66938ae5c6
commit
b1a90c0020
4 changed files with 202 additions and 112 deletions
220
src/index.tsx
220
src/index.tsx
|
@ -2,6 +2,14 @@ import React from "react";
|
|||
import ReactDOM from "react-dom";
|
||||
import rough from "roughjs/bin/wrappers/rough";
|
||||
import { RoughCanvas } from "roughjs/bin/canvas";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import {
|
||||
faMousePointer,
|
||||
faSquare,
|
||||
faCircle,
|
||||
faLongArrowAltRight,
|
||||
faFont
|
||||
} from "@fortawesome/free-solid-svg-icons";
|
||||
|
||||
import "./styles.css";
|
||||
|
||||
|
@ -598,28 +606,28 @@ const KEYS = {
|
|||
|
||||
const SHAPES = [
|
||||
{
|
||||
label: "Rectange",
|
||||
icon: faMousePointer,
|
||||
value: "selection"
|
||||
},
|
||||
{
|
||||
icon: faSquare,
|
||||
value: "rectangle"
|
||||
},
|
||||
{
|
||||
label: "Ellipse",
|
||||
icon: faCircle,
|
||||
value: "ellipse"
|
||||
},
|
||||
{
|
||||
label: "Arrow",
|
||||
icon: faLongArrowAltRight,
|
||||
value: "arrow"
|
||||
},
|
||||
{
|
||||
label: "Text",
|
||||
icon: faFont,
|
||||
value: "text"
|
||||
},
|
||||
{
|
||||
label: "Selection",
|
||||
value: "selection"
|
||||
}
|
||||
];
|
||||
|
||||
const shapesShortcutKeys = SHAPES.map(shape => shape.label[0].toLowerCase());
|
||||
const shapesShortcutKeys = SHAPES.map(shape => shape.value[0]);
|
||||
|
||||
function findElementByKey(key: string) {
|
||||
const defaultElement = "selection";
|
||||
|
@ -716,6 +724,7 @@ class App extends React.Component<{}, AppState> {
|
|||
public render() {
|
||||
return (
|
||||
<div
|
||||
className="container"
|
||||
onCut={e => {
|
||||
e.clipboardData.setData(
|
||||
"text/plain",
|
||||
|
@ -756,28 +765,111 @@ class App extends React.Component<{}, AppState> {
|
|||
e.preventDefault();
|
||||
}}
|
||||
>
|
||||
<fieldset>
|
||||
<legend>Shapes</legend>
|
||||
{SHAPES.map(({ value, label }) => (
|
||||
<label key={value}>
|
||||
<div className="sidePanel">
|
||||
<h4>Shapes</h4>
|
||||
<div className="panelTools">
|
||||
{SHAPES.map(({ value, icon }) => (
|
||||
<label key={value} className="tool">
|
||||
<input
|
||||
type="radio"
|
||||
checked={this.state.elementType === value}
|
||||
onChange={() => {
|
||||
this.setState({ elementType: value });
|
||||
clearSelection();
|
||||
this.forceUpdate();
|
||||
}}
|
||||
/>
|
||||
<div className="toolIcon">
|
||||
<FontAwesomeIcon icon={icon} />
|
||||
</div>
|
||||
</label>
|
||||
))}
|
||||
</div>
|
||||
<h4>Colors</h4>
|
||||
<div className="panelColumn">
|
||||
<label>
|
||||
<input
|
||||
type="radio"
|
||||
checked={this.state.elementType === value}
|
||||
onChange={() => {
|
||||
this.setState({ elementType: value });
|
||||
clearSelection();
|
||||
this.forceUpdate();
|
||||
type="color"
|
||||
value={this.state.viewBackgroundColor}
|
||||
onChange={e => {
|
||||
this.setState({ viewBackgroundColor: e.target.value });
|
||||
}}
|
||||
/>
|
||||
<span>{label}</span>
|
||||
Background
|
||||
</label>
|
||||
))}
|
||||
</fieldset>
|
||||
|
||||
<label>
|
||||
<input
|
||||
type="color"
|
||||
value={this.state.currentItemStrokeColor}
|
||||
onChange={e => {
|
||||
this.setState({ currentItemStrokeColor: e.target.value });
|
||||
}}
|
||||
/>
|
||||
Shape Stroke
|
||||
</label>
|
||||
<label>
|
||||
<input
|
||||
type="color"
|
||||
value={this.state.currentItemBackgroundColor}
|
||||
onChange={e => {
|
||||
this.setState({ currentItemBackgroundColor: e.target.value });
|
||||
}}
|
||||
/>
|
||||
Shape Background
|
||||
</label>
|
||||
</div>
|
||||
<h4>Export</h4>
|
||||
<div className="panelColumn">
|
||||
<button
|
||||
onClick={() => {
|
||||
exportAsPNG({
|
||||
exportBackground: this.state.exportBackground,
|
||||
exportVisibleOnly: this.state.exportVisibleOnly,
|
||||
exportPadding: this.state.exportPadding,
|
||||
viewBackgroundColor: this.state.viewBackgroundColor
|
||||
});
|
||||
}}
|
||||
>
|
||||
Export to png
|
||||
</button>
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={this.state.exportBackground}
|
||||
onChange={e => {
|
||||
this.setState({ exportBackground: e.target.checked });
|
||||
}}
|
||||
/>
|
||||
background
|
||||
</label>
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={this.state.exportVisibleOnly}
|
||||
onChange={e => {
|
||||
this.setState({ exportVisibleOnly: e.target.checked });
|
||||
}}
|
||||
/>
|
||||
visible area only
|
||||
</label>
|
||||
<div>
|
||||
(padding:
|
||||
<input
|
||||
type="number"
|
||||
value={this.state.exportPadding}
|
||||
onChange={e => {
|
||||
this.setState({ exportPadding: Number(e.target.value) });
|
||||
}}
|
||||
disabled={!this.state.exportVisibleOnly}
|
||||
/>
|
||||
px)
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<canvas
|
||||
id="canvas"
|
||||
width={window.innerWidth}
|
||||
height={window.innerHeight - 210}
|
||||
width={window.innerWidth - 250}
|
||||
height={window.innerHeight}
|
||||
onWheel={e => {
|
||||
e.preventDefault();
|
||||
const { deltaX, deltaY } = e;
|
||||
|
@ -958,84 +1050,6 @@ class App extends React.Component<{}, AppState> {
|
|||
this.forceUpdate();
|
||||
}}
|
||||
/>
|
||||
<fieldset>
|
||||
<legend>Colors</legend>
|
||||
<label>
|
||||
<input
|
||||
type="color"
|
||||
value={this.state.viewBackgroundColor}
|
||||
onChange={e => {
|
||||
this.setState({ viewBackgroundColor: e.target.value });
|
||||
}}
|
||||
/>
|
||||
Background
|
||||
</label>
|
||||
<label>
|
||||
<input
|
||||
type="color"
|
||||
value={this.state.currentItemStrokeColor}
|
||||
onChange={e => {
|
||||
this.setState({ currentItemStrokeColor: e.target.value });
|
||||
}}
|
||||
/>
|
||||
Shape Stroke
|
||||
</label>
|
||||
<label>
|
||||
<input
|
||||
type="color"
|
||||
value={this.state.currentItemBackgroundColor}
|
||||
onChange={e => {
|
||||
this.setState({ currentItemBackgroundColor: e.target.value });
|
||||
}}
|
||||
/>
|
||||
Shape Background
|
||||
</label>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend>Export</legend>
|
||||
<button
|
||||
onClick={() => {
|
||||
exportAsPNG({
|
||||
exportBackground: this.state.exportBackground,
|
||||
exportVisibleOnly: this.state.exportVisibleOnly,
|
||||
exportPadding: this.state.exportPadding,
|
||||
viewBackgroundColor: this.state.viewBackgroundColor
|
||||
});
|
||||
}}
|
||||
>
|
||||
Export to png
|
||||
</button>
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={this.state.exportBackground}
|
||||
onChange={e => {
|
||||
this.setState({ exportBackground: e.target.checked });
|
||||
}}
|
||||
/>
|
||||
background
|
||||
</label>
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={this.state.exportVisibleOnly}
|
||||
onChange={e => {
|
||||
this.setState({ exportVisibleOnly: e.target.checked });
|
||||
}}
|
||||
/>
|
||||
visible area only
|
||||
</label>
|
||||
(padding:
|
||||
<input
|
||||
type="number"
|
||||
value={this.state.exportPadding}
|
||||
onChange={e => {
|
||||
this.setState({ exportPadding: Number(e.target.value) });
|
||||
}}
|
||||
disabled={!this.state.exportVisibleOnly}
|
||||
/>
|
||||
px)
|
||||
</fieldset>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -7,25 +7,62 @@
|
|||
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
}
|
||||
|
||||
/* Controls - Begin */
|
||||
fieldset {
|
||||
margin: 5px;
|
||||
.container {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.sidePanel {
|
||||
width: 230px;
|
||||
background-color: #eee;
|
||||
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.sidePanel h4 {
|
||||
margin: 10px 0 10px 0;
|
||||
}
|
||||
|
||||
.sidePanel .panelTools {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.sidePanel .panelColumn {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.tool input[type="radio"] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tool input[type="radio"] + .toolIcon {
|
||||
background-color: #ddd;
|
||||
|
||||
width: 41px;
|
||||
height: 41px;
|
||||
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.tool input[type="radio"]:checked + .toolIcon {
|
||||
background-color: #bdbebc;
|
||||
}
|
||||
|
||||
label {
|
||||
margin-right: 10px;
|
||||
margin-right: 6px;
|
||||
}
|
||||
|
||||
label span {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
label span::first-letter {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
input[type="number"] {
|
||||
width: 30px;
|
||||
}
|
||||
|
@ -33,4 +70,11 @@ input[type="number"] {
|
|||
input {
|
||||
margin-right: 5px;
|
||||
}
|
||||
/* Controls - End */
|
||||
|
||||
button {
|
||||
background-color: #ddd;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
|
||||
padding: 5px;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue