my-avatars
In v1.0.0
I've added the ability to change the color of images. The updates are specified at the bottom of this post. Link.
NB. Thanks to Lucas for this comment. The math is now correct ๐ฅณ
If anything is wrong, please do not hesitate to correct me either ๐
I've for a while had an idea to create avatars like getavataaars.com and such other services. Though I don't have the necessary graphical skills nor the imagination, but what I do have is code experience.
Thus, I decided to create a npm-package for fun. This is not the most useful package, but it's a package nonetheless. It's been quite a while since I created my last package, and to be honest, none of my packages are worth anything ๐คท But you'll only better by trying!
Why only 16
?
Well, to answer this question shortly, this is because I'm not good at creating graphics, nor am I not enjoying doing so. But I do enjoy to code. So I threw together a small face made in (inkscape)[inkscape.org/], this wasn't enough, so I decided to create another, much uglier, one too.
Gave me the option to pick from one of two faces. Easily! But is two enough? Nop, and now that I had two faces to choose from, I decided to create a library, that could take the individual unique pieces from each face, and generate a new unique one!
But how did I come to the 16
unique faces? Well, the math is simple. I have four (4
) item-collections, each with two (2
) items in them. By using these collections, I am able to generate 16
completely unique avatars. This can be calculated by 2 * 2 * 2 * 2
which equals to 16
.
How about another?
If I would add another, say, mouth the equation would be 2 * 2 * 2 * 3
which now equals to 24
! That's an increase of 50%
!
How about that. One more mouth and an 50%
increase. That's not too bad.
One more of each?
What if, on the other hand, I'd add another face, pair of eyes, a nose and a mouth. Then the equation would be 3 * 3 * 3 * 3
which equals to 81
! This an 406.25%
increase of unique faces! Whoop.
More
You can probably imagine how the equations only go up from there. Add two more mouths, a pair of eyes and five funny noses. No new faces added here. The equation is now: 3 * 4 * 8 * 5
which equals to 480
unique avatars!
Holy moly! This is an increase of 2900%
from the original 16
. And it only goes up from there.
A piece a day, keeps the repetition away
What if we made an experiment, and wanted to make 2500
unique faces by the end of November. But didn't want to start until November 1st?
- By the end of the first day you only have a single piece, which is one (
1
) unique face. - By day two (
2
) you'll still have one (1
) unique face, as a face needs at least four (4
) items to be complete, thus you'll need four (4
) days to generate one unique face. - On the fifth (
5
) day, you have two (2
) unique faces! - On the sixth (
6
) day, you have four (4
) unique faces! ...
- On the ninth (
9
) day, you have24
unique faces! - ...and so fourth...
Thus, in these 30
days you'll have 2500
unique avatars! That's a great start.
Imagine if you had a great day, and made two (2
) or three(3
) pieces instead of one (1
)! This could easily become 15000
unique faces!
Code
Enough talk, show me some code, please!
To use this library, you can choose to use my library my-avatars, which can be downloaded from npm. Or take a look at the source code on github.
Anyways, let's get to the code.
// import the library and take the important classes from it.
import { Generator, Layer, Item } from 'my-avatars'
As you can see, there is only three (3
) things to import, these will make up the complete generator at last.
// create two face items from the example images.
const faceItems = [
new Item('./images/face1.png'),
new Item('./images/face2.png'),
]
// add some eyes.
const eyeItems = [
new Item('./images/eyes1.png', { y: 50 }),
new Item('./images/eyes2.png', { y: 50 }),
]
// a few noses.
const noseItems = [
new Item('./images/nose1.png', { y: 200 }),
new Item('./images/nose2.png', { y: 200 }),
]
// and last, but not least. The mouths.
const mouthItems = [
new Item('./images/mouth1.png', { y: 270 }),
new Item('./images/mouth2.png', { y: 270 }),
]
Take a look at the second argument, it states where to draw the item. Also note that not all of the has it. Making it optional.
Lot's of repetition, I'll have to figure a better way, but that will come soon enough.
Next up, we'll create the layers.
// create four new layers.
const faceLayer = new Layer('faces', 0)
const eyeLayer = new Layer('eyes', 1)
const noseLayer = new Layer('noses', 2)
const mouthLayer = new Layer('mouths', 3)
Keep in mind the latter number, it's like the z-index in css, it's super important. The first argument, on the other hand is just for your own convenience. This will be thrown in an error, if one occurs.
Now, let's add the items to the layers.
// add each items to the corresponding layer.
faceItems.forEach((x) => faceLayer.addItem(x))
eyeItems.forEach((x) => eyeLayer.addItem(x))
noseItems.forEach((x) => noseLayer.addItem(x))
mouthItems.forEach((x) => mouthLayer.addItem(x))
Now for the last, but still important part.
// fetch where to put the generated avatar.
const app = document.getElementById('app')
// create the generator with 400x400 avatars, and put in the parent elm.
const g = new Generator(400, 400, app)
// add each layer to the generator.
g.addLayer(faceLayer)
g.addLayer(eyeLayer)
g.addLayer(noseLayer)
g.addLayer(mouthLayer)
Now for that all of that boilerplate is out there, let's get to the fun part!
g.draw()
Boom! You've drawn a new, unique, avatar!
Congratulations! ๐ฅณ
NB. The repo with everything is right here.
v1.0.0
As per v1.0.0
you can add now manipulate colors, it's not fast but it's there.
The API documentation goes as:
Item
new Item(path, opts)
path
is the path to the imageopts
x
:Number
- x-coord to place the imagey
:Number
- y-coord to place the imagecheck
:Boolean
- check if the image can be found - required toreplace
-colorsreplace
:Array
ofObject
's - filled with colors to replace from and tofrom
:String
- color to replace from, in the format ofr,g,b
- e.g.128,128,128
to
:String
- color to replace to, in the format ofr,g,b
- e.g.128,128,128
Layer
new Layer(name, idx)
name
:String
- a friendly name to recogniseidx
:Number
- the z-index of the layer
Generator
new Generator(width, height, parentElm)
width
:Number
- width of the avatarheight
:Number
- height of the avatarparentElm
:Element
- element to place avatar within
{ Best, Mads Bram Cordes }