The creation process of my portfolio website.

The physics UI

The physics UI was a starting point of my portfolio website. I initially thought - since I build games, why not use the same skills to build my portfolio website? And thus a game framework called 'Phaser' was added; however, not to make a game with rules, scores and objectives, but to create buttons with physics.




Obviously, having moving buttons around the screen is a terrible idea. Buttons should stay still and not being chased. But its use is totally optional and it is there only to add a bit of originality and playfulness to the page. As it is an experimental component, it's hidden at first. Bad idea for something unintuitive to be the first thing viewers would see.
I didn’t take the mobile-first approach. Below is the example of how the physics UI looks on mobile devices.




Line animation, page rotation & zoom

What is the best approach to present optional information? The description of the animation on top was irrelevant to the main page. But at the same time, I wanted to give some quick details about it. So have the description or not? ...dilemma Not to draw viewers' attention away from more important points on the page, zooming and unhiding that extra information seemed to be a good solution; the description is displayed only when clicked, meaning that specific element has some level of interest.
On smaller screens the zoom function is disabled.


For the zoom effect a jQuery plugin zoomooz.js was used.


var bzo = (function(){
    var objBegin = {};
    var objCurve = {};
    var objSimulate = {};
        return{
            line : function(){
                objBegin = getControlPoint(getPoint(),false);
                objSimulate = getControlPoint(getPoint(),false);
                objSimulate.count = 0;
                objSimulate.earase = false;
                objSimulate.stage = 1;
            },
            curveline : function(){
                objCurve = getControlPoint(getPoint(),true);
            },simulate : function(){
                return simulate();
            },drawCircle : function(){
                return objBegin;
            },drawCurvyCircle : function(){
                return objCurve;
            },drawCircleSimulate : function(){
                return objSimulate;
            },
    }
})();

var canvasWidth = (function(){
   return document.getElementById("canvas").offsetWidth;
});
var ctx = canvas.getContext("2d")       
window.onload = function(){
    
    var canvas = document.getElementById("canvas");
    canvas.width = canvasWidth();
    ctx.translate(0,0);
    ctx.restore();
    bzo.line();
    bzo.curveline();
    }
        
function update(){     
    var ctxb = canvas.getContext("2d");
        ctxb.beginPath();
        ctxb.rect(0, 0, canvasWidth(), 300);
        ctxb.fillStyle = "snow";
        ctxb.closePath();
        ctxb.fill();

        bzo.simulate();
        render();
}
                
function getPoint(){
         var radius = 120;
         var nsides = 100;
         var obj = {
            line : []
        };        
        var pointArray = [];
        var currentCount = 0;
        var angle = Math.PI*2 / nsides;
        var x = canvasWidth()/2;
        var y = 150;
        for(var i = 0; i < Math.PI*2; i += angle)
        {
            var sx = x + Math.cos(i) * radius; 
            var sy = y + Math.sin(i) * radius;
            pointArray[currentCount] = [{x:sx,xx:sx,y:sy,xy:sy}];
            obj.line.push(pointArray[currentCount]);
            currentCount++;
            ctx.beginPath();
            ctx.stroke();
        }
        return obj;
    }
function getControlPoint(object, random)
    {
        var radius = 150;
        var nsides = 300;
        var pointArray = {};
        var currentCount = 0;
        var currentCount2 = 0;
        var angle = Math.PI*2 / nsides;
        var x = canvasWidth()/2;
        var y = 150;
        for(var i = 0; i < Math.PI*2; i += angle)
        {
            if(!random){
            radius = 120;
            var sx = x + Math.cos(i) * radius; 
            var sy = y + Math.sin(i) * radius;
            }
            if(random){
            var randomNum = ~~(Math.random()*100)-50; 
            var sx = x + Math.cos(i) * radius + randomNum; 
            var sy = y + Math.sin(i) * radius + randomNum/2;
            }
            pointArray[currentCount] = {x:sx,y:sy};
            currentCount++;
            ctx.beginPath();
            ctx.stroke();
        }
        for(var j = 0; j < nsides/3; j += 1)
        {
            var controlList = removeThirdPoint(); 
            object.line[j][1] = pointArray[controlList[currentCount2]];
            object.line[j][2] = pointArray[controlList[currentCount2+1]];
            currentCount2+=2;
        }
        return object;
    } 

function simulate(){
    if(bzo.drawCircleSimulate().count>100){
        bzo.drawCircleSimulate().count = 0;
        
        switch (bzo.drawCircleSimulate().stage) {
            case 1:    
                bzo.drawCircleSimulate().stage = 2;
                break;    
            case 2:
                bzo.drawCircleSimulate().stage = 3;
                break;
            case 3:
                bzo.curveline();
                bzo.drawCircleSimulate().stage = 1;
                break;
            }
    }
    var rotationSpeed;
    var objCircle = jQuery.extend({}, bzo.drawCircle());
    var objCurve = jQuery.extend({}, bzo.drawCurvyCircle());
    var objSimulate = jQuery.extend({}, bzo.drawCircleSimulate());
    for (var i = 0; i < 100; i+=1)
    {
        if(bzo.drawCircleSimulate().stage == 1){
        rotationSpeed = 0.5;
        if(i <= objSimulate.count){
         for(var j = 1; j < 3; j += 1)
            {
            objSimulate.line[i][j].x += (objCurve.line[i][j].x - objSimulate.line[i][j].x)*0.05;
            objSimulate.line[i][j].y += (objCurve.line[i][j].y - objSimulate.line[i][j].y)*0.05;
            }
        }
        if(i >= objSimulate.count){
            for(var j = 1; j < 3; j += 1)
            {
            objSimulate.line[i][j].x += (objCircle.line[i][j].x - objSimulate.line[i][j].x)*0.05;
            objSimulate.line[i][j].y += (objCircle.line[i][j].y - objSimulate.line[i][j].y)*0.05;
            }
        }
    }        
    if(bzo.drawCircleSimulate().stage == 2){
        rotationSpeed = 0.7;
        if(i <= objSimulate.count){
         for(var j = 1; j < 3; j += 1)
            {
            objSimulate.line[i][j].x += (objCircle.line[i][j].x - objSimulate.line[i][j].x)*0.2;
            objSimulate.line[i][j].y += (objCircle.line[i][j].y - objSimulate.line[i][j].y)*0.2;
            }
        }
        if(i >= objSimulate.count){
            for(var j = 1; j < 3; j += 1)
            {   
            objSimulate.line[i][j].x += (objCurve.line[i][j].x - objSimulate.line[i][j].x)*0.05;
            objSimulate.line[i][j].y += (objCurve.line[i][j].y - objSimulate.line[i][j].y)*0.05;
            }
        }
    }
        if(bzo.drawCircleSimulate().stage == 3){
        rotationSpeed = 1.2;
        if(i <= objSimulate.count){
         for(var j = 1; j < 3; j += 1)
            {
            objSimulate.line[i][j].x += (objCircle.line[i][j].x - objSimulate.line[i][j].x)*0.05;
            objSimulate.line[i][j].y += (objCircle.line[i][j].y - objSimulate.line[i][j].y)*0.05;
            }
        }
        if(i >= objSimulate.count){
            for(var j = 1; j < 3; j += 1)
            {   
            objSimulate.line[i][j].x += (objCircle.line[i][j].x - objSimulate.line[i][j].x)*0.05;
            objSimulate.line[i][j].y += (objCircle.line[i][j].y - objSimulate.line[i][j].y)*0.05;
            }
        }
    }   
    }
    bzo.drawCircleSimulate().count+=rotationSpeed;
}
    
function render(reflection){
        var obj = bzo.drawCircleSimulate();
        var reflectionPos = canvasWidth()/2;
        var myopacity;
        
        for(var i = 0; i < 100; i += 1)
        {
        var end = i;
        (end == 99) ?
        end = -1 : end = end;
                    
       if(bzo.drawCircleSimulate().count <= i && bzo.drawCircleSimulate().stage == 1)
            {
                myopacity = 0.0;
            }
        else if(bzo.drawCircleSimulate().count >= i && bzo.drawCircleSimulate().stage == 3)
            {
                myopacity = 0.0;
            }
        else{
            myopacity = 1;
        }
             
        ctx.save();
        ctx.scale(1,1);
        ctx.beginPath();
        ctx.moveTo(obj.line[i][0].x,obj.line[i][0].y);
        ctx.bezierCurveTo(
            obj.line[i][1].x,obj.line[i][1].y,
            obj.line[i][2].x,obj.line[i][2].y,
            obj.line[end+1][0].x,obj.line[end+1][0].y);
            
        ctx.fillStyle = "rgba(255, 255, 255,"+ 0.4/myopacity+ ")";
        ctx.strokeStyle="rgba( 100,0, 0," + myopacity + ")";
        ctx.lineWidth = 1;
        ctx.stroke();
        ctx.closePath();
        ctx.fill();

        ctx.beginPath();    
        ctx.fillStyle = "rgba(255, 255, 255, "+ 0.155/myopacity+ "";
        ctx.moveTo(obj.line[0][0].x,obj.line[0][0].y); 
        ctx.lineTo(obj.line[1][0].x,obj.line[1][0].y); 
        ctx.lineTo(obj.line[2][0].x,obj.line[2][0].y);
        ctx.closePath();
        ctx.fill();
        ctx.restore();          
        ctx.beginPath();
        ctx.arc(obj.line[i][1].x, obj.line[i][1].y, 3, 0, Math.PI * 2, true);
        ctx.stroke();
        ctx.beginPath();
        ctx.arc(obj.line[i][2].x, obj.line[i][2].y, 3, 0, Math.PI * 2, true);
        ctx.strokeStyle="rgba(100,0, 0,0.1)";
        ctx.stroke();   
        }  
        return;
}        

function removeThirdPoint(){
        var numberstring = [];
        for(var i = 1; i < 350; i++){
        if (i % 3 !== 0) {
            numberstring.push(i);
        }else{continue;}}
    return numberstring;
}       
    setInterval(update, 33);