made with requirebin
Last active
December 29, 2020 14:32
-
-
Save blixt/b914062d855df8f3d556 to your computer and use it in GitHub Desktop.
requirebin sketch
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| var procedural = require('procedural'); | |
| var avatar = procedural('avatar') | |
| // The block size is just visual, so it shouldn't affect randomization. | |
| .doNotHash('blockSize') | |
| // The username is needed to create a unique avatar for every user. | |
| .takes('username') | |
| // Size, in blocks. Different sizes will create different avatars. | |
| .takes('size', function validate(avatar, blocks) { | |
| // Ensure that size is a positive integer divisible by 2. | |
| return typeof blocks == 'number' && blocks > 0 && !(blocks % 2); | |
| }) | |
| // The pixel size of a single (square) block. | |
| .takes('blockSize', function validate(avatar, px) { | |
| return typeof px == 'number' && px > 0; | |
| }) | |
| // Calculate the colors that make up the avatar. | |
| .provides('hueAngle', function (avatar) { | |
| // Use a named number generator to get an independent sequence. | |
| return avatar.getRandGen('color').nextInt(360); | |
| }) | |
| .provides('background', function (avatar) { | |
| return 'hsl(' + avatar.hueAngle + ', 100%, 50%)'; | |
| }) | |
| .provides('foreground', function (avatar) { | |
| var hueAngle = (avatar.hueAngle + 180) % 360; | |
| return 'hsl(' + hueAngle + ', 100%, 50%)'; | |
| }) | |
| // 25% of avatars mirror vertically instead. | |
| .provides('mirrorVertically', function (avatar) { | |
| return avatar.getRandGen('mirror').nextFloat() <= .25; | |
| }) | |
| // A particular avatar has a unique set of blocks. | |
| .generates('block') | |
| // The validator will run independently for both parameters. | |
| .takes('x', 'y', function validate(block, xy) { | |
| // We can refer to the parent instance (the avatar). | |
| return typeof xy == 'number' && xy >= 0 && xy < block.avatar.size; | |
| }) | |
| // The color of this block. | |
| .provides('color', function (block) { | |
| // You don't have to use named random generators. | |
| if (block.getRandGen().nextFloat() > .5) { | |
| return block.avatar.foreground; | |
| } else { | |
| return block.avatar.background; | |
| } | |
| }) | |
| // Go back to defining the parent (avatar). | |
| .done() | |
| // Renders to a canvas and returns a URL for <img>. | |
| .provides('url', function (avatar) { | |
| var canvas = document.createElement('canvas'), | |
| context = canvas.getContext('2d'); | |
| canvas.width = avatar.size * avatar.blockSize; | |
| canvas.height = avatar.size * avatar.blockSize; | |
| context.fillStyle = avatar.background; | |
| context.fillRect(0, 0, avatar.size, avatar.size); | |
| var finalX = avatar.mirrorVertically ? avatar.size : avatar.size / 2, | |
| finalY = avatar.mirrorVertically ? avatar.size / 2 : avatar.size, | |
| blockSize = avatar.blockSize; | |
| for (var y = 0; y < finalY; y++) { | |
| for (var x = 0; x < finalX; x++) { | |
| var realX = x * blockSize, realY = y * blockSize; | |
| var block = avatar.block(x, y); | |
| context.fillStyle = block.color; | |
| context.fillRect(realX, realY, blockSize, blockSize); | |
| if (avatar.mirrorVertically) { | |
| var mirroredY = avatar.size * blockSize - realY - blockSize; | |
| context.fillRect(realX, mirroredY, blockSize, blockSize); | |
| } else { | |
| var mirroredX = avatar.size * blockSize - realX - blockSize; | |
| context.fillRect(mirroredX, realY, blockSize, blockSize); | |
| } | |
| } | |
| } | |
| return canvas.toDataURL(); | |
| }); | |
| // Set up document. | |
| document.body.innerHTML = '<p><code>img.src = avatar(<input id="username" size="8" value="bob">, <input id="size" size="2" value="16">, <input id="blockSize" size="2" value="4">).url;</code></p><p><img></p><pre></pre>'; | |
| var img = document.querySelector('img'), | |
| pre = document.querySelector('pre'), | |
| username = document.querySelector('#username'), | |
| size = document.querySelector('#size'), | |
| blockSize = document.querySelector('#blockSize'); | |
| // Create a new "avatar" instance every time a key is pressed. | |
| username.onkeyup = size.onkeyup = blockSize.onkeyup = function () { | |
| var avatarInstance = avatar(username.value, | |
| parseInt(size.value, 10), | |
| parseInt(blockSize.value, 10)); | |
| img.src = avatarInstance.url; | |
| pre.textContent = JSON.stringify(avatarInstance, null, ' '); | |
| }; | |
| username.onkeyup(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| require=function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s}({BmBy9Z:[function(require,module,exports){var murmur3=require("./lib/murmur3");var random=require("./lib/random");var PARAMETER={},COMPUTED={};module.exports=function procedural(name,parent){var values=[],valuesMap={hash:null};var doNotHash=[];var parameterCount=0;function getName(){return name}function getValues(opt_type){var names=[];for(var i=0;i<values.length;i++){if(opt_type&&values[i].type!=opt_type)continue;names.push(values[i].name)}return names}function getParameters(){return getValues(PARAMETER)}function getProvides(){return getValues(COMPUTED)}function ProceduralInstance(parentInstance){if(parentInstance){this[parentInstance.getName()]=parentInstance}else if(parent){console.warn("Creating detached "+name+" instance (expected parent "+parent+")")}}ProceduralInstance.prototype={getName:getName,getParameters:getParameters,getProvides:getProvides,getValues:getValues,get:function(keyPath){var keys=keyPath.split("."),value=this;for(var i=0;i<keys.length;i++){value=value[keys[i]]}return value},getParent:function(){if(!parent)return null;return this[parent.getName()]},getRandGen:function(opt_id){var seed=opt_id?murmur3.hash32(opt_id,this.hash):this.hash;return new random.ParkMiller(seed)},toString:function(){var args,proc=this,pieces=[];while(proc){args=proc.getParameters().map(function(paramName){return paramName+": "+JSON.stringify(proc[paramName])});pieces.unshift(proc.getName()+"("+args.join(", ")+")");proc=proc.getParent()}return pieces.join(".")}};function create(){if(arguments.length!=parameterCount){throw new Error("Wrong number of parameters for "+create+": "+arguments.length)}var parentInstance=parent&&parent.isInstance(this)?this:null;var instance=new ProceduralInstance(parentInstance);var hashParts=[name],hashSeed=parentInstance?parentInstance.hash:0;function createHashOnce(){if("hash"in instance)return;instance.hash=murmur3.hash32(hashParts.join("\x00"),hashSeed)}var argumentIndex=0;for(var i=0;i<values.length;i++){var value=values[i],shouldHash=doNotHash.indexOf(value.name)==-1;if(value.type==PARAMETER){if("hash"in instance&&shouldHash){throw new Error("Cannot define hashed parameters after hash is generated")}var argument=arguments[argumentIndex++];if(value.validator&&!value.validator(instance,argument)){throw new Error("Invalid value for "+name+"."+value.name+": "+argument)}instance[value.name]=argument;if(shouldHash){hashParts.push(JSON.stringify(instance[value.name]))}}else if(value.type==COMPUTED){if(value.fn){createHashOnce();instance[value.name]=value.fn(instance)}else{instance[value.name]=value.constant}}}createHashOnce();Object.freeze(instance);return instance}create.getName=getName;create.getParameters=getParameters;create.getProvides=getProvides;create.getValues=getValues;create.done=function(){return parent};create.doNotHash=function(var_args){Array.prototype.push.apply(doNotHash,arguments);return this};create.generates=function(nameValue){var proc=procedural(nameValue,this);ProceduralInstance.prototype[nameValue]=proc;this[nameValue]=proc;return proc};create.getParent=function(){return parent};create.isInstance=function(obj){return obj instanceof ProceduralInstance};create.provides=function(name,fnOrConstant){if(name in valuesMap){throw new Error("A value named "+name+" is already defined")}var value={name:name,type:COMPUTED};if(typeof fnOrConstant=="function"){value.fn=fnOrConstant}else{value.constant=fnOrConstant}values.push(value);valuesMap[name]=value;return this};create.takes=function(var_args){var numParams=arguments.length,validator;if(typeof arguments[numParams-1]=="function"){validator=arguments[numParams--]}if(!numParams){throw new Error("At least one parameter must be specified")}for(var i=0;i<numParams;i++){var name=arguments[i];if(typeof name!="string"){throw new Error("Invalid parameter name "+name)}if(name in valuesMap){throw new Error("A value named "+name+" is already defined")}var param={name:name,type:PARAMETER};if(typeof validator=="function"){param.validator=validator}values.push(param);valuesMap[name]=param}parameterCount+=numParams;return this};create.toString=function(){var pieces=[],proc=this;while(proc){pieces.unshift(proc.getName());proc=proc.getParent()}var names=this.getParameters().join(", ");return pieces.join(".")+"("+names+")"};return create}},{"./lib/murmur3":3,"./lib/random":4}],procedural:[function(require,module,exports){module.exports=require("BmBy9Z")},{}],3:[function(require,module,exports){exports.hash32=function hash32(key,seed){var remainder,bytes,h1,h1b,c1,c1b,c2,c2b,k1,i;remainder=key.length&3;bytes=key.length-remainder;h1=seed;c1=3432918353;c2=461845907;i=0;while(i<bytes){k1=key.charCodeAt(i)&255|(key.charCodeAt(++i)&255)<<8|(key.charCodeAt(++i)&255)<<16|(key.charCodeAt(++i)&255)<<24;++i;k1=(k1&65535)*c1+(((k1>>>16)*c1&65535)<<16)&4294967295;k1=k1<<15|k1>>>17;k1=(k1&65535)*c2+(((k1>>>16)*c2&65535)<<16)&4294967295;h1^=k1;h1=h1<<13|h1>>>19;h1b=(h1&65535)*5+(((h1>>>16)*5&65535)<<16)&4294967295;h1=(h1b&65535)+27492+(((h1b>>>16)+58964&65535)<<16)}k1=0;switch(remainder){case 3:k1^=(key.charCodeAt(i+2)&255)<<16;case 2:k1^=(key.charCodeAt(i+1)&255)<<8;case 1:k1^=key.charCodeAt(i)&255;k1=(k1&65535)*c1+(((k1>>>16)*c1&65535)<<16)&4294967295;k1=k1<<15|k1>>>17;k1=(k1&65535)*c2+(((k1>>>16)*c2&65535)<<16)&4294967295;h1^=k1}h1^=key.length;h1^=h1>>>16;h1=(h1&65535)*2246822507+(((h1>>>16)*2246822507&65535)<<16)&4294967295;h1^=h1>>>13;h1=(h1&65535)*3266489909+(((h1>>>16)*3266489909&65535)<<16)&4294967295;h1^=h1>>>16;return h1>>>0}},{}],4:[function(require,module,exports){function ParkMiller(seed){this._seed=seed%2147483647;if(this._seed<=0)this._seed+=2147483646}ParkMiller.prototype.next=function(){return this._seed=this._seed*16807%2147483647};ParkMiller.prototype.nextFloat=function(opt_minOrMax,opt_max){var value=(this.next()-1)/2147483646;var min,max;if(typeof opt_max=="number"){min=opt_minOrMax;max=opt_max}else if(typeof opt_minOrMax=="number"){min=0;max=opt_minOrMax}else{return value}return min+value*(max-min)};ParkMiller.prototype.nextInt=function(minOrMax,opt_max){return Math.floor(this.nextFloat(minOrMax,opt_max))};exports.ParkMiller=ParkMiller},{}]},{},[]);var procedural=require("procedural");var avatar=procedural("avatar").doNotHash("blockSize").takes("username").takes("size",function validate(avatar,blocks){return typeof blocks=="number"&&blocks>0&&!(blocks%2)}).takes("blockSize",function validate(avatar,px){return typeof px=="number"&&px>0}).provides("hueAngle",function(avatar){return avatar.getRandGen("color").nextInt(360)}).provides("background",function(avatar){return"hsl("+avatar.hueAngle+", 100%, 50%)"}).provides("foreground",function(avatar){var hueAngle=(avatar.hueAngle+180)%360;return"hsl("+hueAngle+", 100%, 50%)"}).provides("mirrorVertically",function(avatar){return avatar.getRandGen("mirror").nextFloat()<=.25}).generates("block").takes("x","y",function validate(block,xy){return typeof xy=="number"&&xy>=0&&xy<block.avatar.size}).provides("color",function(block){if(block.getRandGen().nextFloat()>.5){return block.avatar.foreground}else{return block.avatar.background}}).done().provides("url",function(avatar){var canvas=document.createElement("canvas"),context=canvas.getContext("2d");canvas.width=avatar.size*avatar.blockSize;canvas.height=avatar.size*avatar.blockSize;context.fillStyle=avatar.background;context.fillRect(0,0,avatar.size,avatar.size);var finalX=avatar.mirrorVertically?avatar.size:avatar.size/2,finalY=avatar.mirrorVertically?avatar.size/2:avatar.size,blockSize=avatar.blockSize;for(var y=0;y<finalY;y++){for(var x=0;x<finalX;x++){var realX=x*blockSize,realY=y*blockSize;var block=avatar.block(x,y);context.fillStyle=block.color;context.fillRect(realX,realY,blockSize,blockSize);if(avatar.mirrorVertically){var mirroredY=avatar.size*blockSize-realY-blockSize;context.fillRect(realX,mirroredY,blockSize,blockSize)}else{var mirroredX=avatar.size*blockSize-realX-blockSize;context.fillRect(mirroredX,realY,blockSize,blockSize)}}}return canvas.toDataURL()});document.body.innerHTML='<p><code>img.src = avatar(<input id="username" size="8" value="bob">, <input id="size" size="2" value="16">, <input id="blockSize" size="2" value="4">).url;</code></p><p><img></p><pre></pre>';var img=document.querySelector("img"),pre=document.querySelector("pre"),username=document.querySelector("#username"),size=document.querySelector("#size"),blockSize=document.querySelector("#blockSize");username.onkeyup=size.onkeyup=blockSize.onkeyup=function(){var avatarInstance=avatar(username.value,parseInt(size.value,10),parseInt(blockSize.value,10));img.src=avatarInstance.url;pre.textContent=JSON.stringify(avatarInstance,null," ")};username.onkeyup(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| "name": "requirebin-sketch", | |
| "version": "1.0.0", | |
| "dependencies": { | |
| "procedural": "0.1.3" | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <style type='text/css'>html, body { margin: 0; padding: 0; border: 0; } | |
| body, html { height: 100%; width: 100%; }</style> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment