Faces.js, a JavaScript library for generating vector-based cartoon faces(zengm.com)
zengm.com
Faces.js, a JavaScript library for generating vector-based cartoon faces
https://zengm.com/facesjs/
100 コメント
This would be fun to use with Chernoff Faces https://en.m.wikipedia.org/wiki/Chernoff_face
Ooh, ooh, I get to be the one to make the Peter Watts reference today! Chernoff Faces make an appearance in Blindsight, where the ship captain Sarasti uses them. The specific details would be a spoiler, though.
Always love a good Peter Watts reference, though this one makes me want to go back and read Blindsight again as I can't remember the reference... As his website says though, my "will to live [has been] getting too strong" lately, so...
In this particular case, I think there are at least two nose shapes close enough to π/2 that Sarasti would find them disturbing.
Never saw such a nose in my life
'Tis a nose of parchment
It is six times as big but
'tis a nose like my nose
https://www.youtube.com/watch?v=bNQKYolhZkghttps://en.wikipedia.org/wiki/The_Kiss_and_Other_Movements
Thank you for evangelizing -- this is amazing and kinda hilarious. Does it count as biohacking? lol.
Imagine these on SRE dashboards to determine system state
Depending on the application that could provide some real benefit as human vision is predisposed to seeing/detecting faces.
Someone I know has done some work to parameterize facial expressions: https://www.redblobgames.com/x/1845-face-generator/
He has a bunch of other interesting things like this, too: https://www.redblobgames.com/
He has a bunch of other interesting things like this, too: https://www.redblobgames.com/
This is pretty common in 3D work. Blender has a feature called “blend shapes” that implements a similar interface, and is commonly used for complex facial animation and general model parameterization.
Duolingo did a talk at their Duocon conference about how they use parametrization to animate the characters in their app.
https://www.youtube.com/watch?v=fgOqvyPif3g
(no affiliation)
https://www.youtube.com/watch?v=fgOqvyPif3g
(no affiliation)
Their post on Polygonal Map Generation for Games [1], from 2010, got me into procedural generation in general.
[1] http://www-cs-students.stanford.edu/~amitp/game-programming/...
[1] http://www-cs-students.stanford.edu/~amitp/game-programming/...
That's cool - I had been thinking with the OP site that quite a number looked like they were scowling/angry so a way to vary that is interesting to explore.
import { display, generate } from "facesjs";
// Generate a random face
const face = generate();
// Display in a div with id "my-div-id"
display("my-div-id", face);
Beautiful API.No, that's poor API. If it wants to generate HTML it should return it's root element.
Let's say I want to add a random face to every div with class "face". With this API have to generate ids. With an API that returns a root element it's trivial and it's not duplicating work (inserting elements into the DOM) that already exists.
Taking a selector would not be much better because it would again be duplicating work and make it harder to customize usage.
Taking a parent element for it to insert into would also be a poor API because it makes it harder to insert next to a sibling.
A good API would be one of
Let's say I want to add a random face to every div with class "face". With this API have to generate ids. With an API that returns a root element it's trivial and it's not duplicating work (inserting elements into the DOM) that already exists.
Taking a selector would not be much better because it would again be duplicating work and make it harder to customize usage.
Taking a parent element for it to insert into would also be a poor API because it makes it harder to insert next to a sibling.
A good API would be one of
const face = generate()
someElem.appendChild(face);
or const face = generate()
someElem.appendChild(face.domElement);
or const face = generate()
someElem.appendChild(face.html()); // assumes it can render to something else too> Taking a parent element for it to insert into would also be a poor API because it makes it harder to insert next to a sibling.
To extend the documentation example, wouldn't you just have "my-div-id-sibling" already and call
To extend the documentation example, wouldn't you just have "my-div-id-sibling" already and call
display("my-div-id", face);
display('my-div-id-sibling", someOtherFace);
Like almost all discussions that use language like "good API" or "bad API" this seems to me entirely personal preference. Personally I find anything where I end up having to call appendChild() myself a bad API.No, that would not be better. Consider
document.querySelectorAll('classIWantFacesIn').forEach(elem => {
const face = generate();
elem.id = `face-${crypto.randomUUID()}`; // this line should not be needed
display(elem.id, face);
});
With the current API I'm required to make ids and make sure they don't collide with other elements. Vs document.querySelectorAll('classIWantFacesIn').forEach(elem => {
const face = generate();
elem.appendChild(face.domElement);
});
Now, no id is needed. It's objectively a better API to not need the id.(faces.js dev here)
A nice thing about the current API is the face objects can be trivially serialized to JSON, which I need do in the application I originally wrote the library for.
Also the `display` function works with a DOM element as the first argument too, in which case you don't need to make up an ID. That's how I use it.
That being said, the API might not be perfect, but you should at least appreciate that it's been stable since v1 in 2015!
A nice thing about the current API is the face objects can be trivially serialized to JSON, which I need do in the application I originally wrote the library for.
Also the `display` function works with a DOM element as the first argument too, in which case you don't need to make up an ID. That's how I use it.
That being said, the API might not be perfect, but you should at least appreciate that it's been stable since v1 in 2015!
See other response this thread why passing in a DOM element is also not a good API.
That said, I wouldn't have spoken up if someone hadn't claimed the API was good. Any one who makes a useful library that provides useful functionality people want is great!
> it's been stable since v1 in 2015!
That's awesome!
That said, I wouldn't have spoken up if someone hadn't claimed the API was good. Any one who makes a useful library that provides useful functionality people want is great!
> it's been stable since v1 in 2015!
That's awesome!
I agree the API could be better, but note that you don't have to use IDs - you can also pass the parent element to display directly: https://github.com/zengm-games/facesjs/blob/master/src/displ...
As mentioned, that's still a poorer API than just returning a root element.
Consider...
Consider...
// insert after every link
document.querySelectorAll('a.funny').forEach(elem =>
const face = generate();
const parentForFace = document.createElement('span');
elem.appendChild(parentForFace);
display(parentForFace);
});
vs // insert after every link
document.querySelectorAll('a.funny').forEach(elem =>
const face = generate();
elem.after(face.domElement);
});
Taking a parent element is still a poor APIAs beautiful as the faces.
The faces are amazing! I hope if he finds an artist they don't get changed too much.
I absolutely am looking for an excuse to use faces.js somewhere.
I absolutely am looking for an excuse to use faces.js somewhere.
(faces.js dev here)
What you see now is already after another contributor came through and redid all my artwork. You don't want to know what it looked like back before then lol
What you see now is already after another contributor came through and redid all my artwork. You don't want to know what it looked like back before then lol
Agree with throwaway, the faces look great. Thanks for this library, the amount of face detail options is really cool.
It would be neat as a forum icon, if you got to pick one and tailor it.
Obviously this also needs to be a library in Zig, Rust, Go, Elixir, Haskell, Java, C#, F#, OCaml, PHP, Python, Ruby, Perl, C, C++ & Lean
So, it now lives as an Extism[0] wasm plugin you can call from those languages: https://modsurfer.dylibso.com/module?hash=2050e7f7a129a48df0...
[0]: https://github.com/extism/extism
So, it now lives as an Extism[0] wasm plugin you can call from those languages: https://modsurfer.dylibso.com/module?hash=2050e7f7a129a48df0...
[0]: https://github.com/extism/extism
Interesting, I hadn't come across extism before. How hard would it be to package https://github.com/biojppm/rapidyaml in this way? (And do you have a extism for dummies guide?)
Extism can be really useful for packaging up and running cross-language libraries!
The most clear information about it is at: https://extism.org, but its a bit focused on the primary use case for Extism, being a universal plugin system.
There is a C PDK (https://github.com/extism/c-pdk) which you'd probably want to use in a new wrapper around your library in C++, and compile it to wasm32 freestanding or WASI, but without emscripten. Extism doesn't currently have an interop layer to emscripten.
The most clear information about it is at: https://extism.org, but its a bit focused on the primary use case for Extism, being a universal plugin system.
There is a C PDK (https://github.com/extism/c-pdk) which you'd probably want to use in a new wrapper around your library in C++, and compile it to wasm32 freestanding or WASI, but without emscripten. Extism doesn't currently have an interop layer to emscripten.
> Don't worry about what some plug-in code might do to your program. Extism is built with security as a core principle, and fully sandboxes the execution of all plug-in code.
I find the wording a bit off here. Responsible security involves transparency along the supply chain and minimum trust, certainly not talking about worries and giving them up with ease.
I find the wording a bit off here. Responsible security involves transparency along the supply chain and minimum trust, certainly not talking about worries and giving them up with ease.
Would you suggest something more appropriate?
I do not know Extism, but I would start from the process of verifying the security of it, and highlight what allows to check it quickly and with certainty. For example documentation of the sandbox and possibility to inspect all syscalls performed with verbose logging.
These are just examples; basically I would put focus on minimal trust and maximum transparency.
Note: there can always be problems of data exfiltration or compute power theft (as part of a botnet or mining), so owning the machine is not the only risk to mitigate.
Both great points! Extism docs assume some level of familiarity with the security model of WebAssembly. Which unless you grant it granular permission, does mitigate the risks you’ve mentioned.
I agree we should do more to specifically call out these security benefits - and also how a user could impact that default security.
I agree we should do more to specifically call out these security benefits - and also how a user could impact that default security.
This is the first I've heard of Extism. I like their goal! "Extism's goal is to make all software programmable." [0]
[0] https://extism.org/docs/overview
[0] https://extism.org/docs/overview
hey thank you! we are trying to make that a reality :)
Woah Extism is exactly what I need for a project where I want a plugin system, nice random find, thank you!
Question: Does extism plan to support Python as a plugin language? That seems like a big gap right now
Edit: I see this issue tracking it https://github.com/extism/extism/issues/116 and the project is ongoing https://github.com/extism/python-pdk/issues/2
Question: Does extism plan to support Python as a plugin language? That seems like a big gap right now
Edit: I see this issue tracking it https://github.com/extism/extism/issues/116 and the project is ongoing https://github.com/extism/python-pdk/issues/2
Yes, we would love to add a Python PDK - and as you discovered have one that is very close.
Python is pretty tricky given most users want libraries with native/C dependencies. With those and the Python runtime, the wasm tends to bloat up to tens of MB, rather unideal for a plug-in.
If you have time, please comment on that issue though and share some thoughts or use cases so we can better prioritize support!
Python is pretty tricky given most users want libraries with native/C dependencies. With those and the Python runtime, the wasm tends to bloat up to tens of MB, rather unideal for a plug-in.
If you have time, please comment on that issue though and share some thoughts or use cases so we can better prioritize support!
Really cool. I would love to see an api for just passing a numeric seed value. Then users of an app can click a "refresh" button to get one they like that could persist across page loads and devices without having to store the entire face object in the db.
The face object is small (it’s the parameters). You can save that.
I did the first part of this (not the API part) a while back to generate avatar faces for minecraft with a random sequence of numbers (one per pixel, gray scale, and the faces were symmetric). I got some fun results as a wide range of anatomical facial morphologies were produced.
You could serialize the JS representation to Base64 or Base10 if you want it to be numeric.
But that's a lot more data than just storing which of the ~2^50 possible faces was generated. You could serialize the entire face including the colors and scaling factors into a much smaller string, or just take one number that is used as a seed for a random number generator that sets the other parameters
The seed version with random parameters doesn't allow you to or your users to design their own. Just random selection until you get one you like, no editing of details.
Very cool. Here's another style! https://getavataaars.com/
Apologies for such a basic question. I have node installed on my machine, but clearly no idea how a JS library is included anymore (among other things...). I created an HTML file, included a div ``a div with id "my-div-id"`` as instructed, and even added type="module" in the script tag, but I get in Chrome ``Uncaught TypeError: Failed to resolve module specifier "facesjs". Relative references must start with either "/", "./", or "../".``
Any pointers on all the steps to running this? Should I expect node to create a js file that could be served together with the HTML file? Or would my hosting server need to have node, and run it every time there is a request? Thanks in advance, I'm sorry for the confusion.
Any pointers on all the steps to running this? Should I expect node to create a js file that could be served together with the HTML file? Or would my hosting server need to have node, and run it every time there is a request? Thanks in advance, I'm sorry for the confusion.
not a basic question at all— front end has jumped the shark.
you can bypass node, npm install, etc for a prototype entirely in an html file leveraging an import map.
this is the importmap i load for all my pages: https://github.com/tylerchilds/plan98/blob/6120e6a80a3d48438...
to support faces, i’d add an entry: “facesjs”: “https://esm.sh/[email protected]”
which should get rid of the import path issue, and to support legacy browsers that still might have that error:
https://github.com/guybedford/es-module-shims
you can bypass node, npm install, etc for a prototype entirely in an html file leveraging an import map.
this is the importmap i load for all my pages: https://github.com/tylerchilds/plan98/blob/6120e6a80a3d48438...
to support faces, i’d add an entry: “facesjs”: “https://esm.sh/[email protected]”
which should get rid of the import path issue, and to support legacy browsers that still might have that error:
https://github.com/guybedford/es-module-shims
> jumped the shark
Genuine question - what does that phrase mean to you?
I've only ever heard it in the context of television shows (meaning "has been renewed for so many seasons that the writers have run out of ideas and have started forcing the characters into ever wackier situations to generate novelty") - and while it's intuitivve to map from that meaning to a more generic "has gone on for too long and thus become bad", the translation is fascinating. When you said this, were you intentionally using a term from another domain with a different meaning in the confidence that your audience could translate it appropriately, or does the phrase "jump the shark" really just mean "be old, and thus bad" to you?
(Asking from a purely non-prescriptivist non-judgemental perspective! I'm interested in understanding your thought process, not in judging or correcting you)
Genuine question - what does that phrase mean to you?
I've only ever heard it in the context of television shows (meaning "has been renewed for so many seasons that the writers have run out of ideas and have started forcing the characters into ever wackier situations to generate novelty") - and while it's intuitivve to map from that meaning to a more generic "has gone on for too long and thus become bad", the translation is fascinating. When you said this, were you intentionally using a term from another domain with a different meaning in the confidence that your audience could translate it appropriately, or does the phrase "jump the shark" really just mean "be old, and thus bad" to you?
(Asking from a purely non-prescriptivist non-judgemental perspective! I'm interested in understanding your thought process, not in judging or correcting you)
> Genuine question - what does that phrase mean to you?
Jumped the shark means roughly the same thing as "lost the plot". In that, the current state of affairs has entered into absurd territories.
Jumped the shark means roughly the same thing as "lost the plot". In that, the current state of affairs has entered into absurd territories.
While I'm aware of the phrase's origins, I've never heard it used to describe a TV show, only an unrelated field just like in this example.
happy days was running out of ideas and wanted to continue to retain audience attention and had The Fonz water ski and jump over a shark.
silicon valley was running out of ideas, but steve ballmer famously delivered the Developers, developers, developers speech paving the way for capturing developer market share, for a platform with platform developers is no platform at all.
there’s tooling that solves technical problems and tooling that business problems.
a system has “jumped the shark” when there are at least five ways to accomplish the same thing and the audience was just trying to have some happy days on the tubes.
my core hunch is that the ecosystem is a compile target versus a respected platform and that’s where i believe the shark has been jumped.
the web is cool, if only we stopped trying to jump it and befriend the shark already.
the long answer is, i’ve got a bespoke markdown like syntax i’m using for both a web publishing and screenplay authoring. i feel no difference between telling stories in interactive web formats or printed pages.
maybe i’m jumping the shark.
silicon valley was running out of ideas, but steve ballmer famously delivered the Developers, developers, developers speech paving the way for capturing developer market share, for a platform with platform developers is no platform at all.
there’s tooling that solves technical problems and tooling that business problems.
a system has “jumped the shark” when there are at least five ways to accomplish the same thing and the audience was just trying to have some happy days on the tubes.
my core hunch is that the ecosystem is a compile target versus a respected platform and that’s where i believe the shark has been jumped.
the web is cool, if only we stopped trying to jump it and befriend the shark already.
the long answer is, i’ve got a bespoke markdown like syntax i’m using for both a web publishing and screenplay authoring. i feel no difference between telling stories in interactive web formats or printed pages.
maybe i’m jumping the shark.
i realize i’m making some claims here, so
server side multi page demo: https://sillyz.computer/sagas/sillyz.computer/en-us/000-000....
if you press esc in the top left, you can play with that in the repl.
if you visit: https://sillyz.computer, that same text based adventure wizard journey as an embedded widget is the lower post it note.
this is the folder i’m using for localizing that journey: https://github.com/tylerchilds/plan98/tree/plan98/client/pub...
any of the short hand web components dynamically load from: https://github.com/tylerchilds/plan98/tree/plan98/client/pub...
full circle— i’m very much playing across domains with the jumping the shark reference
server side multi page demo: https://sillyz.computer/sagas/sillyz.computer/en-us/000-000....
if you press esc in the top left, you can play with that in the repl.
if you visit: https://sillyz.computer, that same text based adventure wizard journey as an embedded widget is the lower post it note.
this is the folder i’m using for localizing that journey: https://github.com/tylerchilds/plan98/tree/plan98/client/pub...
any of the short hand web components dynamically load from: https://github.com/tylerchilds/plan98/tree/plan98/client/pub...
full circle— i’m very much playing across domains with the jumping the shark reference
Love the insight - thank you!
I’ve never heard of importmaps before, thank you.
That is 10x more complicated and unorthodox than simply running "$ npm install --save facesjs".
That's not enough to get it to load in a browser. Which bundler will you use? Shark jumped.
yeah, i thought about asking if OP was using vite, webpack, snowpack or babel, but based on the context of the question, it seemed like vanilla web, so i answered vanilla web.
Thank you very much for your help, just upvoting feels rude! I have not quite gotten there, but thank you for pointing me in the right direction. Clearly I'm an enthusiast at best, but "back in my day" you could put all the needed libraries in the script tag and the CSS under link... sigh... The moment nodejs, supposedly a back end, started being used pervasively for the front end, I lost whatever conceptual map I had. Just as a personal challenge, I'm planning to _study_ [1], which I see referenced a lot, and see if I can "get it", albeit partially. Any other such references would be welcome.
Thanks again! Great website and projects, by the way.
[1] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guid...
Thanks again! Great website and projects, by the way.
[1] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guid...
for an easier way to import, download the module you want to import, put it next to the js file you will import it from, and use "import foo from './foo'". You might need to serve it from a local http server.
thank you!
if it helps, my last commit touches the primary aspects of modules.
overall, i’m integrating a test payment flow on https://thelanding.page
this commit[0] i export two functions from my payment debugger module (i am intentionally overloading the word module to additionally bind a view; this is a personal hot take and not general guidance, just in case you see how i use ‘@sillonious/module’).
so i expose payment-debugger.js in the index.html file import map as @sillonious/payments.
i import that module in the message-pay component.
when the user clicks buy now, i call the newPayment function (which ultimately lands in client.js, after traversing the network; in case you’re curious about the full route). i also set a timer that’ll check the payment status every five seconds for 15 minutes. displaying a timeout message is a not yet implemented edge case.
[0]: https://github.com/tylerchilds/plan98/commit/db3c037345077fe...
if it helps, my last commit touches the primary aspects of modules.
overall, i’m integrating a test payment flow on https://thelanding.page
this commit[0] i export two functions from my payment debugger module (i am intentionally overloading the word module to additionally bind a view; this is a personal hot take and not general guidance, just in case you see how i use ‘@sillonious/module’).
so i expose payment-debugger.js in the index.html file import map as @sillonious/payments.
i import that module in the message-pay component.
when the user clicks buy now, i call the newPayment function (which ultimately lands in client.js, after traversing the network; in case you’re curious about the full route). i also set a timer that’ll check the payment status every five seconds for 15 minutes. displaying a timeout message is a not yet implemented edge case.
[0]: https://github.com/tylerchilds/plan98/commit/db3c037345077fe...
One command: npx.
Well, I didn't find the art very appealing. But I do love the idea behind it. Neat project!
I liked it a lot, including the README. The author seems to be an indie dev who creates sport management sim games [1], all of which run entirely in the browser like the linked library (which is used in the games).
[1] https://zengm.com/
[1] https://zengm.com/
No wonder I instantly recognized these faces as Basketball GM's art! Dumbmatter has made some very cool things.
Thanks for plugging my main project, I came too late to this thread to do it!
I built something similar a few months back [1][2].
Among other things, it accepts an arbitrary key, and will always generate the same avatar for the same key. Very handy for apps which need to generate user-specific avatars.
[1]: https://github.com/monooso/avataraas
[2]: https://github.com/monooso/avatar
Among other things, it accepts an arbitrary key, and will always generate the same avatar for the same key. Very handy for apps which need to generate user-specific avatars.
[1]: https://github.com/monooso/avataraas
[2]: https://github.com/monooso/avatar
Here's a demo of my project shape faces https://shapefaces.com/
If you like that, you may also like:
https://pixelfaces.io/
https://pixelfaces.io/
Aww, it's not making Chernoff faces :(
(https://en.wikipedia.org/wiki/Chernoff_face)
(https://en.wikipedia.org/wiki/Chernoff_face)
Are there any licensing restrictions to using this library and the images it creates?
(faces.js dev here)
Code is Apache license, and you can do whatever you want with the output. If you want to be nice, lmk if you use it somewhere, I like seeing it in the wild!
Code is Apache license, and you can do whatever you want with the output. If you want to be nice, lmk if you use it somewhere, I like seeing it in the wild!
Spinnaker's Face Maker (https://www.youtube.com/watch?v=5K4ovkVLp8Y) for the modern era!
Aren't those like 2d version of nintendo's MIIs? I mean, the eyes noses and mouths are very much like those of MIIs
This is adorable.
very cool. Are there libraries like these that do whole characters with bodies?
Would love to play with those!
Very fun little project. Nice =)
i love this
When are the Faces.js NFTs going for sale? /s
[deleted]
[deleted]
b0bb0(2)
they should have called it "4 non blondes" because there are no blonds
Using the "faces.js editor" link at the bottom of the page, it shows that you can use any color you want for the hair. Also, if it didn't allow blonds, it would probably just be called "no blonds" since there are more than 4 possible variants
* 4 can also be "for"
* There is a band called "4 non blondes"
* There is a band called "4 non blondes"
sounds like you didn't get the joke. oh well.
Back in the day out used to be called NFT