Improve color picker

This commit is contained in:
Christopher Chedeau 2020-01-05 18:05:46 -08:00
parent feefb14bf5
commit 666251c360
2 changed files with 71 additions and 146 deletions

View file

@ -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>

View file

@ -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;