swaponline / swap.io-app

https://app.swap.io
https://app.swap.io
7 stars 13 forks source link

Deterministic CSS styling based on profile public key. The component blueprint. #37

Open vladiuz1 opened 3 years ago

vladiuz1 commented 3 years ago

Background Generator

Background generator component must generate an SVG code that will be used as background and (may be as default avatar) for the profile derived style.

This is not as hard as it seems, we can do it in 4 steps.

Step 1. Random rectangles.

First we create a few random rectangles that go over the borders of the SVG view area:

1-random-rectangles-with-random-colors

The colors are also picked randomly, but they should have the same brightness, color range, and the distance of the color form one rectangle to the other should not be great to avoid too much difference. The right ranges need to be picked manually to result in beautiful sequence of colours every other time.

Step 2. Random ovals with some opacity on top

2-random-ovals-with-random-colors-and-30-opacity

The ovals also have colors and some level of opacity to be transparent. May be transparency is optional, need to experiment.

Step 3. Random skew

We slightly turn the whole area left or right within some ranges.

3-random-rotation

Step 4. Final blur

Now we blur the resulting SVG

4-blur-new

I changed the initial rectangles a bit, turned them into trapezoids, gave a different colour and skew, and here is what i got:

4-blur-alternative

One more:

4-blur-alternative-2

Active/select color

To pick the active color, we can take the dominant color (the color of the widest of the initial rectangles). If the color is not dark enough, we can darken it a little to fit our active color darkness limits.

The selected background color can be the same as active color but with low opacity.

deterministic-colors-2

Source of randomness

There is no randomness of course when we are picking the angle of skew, color within range, etc...

The source of randomness is different parts of the hash of the public key derived from mnemonic phrase of the user profile.

Most likely we will be using bitcoinjs-lib as crypto base for our profiles. The public key will be unpacked into a few values 0-15 (half bytes) or 0-255 (bytes), and these values will be the random source for our colors, angles, sizes.

For now you can just use this class to get random values:

class Randomness {
    constructor(source) {
        this.source = source;
        this.index = 0;
    }
    pop(min, max) {
        var min = Math.ceil(min);
        var max = Math.floor(max);
        return Math.floor(Math.random() * (max - min)) + min; //Максимум не включается, минимум включается
    }
};
var profile = "doesn't matter what for now, as long as you declare an instance once per profile.";
var rand = new Randomness(profile);

// this is how you get random values:
console.log('value 1', rand.pop(128,256));
console.log('value 2', rand.pop(16,128));
console.log('value 3', rand.pop(128,256));

// remember the maximum number is not included, 
// so rand.pop(128,255) will return a number from 128 to 255
vladiuz1 commented 3 years ago

Ok just made a simple class to get deterministic random derived from an array buffer:

class DerivedRandom {
    constructor(source) {
        this.source = source.reduce((str, source) => str + source.toString(2).padStart(8, '0'), '').substr(8);
    }
    pop(bits) {
        var ret = parseInt(this.source.substr(0, bits),2);
        this.source = this.source.substr(bits) + this.source.substr(0, bits);
        return ret;
    }
}

First you need to create the DerivedRandom object, for example like this:

var rnd = new DerivedRandom(window.crypto.getRandomValues(new Uint8Array(16)));

Now this object will give you pseudo-random Int values from 0 to 2^N - 1. For example if you want a value from 0 to 31 you will call rnd.pop(5). Because 2^5 = 32.

Conveniently you can use this method:

console.log(rnd.pop(Math.log2(128)));

Working example here:

https://jsfiddle.net/u87g2Lw4/2/

This now has a bitcoinjs-lib example.