Comparing version 0.0.5 to 0.0.6
# 0.0.6 | ||
* Fixes a bug that caused saved images to grow in size after loading them, then re-saving. | ||
* Stops the pressure decrease on pen-up events from preventing line/arrow objects from having variable width. | ||
# 0.0.5 | ||
@@ -3,0 +7,0 @@ * Configuration options: |
@@ -1,5 +0,5 @@ | ||
import { dirname } from "path"; | ||
import BundledFile from "./BundledFile"; | ||
import { dirname } from 'path'; | ||
import BundledFile from './BundledFile'; | ||
const rootDir = dirname(__dirname); | ||
const mainBundle = new BundledFile('jsdraw', `${rootDir}/src/bundle/bundled.ts`, `${rootDir}/dist/bundle.js`); | ||
void mainBundle.build(); |
@@ -151,5 +151,17 @@ import { Bezier } from 'bezier-js'; | ||
} | ||
const halfVec = Vec2.ofXY(this.currentCurve.normal(projectionT)) | ||
.normalized().times(this.curveStartWidth / 2 * projectionT | ||
+ this.curveEndWidth / 2 * (1 - projectionT)); | ||
const halfVecT = projectionT; | ||
let halfVec = Vec2.ofXY(this.currentCurve.normal(halfVecT)) | ||
.normalized().times(this.curveStartWidth / 2 * halfVecT | ||
+ this.curveEndWidth / 2 * (1 - halfVecT)); | ||
// Computes a boundary curve. [direction] should be either +1 or -1 (determines the side | ||
// of the center curve to place the boundary). | ||
const computeBoundaryCurve = (direction, halfVec) => { | ||
return new Bezier(startPt.plus(startVec.times(direction)), controlPoint.plus(halfVec.times(direction)), endPt.plus(endVec.times(direction))); | ||
}; | ||
const upperBoundary = computeBoundaryCurve(1, halfVec); | ||
const lowerBoundary = computeBoundaryCurve(-1, halfVec); | ||
// If the boundaries have two intersections, increasing the half vector's length could fix this. | ||
if (upperBoundary.intersects(lowerBoundary).length === 2) { | ||
halfVec = halfVec.times(2); | ||
} | ||
const pathCommands = [ | ||
@@ -156,0 +168,0 @@ { |
@@ -26,3 +26,2 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
import { defaultEditorLocalization } from './localization'; | ||
; | ||
export class Editor { | ||
@@ -136,2 +135,10 @@ constructor(parent, settings = {}) { | ||
if (pointer.down) { | ||
const prevData = pointers[pointer.id]; | ||
if (prevData) { | ||
const distanceMoved = pointer.screenPos.minus(prevData.screenPos).magnitude(); | ||
// If the pointer moved less than two pixels, don't send a new event. | ||
if (distanceMoved < 2) { | ||
return; | ||
} | ||
} | ||
pointers[pointer.id] = pointer; | ||
@@ -138,0 +145,0 @@ if (this.toolController.dispatchInputEvent({ |
@@ -18,4 +18,4 @@ import Editor from './Editor'; | ||
new (element: AbstractComponent, applyByFlattening?: boolean): { | ||
readonly "__#1@#element": AbstractComponent; | ||
"__#1@#applyByFlattening": boolean; | ||
readonly "__#2@#element": AbstractComponent; | ||
"__#2@#applyByFlattening": boolean; | ||
apply(editor: Editor): void; | ||
@@ -22,0 +22,0 @@ unapply(editor: Editor): void; |
@@ -280,4 +280,10 @@ import { Bezier } from 'bezier-js'; | ||
let firstPos = null; | ||
let isFirstCommand = true; | ||
const commands = []; | ||
const moveTo = (point) => { | ||
// The first moveTo/lineTo is already handled by the [startPoint] parameter of the Path constructor. | ||
if (isFirstCommand) { | ||
isFirstCommand = false; | ||
return; | ||
} | ||
commands.push({ | ||
@@ -289,2 +295,6 @@ kind: PathCommandType.MoveTo, | ||
const lineTo = (point) => { | ||
if (isFirstCommand) { | ||
isFirstCommand = false; | ||
return; | ||
} | ||
commands.push({ | ||
@@ -395,2 +405,3 @@ kind: PathCommandType.LineTo, | ||
} | ||
isFirstCommand = false; | ||
} | ||
@@ -397,0 +408,0 @@ return new Path(firstPos !== null && firstPos !== void 0 ? firstPos : Vec2.zero, commands); |
@@ -68,3 +68,5 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
for (const part of parts) { | ||
if (part !== '') { | ||
// Skip effective no-ops -- moveTos without additional commands. | ||
const isNoOpMoveTo = /^[0-9., \t\n]+$/.exec(part); | ||
if (part !== '' && !isNoOpMoveTo) { | ||
// We split the path by moveTo commands, so add the 'M' back in | ||
@@ -71,0 +73,0 @@ // if it was present. |
@@ -27,3 +27,2 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
transform-origin: center; | ||
overflow: hidden; | ||
} | ||
@@ -30,0 +29,0 @@ |
@@ -13,3 +13,3 @@ import { CommandLocalization } from './commands/localization'; | ||
new (transform: Mat33): { | ||
readonly "__#2@#inverseTransform": Mat33; | ||
readonly "__#1@#inverseTransform": Mat33; | ||
readonly transform: Mat33; | ||
@@ -16,0 +16,0 @@ apply(editor: Editor): void; |
{ | ||
"name": "js-draw", | ||
"version": "0.0.5", | ||
"version": "0.0.6", | ||
"description": "Draw pictures using a pen, touchscreen, or mouse! JS-draw is a drawing library for JavaScript and TypeScript. ", | ||
@@ -78,3 +78,3 @@ "main": "dist/src/Editor.js", | ||
"ts-node": "^10.9.1", | ||
"typescript": "^4.7.4", | ||
"typescript": "^4.8.2", | ||
"webpack": "^5.74.0" | ||
@@ -81,0 +81,0 @@ }, |
@@ -15,2 +15,3 @@ # js-draw | ||
### With a bundler that supports importing `.css` files | ||
To create a new `Editor` and add it as a child of `document.body`, | ||
@@ -26,3 +27,13 @@ ```ts | ||
### With a bundler that doesn't support importing `.css` files | ||
Import the pre-bundled version of the editor to apply CSS after loading the page. | ||
```ts | ||
import Editor from 'js-draw'; | ||
import 'js-draw/bundle'; | ||
const editor = new Editor(document.body); | ||
``` | ||
`js-draw/bundle` is a version of the editor pre-processed by `Webpack`. As such, `import`ing it applies editor-specific CSS to the document. | ||
### Without a bundler | ||
If you're not using a bundler, consider using the pre-bundled editor: | ||
@@ -39,3 +50,5 @@ ```html | ||
**Note**: To ensure the CDN-hosted version of `js-draw` hasn't been tampered with, consider [including an `integrity="..."` attribute](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity). [Read more about using SRI with JSDelivr](https://www.jsdelivr.com/using-sri-with-dynamic-files). | ||
## Adding a toolbar | ||
@@ -42,0 +55,0 @@ |
@@ -186,3 +186,2 @@ import { Bezier } from 'bezier-js'; | ||
let projectionT = this.currentCurve.project(controlPoint.xy).t; | ||
if (!projectionT) { | ||
@@ -196,8 +195,28 @@ if (startPt.minus(controlPoint).magnitudeSquared() < endPt.minus(controlPoint).magnitudeSquared()) { | ||
const halfVec = Vec2.ofXY(this.currentCurve.normal(projectionT)) | ||
const halfVecT = projectionT; | ||
let halfVec = Vec2.ofXY(this.currentCurve.normal(halfVecT)) | ||
.normalized().times( | ||
this.curveStartWidth / 2 * projectionT | ||
+ this.curveEndWidth / 2 * (1 - projectionT) | ||
this.curveStartWidth / 2 * halfVecT | ||
+ this.curveEndWidth / 2 * (1 - halfVecT) | ||
); | ||
// Computes a boundary curve. [direction] should be either +1 or -1 (determines the side | ||
// of the center curve to place the boundary). | ||
const computeBoundaryCurve = (direction: number, halfVec: Vec2) => { | ||
return new Bezier( | ||
startPt.plus(startVec.times(direction)), | ||
controlPoint.plus(halfVec.times(direction)), | ||
endPt.plus(endVec.times(direction)), | ||
); | ||
}; | ||
const upperBoundary = computeBoundaryCurve(1, halfVec); | ||
const lowerBoundary = computeBoundaryCurve(-1, halfVec); | ||
// If the boundaries have two intersections, increasing the half vector's length could fix this. | ||
if (upperBoundary.intersects(lowerBoundary).length === 2) { | ||
halfVec = halfVec.times(2); | ||
} | ||
const pathCommands: PathCommand[] = [ | ||
@@ -204,0 +223,0 @@ { |
@@ -189,4 +189,14 @@ | ||
if (pointer.down) { | ||
const prevData = pointers[pointer.id]; | ||
if (prevData) { | ||
const distanceMoved = pointer.screenPos.minus(prevData.screenPos).magnitude(); | ||
// If the pointer moved less than two pixels, don't send a new event. | ||
if (distanceMoved < 2) { | ||
return; | ||
} | ||
} | ||
pointers[pointer.id] = pointer; | ||
if (this.toolController.dispatchInputEvent({ | ||
@@ -193,0 +203,0 @@ kind: InputEvtType.PointerMoveEvt, |
@@ -17,15 +17,11 @@ // Tests to ensure that Paths can be deserialized | ||
expect(path1.parts[0]).toMatchObject({ | ||
kind: PathCommandType.MoveTo, | ||
point: Vec2.zero, | ||
}); | ||
expect(path2.parts).toMatchObject(path1.parts); | ||
expect(path1.parts.length).toBe(0); | ||
expect(path1.startPoint).toMatchObject(Vec2.zero); | ||
expect(path2.parts.length).toBe(0); | ||
expect(path2.startPoint).toMatchObject(Vec2.zero); | ||
expect(path3.parts).toMatchObject([ | ||
{ | ||
kind: PathCommandType.MoveTo, | ||
point: Vec2.of(1, 1), | ||
}, | ||
{ | ||
kind: PathCommandType.MoveTo, | ||
point: Vec2.of(2, 2), | ||
@@ -50,9 +46,6 @@ }, | ||
kind: PathCommandType.MoveTo, | ||
point: Vec2.of(1, 1), | ||
}, | ||
{ | ||
kind: PathCommandType.MoveTo, | ||
point: Vec2.of(4, 4), | ||
}, | ||
]); | ||
expect(path.startPoint).toMatchObject(Vec2.of(1, 1)); | ||
}); | ||
@@ -62,12 +55,10 @@ | ||
const path = Path.fromString('l1,2L-1,0l0.1,-1.0'); | ||
// l is a relative lineTo, but because there | ||
// is no previous command, it should act like an | ||
// absolute moveTo. | ||
expect(path.startPoint).toMatchObject(Vec2.of(1, 2)); | ||
expect(path.parts).toMatchObject([ | ||
{ | ||
kind: PathCommandType.LineTo, | ||
// l is a relative lineTo, but because there | ||
// is no previous command, it should act like an | ||
// absolute moveTo. | ||
point: Vec2.of(1, 2), | ||
}, | ||
{ | ||
kind: PathCommandType.LineTo, | ||
point: Vec2.of(-1, 0), | ||
@@ -91,6 +82,2 @@ }, | ||
{ | ||
kind: PathCommandType.MoveTo, | ||
point: Vec2.of(3, 3), | ||
}, | ||
{ | ||
kind: PathCommandType.LineTo, | ||
@@ -97,0 +84,0 @@ point: Vec2.of(4, 5), |
@@ -370,2 +370,3 @@ import { Bezier } from 'bezier-js'; | ||
let firstPos: Point2|null = null; | ||
let isFirstCommand: boolean = true; | ||
const commands: PathCommand[] = []; | ||
@@ -375,2 +376,8 @@ | ||
const moveTo = (point: Point2) => { | ||
// The first moveTo/lineTo is already handled by the [startPoint] parameter of the Path constructor. | ||
if (isFirstCommand) { | ||
isFirstCommand = false; | ||
return; | ||
} | ||
commands.push({ | ||
@@ -382,2 +389,7 @@ kind: PathCommandType.MoveTo, | ||
const lineTo = (point: Point2) => { | ||
if (isFirstCommand) { | ||
isFirstCommand = false; | ||
return; | ||
} | ||
commands.push({ | ||
@@ -498,2 +510,3 @@ kind: PathCommandType.LineTo, | ||
} | ||
isFirstCommand = false; | ||
} | ||
@@ -500,0 +513,0 @@ |
@@ -69,6 +69,10 @@ import Color4 from './Color4'; | ||
for (const part of parts) { | ||
if (part !== '') { | ||
// Skip effective no-ops -- moveTos without additional commands. | ||
const isNoOpMoveTo = /^[0-9., \t\n]+$/.exec(part); | ||
if (part !== '' && !isNoOpMoveTo) { | ||
// We split the path by moveTo commands, so add the 'M' back in | ||
// if it was present. | ||
const current = !isFirst ? `M${part}` : part; | ||
const path = Path.fromString(current); | ||
@@ -75,0 +79,0 @@ const spec = path.toRenderable(style); |
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
635263
13180
185