New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

canvas-transform-context

Package Overview
Dependencies
Maintainers
1
Versions
12
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

canvas-transform-context - npm Package Compare versions

Comparing version 0.1.5 to 1.0.0

dist/bundle.min.js

49

dist/index.d.ts

@@ -1,46 +0,3 @@

export interface TransformCanvasRenderingContext2D extends CanvasRenderingContext2D {
getTransform(): SVGMatrix;
transformedPoint(x: number, y: number): DOMPoint;
clearCanvas(): void;
/**
* Marks the start of a canvas drag.
* Should be used on the onmousedown event
* @param e
*/
beginPan(e: MouseEvent): void;
/**
* Drags the canvas.
* Should be used on the onmousemove event
* @param e
*/
pan(e: MouseEvent): void;
/**
* Ends the canvas draw.
* Should be used on the onmousemove event
* @param e
*/
endPan(e: MouseEvent): void;
/**
* Zooms in or out
* @param amount Amount in integers to zoom by. Applies zoom on top of previous zoom
* @param factor Zoom factor. Defaults to 1.1
* @param center The center to zoom to. If undefined, will zoom to the last mouse pos in endDraw
*/
zoom(amount: number, factor?: number, center?: {
x: number;
y: number;
}): number;
}
/**
* Type guard for transformed context
* @param ctx
* @returns
*/
export declare function isTransformedContext(ctx: CanvasRenderingContext2D): ctx is TransformCanvasRenderingContext2D;
/**
* Extends a canvas context IN PLACE.
* The return value is for type change typescript usage
* @param ctx
* @returns The canvas context.
*/
export declare function toTransformedContext(ctx: CanvasRenderingContext2D): TransformCanvasRenderingContext2D;
import { toTransformedContext, isTransformedContext, TransformCanvasRenderingContext2D } from "./toTransformedContext";
import { default as TransformContext } from "./TransformContext";
export { TransformContext, toTransformedContext, isTransformedContext, TransformCanvasRenderingContext2D, };

@@ -1,115 +0,3 @@

/**
* Type guard for transformed context
* @param ctx
* @returns
*/
export function isTransformedContext(ctx) {
return "zoom" in ctx && "beginPan" in ctx && "pan" in ctx && "endPan" in ctx;
}
/**
* Extends a canvas context IN PLACE.
* The return value is for type change typescript usage
* @param ctx
* @returns The canvas context.
*/
export function toTransformedContext(ctx) {
if (isTransformedContext(ctx)) {
console.warn("[canvas-transform] Canvas is already a transformed canvas!");
return ctx;
}
let svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
let xform = svg.createSVGMatrix();
ctx.getTransform = function () {
return xform;
};
const savedTransforms = [];
ctx.save = function () {
savedTransforms.push(xform.translate(0, 0));
return CanvasRenderingContext2D.prototype.save.call(ctx);
};
ctx.restore = function () {
xform = savedTransforms.pop();
return CanvasRenderingContext2D.prototype.restore.call(ctx);
};
ctx.scale = function (sx, sy) {
xform = xform.scale(sx, sy);
return CanvasRenderingContext2D.prototype.scale.call(ctx, sx, sy);
};
ctx.rotate = function (radians) {
xform = xform.rotate((radians * 180) / Math.PI);
return CanvasRenderingContext2D.prototype.rotate.call(ctx, radians);
};
ctx.translate = function (dx, dy) {
xform = xform.translate(dx, dy);
return CanvasRenderingContext2D.prototype.translate.call(ctx, dx, dy);
};
ctx.transform = function (a, b, c, d, e, f) {
let m2 = svg.createSVGMatrix();
m2.a = a;
m2.b = b;
m2.c = c;
m2.d = d;
m2.e = e;
m2.f = f;
xform = xform.multiply(m2);
return CanvasRenderingContext2D.prototype.transform.call(ctx, a, b, c, d, e, f);
};
ctx.setTransform = function (a, b, c, d, e, f) {
if (typeof a === "number") {
xform.a = a;
xform.b = b;
xform.c = c;
xform.d = d;
xform.e = e;
xform.f = f;
return CanvasRenderingContext2D.prototype.setTransform.call(ctx, a, b, c, d, e, f);
}
else {
return CanvasRenderingContext2D.prototype.setTransform.call(ctx, a);
}
};
// Extensions
let pt = svg.createSVGPoint();
ctx.transformedPoint = function (x, y) {
pt.x = x;
pt.y = y;
return pt.matrixTransform(xform.inverse());
};
let lastX = 0, lastY = 0, dragged = false, dragStart = undefined;
ctx.clearCanvas = function () {
var p1 = this.transformedPoint(0, 0);
var p2 = this.transformedPoint(this.canvas.width, this.canvas.height);
this.clearRect(p1.x, p1.y, p2.x - p1.x, p2.y - p1.y);
};
ctx.beginPan = function (e) {
lastX = e.offsetX || e.pageX - ctx.canvas.offsetLeft;
lastY = e.offsetY || e.pageY - ctx.canvas.offsetTop;
dragStart = this.transformedPoint(lastX, lastY);
dragged = false;
};
ctx.pan = function (e) {
lastX = e.offsetX || e.pageX - ctx.canvas.offsetLeft;
lastY = e.offsetY || e.pageY - ctx.canvas.offsetTop;
dragged = true;
if (dragStart) {
let pt = this.transformedPoint(lastX, lastY);
this.translate(pt.x - dragStart.x, pt.y - dragStart.y);
}
};
ctx.endPan = function () {
dragStart = null;
};
let zoom = 0;
ctx.zoom = function (amount, zoomFactor = 1.1, center) {
let pt = center
? this.transformedPoint(center.x, center.y)
: this.transformedPoint(lastX, lastY);
zoom + amount;
this.translate(pt.x, pt.y);
const factor = Math.pow(zoomFactor, amount);
this.scale(factor, factor);
this.translate(-pt.x, -pt.y);
return zoom;
};
return ctx;
}
import { toTransformedContext, isTransformedContext, } from "./toTransformedContext";
import { default as TransformContext } from "./TransformContext";
export { TransformContext, toTransformedContext, isTransformedContext, };
{
"name": "canvas-transform-context",
"version": "0.1.5",
"version": "1.0.0",
"description": "A wrapper for HTML canvas context for easy zooming/panning/translating",

@@ -8,3 +8,4 @@ "main": "dist/index.js",

"scripts": {
"build": "tsc && uglifyjs --compress --mangle -o ./dist/index.min.js -- ./dist/index.js",
"build": "tsc && rollup dist/index.js --file dist/bundle.mjs --format esm && uglifyjs dist/bundle.mjs --compress -o dist/bundle.min.js",
"build:test": "npm run build && cp dist/bundle.mjs examples/dist/canvas-transform.js",
"deploy": "gh-pages --dist examples",

@@ -28,6 +29,8 @@ "test": "jest --env=jsdom"

"gh-pages": "^4.0.0",
"tsc": "^2.0.4",
"typescript": "^4.7.4",
"uglifyjs": "^2.4.11"
"husky": "^8.0.1",
"minify": "^9.1.0",
"rollup": "^2.76.0",
"terser": "^5.14.1",
"typescript": "^4.7.4"
}
}

@@ -5,12 +5,12 @@ # Canvas Transform Context

A canvas context extension based on [this](http://phrogz.net/tmp/canvas_zoom_to_cursor.html) example by [phrogz](https://stackoverflow.com/users/405017/phrogz).
A canvas context extension based on [this](http://phrogz.net/tmp/canvas_zoom_to_cursor.html) example by [phrogz](https://stackoverflow.com/users/405017/phrogz).
Extends the 2d canvas context to support zooming and panning, allowing any canvas to be easily extended with panning and zooming functionalities. Perfect for visual web apps that requires extra canvas functionalities without the hassle of custom canvas implementations.
A class wrapper for a 2D canvas context that keeps track of transform information, allowing for easy coordinate control with scaled/transformed canvases. Perfect for visual web apps that requires extra canvas functionalities without the hassle of custom canvas implementations.
## [Demo](https://poohcom1.github.io/canvas-transform-context/basic/)
## Installation
### via npm
```

@@ -21,7 +21,9 @@ npm i canvas-transform-context

```javascript
import { toTransformedContext } from "canvas-transform-context"
import { TransformContext } from "canvas-transform-context"
```
### via browser
```javascript
import { toTransformedContext } from "https://unpkg.com/canvas-transform-context@latest/dist/index.min.js";
import { TransformContext } from "https://unpkg.com/canvas-transform-context@latest/dist/bundle.min.js";
```

@@ -31,64 +33,178 @@

Basic setup
```javascript
import { toTransformedContext } from "https://unpkg.com/canvas-transform-context@latest/dist/index.min.js"
// import { toTransformedContext } from "canvas-transform"
const canvas = getDocumentById("myCanvas")
const canvas = getDocumentById(/* canvas id */)
const ctx = canvas.getContext('2d')
toTransformedContext(ctx)
const transformCtx = new TransformContext(ctx);
// Create reusable draw function
function draw(ctx) {
/* draw on canvas */
}
transformCtx.onDraw((ctx) => {
/* Draw on canvas... */
})
// Mouse dragging
canvas.addEventListener("mousedown", (e) => {
ctx.beginPan(e);
draw(ctx);
});
canvas.addEventListener("mousemove", (e) => {
ctx.pan(e);
draw(ctx);
});
canvas.addEventListener("mouseup", (e) => {
ctx.endPan(e);
draw(ctx);
});
canvas.addEventListener("mousedown", (e) => transformCtx.beginMousePan(e));
canvas.addEventListener("mousemove", (e) => transformCtx.moveMousePan(e));
canvas.addEventListener("mouseup", (e) => transformCtx.endPan(e));
// Wheel zooming
canvas.addEventListener("wheel", (e) => {
ctx.zoom(-Math.sign(e.deltaY));
draw(ctx);
})
canvas.addEventListener("wheel", (e) => transformCtx.zoomByMouse(e));
```
## Documentation
# Documentation
| Function | Description |
| -- | -- |
| toTransformedContext(ctx) | Extends the canvas context with new methods for rotation and panning (see below). Since the context is directly modified, the value does not need to be reassigned. However, the function does also return the modified context for the sake of typing when using with Typescript. |
## Action Methods
### Utility methods
| Method | Description |
| -- | -- |
| ctx.transformedPoint(x, y)| Converts a coordinate to the correct translated/scaled coordinates. Returns a DOMPoint (contains `x` and `y` properties). |
Batteries-included methods for commonly use actions, included methods that can directly take mouse events as a parameter.
### Panning methods
| Method | Description |
| -- | -- |
| ctx.beginPan(mouseEvent) | Sets the initial panning point. Call from `mousedown`. |
| ctx.pan(mouseEvent) | Pans the canvas. Call from `mousemove`. |
| ctx.endPan(mouseEvent) | Stops the panning. Call form `mouseup`. |
### Zooming methods
| Method | Description |
| -- | -- |
| ctx.zoom(amount, factor?, center?) | Zooms the canvas. `amount` represents the increment to zoom (in integers). `factor` is the percentage to scale by. Defaults to 1.1. `center` is the canvas position to zoom to; if undefined, it will infer from the latest panned position from `endPan`. |
### `beginMousePan(e)`
Begins a pan given the current position from the mouse event
| Param |
| ------- |
| e |
### `moveMousePan(e)`
Pans the canvas to the new position from the mouse event.
Does nothing if beginMousePan wasn't called, or if endPan was just called
| Param |
| ------- |
| e |
### `endMousePan()`
Ends a mouse pan
### `zoomByMouse(e, zoomScale)`
Zooms via the mouse wheel event
| Param | Default | Description |
| ----------- | ------------------ | ------------------------------------------------- |
| e | | mouse wheel event |
| zoomScale | <code>1.1</code> | The scale percentage to zoom by. Default is 1.1 |
### `beginPan(start, transform)`
Sets the anchor for a panning action
| Param | Default | Description |
| ----------- | ------------------- | --------------------------------------------------- |
| start | | Starting coordinates for a pan |
| transform | <code>true</code> | Whether or not to transform the start coordinates |
### `movePan(current, transform)`
Pans the canvas to the new coordinates given the starting point in beginPan.
Does nothing if beginPan was not called, or if endPan was just called
| Param | Default | Description |
| ----------- | ------------------- | --------------------------------------------------- |
| current | | |
| transform | <code>true</code> | Whether or not to transform the start coordinates |
### `endPan()`
Stops a pan
### `zoomBy(amount, zoomScale, center, transform) ⇒`
Zoom by a given integer amount
**Returns**: Current zoom amount in integers
| Param | Default | Description |
| ----------- | ------------------------ | --------------------------------------------------------------------------------------------- |
| amount | | Amount to zoom by in integers. Positive integer zooms in |
| zoomScale | <code>1.1</code> | The scale percentage to zoom by. Default is 1.1 |
| center | <code>undefined</code> | The point to zoom in towards. If undefined, it will zoom towards the latest panned position |
| transform | <code>true</code> | Whether or not to transform the center coordinates |
### `reset()`
Resets all transformations
## Action Helpers
### `onDraw(callback)`
Creates a callback to be called after each action method above.
| Param | Description |
| ------------- | -------------------- |
| callback | A callback function with the canvas context as a parameter |
## Transform Helpers
Helper methods to deal with coordinate transformations
### `transformPoint(canvasPoint) ⇒`
Converts canvas coordinates to transformed coordinates
**Returns**: Transformed coordinates
| Param | Description |
| ------------- | -------------------- |
| canvasPoint | Canvas coordinates |
### `mouseToTransformed(e) ⇒`
Converts a mouse event to the transformed coordinates within the canvas
**Returns**: Transformed point
| Param | Description |
| ------- | ------------- |
| e | mouse event |
### `clearCanvas()`
Clear the canvas given the current transformations
## General Helpers
General purpose canvas helpers unrelated to transform
### `mouseToCanvas(e) ⇒`
Converts a mouse event to the correct canvas coordinates
**Returns**: Canvas coordinates
| Param | Description |
| ------- | ------------- |
| e | mouse event |
## Attributions
Main implementation based on code by phrogz:
- http://phrogz.net/tmp/canvas_zoom_to_cursor.html
- https://github.com/Phrogz
- http://phrogz.net/tmp/canvas_zoom_to_cursor.html
- https://github.com/Phrogz

@@ -1,213 +0,13 @@

export interface TransformCanvasRenderingContext2D
extends CanvasRenderingContext2D {
getTransform(): SVGMatrix;
transformedPoint(x: number, y: number): DOMPoint;
clearCanvas(): void;
import {
toTransformedContext,
isTransformedContext,
TransformCanvasRenderingContext2D,
} from "./toTransformedContext";
import { default as TransformContext } from "./TransformContext";
// Transform functions
/**
* Marks the start of a canvas drag.
* Should be used on the onmousedown event
* @param e
*/
beginPan(e: MouseEvent): void;
/**
* Drags the canvas.
* Should be used on the onmousemove event
* @param e
*/
pan(e: MouseEvent): void;
/**
* Ends the canvas draw.
* Should be used on the onmousemove event
* @param e
*/
endPan(e: MouseEvent): void;
/**
* Zooms in or out
* @param amount Amount in integers to zoom by. Applies zoom on top of previous zoom
* @param factor Zoom factor. Defaults to 1.1
* @param center The center to zoom to. If undefined, will zoom to the last mouse pos in endDraw
*/
zoom(
amount: number,
factor?: number,
center?: { x: number; y: number }
): number;
}
/**
* Type guard for transformed context
* @param ctx
* @returns
*/
export function isTransformedContext(
ctx: CanvasRenderingContext2D
): ctx is TransformCanvasRenderingContext2D {
return "zoom" in ctx && "beginPan" in ctx && "pan" in ctx && "endPan" in ctx;
}
/**
* Extends a canvas context IN PLACE.
* The return value is for type change typescript usage
* @param ctx
* @returns The canvas context.
*/
export function toTransformedContext(
ctx: CanvasRenderingContext2D
): TransformCanvasRenderingContext2D {
if (isTransformedContext(ctx)) {
console.warn("[canvas-transform] Canvas is already a transformed canvas!");
return ctx;
}
let svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
let xform = svg.createSVGMatrix();
ctx.getTransform = function () {
return xform;
};
const savedTransforms: DOMMatrix[] = [];
ctx.save = function () {
savedTransforms.push(xform.translate(0, 0));
return CanvasRenderingContext2D.prototype.save.call(ctx);
};
ctx.restore = function () {
xform = savedTransforms.pop()!;
return CanvasRenderingContext2D.prototype.restore.call(ctx);
};
ctx.scale = function (sx, sy) {
xform = xform.scale(sx, sy);
return CanvasRenderingContext2D.prototype.scale.call(ctx, sx, sy);
};
ctx.rotate = function (radians) {
xform = xform.rotate((radians * 180) / Math.PI);
return CanvasRenderingContext2D.prototype.rotate.call(ctx, radians);
};
ctx.translate = function (dx, dy) {
xform = xform.translate(dx, dy);
return CanvasRenderingContext2D.prototype.translate.call(ctx, dx, dy);
};
ctx.transform = function (a, b, c, d, e, f) {
let m2 = svg.createSVGMatrix();
m2.a = a;
m2.b = b;
m2.c = c;
m2.d = d;
m2.e = e;
m2.f = f;
xform = xform.multiply(m2);
return CanvasRenderingContext2D.prototype.transform.call(
ctx,
a,
b,
c,
d,
e,
f
);
};
ctx.setTransform = function (
a: number | DOMMatrix2DInit,
b?: number,
c?: number,
d?: number,
e?: number,
f?: number
) {
if (typeof a === "number") {
xform.a = a;
xform.b = b;
xform.c = c;
xform.d = d;
xform.e = e;
xform.f = f;
return CanvasRenderingContext2D.prototype.setTransform.call(
ctx,
a,
b,
c,
d,
e,
f
);
} else {
return CanvasRenderingContext2D.prototype.setTransform.call(ctx, a);
}
};
// Extensions
let pt = svg.createSVGPoint();
(ctx as TransformCanvasRenderingContext2D).transformedPoint = function (
x,
y
) {
pt.x = x;
pt.y = y;
return pt.matrixTransform(xform.inverse());
};
let lastX = 0,
lastY = 0,
dragged = false,
dragStart: DOMPoint | undefined = undefined;
(ctx as TransformCanvasRenderingContext2D).clearCanvas = function () {
var p1 = this.transformedPoint(0, 0);
var p2 = this.transformedPoint(this.canvas.width, this.canvas.height);
this.clearRect(p1.x, p1.y, p2.x - p1.x, p2.y - p1.y);
};
(ctx as TransformCanvasRenderingContext2D).beginPan = function (e) {
lastX = e.offsetX || e.pageX - ctx.canvas.offsetLeft;
lastY = e.offsetY || e.pageY - ctx.canvas.offsetTop;
dragStart = this.transformedPoint(lastX, lastY);
dragged = false;
};
(ctx as TransformCanvasRenderingContext2D).pan = function (e) {
lastX = e.offsetX || e.pageX - ctx.canvas.offsetLeft;
lastY = e.offsetY || e.pageY - ctx.canvas.offsetTop;
dragged = true;
if (dragStart) {
let pt = this.transformedPoint(lastX, lastY);
this.translate(pt.x - dragStart.x, pt.y - dragStart.y);
}
};
(ctx as TransformCanvasRenderingContext2D).endPan = function () {
dragStart = null;
};
let zoom = 0;
(ctx as TransformCanvasRenderingContext2D).zoom = function (
amount,
zoomFactor = 1.1,
center?: { x: number; y: number }
) {
let pt = center
? this.transformedPoint(center.x, center.y)
: this.transformedPoint(lastX, lastY);
zoom + amount;
this.translate(pt.x, pt.y);
const factor = Math.pow(zoomFactor, amount);
this.scale(factor, factor);
this.translate(-pt.x, -pt.y);
return zoom;
};
return ctx as TransformCanvasRenderingContext2D;
}
export {
TransformContext,
toTransformedContext,
isTransformedContext,
TransformCanvasRenderingContext2D,
};
{
"compilerOptions": {
"strict": true,
"lib": ["es6", "dom", "dom.iterable"],
"module": "es6",
"target": "es6",
"allowJs": true,
"outDir": "dist",
"declaration": true,
"strict": false
"declaration": true
},
"include": ["src"]
"include": ["src", "src/index.js"]
}

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc