webdesserts / alchemist-js Goto Github PK
View Code? Open in Web Editor NEWThe extensible color library
Home Page: https://webdesserts.gitbooks.io/alchemist-js/
License: MIT License
The extensible color library
Home Page: https://webdesserts.gitbooks.io/alchemist-js/
License: MIT License
Right now precision is enforced throughout the entire conversion process. For color spaces like Lab where a small decimal change makes a big difference, this can ruin a conversion. we should wait to round the value until it's exported via a .to()
method.
Note: this might also be a reason to use fixed
instead of precision
Rounding is currently not working as I originally expected. When dealing with larger floats that happen to be simple enough, toPrecision will store them in scientific notation.
0.0000000001.toPrecision(4) //=>1.000e-10
I need to decide if this is expected behavior or not and if not, how to solve it.
The final step before v1.0
The css parser is weird. We need to figure out if it actually fits into the current plugin architecture or if we need to do something special for it.
Add a hexidecimal "ColorSpace" plugin
alchemist.rgb(25, 25, 25).as('rgb')
Should just pass the color straight through. Right now it throws an error.
I believe the future of JavaScript modules is es6. It solves many of the issues found in both AMD and Common.js and it is the future standard for the language. I would like to start using es6 modules to develop alchemist as soon as possible. That way, when es6 modules are ready for prime-time, alchemist is as well. http://esperantojs.org/ looked like it might be a good way to get this working.
Currently when you try to set the precision to 0 (for an intenger) it breaks.
Include an option to override the default precision for a given conversion.
We're defining the same empty color spaces in every other test. This es no bueno.
How should alchemist handle boundries and clipping?
The end user api might look something like this:
alchemize.rgb(255, 255, 255) // => Color
alchemize.rgb(256, 255, 255) // => null
what the plugin interface might look like:
alchelmize.use({
name: 'rgb',
bounds: function bounds (r, g, b) {
// success?
return true
// clipped?
return [r, g, b]
// invalid?
return false
},
to: function () {}
})
Ya, that's pretty messy. If there's a way that I could make that cleaner, it would be nice. I'm not even sure if I want to allow clipping yet. The problem though, is that if I don't implement it inside the library, the color space developer would implement it inside their conversion functions and the user would have no way to turn the clipping off if they just want a null value when something fails.
This also brings up the issue of wether or not we should return a soft error as null, or actually throw an error and let the user handle it with something like promises. Maybe we should make this a configuration option?
Alchemist.create({bounds: true}).rgb(256,255,255) // => null (the default)
Alchemist.create({bounds: 'strict'}).rgb(256,255,255) // Throws Error
Alchemist.create({bounds: 'clip'}).rgb(256,256,256) // => [255,255,255]
...aaaand finally this brings up the issue of whether we should clip on color interpretation or just color conversion?
var alchemize() = Alchemist.create({bounds: 'clip'})
alchemize.rgb(256, 255, 255) // Seems like an error would be expected
alchemize.lch(200, 200, 200).rgb() // => [91, 50, 197] (clipped value)
So all along I've been using the term "precision" and I didn't know that there was actually a toPrecision()
function that does something completely different to toFixed()
.
var num = 10.23456
num.toFixed(3) // 10.235
num.toPrecision(3) // 10.2
It might be good to provide an option for both of these. Either way, I should reassess the default.
So I pulled Creatable
out into it's own repository so that I can track it's development and document it separately. I figured it would be hard explaining it if we could only point to a source file within Alchemist. I also didn't want it adding complexity to the documentation. So now that's it's out, I need to be sure to point to Stateless and explain "Hey! Alchemist uses this library. Look at it's docs to see what it is and why we use it"
Look into the possibility of using https://github.com/hapijs/lab for testing. From a glance:
This would mainly be used internally when a user wants to use a different version of a color space. For example, say a user wants to use alchemist-common, but would like to use their own version of rgb. We would "unuse" the current rgb plugin and add the new one in.
Right now, we define all of a color's conversion methods each time we instantiate a Color
. This probably won't be good for performance. Look into whether it is worth creating Color Space specific constructors that inherit from Color
.
Basic outline:
The version of every build should be included in both the name (e.g. alchemist-0.1.1.min.js
) and at the top of each file in a comment. They comment should probably also include a link to the repository, as well as the license the software uses.
Note: it's been awhile since i've worked with the internals of the library itself, so I'm going to have to
remind myself how every thing hooks together. After a quick review, most of these comments don't
make any sense, I'll be cleaning it up as I go.
Currently, we are using objects as plugins. The upside to this is that we have more control over how a user interacts with alchemist within plugins. The downside is that it limits what the user can do.
In my mind the "upside" of plugins as objects is a false benefit as a user who really wants do whatever they want can always avoid the plugin system all together with a top-level function
function SUBVERT_THE_SYSTEM (alchemist) {
/* whatever the hell I want */
}
alchemist.use(xyz());
alchemist.use(rgb());
SUBVERT_THE_SYSTEM(alchemist)
So if someone wants to "subvert the system" we might as well make alchemist extensible enough to do so cleanly.
alchemist.use(function(alchemist) {
/* define color conversions directly on alchemist */
})
This would mean that we would need a way for users to define color-spaces and methods directly on alchemist. Here are my initial thoughts on the API.
In this example I am using the concept of a ColorSpacePlugin
object. I'm a little conflicted on this, mainly because of the to
and from
methods. If we use the internal BaseSpace
instead this would mean I would have to overload our main conversion methods and I have a feeling this would affect performance. I like how intuitive and readable the to
and from
is, but if we were to use BaseSpace
directly I would need to rename these methods to something like defineConversionTo
, which is longer (larger alchemist bundles) and bleeeehhhh, but only as bleeeeh as having two ColorSpace
objects (which would also lead to larger bundles).
alchemist.use(function(alchemist) {
var rgb = alchemist.ColorSpacePlugin.create('rgb')
rgb.min([0,0,0])
rgb.max([255,255,255])
rgb.to('xyz', function (values) { /* ... */ })
rgb.from('xyz', function (values) { /* ... */})
alchemist.spaces.add(rgb)
})
Even though a user could now technically define the methods themselves I would still like them to go through a define
function so that we can throw an error if they overwrite an existing method rather than plugins silently overwriting each other when a user includes multiple plugins using the same method name.
alchemist.spaces.define('lighten', function (amount) {
var lab = this.as('lab');
/* do stuff... */
return lab;
})
alchemist.define('lighten', function (color, amount) {
return color.lighten(amount)
})
})
I'm leaning towards putting the define
for color spaces on the ColorSpaceStore
itself as opposed to putting it on the BaseSpace
as I want to keep the BaseSpace
as simple and readable as possible.
Currently I am not handling the alpha channel. Considering alpha is pretty much always 0:1 I should be handing this with alchemist. My assumption is that I'll probably be doing something like Color.alpha(.5)
I forgot to update the History.md when I released v1.0. Include this and add all changes to the release page on github.
Now that we are pulling Creatable
out into it's own repo (see #20) I've added the ability to reset objects that inherit from it. This should allow the user to take any Alchemist object and clear any plugins and configuration they had on it at any time. I should at least add a note about this in the documentation. I should also consider if there are other ways this could be useful.
It would be a waste to go through all of this effort to produce a modular system without actually seperating the colorspaces out into their own modules.
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.