Proper text sizing
This commit is contained in:
parent
47e626f510
commit
9dc19dde1d
89
src/index.js
89
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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user