Giter Club home page Giter Club logo

board's Introduction

board

board supercharges your html canvas element giving it the capabilities to pan, zoom, rotate, and much more.

continuous integration contributors contributors

InstallKey FeaturesBare Minimum ExampleHow To Use

This is not a complete drawing canvas library like excalidraw or tl;draw, but a library which you can build on top of to make an app like excalidraw. This library saves you from the hassle of manually implementing panning, zooming, and rotating functionalities on the HTML canvas element, and math if your not a fan of math.

CodeSandbox Link You Can try it out to see if it's for you.

Docs

Installation and Usage

Package manager

npm install @niuee/board

and import it in other JavaScript module

import { BoardV2 } from "@niuee/board";

Download From Github

Download the bundled JavaScript (board.js) in the releases of the repository and put it in the your project directory for other JavaScript module to import like this.

import { Board } from "./board.js";

Import From jsdelivr

import { Board } from "https://cdn.jsdelivr.net/npm/@niuee/board@latest/index.mjs";

Use iife bundle

In an HTML file use the script tag. (instead of importing from jsdelivr you can also download it as source and put it in you project directly)

<script src="https://cdn.jsdelivr.net/npm/@niuee/board@latest/iife/index.js"></script>

and then in other JavaScript file you can use the exports of @niuee/board using the name Board.{some export}

For example the constructor for the Board class.

const newBoard = new Board.Board(canvasElement);

Key Features

  • Supports a wide variety of input methods. (touch, trackpad(macOS), keyboard mouse)
  • Works with just HTML and JavaScript but also works with frontend frameworks/libraries with a little bit of extra work.
  • Rich API for board camera. (You can do a lot of cool stuff with the camera e.g. animating the camera moving along a path, zooming and rotating can also be animated)

Bare Minimum Example

import { Board } from "@niuee/board"; // or other import style mentioned above

const canvasElement = document.querySelector("canvas");
const board = new Board(canvasElement);


// this is the callback function for the requestAnimationFrame
function step(timestamp){
    // timestamp is the argument requestAnimationFrame pass to its callback function

    // step the board first before everything else because stepping the board would wipe the canvas
    // pass in the timestamp as it is to the board's step function.
    board.step(timestamp);

    // if you want to draw stuff draw it in the step function otherwise it would not persist
    // draw a circle at (100, 100) with a width of 1px
    board.context.beginPath();
    board.context.arc(100, 100, 1, 0, 2 * Math.PI);
    board.context.stroke();

    // and then call the requestAnimationFrame
    window.requestAnimationFrame(step);
}

// start the animation loop
step(0);

How To Use

The Board class extends an existing canvas element in the DOM to have extra capabilities such as pan, zoom, and rotation. To instantiate a new board, must have a canvas element in your html.

<canvas id="board"></canvas>

Call the step function of the Board class and in a requestAnimationFrame callback.

import { Board } from "@niuee/board";

const canvasElement = document.getElementById("board");
const board = new Board(canvasElement); // if you are using this library through iife don't use the variable name board since it would have name conflict with the library

// this is the callback function for the requestAnimationFrame
function step(timestamp){
    // timestamp is the argument requestAnimationFrame pass to its callback function

    // step the board first before everything else because stepping the board would wipe the canvas
    // pass in the timestamp as it is to the board's step function.
    board.step(timestamp);

    // do your stuff

    // and then call the requestAnimationFrame
    window.requestAnimationFrame(step);
}

// start the animation loop
step(0);

Now the board should have the basic functionalities like pan and zoom. But there's probably nothing on your canvas.

The default coordinate system @niuee/board uses is the same as the one of the canvas API which is "Down" for positive Y direction.

To draw stuff on the board first get the 2d context of the board.

// draw a circle at the location (10, 10)
board.context.beginPath();
board.context.arc(10, 10, 5, 0, 2 * Math.PI);
board.context.stroke();

This would result in a circle drawn to the bottom right of the origin. The same as a regular canvas.

This is probably a good time to talk about the coordinate system @niuee/board uses.

In Most use cases the default coordinate system would be what you want as you might already be familiar with the canvas API.

In case you want to flip the Y axis so that positive direction for Y axis is point up in the screen.

Set the alignCoordinateSystem of the Board class to false.

board.alignCoordinateSystem = false;

This would flip the Y axis. There's a catch though. Even though the Y axis is flipped the context that the board uses is still the same as a regular canvas. This means that to draw something in the coordinate of the flipped coordinate system, you would need to flip the Y axis coordinate (negate the coordinate) before feeding it to the context to draw.

For example if you want to draw a circle at (30, 30), for the flipped coordinate system, you would need to do it like this.

// notice the negative sign for the y coordinate
context.arc(30, -30, 5, 0, Math.PI * 2);

There is also another difference other than the flipped Y axis. The positive direction of an angle is also reversed. For the flipped coordinate system. Positive rotation is counter clockwise. As for the default coordintate system it's the same as the regular canvas API where positive rotation is clockwise.

The API documentation has all the APIs listed.

I am setting up a documentation site for examples and explanations of the entire project. Stay tuned.

board's People

Contributors

niuee avatar

Watchers

 avatar

board's Issues

Consolidate the keyboard mouse and trackpad input strategy

Currently, the keyboard mouse and trackpad control input strategy are separated into two different strategies. However, the two strategies are tied together because some of the event listeners, for example, the scroll event, are shared between the trackpad and keyboard mouse. Grainier control on disabling strategy is hard to implement because of this. Disabling zoom on the trackpad strategy would also affect the keyboard mouse strategy.

Add an option to use the same coordinate system as a regular canvas's

This library's coordinate system is not the same as that of a regular canvas. However, the context returned from the board class uses the same one as a regular canvas. This can be confusing, as one might use the wrong y-axis coordinate (however, it's just negating the y-axis to convert between the two). We are considering adding an option to use the same coordinate system.

Keyboard Mouse Input For panning is buggy.

Currently, the panning involving keyboard and mouse would engage if the mouse is moving while the scroll wheel is held down or if the meta key (cmd for Mac and windows key for Windows). This would cause a problem on windows as the windows key would open up the windows menu after the panning is over. Planning to switch over to the spacebar for panning like figma.

Grainier Control on the input strategies

There are currently restrictions on camera movements and transformations. This is on the camera side; if the canvas gets input from the users, it will still try to fire a camera movement command. There is also an option to turn off the input strategy entirely. I want to add options to turn off the input strategy on only pan, zoom, and rotate separately. This restriction will stop the canvas from handling specific user inputs. This way, the camera would not even be given the movement commands.

Flexible Zoom level boundary

Currently, the minimum zoom level is adjusted whenever the canvas element resizes. Adjusting the minimum zoom level only happens when the current dimension of the canvas element and the current minimum zoom level allow the viewport to zoom out to a point where the viewport would contain a portion out of the boundaries of the board. The direction of readjustment only goes in one direction, from a lower minimum zoom level to a higher minimum zoom level, not the other way around. When the dimensions of the canvas element allow for a lower minimum zoom level, the adjustment would not happen. This is intended to take into account that users can explicitly set a minimum zoom level. When the canvas element resizes, the user would expect the minimum zoom level to stay the same except when shrinking to accommodate the "limitEntireViewport" attribute. The proposed flexibility would still preserve this behavior but accommodate the situation when user would like the adjustment of minimum zoom level to go both ways.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.