mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-05-03 10:00:07 -04:00
Improve color picker
This commit is contained in:
parent
feefb14bf5
commit
666251c360
2 changed files with 71 additions and 146 deletions
216
src/index.tsx
216
src/index.tsx
|
@ -2,7 +2,7 @@ import React from "react";
|
||||||
import ReactDOM from "react-dom";
|
import ReactDOM from "react-dom";
|
||||||
import rough from "roughjs/bin/wrappers/rough";
|
import rough from "roughjs/bin/wrappers/rough";
|
||||||
import { RoughCanvas } from "roughjs/bin/canvas";
|
import { RoughCanvas } from "roughjs/bin/canvas";
|
||||||
import { SketchPicker } from "react-color";
|
import { TwitterPicker } from "react-color";
|
||||||
|
|
||||||
import { moveOneLeft, moveAllLeft, moveOneRight, moveAllRight } from "./zindex";
|
import { moveOneLeft, moveAllLeft, moveOneRight, moveAllRight } from "./zindex";
|
||||||
import { roundRect } from "./roundRect";
|
import { roundRect } from "./roundRect";
|
||||||
|
@ -795,12 +795,7 @@ function generateDraw(element: ExcalidrawElement) {
|
||||||
leftY
|
leftY
|
||||||
] = getDiamondPoints(element);
|
] = getDiamondPoints(element);
|
||||||
return generator.polygon(
|
return generator.polygon(
|
||||||
[
|
[[topX, topY], [rightX, rightY], [bottomX, bottomY], [leftX, leftY]],
|
||||||
[topX, topY],
|
|
||||||
[rightX, rightY],
|
|
||||||
[bottomX, bottomY],
|
|
||||||
[leftX, leftY]
|
|
||||||
],
|
|
||||||
{
|
{
|
||||||
stroke: element.strokeColor,
|
stroke: element.strokeColor,
|
||||||
fill: element.backgroundColor,
|
fill: element.backgroundColor,
|
||||||
|
@ -981,16 +976,9 @@ function restore(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ColorPicker {
|
|
||||||
CANVAS_BACKGROUND,
|
|
||||||
SHAPE_STROKE,
|
|
||||||
SHAPE_BACKGROUND
|
|
||||||
}
|
|
||||||
|
|
||||||
type AppState = {
|
type AppState = {
|
||||||
draggingElement: ExcalidrawElement | null;
|
draggingElement: ExcalidrawElement | null;
|
||||||
resizingElement: ExcalidrawElement | null;
|
resizingElement: ExcalidrawElement | null;
|
||||||
currentColorPicker: ColorPicker | null;
|
|
||||||
elementType: string;
|
elementType: string;
|
||||||
exportBackground: boolean;
|
exportBackground: boolean;
|
||||||
currentItemStrokeColor: string;
|
currentItemStrokeColor: string;
|
||||||
|
@ -1035,7 +1023,7 @@ const SHAPES = [
|
||||||
icon: (
|
icon: (
|
||||||
// custom
|
// custom
|
||||||
<svg viewBox="0 0 223.646 223.646">
|
<svg viewBox="0 0 223.646 223.646">
|
||||||
<path d="M111.823 0L16.622 111.823 111.823 223.646 207.025 111.823z"></path>
|
<path d="M111.823 0L16.622 111.823 111.823 223.646 207.025 111.823z" />
|
||||||
</svg>
|
</svg>
|
||||||
),
|
),
|
||||||
value: "diamond"
|
value: "diamond"
|
||||||
|
@ -1232,6 +1220,56 @@ function getElementAtPosition(x: number, y: number) {
|
||||||
return hitElement;
|
return hitElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function ColorPicker({
|
||||||
|
color,
|
||||||
|
onChange
|
||||||
|
}: {
|
||||||
|
color: string;
|
||||||
|
onChange: (color: string) => void;
|
||||||
|
}) {
|
||||||
|
const [isActive, setActive] = React.useState(false);
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<button
|
||||||
|
className="swatch"
|
||||||
|
style={{ backgroundColor: color }}
|
||||||
|
onClick={() => setActive(!isActive)}
|
||||||
|
/>
|
||||||
|
{isActive ? (
|
||||||
|
<div className="popover">
|
||||||
|
<div className="cover" onClick={() => setActive(false)} />
|
||||||
|
<TwitterPicker
|
||||||
|
colors={[
|
||||||
|
"#000000",
|
||||||
|
"#ABB8C3",
|
||||||
|
"#FFFFFF",
|
||||||
|
"#FF6900",
|
||||||
|
"#FCB900",
|
||||||
|
"#00D084",
|
||||||
|
"#8ED1FC",
|
||||||
|
"#0693E3",
|
||||||
|
"#EB144C",
|
||||||
|
"#F78DA7",
|
||||||
|
"#9900EF"
|
||||||
|
]}
|
||||||
|
width="205px"
|
||||||
|
color={color}
|
||||||
|
onChange={changedColor => {
|
||||||
|
onChange(changedColor.hex);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
className="swatch-input"
|
||||||
|
value={color}
|
||||||
|
onChange={e => onChange(e.target.value)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const ELEMENT_SHIFT_TRANSLATE_AMOUNT = 5;
|
const ELEMENT_SHIFT_TRANSLATE_AMOUNT = 5;
|
||||||
const ELEMENT_TRANSLATE_AMOUNT = 1;
|
const ELEMENT_TRANSLATE_AMOUNT = 1;
|
||||||
|
|
||||||
|
@ -1260,7 +1298,6 @@ class App extends React.Component<{}, AppState> {
|
||||||
draggingElement: null,
|
draggingElement: null,
|
||||||
resizingElement: null,
|
resizingElement: null,
|
||||||
elementType: "selection",
|
elementType: "selection",
|
||||||
currentColorPicker: null,
|
|
||||||
exportBackground: true,
|
exportBackground: true,
|
||||||
currentItemStrokeColor: "#000000",
|
currentItemStrokeColor: "#000000",
|
||||||
currentItemBackgroundColor: "#ffffff",
|
currentItemBackgroundColor: "#ffffff",
|
||||||
|
@ -1519,45 +1556,10 @@ class App extends React.Component<{}, AppState> {
|
||||||
<h4>Canvas</h4>
|
<h4>Canvas</h4>
|
||||||
<div className="panelColumn">
|
<div className="panelColumn">
|
||||||
<h5>Canvas Background Color</h5>
|
<h5>Canvas Background Color</h5>
|
||||||
<div>
|
<ColorPicker
|
||||||
<button
|
color={this.state.viewBackgroundColor}
|
||||||
className="swatch"
|
onChange={color => this.setState({ viewBackgroundColor: color })}
|
||||||
style={{
|
/>
|
||||||
backgroundColor: this.state.viewBackgroundColor
|
|
||||||
}}
|
|
||||||
onClick={() =>
|
|
||||||
this.setState(s => ({
|
|
||||||
currentColorPicker:
|
|
||||||
s.currentColorPicker === ColorPicker.CANVAS_BACKGROUND
|
|
||||||
? null
|
|
||||||
: ColorPicker.CANVAS_BACKGROUND
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
{this.state.currentColorPicker ===
|
|
||||||
ColorPicker.CANVAS_BACKGROUND ? (
|
|
||||||
<div className="popover">
|
|
||||||
<div
|
|
||||||
className="cover"
|
|
||||||
onClick={() => this.setState({ currentColorPicker: null })}
|
|
||||||
/>
|
|
||||||
<SketchPicker
|
|
||||||
color={this.state.viewBackgroundColor}
|
|
||||||
onChange={color => {
|
|
||||||
this.setState({ viewBackgroundColor: color.hex });
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
) : null}
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
className="swatch-input"
|
|
||||||
value={this.state.viewBackgroundColor}
|
|
||||||
onChange={e =>
|
|
||||||
this.setState({ viewBackgroundColor: e.target.value })
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<button
|
<button
|
||||||
onClick={this.clearCanvas}
|
onClick={this.clearCanvas}
|
||||||
title="Clear the canvas & reset background color"
|
title="Clear the canvas & reset background color"
|
||||||
|
@ -1614,100 +1616,22 @@ class App extends React.Component<{}, AppState> {
|
||||||
<h4>Colors</h4>
|
<h4>Colors</h4>
|
||||||
<div className="panelColumn">
|
<div className="panelColumn">
|
||||||
<h5>Shape Stroke Color</h5>
|
<h5>Shape Stroke Color</h5>
|
||||||
<div>
|
<ColorPicker
|
||||||
<button
|
color={
|
||||||
className="swatch"
|
getSelectedStrokeColor() ||
|
||||||
style={{
|
this.state.currentItemStrokeColor
|
||||||
backgroundColor:
|
}
|
||||||
getSelectedStrokeColor() ||
|
onChange={color => this.changeStrokeColor(color)}
|
||||||
this.state.currentItemStrokeColor
|
/>
|
||||||
}}
|
|
||||||
onClick={() =>
|
|
||||||
this.setState(s => ({
|
|
||||||
currentColorPicker:
|
|
||||||
s.currentColorPicker === ColorPicker.SHAPE_STROKE
|
|
||||||
? null
|
|
||||||
: ColorPicker.SHAPE_STROKE
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
{this.state.currentColorPicker ===
|
|
||||||
ColorPicker.SHAPE_STROKE && (
|
|
||||||
<div className="popover">
|
|
||||||
<div
|
|
||||||
className="cover"
|
|
||||||
onClick={() =>
|
|
||||||
this.setState({ currentColorPicker: null })
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<SketchPicker
|
|
||||||
color={this.state.currentItemStrokeColor}
|
|
||||||
onChange={color => this.changeStrokeColor(color.hex)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
className="swatch-input"
|
|
||||||
value={
|
|
||||||
getSelectedStrokeColor() ||
|
|
||||||
this.state.currentItemStrokeColor
|
|
||||||
}
|
|
||||||
onChange={e => this.changeStrokeColor(e.target.value)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{someElementIsSelectedIsRectangleOrEllipseOrDiamond() && (
|
{someElementIsSelectedIsRectangleOrEllipseOrDiamond() && (
|
||||||
<div className="panelColumn">
|
<div className="panelColumn">
|
||||||
<h5>Shape Background Color</h5>
|
<h5>Shape Background Color</h5>
|
||||||
<div>
|
<ColorPicker
|
||||||
<button
|
color={this.state.currentItemBackgroundColor}
|
||||||
className="swatch"
|
onChange={color => this.changeBackgroundColor(color)}
|
||||||
style={{
|
/>
|
||||||
backgroundColor:
|
|
||||||
getSelectedBackgroundColor() ||
|
|
||||||
this.state.currentItemBackgroundColor
|
|
||||||
}}
|
|
||||||
onClick={() =>
|
|
||||||
this.setState(s => ({
|
|
||||||
currentColorPicker:
|
|
||||||
s.currentColorPicker ===
|
|
||||||
ColorPicker.SHAPE_BACKGROUND
|
|
||||||
? null
|
|
||||||
: ColorPicker.SHAPE_BACKGROUND
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
{this.state.currentColorPicker ===
|
|
||||||
ColorPicker.SHAPE_BACKGROUND ? (
|
|
||||||
<div className="popover">
|
|
||||||
<div
|
|
||||||
className="cover"
|
|
||||||
onClick={() =>
|
|
||||||
this.setState({ currentColorPicker: null })
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<SketchPicker
|
|
||||||
color={this.state.currentItemBackgroundColor}
|
|
||||||
onChange={color =>
|
|
||||||
this.changeBackgroundColor(color.hex)
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
) : null}
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
className="swatch-input"
|
|
||||||
value={
|
|
||||||
getSelectedBackgroundColor() ||
|
|
||||||
this.state.currentItemBackgroundColor
|
|
||||||
}
|
|
||||||
onChange={e =>
|
|
||||||
this.changeBackgroundColor(e.target.value)
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
|
@ -1798,7 +1722,7 @@ class App extends React.Component<{}, AppState> {
|
||||||
onChange={this.changeStrokeWidth}
|
onChange={this.changeStrokeWidth}
|
||||||
value={getSelectedStrokeWidth()}
|
value={getSelectedStrokeWidth()}
|
||||||
>
|
>
|
||||||
<option hidden disabled value=""></option>
|
<option hidden disabled value="" />
|
||||||
<option value="1">1</option>
|
<option value="1">1</option>
|
||||||
<option value="2">2</option>
|
<option value="2">2</option>
|
||||||
<option value="4">4</option>
|
<option value="4">4</option>
|
||||||
|
@ -1812,7 +1736,7 @@ class App extends React.Component<{}, AppState> {
|
||||||
onChange={this.changeRoughness}
|
onChange={this.changeRoughness}
|
||||||
value={getSelectedRoughness()}
|
value={getSelectedRoughness()}
|
||||||
>
|
>
|
||||||
<option hidden disabled value=""></option>
|
<option hidden disabled value="" />
|
||||||
<option value="1">1</option>
|
<option value="1">1</option>
|
||||||
<option value="2">2</option>
|
<option value="2">2</option>
|
||||||
<option value="4">4</option>
|
<option value="4">4</option>
|
||||||
|
|
|
@ -24,6 +24,7 @@ body {
|
||||||
background-color: #eee;
|
background-color: #eee;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
h4 {
|
h4 {
|
||||||
margin: 10px 0 10px 0;
|
margin: 10px 0 10px 0;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue