mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-05-03 10:00:07 -04:00
Roughness, opacity and more styles
This commit is contained in:
parent
e6d032b6c5
commit
e3a450b021
2 changed files with 362 additions and 106 deletions
454
src/index.tsx
454
src/index.tsx
|
@ -2,7 +2,7 @@ import React, { ChangeEvent } 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 { SketchPicker, ColorResult } 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";
|
||||||
|
@ -255,6 +255,9 @@ function newElement(
|
||||||
strokeColor: string,
|
strokeColor: string,
|
||||||
backgroundColor: string,
|
backgroundColor: string,
|
||||||
fillStyle: string,
|
fillStyle: string,
|
||||||
|
strokeWidth: number,
|
||||||
|
roughness: number,
|
||||||
|
opacity: number,
|
||||||
width = 0,
|
width = 0,
|
||||||
height = 0
|
height = 0
|
||||||
) {
|
) {
|
||||||
|
@ -268,6 +271,9 @@ function newElement(
|
||||||
strokeColor: strokeColor,
|
strokeColor: strokeColor,
|
||||||
backgroundColor: backgroundColor,
|
backgroundColor: backgroundColor,
|
||||||
fillStyle: fillStyle,
|
fillStyle: fillStyle,
|
||||||
|
strokeWidth: strokeWidth,
|
||||||
|
roughness: roughness,
|
||||||
|
opacity: opacity,
|
||||||
seed: randomSeed(),
|
seed: randomSeed(),
|
||||||
draw(
|
draw(
|
||||||
rc: RoughCanvas,
|
rc: RoughCanvas,
|
||||||
|
@ -747,7 +753,6 @@ function getDiamondPoints(element: ExcalidrawElement) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function generateDraw(element: ExcalidrawElement) {
|
function generateDraw(element: ExcalidrawElement) {
|
||||||
console.log(element);
|
|
||||||
if (element.type === "selection") {
|
if (element.type === "selection") {
|
||||||
element.draw = (rc, context, { scrollX, scrollY }) => {
|
element.draw = (rc, context, { scrollX, scrollY }) => {
|
||||||
const fillStyle = context.fillStyle;
|
const fillStyle = context.fillStyle;
|
||||||
|
@ -765,13 +770,17 @@ function generateDraw(element: ExcalidrawElement) {
|
||||||
return generator.rectangle(0, 0, element.width, element.height, {
|
return generator.rectangle(0, 0, element.width, element.height, {
|
||||||
stroke: element.strokeColor,
|
stroke: element.strokeColor,
|
||||||
fill: element.backgroundColor,
|
fill: element.backgroundColor,
|
||||||
fillStyle: element.fillStyle
|
fillStyle: element.fillStyle,
|
||||||
|
strokeWidth: element.strokeWidth,
|
||||||
|
roughness: element.roughness
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
element.draw = (rc, context, { scrollX, scrollY }) => {
|
element.draw = (rc, context, { scrollX, scrollY }) => {
|
||||||
|
context.globalAlpha = element.opacity / 100;
|
||||||
context.translate(element.x + scrollX, element.y + scrollY);
|
context.translate(element.x + scrollX, element.y + scrollY);
|
||||||
rc.draw(shape);
|
rc.draw(shape);
|
||||||
context.translate(-element.x - scrollX, -element.y - scrollY);
|
context.translate(-element.x - scrollX, -element.y - scrollY);
|
||||||
|
context.globalAlpha = 1;
|
||||||
};
|
};
|
||||||
} else if (element.type === "diamond") {
|
} else if (element.type === "diamond") {
|
||||||
const shape = withCustomMathRandom(element.seed, () => {
|
const shape = withCustomMathRandom(element.seed, () => {
|
||||||
|
@ -810,33 +819,56 @@ function generateDraw(element: ExcalidrawElement) {
|
||||||
element.height / 2,
|
element.height / 2,
|
||||||
element.width,
|
element.width,
|
||||||
element.height,
|
element.height,
|
||||||
{ stroke: element.strokeColor, fill: element.backgroundColor }
|
{
|
||||||
|
stroke: element.strokeColor,
|
||||||
|
fill: element.backgroundColor,
|
||||||
|
fillStyle: element.fillStyle,
|
||||||
|
strokeWidth: element.strokeWidth,
|
||||||
|
roughness: element.roughness
|
||||||
|
}
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
element.draw = (rc, context, { scrollX, scrollY }) => {
|
element.draw = (rc, context, { scrollX, scrollY }) => {
|
||||||
|
context.globalAlpha = element.opacity / 100;
|
||||||
context.translate(element.x + scrollX, element.y + scrollY);
|
context.translate(element.x + scrollX, element.y + scrollY);
|
||||||
rc.draw(shape);
|
rc.draw(shape);
|
||||||
context.translate(-element.x - scrollX, -element.y - scrollY);
|
context.translate(-element.x - scrollX, -element.y - scrollY);
|
||||||
|
context.globalAlpha = 1;
|
||||||
};
|
};
|
||||||
} else if (element.type === "arrow") {
|
} else if (element.type === "arrow") {
|
||||||
const [x1, y1, x2, y2, x3, y3, x4, y4] = getArrowPoints(element);
|
const [x1, y1, x2, y2, x3, y3, x4, y4] = getArrowPoints(element);
|
||||||
const shapes = withCustomMathRandom(element.seed, () => [
|
const shapes = withCustomMathRandom(element.seed, () => [
|
||||||
// \
|
// \
|
||||||
generator.line(x3, y3, x2, y2, { stroke: element.strokeColor }),
|
generator.line(x3, y3, x2, y2, {
|
||||||
|
stroke: element.strokeColor,
|
||||||
|
strokeWidth: element.strokeWidth,
|
||||||
|
roughness: element.roughness
|
||||||
|
}),
|
||||||
// -----
|
// -----
|
||||||
generator.line(x1, y1, x2, y2, { stroke: element.strokeColor }),
|
generator.line(x1, y1, x2, y2, {
|
||||||
|
stroke: element.strokeColor,
|
||||||
|
strokeWidth: element.strokeWidth,
|
||||||
|
roughness: element.roughness
|
||||||
|
}),
|
||||||
// /
|
// /
|
||||||
generator.line(x4, y4, x2, y2, { stroke: element.strokeColor })
|
generator.line(x4, y4, x2, y2, {
|
||||||
|
stroke: element.strokeColor,
|
||||||
|
strokeWidth: element.strokeWidth,
|
||||||
|
roughness: element.roughness
|
||||||
|
})
|
||||||
]);
|
]);
|
||||||
|
|
||||||
element.draw = (rc, context, { scrollX, scrollY }) => {
|
element.draw = (rc, context, { scrollX, scrollY }) => {
|
||||||
|
context.globalAlpha = element.opacity / 100;
|
||||||
context.translate(element.x + scrollX, element.y + scrollY);
|
context.translate(element.x + scrollX, element.y + scrollY);
|
||||||
shapes.forEach(shape => rc.draw(shape));
|
shapes.forEach(shape => rc.draw(shape));
|
||||||
context.translate(-element.x - scrollX, -element.y - scrollY);
|
context.translate(-element.x - scrollX, -element.y - scrollY);
|
||||||
|
context.globalAlpha = 1;
|
||||||
};
|
};
|
||||||
return;
|
return;
|
||||||
} else if (isTextElement(element)) {
|
} else if (isTextElement(element)) {
|
||||||
element.draw = (rc, context, { scrollX, scrollY }) => {
|
element.draw = (rc, context, { scrollX, scrollY }) => {
|
||||||
|
context.globalAlpha = element.opacity / 100;
|
||||||
const font = context.font;
|
const font = context.font;
|
||||||
context.font = element.font;
|
context.font = element.font;
|
||||||
const fillStyle = context.fillStyle;
|
const fillStyle = context.fillStyle;
|
||||||
|
@ -848,6 +880,7 @@ function generateDraw(element: ExcalidrawElement) {
|
||||||
);
|
);
|
||||||
context.fillStyle = fillStyle;
|
context.fillStyle = fillStyle;
|
||||||
context.font = font;
|
context.font = font;
|
||||||
|
context.globalAlpha = 1;
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
throw new Error("Unimplemented type " + element.type);
|
throw new Error("Unimplemented type " + element.type);
|
||||||
|
@ -1068,6 +1101,88 @@ function getSelectedIndices() {
|
||||||
const someElementIsSelected = () =>
|
const someElementIsSelected = () =>
|
||||||
elements.some(element => element.isSelected);
|
elements.some(element => element.isSelected);
|
||||||
|
|
||||||
|
const someElementIsSelectedIsRectangleOrEllipse = () =>
|
||||||
|
elements.some(
|
||||||
|
element =>
|
||||||
|
element.isSelected &&
|
||||||
|
(element.type === "rectangle" || element.type === "ellipse")
|
||||||
|
);
|
||||||
|
|
||||||
|
const someElementIsSelectedIsRectangleOrEllipseOrArrow = () =>
|
||||||
|
elements.some(
|
||||||
|
element =>
|
||||||
|
element.isSelected &&
|
||||||
|
(element.type === "rectangle" ||
|
||||||
|
element.type === "ellipse" ||
|
||||||
|
element.type === "arrow")
|
||||||
|
);
|
||||||
|
|
||||||
|
function getSelectedFillStyles() {
|
||||||
|
const fillStyles = Array.from(
|
||||||
|
new Set(
|
||||||
|
elements
|
||||||
|
.filter(element => element.isSelected)
|
||||||
|
.map(element => element.fillStyle)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
return fillStyles.length === 1 ? fillStyles[0] : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSelectedStrokeWidth() {
|
||||||
|
const strokeWidth = Array.from(
|
||||||
|
new Set(
|
||||||
|
elements
|
||||||
|
.filter(element => element.isSelected)
|
||||||
|
.map(element => `${element.strokeWidth}`)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
return strokeWidth.length === 1 ? +strokeWidth[0] : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSelectedRoughness() {
|
||||||
|
const roughness = Array.from(
|
||||||
|
new Set(
|
||||||
|
elements
|
||||||
|
.filter(element => element.isSelected)
|
||||||
|
.map(element => `${element.roughness}`)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
return roughness.length === 1 ? +roughness[0] : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSelectedOpacity() {
|
||||||
|
const opacity = Array.from(
|
||||||
|
new Set(
|
||||||
|
elements
|
||||||
|
.filter(element => element.isSelected)
|
||||||
|
.map(element => `${element.opacity}`)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
return opacity.length === 1 ? +opacity[0] : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSelectedStrokeColor() {
|
||||||
|
const strokeColors = Array.from(
|
||||||
|
new Set(
|
||||||
|
elements
|
||||||
|
.filter(element => element.isSelected)
|
||||||
|
.map(element => element.strokeColor)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
return strokeColors.length === 1 ? strokeColors[0] : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSelectedBackgroundColor() {
|
||||||
|
const backgroundColors = Array.from(
|
||||||
|
new Set(
|
||||||
|
elements
|
||||||
|
.filter(element => element.isSelected)
|
||||||
|
.map(element => element.backgroundColor)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
return backgroundColors.length === 1 ? backgroundColors[0] : null;
|
||||||
|
}
|
||||||
|
|
||||||
const ELEMENT_SHIFT_TRANSLATE_AMOUNT = 5;
|
const ELEMENT_SHIFT_TRANSLATE_AMOUNT = 5;
|
||||||
const ELEMENT_TRANSLATE_AMOUNT = 1;
|
const ELEMENT_TRANSLATE_AMOUNT = 1;
|
||||||
|
|
||||||
|
@ -1232,19 +1347,43 @@ class App extends React.Component<{}, AppState> {
|
||||||
this.setState({ name });
|
this.setState({ name });
|
||||||
}
|
}
|
||||||
|
|
||||||
private changeFillStyle = (event: ChangeEvent<HTMLSelectElement>) => {
|
private changeProperty = (callback: (element: ExcalidrawElement) => void) => {
|
||||||
console.log(event.target.value);
|
|
||||||
elements.forEach(element => {
|
elements.forEach(element => {
|
||||||
console.log("forceUpdate");
|
|
||||||
if (element.isSelected) {
|
if (element.isSelected) {
|
||||||
element.fillStyle = event.target.value;
|
callback(element);
|
||||||
|
generateDraw(element);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log("forceUpdate");
|
|
||||||
this.forceUpdate();
|
this.forceUpdate();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private changeFillStyle = (style: string) => {
|
||||||
|
this.changeProperty(element => (element.fillStyle = style));
|
||||||
|
};
|
||||||
|
|
||||||
|
private changeStrokeWidth = (event: ChangeEvent<HTMLSelectElement>) => {
|
||||||
|
this.changeProperty(element => (element.strokeWidth = +event.target.value));
|
||||||
|
};
|
||||||
|
|
||||||
|
private changeRoughness = (event: ChangeEvent<HTMLSelectElement>) => {
|
||||||
|
this.changeProperty(element => (element.roughness = +event.target.value));
|
||||||
|
};
|
||||||
|
|
||||||
|
private changeOpacity = (event: ChangeEvent<HTMLInputElement>) => {
|
||||||
|
this.changeProperty(element => (element.opacity = +event.target.value));
|
||||||
|
};
|
||||||
|
|
||||||
|
private changeSrokeColor = (color: string) => {
|
||||||
|
this.changeProperty(element => (element.strokeColor = color));
|
||||||
|
this.setState({ currentItemStrokeColor: color });
|
||||||
|
};
|
||||||
|
|
||||||
|
private changeBackgroundColor = (color: string) => {
|
||||||
|
this.changeProperty(element => (element.backgroundColor = color));
|
||||||
|
this.setState({ currentItemBackgroundColor: color });
|
||||||
|
};
|
||||||
|
|
||||||
public render() {
|
public render() {
|
||||||
const canvasWidth = window.innerWidth - CANVAS_WINDOW_OFFSET_LEFT;
|
const canvasWidth = window.innerWidth - CANVAS_WINDOW_OFFSET_LEFT;
|
||||||
const canvasHeight = window.innerHeight - CANVAS_WINDOW_OFFSET_TOP;
|
const canvasHeight = window.innerHeight - CANVAS_WINDOW_OFFSET_TOP;
|
||||||
|
@ -1370,85 +1509,6 @@ class App extends React.Component<{}, AppState> {
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<h5>Shape Stroke Color</h5>
|
|
||||||
<div>
|
|
||||||
<button
|
|
||||||
className="swatch"
|
|
||||||
style={{
|
|
||||||
backgroundColor: 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.setState({ currentItemStrokeColor: color.hex });
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
) : null}
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
className="swatch-input"
|
|
||||||
value={this.state.currentItemStrokeColor}
|
|
||||||
onChange={e => {
|
|
||||||
this.setState({ currentItemStrokeColor: e.target.value });
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<h5>Shape Background Color</h5>
|
|
||||||
<div>
|
|
||||||
<button
|
|
||||||
className="swatch"
|
|
||||||
style={{
|
|
||||||
backgroundColor: 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.setState({ currentItemBackgroundColor: color.hex });
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
) : null}
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
className="swatch-input"
|
|
||||||
value={this.state.currentItemStrokeColor}
|
|
||||||
onChange={e => {
|
|
||||||
this.setState({ currentItemStrokeColor: 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"
|
||||||
|
@ -1501,6 +1561,89 @@ class App extends React.Component<{}, AppState> {
|
||||||
</div>
|
</div>
|
||||||
{someElementIsSelected() && (
|
{someElementIsSelected() && (
|
||||||
<>
|
<>
|
||||||
|
<>
|
||||||
|
<h4>Colors</h4>
|
||||||
|
<div className='panelColumn'>
|
||||||
|
<h5>Shape Stroke Color</h5>
|
||||||
|
<div>
|
||||||
|
<button
|
||||||
|
className="swatch"
|
||||||
|
style={{
|
||||||
|
backgroundColor: getSelectedStrokeColor() || 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.changeSrokeColor(color.hex)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
className="swatch-input"
|
||||||
|
value={getSelectedStrokeColor() || this.state.currentItemStrokeColor}
|
||||||
|
onChange={e => this.changeSrokeColor(e.target.value)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{someElementIsSelectedIsRectangleOrEllipse() && (
|
||||||
|
<div className='panelColumn'>
|
||||||
|
<h5>Shape Background Color</h5>
|
||||||
|
<div>
|
||||||
|
<button
|
||||||
|
className="swatch"
|
||||||
|
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>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
|
||||||
<h4>Shape options</h4>
|
<h4>Shape options</h4>
|
||||||
<div className="panelColumn">
|
<div className="panelColumn">
|
||||||
<button onClick={this.deleteSelectedElements}>Delete</button>
|
<button onClick={this.deleteSelectedElements}>Delete</button>
|
||||||
|
@ -1510,19 +1653,125 @@ class App extends React.Component<{}, AppState> {
|
||||||
<button onClick={this.moveAllLeft}>Send to back</button>
|
<button onClick={this.moveAllLeft}>Send to back</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{someElementIsSelectedIsRectangleOrEllipse() && (
|
||||||
|
<>
|
||||||
<h4>Fill</h4>
|
<h4>Fill</h4>
|
||||||
<div className="panelColumn">
|
<div className="panelColumn">
|
||||||
<select onChange={this.changeFillStyle}>
|
{/* <select onChange={this.changeFillStyle} value={getSelectedFillStyles()}> */}
|
||||||
<option value="hachure">Hachure</option>
|
<button
|
||||||
<option value="solid">Solid</option>
|
onClick={() => this.changeFillStyle("hachure")}
|
||||||
<option value="zigzag">Zigzag</option>
|
className={
|
||||||
<option value="cross-hatch">Cross-hatch</option>
|
getSelectedFillStyles() === "hachure" ? "active" : ""
|
||||||
<option value="dots">Dots</option>
|
}
|
||||||
<option value="sunburst">Sunburst</option>
|
>
|
||||||
<option value="dashed">Dashed</option>
|
Hachure
|
||||||
<option value="zigzag-line">Zigzag-line</option>
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={() => this.changeFillStyle("solid")}
|
||||||
|
className={
|
||||||
|
getSelectedFillStyles() === "solid" ? "active" : ""
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Solid
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={() => this.changeFillStyle("zigzag")}
|
||||||
|
className={
|
||||||
|
getSelectedFillStyles() === "zigzag" ? "active" : ""
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Zigzag
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={() => this.changeFillStyle("cross-hatch")}
|
||||||
|
className={
|
||||||
|
getSelectedFillStyles() === "cross-hatch"
|
||||||
|
? "active"
|
||||||
|
: ""
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Cross-hatch
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={() => this.changeFillStyle("dots")}
|
||||||
|
className={
|
||||||
|
getSelectedFillStyles() === "dots" ? "active" : ""
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Dots
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={() => this.changeFillStyle("sunburst")}
|
||||||
|
className={
|
||||||
|
getSelectedFillStyles() === "sunburst" ? "active" : ""
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Sunburst
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={() => this.changeFillStyle("dashed")}
|
||||||
|
className={
|
||||||
|
getSelectedFillStyles() === "dashed" ? "active" : ""
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Dashed
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={() => this.changeFillStyle("zigzag-line")}
|
||||||
|
className={
|
||||||
|
getSelectedFillStyles() === "zigzag-line"
|
||||||
|
? "active"
|
||||||
|
: ""
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Zigzag-line
|
||||||
|
</button>
|
||||||
|
{/* </select> */}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{someElementIsSelectedIsRectangleOrEllipseOrArrow() && (
|
||||||
|
<>
|
||||||
|
<h4>Stroke width</h4>
|
||||||
|
<div className="panelColumn">
|
||||||
|
<select
|
||||||
|
onChange={this.changeStrokeWidth}
|
||||||
|
value={getSelectedStrokeWidth()}
|
||||||
|
>
|
||||||
|
<option hidden disabled value=""></option>
|
||||||
|
<option value="1">1</option>
|
||||||
|
<option value="2">2</option>
|
||||||
|
<option value="4">4</option>
|
||||||
|
<option value="8">8</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<h4>Roughness</h4>
|
||||||
|
<div className="panelColumn">
|
||||||
|
<select
|
||||||
|
onChange={this.changeRoughness}
|
||||||
|
value={getSelectedRoughness()}
|
||||||
|
>
|
||||||
|
<option hidden disabled value=""></option>
|
||||||
|
<option value="1">1</option>
|
||||||
|
<option value="2">2</option>
|
||||||
|
<option value="4">4</option>
|
||||||
|
<option value="8">8</option>
|
||||||
|
<option value="10">10</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<h4>Opacity</h4>
|
||||||
|
<input
|
||||||
|
type="range"
|
||||||
|
min="0"
|
||||||
|
max="100"
|
||||||
|
onChange={this.changeOpacity}
|
||||||
|
value={getSelectedOpacity()}
|
||||||
|
/>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
@ -1600,7 +1849,10 @@ class App extends React.Component<{}, AppState> {
|
||||||
y,
|
y,
|
||||||
this.state.currentItemStrokeColor,
|
this.state.currentItemStrokeColor,
|
||||||
this.state.currentItemBackgroundColor,
|
this.state.currentItemBackgroundColor,
|
||||||
"hachure"
|
"hachure",
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
100
|
||||||
);
|
);
|
||||||
let resizeHandle: string | false = false;
|
let resizeHandle: string | false = false;
|
||||||
let isDraggingElements = false;
|
let isDraggingElements = false;
|
||||||
|
|
|
@ -110,6 +110,10 @@ input[type="color"] {
|
||||||
margin: 2px;
|
margin: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input[type="range"] {
|
||||||
|
width: 230px;
|
||||||
|
}
|
||||||
|
|
||||||
input {
|
input {
|
||||||
margin-right: 5px;
|
margin-right: 5px;
|
||||||
|
|
||||||
|
@ -136,7 +140,7 @@ button {
|
||||||
border-color: #d6d4d4;
|
border-color: #d6d4d4;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:active {
|
&:active, &.active {
|
||||||
background-color: #bdbebc;
|
background-color: #bdbebc;
|
||||||
border-color: #bdbebc;
|
border-color: #bdbebc;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue