|
/* A lot of forks here. |
|
I wonder if somebody give me a better fork, with a nicer GUI. |
|
Any maybe a solution for making a screenshot PNG. |
|
|
|
|
|
Not sure why the bowtie looks so bad in Opera, maybe something about border-radius? |
|
+ |
|
|
|
<span>CSS Robot</span> |
|
<br> |
|
Illustration taken from <a href="http://www.souljade.com/" target="_blank">Robert Dabi</a> |
|
<br> |
|
Specifically his <a href="http://dribbble.com/shots/664589-Wedding-Stamp" target="_blank">Dribbble</a> |
|
<br> |
|
His Twitter: <a href="https://twitter.com/soulja_de" target="_blank">soulja_de</a> |
|
<br> |
|
My Twitter: <a href="https://twitter.com/monstasaurous" target="_blank">monstasaurous</a> |
|
</p> |
|
|
|
|
|
|
|
|
|
*/ |
|
|
|
// forked from y3i12's "Holy Caffeine: The Strange Fractal Generator" http://jsdo.it/y3i12/strange_fract |
|
var ctx; |
|
var width = 0; |
|
var height = 0; |
|
var iterations = 2; |
|
var current_fract; |
|
var stack = []; |
|
var the_command_list; |
|
var the_timer; |
|
|
|
// some useful definitions |
|
var PI = 3.14159265; |
|
var DEG_TO_RAD = 0.0174532925; |
|
|
|
function StackItem( x, y, sz, a, l, i ) |
|
{ |
|
this.originX = x; |
|
this.originY = y; |
|
this.size = sz; |
|
this.angle = a; |
|
this.level = l; |
|
this.index = i; |
|
this.toString = function( ) |
|
{ |
|
return "{ x: " + this.originX + ", y: " + this.originY + ", sz: " + this.size + ", a: " + this.angle + ", l: " + this.level + ", i: " + this.index + "}"; |
|
}; |
|
} |
|
|
|
function Fractal( n, s ) { this.name = n; this.script = s; } |
|
|
|
// pre-defined fractals |
|
var fracts = [ new Fractal( "I", "F0.5\nR90\nF0.5\nL180\nF0.5\nR90\nF0.5" ), |
|
new Fractal( "+", "F0.5\nR90\nF0.250\nR90\nF0.250\nL180\nF0.250\nR90\nF0.250\nL180\nF0.250\nR90\nF0.250\nL180\nF0.250\nR90\nF0.250\nR90\nF0.5" ), |
|
new Fractal( "+o", "F0.5\nR90\nF0.125\nR45\nF0.125\nR45\nF0.125\nL180\nF0.125\nR45\nF0.125\nR45\nF0.125\nL180\nF0.125\nR45\nF0.125\nR45\nF0.125\nL180\nF0.125\nR45\nF0.125\nR45\nF0.125\nR90\nF0.5\n" ), |
|
new Fractal( "V", "F0.35\nR60\nF0.3\nL120\nF0.3\nR60\nF0.35" ), |
|
new Fractal( "U", "F0.333\nR90\nF0.333\nL90\nF0.333\nL90\nF0.333\nR90\nF0.333" ), |
|
new Fractal( "W", "F0.333\nR90\nF0.444\nL90\nF0.111\nL90\nF0.333\nR90\nF0.111\nR90\nF0.333\nL90\nF0.111\nL90\nF0.444\nR90\nF0.333" ), |
|
new Fractal( "P", "F0.5\nR90\nF0.5\nL90\nF0.25\nL90\nF0.25\nL90\nF0.25\nR90\nF0.25\nR90\nF0.5" ), |
|
new Fractal( "PI", "F0.25\nR90\nF0.5\nL90\nF0.25\nL90\nF0.25\nL90\nF0.25\nR90\nF0.25\nR90\nF0.5\nR90\nF0.5\nL180\nF0.5\nR90\nF0.25" ), |
|
new Fractal( "T", "F0.45\nR90\nF0.250\nR90\nF0.125\nL90\nF0.1\nL90\nF0.350\nL90\nF0.1\nL90\nF0.125\nR90\nF0.250\nR90\nF0.45" ), |
|
new Fractal( "A", "F0.5\nR120\nF0.25\nL180\nF0.25\nR120\nF0.25\nL180\nF0.25\nR120\nF0.5" ), |
|
new Fractal( "Star", "F0.333\nR72\nF0.5\nL144\nF0.5\nL144\nF0.5\nL144\nF0.5\nL144\nF0.5\nR144\nF0.666" )]; |
|
|
|
|
|
function init( ) |
|
{ |
|
for ( var i = 0; i < fracts.length; ++i ) |
|
{ |
|
var opt = new Element("option"); |
|
opt.text = fracts[ i ].name; |
|
|
|
$("selector").options.add( opt ); |
|
} |
|
ctx = $("canvas").getContext("2d"); |
|
width = $("canvas").width; |
|
height = $("canvas").height; |
|
selectorChange(); |
|
} |
|
|
|
function doit( ) |
|
{ |
|
if (the_timer) |
|
{ |
|
clearTimeout(the_timer); |
|
} |
|
|
|
the_command_list = getCommandList( $("script_input").value ); |
|
stack = []; |
|
|
|
ctx.width = ctx.width; |
|
ctx.fillStyle = 'white'; |
|
ctx.fillRect( 0, 0, width, height ); |
|
|
|
iterations = new Number( $('iterations').textContent ); |
|
stack.push( new StackItem( 0, 0, width, 0, 0, 0 ) ); |
|
the_timer = setTimeout( stackFract, 0 ); |
|
} |
|
|
|
function stackFract( ) |
|
{ |
|
try |
|
{ |
|
var stack_item = stack[ stack.length - 1 ]; |
|
drawFractal( stack_item ); |
|
if ( stack.length ) |
|
{ |
|
the_timer = setTimeout( stackFract, 0 ); |
|
} |
|
} |
|
catch(err) |
|
{ |
|
var txt = "There was an error on page.\n\n"; |
|
txt += "Error description: '" + err.toString() + "'\n\n"; |
|
txt += "Click OK to continue.\n\n"; |
|
alert(txt); |
|
} |
|
} |
|
|
|
function getCommandList( the_fractal ) |
|
{ |
|
var command_lines = the_fractal.split('\n'); |
|
var command_list = []; |
|
for (var i = command_lines.length - 1; i >= 0; i--) { |
|
command_list[i] = |
|
{ |
|
cmd: command_lines[i][0], |
|
param: new Number( command_lines[i].substr(1) ) |
|
}; |
|
} |
|
|
|
return command_list; |
|
} |
|
|
|
function drawFractal( a_item ) |
|
{ |
|
var the_stack = stack; |
|
var command = the_command_list[ a_item.index ]; |
|
var new_item = new StackItem( a_item.originX, a_item.originY, a_item.size, a_item.angle, a_item.level, a_item.index ); |
|
stack.pop(); |
|
if ( command.cmd == 'L' ) |
|
{ |
|
new_item.angle -= command.param; |
|
new_item.index++; |
|
stack.push( new_item ); |
|
} |
|
else if ( command.cmd == 'R' ) |
|
{ |
|
new_item.angle += command.param; |
|
new_item.index++; |
|
stack.push( new_item ); |
|
} |
|
else if ( command.cmd == 'F' ) |
|
{ |
|
|
|
if ( iterations == new_item.level ) |
|
{ |
|
var new_size = new_item.size * command.param; |
|
|
|
new_item.size = new_size; |
|
drawItem( new_item, ctx, "#FFFF00" ); |
|
new_item.size = a_item.size; |
|
|
|
|
|
new_item.index++; |
|
new_item.originX += Math.cos( new_item.angle * DEG_TO_RAD ) * new_size; |
|
new_item.originY += Math.sin( new_item.angle * DEG_TO_RAD ) * new_size; |
|
|
|
|
|
if ( new_item.index + 1 < the_command_list.length ) |
|
{ |
|
stack.push( new_item ); |
|
|
|
} |
|
|
|
|
|
} |
|
else |
|
{ |
|
|
|
var new_item_rec = new StackItem( new_item.originX, new_item.originY, new_item.size, new_item.angle, new_item.level, new_item.index ); |
|
|
|
//if ( ( new_item.level != 0 ) && ( new_item.index + 1 < the_command_list.length ) ) |
|
if ( new_item.index + 1 < the_command_list.length ) |
|
{ |
|
new_size = new_item.size * command.param; |
|
|
|
new_item.index++; |
|
new_item.originX += Math.cos( new_item.angle * DEG_TO_RAD ) * new_size;//new_item.size;// * command.param; |
|
new_item.originY += Math.sin( new_item.angle * DEG_TO_RAD ) * new_size;//new_item.size;// * command.param; |
|
stack.push( new_item ); |
|
} |
|
|
|
|
|
new_item_rec.index = 0; |
|
new_item_rec.size *= command.param; |
|
new_item_rec.level++; |
|
stack.push( new_item_rec ); |
|
} |
|
} |
|
} |
|
|
|
function drawPreview( a_string ) |
|
{ |
|
command_list = getCommandList( a_string ); |
|
var prv = $("preview").getContext("2d"); |
|
var w = $("preview").width; |
|
|
|
prv.width = prv.width; |
|
prv.fillStyle = 'white'; |
|
prv.fillRect( 0, 0, $("preview").width, $("preview").height ); |
|
|
|
var item = new StackItem( 0, 0, 0, 0, 0, 0 ); |
|
for ( var i = 0; i < command_list.length; ++i ) |
|
{ |
|
var command = command_list[ i ]; |
|
if ( command.cmd == 'L' ) |
|
{ |
|
item.angle -= command.param; |
|
item.index++; |
|
} |
|
else if ( command.cmd == 'R' ) |
|
{ |
|
item.angle += command.param; |
|
item.index++; |
|
} |
|
else if ( command.cmd == 'F' ) |
|
{ |
|
item.size = w * command.param; |
|
drawItem( item, prv ); |
|
item.index++; |
|
item.originX += Math.cos( item.angle * DEG_TO_RAD ) * item.size; |
|
item.originY += Math.sin( item.angle * DEG_TO_RAD ) * item.size; |
|
} |
|
} |
|
} |
|
|
|
|
|
function drawItem( a_item, the_context, stroke ) |
|
{ |
|
var dx = Math.cos( a_item.angle * DEG_TO_RAD ); |
|
var dy = Math.sin( a_item.angle * DEG_TO_RAD ); |
|
drawLine( the_context, a_item.originX, a_item.originY, a_item.originX + dx * a_item.size, a_item.originY + dy * a_item.size ); |
|
} |
|
|
|
function drawLine( context, x, y, x2, y2, the_stroke_style ) |
|
{ |
|
context.beginPath(); |
|
|
|
if ( the_stroke_style ) |
|
{ |
|
context.strokeStyle = the_stroke_style; |
|
} |
|
else |
|
{ |
|
context.strokeStyle = "#4F4F4F"; |
|
} |
|
//the_context.strokeStyle = "#00FF00"; |
|
context.moveTo( x, y ); |
|
context.lineTo( x2, y2 ); |
|
|
|
context.stroke( ); // chama a funcao de desenhar para o path criado acima |
|
context.closePath( ); |
|
} |
|
|
|
// for the events |
|
function selectorChange() |
|
{ |
|
$("script_input").value = fracts[ $("selector").selectedIndex ].script; |
|
scriptChange(); |
|
} |
|
|
|
function scriptChange() |
|
{ |
|
drawPreview( $("script_input").value ); |
|
} |
|
|
|
init(); |