Fix horizontalLine being one pixel short, add canvas center support

main
Shad Amethyst 2 years ago
parent a9b894d066
commit 5121ffddfa

4
package-lock.json generated

@ -1,12 +1,12 @@
{ {
"name": "@shadryx/pptk", "name": "@shadryx/pptk",
"version": "0.1.7", "version": "0.1.8",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@shadryx/pptk", "name": "@shadryx/pptk",
"version": "0.1.7", "version": "0.1.8",
"license": "MIT", "license": "MIT",
"devDependencies": { "devDependencies": {
"solid-js": "^1.6.2", "solid-js": "^1.6.2",

@ -1,6 +1,6 @@
{ {
"name": "@shadryx/pptk", "name": "@shadryx/pptk",
"version": "0.1.7", "version": "0.1.8",
"description": "Pixel-Perfect ToolKit, a library to help make pixel-perfect applications on high-DPI devices", "description": "Pixel-Perfect ToolKit, a library to help make pixel-perfect applications on high-DPI devices",
"keywords": [ "keywords": [
"pixel-perfect", "pixel-perfect",
@ -44,8 +44,7 @@
"dev:solid": "vite dev test/solid", "dev:solid": "vite dev test/solid",
"dev:vanilla": "vite dev test/vanilla", "dev:vanilla": "vite dev test/vanilla",
"build": "npm run prepare-dev && vite build && tsc && cp src/index.d.ts dist/types/index.d.ts", "build": "npm run prepare-dev && vite build && tsc && cp src/index.d.ts dist/types/index.d.ts",
"clean": "rm -rf dist/ src/index.d.ts", "clean": "rm -rf dist/ src/index.d.ts"
"publish": "npm i && npm run build && npm publish --access public"
}, },
"repository": { "repository": {
"type": "git", "type": "git",

@ -358,7 +358,7 @@ export class Pannable {
} }
/** @private **/ /** @private **/
_getValues(touches) { _getValues(touches, cx = 0, cy = 0) {
// First-order moments of touches.x and touches.y // First-order moments of touches.x and touches.y
let mx = 0; let mx = 0;
let my = 0; let my = 0;
@ -375,14 +375,14 @@ export class Pannable {
const n = touches.size; const n = touches.size;
if (n <= 1) { if (n <= 1) {
return [mx, my, 1]; return [mx - cx, my - cy, 1];
} }
// Unbiased sample variance, from https://en.wikipedia.org/wiki/Bessel%27s_correction#Formula // Unbiased sample variance, from https://en.wikipedia.org/wiki/Bessel%27s_correction#Formula
const sx = mx2 / (n - 1) - (mx * mx) / (n * (n - 1)); const sx = mx2 / (n - 1) - (mx * mx) / (n * (n - 1));
const sy = my2 / (n - 1) - (my * my) / (n * (n - 1)); const sy = my2 / (n - 1) - (my * my) / (n * (n - 1));
return [mx / n, my / n, Math.sqrt(sx + sy)]; return [mx / n - cx, my / n - cy, Math.sqrt(sx + sy)];
} }
/** @returns {number} **/ /** @returns {number} **/
@ -409,8 +409,8 @@ export class Pannable {
/** /**
* @param {Map<number, Touch>} touches * @param {Map<number, Touch>} touches
**/ **/
move(touches) { move(touches, cx = 0, cy = 0) {
const currentValues = this._getValues(touches); const currentValues = this._getValues(touches, cx, cy);
let deltaLogScale = Math.log2(currentValues[2] / this.lastValues[2]); let deltaLogScale = Math.log2(currentValues[2] / this.lastValues[2]);
if (Number.isNaN(deltaLogScale) || !Number.isFinite(deltaLogScale)) { if (Number.isNaN(deltaLogScale) || !Number.isFinite(deltaLogScale)) {
deltaLogScale = 0; deltaLogScale = 0;
@ -443,8 +443,8 @@ export class Pannable {
/** /**
* @param {Map<number, Touch>} touches * @param {Map<number, Touch>} touches
**/ **/
update(touches) { update(touches, cx = 0, cy = 0) {
this.lastValues = this._getValues(touches); this.lastValues = this._getValues(touches, cx, cy);
} }
} }
@ -794,10 +794,10 @@ export class PixelPerfectContext2D {
if (y2 < y1) { if (y2 < y1) {
this.context.moveTo(this._unscaleX(x1 + dx), this._unscaleY(y2 + dy)); this.context.moveTo(this._unscaleX(x1 + dx), this._unscaleY(y2 + dy));
this.context.lineTo(this._unscaleX(x1 + dx), this._unscaleY(y1 - dy)); this.context.lineTo(this._unscaleX(x1 + dx), this._unscaleY(y1 - dy) - 1);
} else { } else {
this.context.moveTo(this._unscaleX(x1 + dx), this._unscaleY(y1 + dy)); this.context.moveTo(this._unscaleX(x1 + dx), this._unscaleY(y1 + dy));
this.context.lineTo(this._unscaleX(x1 + dx), this._unscaleY(y2 - dy)); this.context.lineTo(this._unscaleX(x1 + dx), this._unscaleY(y2 - dy) + 1);
} }
this.context.stroke(); this.context.stroke();
@ -830,10 +830,10 @@ export class PixelPerfectContext2D {
if (x2 < x1) { if (x2 < x1) {
this.context.moveTo(this._unscaleX(x2 + dx), this._unscaleY(y1 + dy)); this.context.moveTo(this._unscaleX(x2 + dx), this._unscaleY(y1 + dy));
this.context.lineTo(this._unscaleX(x1 - dx), this._unscaleY(y1 + dy)); this.context.lineTo(this._unscaleX(x1 - dx) - 1, this._unscaleY(y1 + dy));
} else { } else {
this.context.moveTo(this._unscaleX(x1 + dx), this._unscaleY(y1 + dy)); this.context.moveTo(this._unscaleX(x1 + dx), this._unscaleY(y1 + dy));
this.context.lineTo(this._unscaleX(x2 - dx), this._unscaleY(y1 + dy)); this.context.lineTo(this._unscaleX(x2 - dx) + 1, this._unscaleY(y1 + dy));
} }
this.context.stroke(); this.context.stroke();

@ -1,26 +1,40 @@
import { createSignal } from "solid-js"; import { createSignal } from "solid-js";
import { Pannable, PannableOptions, PannableState, Touch } from "../index.js"; import { Pannable, PannableOptions, PannableState, Touch } from "../index.js";
export function usePannable(config: PannableOptions) { export type UsePannableOptions = {
center?: () => [x: number, y: number],
};
export function usePannable(config: PannableOptions & UsePannableOptions) {
const pannable = new Pannable(config); const pannable = new Pannable(config);
const [state, setState] = createSignal<PannableState>(pannable.getState()); const [state, setState] = createSignal<PannableState>(pannable.getState());
const center = config.center ?? (() => [0, 0]);
return { return {
update(touches: Map<number, Touch>) { update(touches: Map<number, Touch>) {
pannable.update(touches); pannable.update(touches, ...center());
}, },
move(touches: Map<number, Touch>) { move(touches: Map<number, Touch>) {
pannable.move(touches); pannable.move(touches, ...center());
const newState = pannable.getState(); const newState = pannable.getState();
setState(newState); setState(newState);
return newState; return newState;
}, },
zoom(amount: number, clientX?: number, clientY?: number) { zoom(amount: number, clientX?: number, clientY?: number) {
pannable.zoom(amount, clientX, clientY); const [cx, cy] = center();
pannable.zoom(amount, (clientX ?? 0) - cx, (clientY ?? 0) - cy);
const newState = pannable.getState(); const newState = pannable.getState();
setState(newState); setState(newState);
return newState; return newState;
}, },
getState: state, getState: () => {
const result = state();
const [cx, cy] = center();
return {
...result,
dx: result.dx + cx,
dy: result.dy + cy,
};
}
}; };
} }

Loading…
Cancel
Save