pencil-js / pencil.js Goto Github PK
View Code? Open in Web Editor NEW✏️ Nice modular interactive 2D drawing library
Home Page: https://pencil.js.org/
License: MIT License
✏️ Nice modular interactive 2D drawing library
Home Page: https://pencil.js.org/
License: MIT License
Similarly to #55, Slider rely on difference of mouse position across the x axis. But once rotated, the Component and browser axis don't match up.
Slider handle is a simple draggable component. It'll be hard to hack the draggable constrain option to work with rotation.
const slider = new P.Slider(scene.center, {
rotation: 1 / 8,
});
A recurring use-case for drawing engine like Pencil.js is to display sprite. Sprites are a large image composed of other images, the point is to go through them to create the illusion of movement (ex)
Mostly used in games, a sprite must have an image and the metadata for each position in that image.
As far as I know, there's no standard, but we should be able to read from JSON output of popular image packers (TexturePacker, ShoeBox, Spritesheet.js ...)
// Will preload the json and the meta texture
const sheet = new SpriteSheet("sheet.json");
// Return all corresponding data
const array = sheet.get(globPattern);
// Create the component
const sprite = new Sprite(position, array, {
loop: true, // default, should the animation start over when done
speed: 1, // default, number of animation frame per scene frame
});
const sheet = new SpriteSheet("sheet.json");
// Define states
const object = {
state1: sheet.get(globPattern1),
state2: sheet.get(globPattern2),
};
const sprite = new Sprite(position, object);
// Change the sprite state (default to the first)
sprite.setState("state1");
const sheet = new SpriteSheet("sheet.json");
const sprite = new Sprite(position, sheet.get(globPattern1), {
loop: false,
});
// Set of event
sprite.on("animation-start", () => sprite.show());
sprite.on("animation-frame", () => {});
sprite.on("animation-end", () => sprite.hide());
// Set of playback methods
sprite.play();
sprite.pause();
sprite.setFrame(0);
In Text class, the _cachedMeasures
prevents re-computing measures each times when text hasn't changed.
It could be a slight improvement to share this cache across all Text instances. Getters and setters should exist through a Text static property.
It's not important for the user to access the cache, but it should be possible to:
Your current navigator: Chrome v65
The package you used: @pencil.js/container
The function getAbsolutePosition
returns wrong position when the container is nested inside another with a rotation.
const parent = new Container([0, 0], {
rotation: 0.5,
});
const child = new Container([10, 10]);
parent.add(child);
child.getAbsolutePosition(); // => fail
We should be able to wrap the mouse scroll events under MouseEvent with easy to use params.
Since node 10.10.0, code coverage is natively supported. The c8 package use this new feature and report a ~300% performance improvement.
Once this feature has live a little and node is more widely used, we should use it instead of nyc.
It's not currently possible to change the baseline of texts. A new option would be great.
It would be an enum, much like the align
option. With "top"
, "middle"
and "bottom"
for a start.
Should we can call it baseline
?
// This text is not center on screen :/
const text = new Text(scene.center, "Hello\nWorld", {
align: "center",
});
Low level documentation could be generated from jsDoc. We need to find a good module able to handle this for each sub-packages.
Generated documentation should be easily readable, display all informations present in jsDoc and have links to other files (for types for example).
PS: High level documentation ("readme", "first steps", "changelog" ...) should still be written by hand.
Points of a Line object have absolute position. That way, in order to draw a polygon between 3 shapes, it's easy to write:
const line = new Polygon([
shape1.position,
shape2.position,
shape3.position,
]);
This means that moving one position don't change the others.
In the other hand, relative position could allow to move the polygon position and keep the polygon shape.
When a component is rotated (by itself or any of its parents) the draggable
package will produce unexpected result. This impact other package like resizable
and Slider
that use draggable
and prevent them to work when rotated.
A solution might be to climb the component ancestry to compute its absolute rotation and act accordingly in draggable.js
.
const circle = new Circle(scene.center, 200, {
rotation: 0.25,
fill: "red",
});
const square = new Square(undefined, 200);
square.draggable();
circle.add(square);
scene.add(circle);
In current version (v1.13.0) Slider and Knob input have a default options max
value of 10
. This doesn't really make sense.
All Pencil.js works with value between 0 and 1 except those.
Fixing this should only require to change the value in the defaultOptions
static function. But both component should be manually tested (using drawingTests
folder) to be sure.
All packages should have their own tests.
Ellipses are one of the most common shape and it's easy to draw in canvas.
However, I don't know how it should integrate in the current dependency tree.
Current tree:
Possible solutions:
(1) IMO, arcs (ellipse or circle) should be treated by default as stroke (like lines and paths). Which mean that they could even inherit from Line.
(2) In the other hand, circle is just a specific arc (just as square is a specific rectangle) as much as a specific ellipse. Since double inheritance is impossible in JS, it's not an option.
We should setup the all-contributor CLI to automatically manage the contributor list.
I prefer not to use the bot for more fine tune configuration.
Webpack has got a major update to v4.
We should update, but it seams to mean some changes on the webpack.config.js
Branch | Build failing 🚨 |
---|---|
Dependency | @gmartigny/eslint-config |
Current Version | 1.2.0 |
Type | devDependency |
This version is covered by your current version range and after updating it in your project the build failed.
@gmartigny/eslint-config is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.
There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.
Your Greenkeeper Bot 🌴
A few things was missing from the first implementation of the Heart component.
this.position
)radius
is not representative of the actual radius.static from
function is missing// The heart won't be at the center neither will have a radius of 100px
const heart = new Heart(scene.center, 100, {
fill: "red",
});
// missing function
const clone = Heart.from(heart.toJSON());
Vector should be a direction and a amplitude. Two Positions better represent a segment.
In a second time, a real vector implementation should be done.
Reamdes for all components should have an image showing the result of the demo code.
Your current navigator: Chrome v65
The package you used: @pencil.js/container
The z-index sorting of children in a container sometimes change order.
This induce shapes to quickly move over and under each others and flicker.
Don't find code that reproduce 100%, but a bunch of shapes with the same z-index (1) can d it.
The main page is hosted on github via the gh-pages branch and it seriously need some love.
The content is pretty much ok, but the look is awful.
Open to suggestion.
Branch | Build failing 🚨 |
---|---|
Dependency | @gmartigny/eslint-config |
Current Version | 1.1.2 |
Type | devDependency |
This version is covered by your current version range and after updating it in your project the build failed.
@gmartigny/eslint-config is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.
There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.
Your Greenkeeper Bot 🌴
Every classes and every functions should have a jsDoc documentation.
Moreover, all modules should have a readme.md
and a documentation.md
.
I'm not a great writer, so someone else should check all texts for misspelling or incoherence.
It could be a huge performance boost to only render part of the scene that need to be redrawn.
The scene could be split into an arbitrary number of parts (3x3 ...) and component should "dirty" the part their into.
Alternatively, component can return informations on their bounding box (AABB). Then scene only redraw the union of all AABB. (see below comment)
An error is thrown when the user tries to make a rotated rectangle resizable. This is expected as it's not possible to directly compare x and y position to compute width and height.
A bit of trigonometry should do the trick with something along the line of:
this.width = diffX * Math.cos(this.options.rotation * 2 * PI) +
diffY * Math.sin(this.options.rotation * 2 * PI);
const rect = new Rectangle([0, 0], 100, 200, {
rotation: 1 / 8,
});
rect.resizable();
We could add clip
to the component options taking any component as parameter (default as null
).
If set, it will use the shape as a clip path using the clip
function of CanvasRenderingContext2D
The Component's isHover
function returns true only if the Component is either filled or stroked. Image can be drawn without neither of these and are not detected as hovered.
As with malePath
, maybe Image need its own duplication of isHover
to account for this.
May be fixed by a refacto when doing #67.
const img = new P.Image(scene.center, "url.png", {
fill: "white", // <- The image can't be hovered without this
});
img.on("ready", () => scene.add(img).render())
.on("hover", console.log("Hover"));
Would be great to have an image manager.
Your current navigator: Chrome v65
The package you used: @pencil.js/polygon
The ishover
method always return false.
It use the Ray casting algorythm using Vector class.
But according to test Vector.prototype.intersect
is working.
const poly = new Polygon(points, {
cursor: "crosshair", // The cursor will never change
});
Would be great to have a comprehensive, easy to use color manager.
Maybe a wrapper around Qix-color
## Need
Your current navigator: Chrome v66
The package you used: @pencil.js/image
Regardless of the z-index of its children, Image are drawn on top.
It's caused by the override of the render
function in Image module.
However, drawImage
is not on Path2D
prototype and can't be called on trace
. (like it should be)
const img = new Image([], "url");
img.on("load", () => {
img.add(new Rectangle([], img.width, img.height);
scene.add(img).render();
});
At the beginning, I wanted to change the "position" of rectangle. For example, the user could specify the bottom-right corner as origin.
Then, I wonder about allowing this behavior for all components. But it gets confusing really fast and moreover broke rotations.
Should Pencil.js have an origin option on Component to move the shape drawing relative to its position ?
How is it suppose to interact with rotations and rotation anchor ?
Add mono-select input. Should work like <select>
or <input type="radio">
, but could be better designed.
Solution | Pros | Cons |
---|---|---|
Radio | Display every options | How to group them ? |
Branch | Build failing 🚨 |
---|---|
Dependency | webpack |
Current Version | 4.17.3 |
Type | devDependency |
This version is covered by your current version range and after updating it in your project the build failed.
webpack is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.
The new version differs by 12 commits.
ee7d948
4.18.0
de85978
Merge pull request #7732 from xtuc/chore-bump-webassemblyjs11
4e02cac
chore: bump webassemblyjs
52e1630
bump webassemblyjs
e0e0061
Merge branch 'master' into chore-bump-webassemblyjs11
c9d6ec1
feat: remove wasm-opt
075208d
fix: merging
38c3403
Merge remote-tracking branch 'upstream/master' into chore-bump-webassemblyjs11
8214d56
chore: bump webassemblyjs
59114c1
chore: bump webassemblyjs
b310b9b
feat: remove LEB128 opt
f744c4a
chore: bump webassemblyjs 1.6.0
See the full diff
There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.
Your Greenkeeper Bot 🌴
When setting a component draggable, the cursor option change to "grab"
=> ok. But when the component is actively dragged, the cursor should change to "grabbing"
=> ko.
The Scene setCursor
function seems not to be called with the updated option.
const square = new Square(scene.center, 200);
square.draggable();
scene.add(square);
Grabbing the square doesn't update the cursor.
The question was settled in #18, but I wanted to re-open the debate for the Line class here.
I often find myself wanting to draw a line between two moving shape in a scene (absolute positions). If the shapes are moving and the line is not keeping reference to these positions, it's not possible without using absolute positions.
In the other hand, being able to move the Line as a whole (with dra'n'drop or programatically) makes more sense. Moreover, Pencil.js is build around relative positions and they're used everywhere else.
Relative over absolute positions
Pros:
Any opinion on that ?
Branch | Build failing 🚨 |
---|---|
Dependency |
[webpack](https://github.com/webpack/webpack)
|
Current Version | 4.12.1 |
Type | devDependency |
This version is covered by your current version range and after updating it in your project the build failed.
webpack is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.
The new version differs by 19 commits.
c384c3f
4.12.2
9dacf86
Merge pull request #7601 from webpack/bugfix/hash-entry-chunks
e38e076
fixes #7577
aab3554
Merge pull request #7574 from byzyk/types/ignore-plugin
258d9b6
Merge pull request #7600 from webpack/bugfix/missing-module
8cb9241
Merge pull request #7595 from webpack/remove_circle
504e1d8
Merge pull request #7590 from webpack/bugfix/json-stringify
ab7ecb3
fixes #7499
3e3827e
Remove CircleCI
35a7f65
add test case
4d57d78
generate error code when json wasn't parsed
a5e55de
skip harmony accept dependency in non-harmony modules
720f3b2
make hot cases better
94c7273
Merge branch 'master' of https://github.com/kamranahmedse/webpack into bugfix/json-stringify
a96ac96
add type for resource and context
There are 19 commits in total.
See the full diff
There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.
Your Greenkeeper Bot 🌴
Adding shape with a single class instantiation is nice, but sometimes you could want more in-depth drawing.
Could be a declarative set of rules
// Easy to read but blotted
const startingPoint = new Position();
new Shape(startingPoint, [
Shape.lineTo(position),
Shape.arcTo(position, center),
Shape.quadTo(position, controlPoint),
Shape.bezierTo(position, controlPoints),
], options);
Or a set of code like SVG
// Clean but hard to read
const startingPoint = new Position();
new Shape(startingPoint, "M 20 230 Q 40 205, 50 230 T 90230", options);
Branch | Build failing 🚨 |
---|---|
Dependency | lerna |
Current Version | 3.3.0 |
Type | devDependency |
This version is covered by your current version range and after updating it in your project the build failed.
lerna is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.
The new version differs by 13 commits.
5da1319
chore(release): publish v3.3.1
367bf4e
test(integration): Avoid inexplicable snapshot comparison errors on Windows
5880788
test(helpers): Replace normalize-test-root with augmented placeholder serialization
ed16536
test(helpers): Make serialize-tempdir placeholder consistent with normalize-test-root
00842d6
fix(create): Upgrade whatwg-url to ^7.0.0
ebb7ee4
fix(prompt): Upgrade inquirer to ^6.2.0
b8d11b8
chore(deps): Update eslint + jest
7bd3179
chore: flailing around trying avoid 'no visual difference' snapshot garbage on Windows
b8915e7
fix(run-lifecycle): Remove repetitive error logging
a379266
chore(helpers): Normalize newlines to coddle windows
2a6f0a4
fix(publish): Tell yarn to stop creating git tags
ac0baa7
test(integration): avoid quoting arguments to coddle windows
b084293
fix(import): Handle filepaths with spaces more robustly (#1655)
See the full diff
There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.
Your Greenkeeper Bot 🌴
When a component has a scale
option different from the default [1, 1]
the function isHover
is not working properly. The detection just don't take the scaling into account and consider the component still at its original size.
It would probably be better to make a setContext
function in Container class. This function would be in charge of clip, rotation and scale (instead of doing that in render
).
Then, it might be possible to lean on isPointInPath
with the right context. It means that the manual rotation of position would not be needed anymore.
const square = new Square(scene.center, 400, {
scale: [0.5, 0.5],
});
square.on("hover", () => console.log("hover"));
scene.add(square).startLoop();
Code coverage don't correctly go to codeclimate.
Since update to webpack@4, the https://github.com/mzgoddard/jest-webpack module doesn't work.
The issue mzgoddard/jest-webpack#27 need to be addressed.
Since Chrome v70, all major browsers sort algorithm is stable. So, when this version is more widespread, we can drop the stable
dependency from @pencil.js/container
module.
Branch | Build failing 🚨 |
---|---|
Monorepo release group | babel7 |
Current Version | 7.0.0 |
Type | devDependency |
This version is covered by your current version range and after updating it in your project the build failed.
This monorepo update includes releases of one or more dependencies which all belong to the babel7 group definition.
babel7 is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.
There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.
Your Greenkeeper Bot 🌴
We should add the ❤️ shape.
I have no idea why I used rotationAnchor
instead of center.
The remove
and delete
function on Containers are confusing. Do we need both ?
The HTMLElement remove
function remove the element itself. What other alternatives is there (detach, removeChild ...)?
In term of clarity, both feel natural:
parent.remove(child1, child2);
child.delete();
As an abstract renderer, Pencil.js could be run in node. However, there's still browser dependencies (Path2D, FontFace, CSS ...) that should be dealt with.
In the end, Pencil.js could generated images out of the browser context with the help of https://www.npmjs.com/package/canvas for example.
Add the possibility to have multi-lined texts.
Instead of many Text
, the user could just passed an array of string to one Text
to have multi-lines.
The CanvasRenderingContext2D
API doesn't support multi-line, so it should be a "housemade" solution based on measureText
.
This also impact Text.prototype.getMeasures
.
new Text(position, ["First line", "second line"]);
new Text(position, "First line\nsecond line");
new Text(position, `First line
second line`);
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.