mirror of
				https://github.com/excalidraw/excalidraw.git
				synced 2025-11-04 12:54:23 +01:00 
			
		
		
		
	Scroll with mouse wheel
This commit is contained in:
		@@ -142,22 +142,32 @@ function newElement(
 | 
			
		||||
    strokeColor: strokeColor,
 | 
			
		||||
    backgroundColor: backgroundColor,
 | 
			
		||||
    seed: Math.floor(Math.random() * 2 ** 31),
 | 
			
		||||
    draw(rc: RoughCanvas, context: CanvasRenderingContext2D) {}
 | 
			
		||||
    draw(
 | 
			
		||||
      rc: RoughCanvas,
 | 
			
		||||
      context: CanvasRenderingContext2D,
 | 
			
		||||
      sceneState: SceneState
 | 
			
		||||
    ) {}
 | 
			
		||||
  };
 | 
			
		||||
  return element;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type SceneState = {
 | 
			
		||||
  scrollX: number;
 | 
			
		||||
  scrollY: number;
 | 
			
		||||
  // null indicates transparent bg
 | 
			
		||||
  viewBackgroundColor: string | null;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function renderScene(
 | 
			
		||||
  rc: RoughCanvas,
 | 
			
		||||
  context: CanvasRenderingContext2D,
 | 
			
		||||
  // null indicates transparent bg
 | 
			
		||||
  viewBackgroundColor: string | null
 | 
			
		||||
  sceneState: SceneState
 | 
			
		||||
) {
 | 
			
		||||
  if (!context) return;
 | 
			
		||||
 | 
			
		||||
  const fillStyle = context.fillStyle;
 | 
			
		||||
  if (typeof viewBackgroundColor === "string") {
 | 
			
		||||
    context.fillStyle = viewBackgroundColor;
 | 
			
		||||
  if (typeof sceneState.viewBackgroundColor === "string") {
 | 
			
		||||
    context.fillStyle = sceneState.viewBackgroundColor;
 | 
			
		||||
    context.fillRect(-0.5, -0.5, canvas.width, canvas.height);
 | 
			
		||||
  } else {
 | 
			
		||||
    context.clearRect(-0.5, -0.5, canvas.width, canvas.height);
 | 
			
		||||
@@ -165,7 +175,7 @@ function renderScene(
 | 
			
		||||
  context.fillStyle = fillStyle;
 | 
			
		||||
 | 
			
		||||
  elements.forEach(element => {
 | 
			
		||||
    element.draw(rc, context);
 | 
			
		||||
    element.draw(rc, context, sceneState);
 | 
			
		||||
    if (element.isSelected) {
 | 
			
		||||
      const margin = 4;
 | 
			
		||||
 | 
			
		||||
@@ -176,8 +186,8 @@ function renderScene(
 | 
			
		||||
      const lineDash = context.getLineDash();
 | 
			
		||||
      context.setLineDash([8, 4]);
 | 
			
		||||
      context.strokeRect(
 | 
			
		||||
        elementX1 - margin,
 | 
			
		||||
        elementY1 - margin,
 | 
			
		||||
        elementX1 - margin + sceneState.scrollX,
 | 
			
		||||
        elementY1 - margin + sceneState.scrollY,
 | 
			
		||||
        elementX2 - elementX1 + 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
 | 
			
		||||
    //  (it's reset again, below)
 | 
			
		||||
    if (!exportBackground) {
 | 
			
		||||
      renderScene(rc, context, null);
 | 
			
		||||
      renderScene(rc, context, {
 | 
			
		||||
        viewBackgroundColor: null,
 | 
			
		||||
        scrollX: 0,
 | 
			
		||||
        scrollY: 0
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // copy our original canvas onto the temp canvas
 | 
			
		||||
@@ -259,7 +273,7 @@ function exportAsPNG({
 | 
			
		||||
 | 
			
		||||
    // reset transparent bg back to original
 | 
			
		||||
    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
 | 
			
		||||
@@ -316,10 +330,15 @@ function getArrowPoints(element: ExcalidrawElement) {
 | 
			
		||||
 | 
			
		||||
function generateDraw(element: ExcalidrawElement) {
 | 
			
		||||
  if (element.type === "selection") {
 | 
			
		||||
    element.draw = (rc, context) => {
 | 
			
		||||
    element.draw = (rc, context, { scrollX, scrollY }) => {
 | 
			
		||||
      const fillStyle = context.fillStyle;
 | 
			
		||||
      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;
 | 
			
		||||
    };
 | 
			
		||||
  } else if (element.type === "rectangle") {
 | 
			
		||||
@@ -329,11 +348,10 @@ function generateDraw(element: ExcalidrawElement) {
 | 
			
		||||
        fill: element.backgroundColor
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    element.draw = (rc, context) => {
 | 
			
		||||
      context.translate(element.x, element.y);
 | 
			
		||||
    element.draw = (rc, context, { scrollX, scrollY }) => {
 | 
			
		||||
      context.translate(element.x + scrollX, element.y + scrollY);
 | 
			
		||||
      rc.draw(shape);
 | 
			
		||||
      context.translate(-element.x, -element.y);
 | 
			
		||||
      context.translate(-element.x - scrollX, -element.y - scrollY);
 | 
			
		||||
    };
 | 
			
		||||
  } else if (element.type === "ellipse") {
 | 
			
		||||
    const shape = withCustomMathRandom(element.seed, () =>
 | 
			
		||||
@@ -345,10 +363,10 @@ function generateDraw(element: ExcalidrawElement) {
 | 
			
		||||
        { stroke: element.strokeColor, fill: element.backgroundColor }
 | 
			
		||||
      )
 | 
			
		||||
    );
 | 
			
		||||
    element.draw = (rc, context) => {
 | 
			
		||||
      context.translate(element.x, element.y);
 | 
			
		||||
    element.draw = (rc, contex, { scrollX, scrollY }) => {
 | 
			
		||||
      context.translate(element.x + scrollX, element.y + scrollY);
 | 
			
		||||
      rc.draw(shape);
 | 
			
		||||
      context.translate(-element.x, -element.y);
 | 
			
		||||
      context.translate(-element.x - scrollX, -element.y - scrollY);
 | 
			
		||||
    };
 | 
			
		||||
  } else if (element.type === "arrow") {
 | 
			
		||||
    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 })
 | 
			
		||||
    ]);
 | 
			
		||||
 | 
			
		||||
    element.draw = (rc, context) => {
 | 
			
		||||
      context.translate(element.x, element.y);
 | 
			
		||||
    element.draw = (rc, context, { scrollX, scrollY }) => {
 | 
			
		||||
      context.translate(element.x + scrollX, element.y + scrollY);
 | 
			
		||||
      shapes.forEach(shape => rc.draw(shape));
 | 
			
		||||
      context.translate(-element.x, -element.y);
 | 
			
		||||
      context.translate(-element.x - scrollX, -element.y - scrollY);
 | 
			
		||||
    };
 | 
			
		||||
    return;
 | 
			
		||||
  } else if (isTextElement(element)) {
 | 
			
		||||
    element.draw = (rc, context) => {
 | 
			
		||||
    element.draw = (rc, context, { scrollX, scrollY }) => {
 | 
			
		||||
      const font = context.font;
 | 
			
		||||
      context.font = element.font;
 | 
			
		||||
      const fillStyle = context.fillStyle;
 | 
			
		||||
      context.fillStyle = element.strokeColor;
 | 
			
		||||
      context.fillText(
 | 
			
		||||
        element.text,
 | 
			
		||||
        element.x,
 | 
			
		||||
        element.y + element.actualBoundingBoxAscent
 | 
			
		||||
        element.x + scrollX,
 | 
			
		||||
        element.y + element.actualBoundingBoxAscent + scrollY
 | 
			
		||||
      );
 | 
			
		||||
      context.fillStyle = fillStyle;
 | 
			
		||||
      context.font = font;
 | 
			
		||||
@@ -467,6 +485,8 @@ type AppState = {
 | 
			
		||||
  currentItemStrokeColor: string;
 | 
			
		||||
  currentItemBackgroundColor: string;
 | 
			
		||||
  viewBackgroundColor: string;
 | 
			
		||||
  scrollX: number;
 | 
			
		||||
  scrollY: number;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const KEYS = {
 | 
			
		||||
@@ -513,7 +533,9 @@ class App extends React.Component<{}, AppState> {
 | 
			
		||||
    exportPadding: 10,
 | 
			
		||||
    currentItemStrokeColor: "#000000",
 | 
			
		||||
    currentItemBackgroundColor: "#ffffff",
 | 
			
		||||
    viewBackgroundColor: "#ffffff"
 | 
			
		||||
    viewBackgroundColor: "#ffffff",
 | 
			
		||||
    scrollX: 0,
 | 
			
		||||
    scrollY: 0
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  private onKeyDown = (event: KeyboardEvent) => {
 | 
			
		||||
@@ -630,6 +652,14 @@ class App extends React.Component<{}, AppState> {
 | 
			
		||||
          id="canvas"
 | 
			
		||||
          width={window.innerWidth}
 | 
			
		||||
          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 => {
 | 
			
		||||
            const x = e.clientX - (e.target as HTMLElement).offsetLeft;
 | 
			
		||||
            const y = e.clientY - (e.target as HTMLElement).offsetTop;
 | 
			
		||||
@@ -871,7 +901,11 @@ class App extends React.Component<{}, AppState> {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  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);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user