Scroll with mouse wheel
This commit is contained in:
parent
3fb6f0413e
commit
51e19b977e
@ -142,22 +142,32 @@ function newElement(
|
|||||||
strokeColor: strokeColor,
|
strokeColor: strokeColor,
|
||||||
backgroundColor: backgroundColor,
|
backgroundColor: backgroundColor,
|
||||||
seed: Math.floor(Math.random() * 2 ** 31),
|
seed: Math.floor(Math.random() * 2 ** 31),
|
||||||
draw(rc: RoughCanvas, context: CanvasRenderingContext2D) {}
|
draw(
|
||||||
|
rc: RoughCanvas,
|
||||||
|
context: CanvasRenderingContext2D,
|
||||||
|
sceneState: SceneState
|
||||||
|
) {}
|
||||||
};
|
};
|
||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type SceneState = {
|
||||||
|
scrollX: number;
|
||||||
|
scrollY: number;
|
||||||
|
// null indicates transparent bg
|
||||||
|
viewBackgroundColor: string | null;
|
||||||
|
};
|
||||||
|
|
||||||
function renderScene(
|
function renderScene(
|
||||||
rc: RoughCanvas,
|
rc: RoughCanvas,
|
||||||
context: CanvasRenderingContext2D,
|
context: CanvasRenderingContext2D,
|
||||||
// null indicates transparent bg
|
sceneState: SceneState
|
||||||
viewBackgroundColor: string | null
|
|
||||||
) {
|
) {
|
||||||
if (!context) return;
|
if (!context) return;
|
||||||
|
|
||||||
const fillStyle = context.fillStyle;
|
const fillStyle = context.fillStyle;
|
||||||
if (typeof viewBackgroundColor === "string") {
|
if (typeof sceneState.viewBackgroundColor === "string") {
|
||||||
context.fillStyle = viewBackgroundColor;
|
context.fillStyle = sceneState.viewBackgroundColor;
|
||||||
context.fillRect(-0.5, -0.5, canvas.width, canvas.height);
|
context.fillRect(-0.5, -0.5, canvas.width, canvas.height);
|
||||||
} else {
|
} else {
|
||||||
context.clearRect(-0.5, -0.5, canvas.width, canvas.height);
|
context.clearRect(-0.5, -0.5, canvas.width, canvas.height);
|
||||||
@ -165,7 +175,7 @@ function renderScene(
|
|||||||
context.fillStyle = fillStyle;
|
context.fillStyle = fillStyle;
|
||||||
|
|
||||||
elements.forEach(element => {
|
elements.forEach(element => {
|
||||||
element.draw(rc, context);
|
element.draw(rc, context, sceneState);
|
||||||
if (element.isSelected) {
|
if (element.isSelected) {
|
||||||
const margin = 4;
|
const margin = 4;
|
||||||
|
|
||||||
@ -176,8 +186,8 @@ function renderScene(
|
|||||||
const lineDash = context.getLineDash();
|
const lineDash = context.getLineDash();
|
||||||
context.setLineDash([8, 4]);
|
context.setLineDash([8, 4]);
|
||||||
context.strokeRect(
|
context.strokeRect(
|
||||||
elementX1 - margin,
|
elementX1 - margin + sceneState.scrollX,
|
||||||
elementY1 - margin,
|
elementY1 - margin + sceneState.scrollY,
|
||||||
elementX2 - elementX1 + margin * 2,
|
elementX2 - elementX1 + margin * 2,
|
||||||
elementY2 - elementY1 + margin * 2
|
elementY2 - elementY1 + margin * 2
|
||||||
);
|
);
|
||||||
@ -233,7 +243,11 @@ function exportAsPNG({
|
|||||||
// if we're exporting without bg, we need to rerender the scene without it
|
// if we're exporting without bg, we need to rerender the scene without it
|
||||||
// (it's reset again, below)
|
// (it's reset again, below)
|
||||||
if (!exportBackground) {
|
if (!exportBackground) {
|
||||||
renderScene(rc, context, null);
|
renderScene(rc, context, {
|
||||||
|
viewBackgroundColor: null,
|
||||||
|
scrollX: 0,
|
||||||
|
scrollY: 0
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// copy our original canvas onto the temp canvas
|
// copy our original canvas onto the temp canvas
|
||||||
@ -259,7 +273,7 @@ function exportAsPNG({
|
|||||||
|
|
||||||
// reset transparent bg back to original
|
// reset transparent bg back to original
|
||||||
if (!exportBackground) {
|
if (!exportBackground) {
|
||||||
renderScene(rc, context, viewBackgroundColor);
|
renderScene(rc, context, { viewBackgroundColor, scrollX: 0, scrollY: 0 });
|
||||||
}
|
}
|
||||||
|
|
||||||
// create a temporary <a> elem which we'll use to download the image
|
// create a temporary <a> elem which we'll use to download the image
|
||||||
@ -316,10 +330,15 @@ function getArrowPoints(element: ExcalidrawElement) {
|
|||||||
|
|
||||||
function generateDraw(element: ExcalidrawElement) {
|
function generateDraw(element: ExcalidrawElement) {
|
||||||
if (element.type === "selection") {
|
if (element.type === "selection") {
|
||||||
element.draw = (rc, context) => {
|
element.draw = (rc, context, { scrollX, scrollY }) => {
|
||||||
const fillStyle = context.fillStyle;
|
const fillStyle = context.fillStyle;
|
||||||
context.fillStyle = "rgba(0, 0, 255, 0.10)";
|
context.fillStyle = "rgba(0, 0, 255, 0.10)";
|
||||||
context.fillRect(element.x, element.y, element.width, element.height);
|
context.fillRect(
|
||||||
|
element.x + scrollX,
|
||||||
|
element.y + scrollY,
|
||||||
|
element.width,
|
||||||
|
element.height
|
||||||
|
);
|
||||||
context.fillStyle = fillStyle;
|
context.fillStyle = fillStyle;
|
||||||
};
|
};
|
||||||
} else if (element.type === "rectangle") {
|
} else if (element.type === "rectangle") {
|
||||||
@ -329,11 +348,10 @@ function generateDraw(element: ExcalidrawElement) {
|
|||||||
fill: element.backgroundColor
|
fill: element.backgroundColor
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
element.draw = (rc, context, { scrollX, scrollY }) => {
|
||||||
element.draw = (rc, context) => {
|
context.translate(element.x + scrollX, element.y + scrollY);
|
||||||
context.translate(element.x, element.y);
|
|
||||||
rc.draw(shape);
|
rc.draw(shape);
|
||||||
context.translate(-element.x, -element.y);
|
context.translate(-element.x - scrollX, -element.y - scrollY);
|
||||||
};
|
};
|
||||||
} else if (element.type === "ellipse") {
|
} else if (element.type === "ellipse") {
|
||||||
const shape = withCustomMathRandom(element.seed, () =>
|
const shape = withCustomMathRandom(element.seed, () =>
|
||||||
@ -345,10 +363,10 @@ function generateDraw(element: ExcalidrawElement) {
|
|||||||
{ stroke: element.strokeColor, fill: element.backgroundColor }
|
{ stroke: element.strokeColor, fill: element.backgroundColor }
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
element.draw = (rc, context) => {
|
element.draw = (rc, contex, { scrollX, scrollY }) => {
|
||||||
context.translate(element.x, element.y);
|
context.translate(element.x + scrollX, element.y + scrollY);
|
||||||
rc.draw(shape);
|
rc.draw(shape);
|
||||||
context.translate(-element.x, -element.y);
|
context.translate(-element.x - scrollX, -element.y - scrollY);
|
||||||
};
|
};
|
||||||
} 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);
|
||||||
@ -361,22 +379,22 @@ function generateDraw(element: ExcalidrawElement) {
|
|||||||
generator.line(x4, y4, x2, y2, { stroke: element.strokeColor })
|
generator.line(x4, y4, x2, y2, { stroke: element.strokeColor })
|
||||||
]);
|
]);
|
||||||
|
|
||||||
element.draw = (rc, context) => {
|
element.draw = (rc, context, { scrollX, scrollY }) => {
|
||||||
context.translate(element.x, element.y);
|
context.translate(element.x + scrollX, element.y + scrollY);
|
||||||
shapes.forEach(shape => rc.draw(shape));
|
shapes.forEach(shape => rc.draw(shape));
|
||||||
context.translate(-element.x, -element.y);
|
context.translate(-element.x - scrollX, -element.y - scrollY);
|
||||||
};
|
};
|
||||||
return;
|
return;
|
||||||
} else if (isTextElement(element)) {
|
} else if (isTextElement(element)) {
|
||||||
element.draw = (rc, context) => {
|
element.draw = (rc, context, { scrollX, scrollY }) => {
|
||||||
const font = context.font;
|
const font = context.font;
|
||||||
context.font = element.font;
|
context.font = element.font;
|
||||||
const fillStyle = context.fillStyle;
|
const fillStyle = context.fillStyle;
|
||||||
context.fillStyle = element.strokeColor;
|
context.fillStyle = element.strokeColor;
|
||||||
context.fillText(
|
context.fillText(
|
||||||
element.text,
|
element.text,
|
||||||
element.x,
|
element.x + scrollX,
|
||||||
element.y + element.actualBoundingBoxAscent
|
element.y + element.actualBoundingBoxAscent + scrollY
|
||||||
);
|
);
|
||||||
context.fillStyle = fillStyle;
|
context.fillStyle = fillStyle;
|
||||||
context.font = font;
|
context.font = font;
|
||||||
@ -467,6 +485,8 @@ type AppState = {
|
|||||||
currentItemStrokeColor: string;
|
currentItemStrokeColor: string;
|
||||||
currentItemBackgroundColor: string;
|
currentItemBackgroundColor: string;
|
||||||
viewBackgroundColor: string;
|
viewBackgroundColor: string;
|
||||||
|
scrollX: number;
|
||||||
|
scrollY: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
const KEYS = {
|
const KEYS = {
|
||||||
@ -513,7 +533,9 @@ class App extends React.Component<{}, AppState> {
|
|||||||
exportPadding: 10,
|
exportPadding: 10,
|
||||||
currentItemStrokeColor: "#000000",
|
currentItemStrokeColor: "#000000",
|
||||||
currentItemBackgroundColor: "#ffffff",
|
currentItemBackgroundColor: "#ffffff",
|
||||||
viewBackgroundColor: "#ffffff"
|
viewBackgroundColor: "#ffffff",
|
||||||
|
scrollX: 0,
|
||||||
|
scrollY: 0
|
||||||
};
|
};
|
||||||
|
|
||||||
private onKeyDown = (event: KeyboardEvent) => {
|
private onKeyDown = (event: KeyboardEvent) => {
|
||||||
@ -630,6 +652,14 @@ class App extends React.Component<{}, AppState> {
|
|||||||
id="canvas"
|
id="canvas"
|
||||||
width={window.innerWidth}
|
width={window.innerWidth}
|
||||||
height={window.innerHeight - 200}
|
height={window.innerHeight - 200}
|
||||||
|
onWheel={e => {
|
||||||
|
e.preventDefault();
|
||||||
|
const { deltaX, deltaY } = e;
|
||||||
|
this.setState(state => ({
|
||||||
|
scrollX: state.scrollX - deltaX,
|
||||||
|
scrollY: state.scrollY - deltaY
|
||||||
|
}));
|
||||||
|
}}
|
||||||
onMouseDown={e => {
|
onMouseDown={e => {
|
||||||
const x = e.clientX - (e.target as HTMLElement).offsetLeft;
|
const x = e.clientX - (e.target as HTMLElement).offsetLeft;
|
||||||
const y = e.clientY - (e.target as HTMLElement).offsetTop;
|
const y = e.clientY - (e.target as HTMLElement).offsetTop;
|
||||||
@ -871,7 +901,11 @@ class App extends React.Component<{}, AppState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate() {
|
componentDidUpdate() {
|
||||||
renderScene(rc, context, this.state.viewBackgroundColor);
|
renderScene(rc, context, {
|
||||||
|
scrollX: this.state.scrollX,
|
||||||
|
scrollY: this.state.scrollY,
|
||||||
|
viewBackgroundColor: this.state.viewBackgroundColor
|
||||||
|
});
|
||||||
save(this.state);
|
save(this.state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user