Christopher Chedeau 5 anos atrás
pai
commit
b18a0efe2c
1 arquivos alterados com 32 adições e 11 exclusões
  1. 32 11
      src/index.tsx

+ 32 - 11
src/index.tsx

@@ -18,6 +18,21 @@ const LOCAL_STORAGE_KEY_STATE = "excalidraw-state";
 
 var elements = Array.of<ExcalidrawElement>();
 
+// https://stackoverflow.com/questions/521295/seeding-the-random-number-generator-in-javascript/47593316#47593316
+const LCG = (seed: number) => () =>
+  ((2 ** 31 - 1) & (seed = Math.imul(48271, seed))) / 2 ** 31;
+
+// Unfortunately, roughjs doesn't support a seed attribute (https://github.com/pshihn/rough/issues/27).
+// We can achieve the same result by overriding the Math.random function with a
+// pseudo random generator that supports a random seed and swapping it back after.
+function withCustomMathRandom<T>(seed: number, cb: () => T): T {
+  const random = Math.random;
+  Math.random = LCG(seed);
+  const result = cb();
+  Math.random = random;
+  return result;
+}
+
 // https://stackoverflow.com/a/6853926/232122
 function distanceBetweenPointAndSegment(
   x: number,
@@ -126,6 +141,7 @@ function newElement(
     isSelected: false,
     strokeColor: strokeColor,
     backgroundColor: backgroundColor,
+    seed: Math.floor(Math.random() * 2 ** 31),
     draw(rc: RoughCanvas, context: CanvasRenderingContext2D) {}
   };
   return element;
@@ -307,22 +323,27 @@ function generateDraw(element: ExcalidrawElement) {
       context.fillStyle = fillStyle;
     };
   } else if (element.type === "rectangle") {
-    const shape = generator.rectangle(0, 0, element.width, element.height, {
-      stroke: element.strokeColor,
-      fill: element.backgroundColor
+    const shape = withCustomMathRandom(element.seed, () => {
+      return generator.rectangle(0, 0, element.width, element.height, {
+        stroke: element.strokeColor,
+        fill: element.backgroundColor
+      });
     });
+
     element.draw = (rc, context) => {
       context.translate(element.x, element.y);
       rc.draw(shape);
       context.translate(-element.x, -element.y);
     };
   } else if (element.type === "ellipse") {
-    const shape = generator.ellipse(
-      element.width / 2,
-      element.height / 2,
-      element.width,
-      element.height,
-      { stroke: element.strokeColor, fill: element.backgroundColor }
+    const shape = withCustomMathRandom(element.seed, () =>
+      generator.ellipse(
+        element.width / 2,
+        element.height / 2,
+        element.width,
+        element.height,
+        { stroke: element.strokeColor, fill: element.backgroundColor }
+      )
     );
     element.draw = (rc, context) => {
       context.translate(element.x, element.y);
@@ -331,14 +352,14 @@ function generateDraw(element: ExcalidrawElement) {
     };
   } else if (element.type === "arrow") {
     const [x1, y1, x2, y2, x3, y3, x4, y4] = getArrowPoints(element);
-    const shapes = [
+    const shapes = withCustomMathRandom(element.seed, () => [
       //    \
       generator.line(x3, y3, x2, y2, { stroke: element.strokeColor }),
       // -----
       generator.line(x1, y1, x2, y2, { stroke: element.strokeColor }),
       //    /
       generator.line(x4, y4, x2, y2, { stroke: element.strokeColor })
-    ];
+    ]);
 
     element.draw = (rc, context) => {
       context.translate(element.x, element.y);