Explorar o código

Proper text sizing

Christopher Chedeau %!s(int64=5) %!d(string=hai) anos
pai
achega
9dc19dde1d
Modificáronse 1 ficheiros con 57 adicións e 32 borrados
  1. 57 32
      src/index.js

+ 57 - 32
src/index.js

@@ -15,7 +15,6 @@ function newElement(type, x, y) {
     height: 0,
     isSelected: false
   };
-  generateShape(element);
   return element;
 }
 
@@ -34,8 +33,10 @@ var generator = rough.generator();
 function generateShape(element) {
   if (element.type === "selection") {
     element.draw = (rc, context) => {
+      const fillStyle = context.fillStyle;
       context.fillStyle = "rgba(0, 0, 255, 0.10)";
       context.fillRect(element.x, element.y, element.width, element.height);
+      context.fillStyle = fillStyle;
     };
   } else if (element.type === "rectangle") {
     const shape = generator.rectangle(
@@ -85,29 +86,37 @@ function generateShape(element) {
     };
     return;
   } else if (element.type === "text") {
-    if (element.text === undefined) {
-      element.text = prompt("What text do you want?");
-    }
     element.draw = (rc, context) => {
-      context.font = "20px Virgil";
-      const measure = context.measureText(element.text);
+      const font = context.font;
+      context.font = element.font;
       const height =
-        measure.actualBoundingBoxAscent + measure.actualBoundingBoxDescent;
+        element.measure.actualBoundingBoxAscent +
+        element.measure.actualBoundingBoxDescent;
       context.fillText(
         element.text,
-        element.x - measure.width / 2,
-        element.y + measure.actualBoundingBoxAscent - height / 2
+        element.x,
+        element.y + 2 * element.measure.actualBoundingBoxAscent - height / 2
       );
+      context.font = font;
     };
   } else {
     throw new Error("Unimplemented type " + element.type);
   }
 }
 
+function setSelection(selection) {
+  elements.forEach(element => {
+    element.isSelected =
+      selection.x < element.x &&
+      selection.y < element.y &&
+      selection.x + selection.width > element.x + element.width &&
+      selection.y + selection.height > element.y + element.height;
+  });
+}
+
 function App() {
   const [draggingElement, setDraggingElement] = React.useState(null);
   const [elementType, setElementType] = React.useState("selection");
-  const [selectedElements, setSelectedElements] = React.useState([]);
   function ElementOption({ type, children }) {
     return (
       <label>
@@ -132,21 +141,42 @@ function App() {
         width={window.innerWidth}
         height={window.innerHeight}
         onMouseDown={e => {
-          const element = newElement(
-            elementType,
-            e.clientX - e.target.offsetLeft,
-            e.clientY - e.target.offsetTop
-          );
+          const x = e.clientX - e.target.offsetLeft;
+          const y = e.clientY - e.target.offsetTop;
+          const element = newElement(elementType, x, y);
+
+          if (elementType === "text") {
+            element.text = prompt("What text do you want?");
+            element.font = "20px Virgil";
+            const font = context.font;
+            context.font = element.font;
+            element.measure = context.measureText(element.text);
+            context.font = font;
+            const height =
+              element.measure.actualBoundingBoxAscent +
+              element.measure.actualBoundingBoxDescent;
+            // Center the text
+            element.x -= element.measure.width / 2;
+            element.y -= element.measure.actualBoundingBoxAscent;
+            element.width = element.measure.width;
+            element.height = height;
+          }
+
+          generateShape(element);
           elements.push(element);
-          setDraggingElement(element);
+          if (elementType === "text") {
+            setDraggingElement(null);
+          } else {
+            setDraggingElement(element);
+          }
           drawScene();
         }}
         onMouseUp={e => {
           setDraggingElement(null);
           if (elementType === "selection") {
-            elements.forEach(element => {
-              element.isSelected = false;
-            });
+            // Remove actual selection element
+            elements.pop();
+            setSelection(draggingElement);
           }
           drawScene();
         }}
@@ -157,18 +187,11 @@ function App() {
           draggingElement.width = width;
           // Make a perfect square or circle when shift is enabled
           draggingElement.height = e.shiftKey ? width : height;
+
           generateShape(draggingElement);
 
           if (elementType === "selection") {
-            elements.forEach(element => {
-              element.isSelected =
-                draggingElement.x <= element.x &&
-                draggingElement.y <= element.y &&
-                draggingElement.x + draggingElement.width >=
-                  element.x + element.width &&
-                draggingElement.y + draggingElement.height >=
-                  element.y + element.height;
-            });
+            setSelection(draggingElement);
           }
           drawScene();
         }}
@@ -177,19 +200,21 @@ function App() {
   );
 }
 const rootElement = document.getElementById("root");
+ReactDOM.render(<App />, rootElement);
+const canvas = document.getElementById("canvas");
+const rc = rough.canvas(canvas);
+const context = canvas.getContext("2d");
 
 function drawScene() {
   ReactDOM.render(<App />, rootElement);
 
-  const canvas = document.getElementById("canvas");
-  const rc = rough.canvas(canvas);
-  const context = canvas.getContext("2d");
   context.clearRect(0, 0, canvas.width, canvas.height);
 
   elements.forEach(element => {
     element.draw(rc, context);
     if (element.isSelected) {
       const margin = 4;
+      const lineDash = context.getLineDash();
       context.setLineDash([8, 4]);
       context.strokeRect(
         element.x - margin,
@@ -197,7 +222,7 @@ function drawScene() {
         element.width + margin * 2,
         element.height + margin * 2
       );
-      context.setLineDash([]);
+      context.setLineDash(lineDash);
     }
   });
 }