Quellcode durchsuchen

rewrite picker color handling (#1487)

David Luzar vor 5 Jahren
Ursprung
Commit
2c5c770e78
2 geänderte Dateien mit 19 neuen und 25 gelöschten Zeilen
  1. 16 23
      src/components/ColorPicker.tsx
  2. 3 2
      src/renderer/renderScene.ts

+ 16 - 23
src/components/ColorPicker.tsx

@@ -7,23 +7,22 @@ import { t, getLanguage } from "../i18n";
 import { isWritableElement } from "../utils";
 import colors from "../colors";
 
-const normalizeColor = (
-  color: string,
-  canvasContext: CanvasRenderingContext2D,
-): string | null => {
-  // Excalidraw only supports "transparent" as a valid transparent value.
-  // Default canvas fill style value is `#000000`, which is also a valid
-  // Excalidraw color. Let's set it to another Canvas-valid but
-  // Excalidraw-invalid value to detect successful normalizations.
+function isValidColor(color: string) {
+  const style = new Option().style;
+  style.color = color;
+  return !!style.color;
+}
+
+const getColor = (color: string): string | null => {
   if (color === "transparent") {
     return color;
   }
 
-  const defaultColor = "rgba(0,0,0,0)";
-  canvasContext.fillStyle = defaultColor;
-  canvasContext.fillStyle = color;
-  const hexColor = canvasContext.fillStyle;
-  return hexColor.startsWith("#") ? hexColor : null;
+  return isValidColor(color)
+    ? color
+    : isValidColor(`#${color}`)
+    ? `#${color}`
+    : null;
 };
 
 // This is a narrow reimplementation of the awesome react-color Twitter component
@@ -200,9 +199,6 @@ const ColorInput = React.forwardRef(
   ) => {
     const [innerValue, setInnerValue] = React.useState(color);
     const inputRef = React.useRef(null);
-    const canvasContext = React.useRef<CanvasRenderingContext2D>(
-      document.createElement("canvas").getContext("2d"),
-    );
 
     React.useEffect(() => {
       setInnerValue(color);
@@ -213,15 +209,13 @@ const ColorInput = React.forwardRef(
     const changeColor = React.useCallback(
       (inputValue: string) => {
         const value = inputValue.toLowerCase();
-        if (canvasContext.current) {
-          const normalizedValue = normalizeColor(value, canvasContext.current);
-          if (normalizedValue) {
-            onChange(normalizedValue);
-          }
+        const color = getColor(value);
+        if (color) {
+          onChange(color);
         }
         setInnerValue(value);
       },
-      [canvasContext, onChange, setInnerValue],
+      [onChange],
     );
 
     return (
@@ -233,7 +227,6 @@ const ColorInput = React.forwardRef(
           aria-label={label}
           onChange={(event) => changeColor(event.target.value)}
           value={(innerValue || "").replace(/^#/, "")}
-          onPaste={(event) => changeColor(event.clipboardData.getData("text"))}
           onBlur={() => setInnerValue(color)}
           ref={inputRef}
         />

+ 3 - 2
src/renderer/renderScene.ts

@@ -114,8 +114,9 @@ export function renderScene(
   if (typeof sceneState.viewBackgroundColor === "string") {
     const hasTransparence =
       sceneState.viewBackgroundColor === "transparent" ||
-      sceneState.viewBackgroundColor.length === 5 ||
-      sceneState.viewBackgroundColor.length === 9;
+      sceneState.viewBackgroundColor.length === 5 || // #RGBA
+      sceneState.viewBackgroundColor.length === 9 || // #RRGGBBA
+      /(hsla|rgba)\(/.test(sceneState.viewBackgroundColor);
     if (hasTransparence) {
       context.clearRect(0, 0, normalizedCanvasWidth, normalizedCanvasHeight);
     }