Scroll with mouse wheel

This commit is contained in:
hazam 2020-01-04 01:27:25 +05:00
parent 3fb6f0413e
commit 51e19b977e

View File

@ -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);
} }
} }