CSS3 Volume Control. Part 2

In my previous post we’ve built basic functionality for image-free volume control. Now it’s time to make it sexy. Just to remind you, here is what our final result should look like:

image

But now it looks like this

image

First of all let’s make our knob look like metal one. For this purpose we can add metal “scratches” by using repeat radial gradient:

.metal { 
    background-image:    /* metal radial scratches */ 
                        -webkit-repeating-radial-gradient(    50% 50%, 100% 100%, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0) 3%, rgba(0, 0, 0, .1) 2.5%), 
                        -webkit-repeating-radial-gradient(    50% 50%, 100% 100%, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0)   6%, rgba(255, 255, 255, .1) 7.3%), 
                        -webkit-repeating-radial-gradient(    50% 50%, 100% 100%, rgba(255, 255, 255, 0    ) 0%, rgba(255, 255, 255, 0) 1.2%, rgba(255, 255, 255, .2) 2.1%) 
}

image

So here we have three types of “scratches” which do overlap each other at some points. This makes an illusion of random metal scratches.

Next part of metal effect is light:

.metal { 
    background-image:    /* light conical gradients */ 
                        -webkit-radial-gradient(  50%   0%,  9% 50%, rgba(255, 255, 255, 0.5) 0%, rgba(255, 255, 255, 0) 100%), /* north-east */ 
                        -webkit-radial-gradient(  50% 100%, 11% 50%, rgba(255, 255, 255, 0.6) 0%, rgba(255, 255, 255, 0) 100%), /* south-west */ 
                        -webkit-radial-gradient(   0%  50%, 50%  9%,rgba(255, 255, 255, 0.4) 0%, rgba(255, 255, 255, 0) 100%), /* notrh-west */ 
                        -webkit-radial-gradient( 100%  50%, 50%  11%, rgba(255, 255, 255, 0.5) 0%, rgba(255, 255, 255, 0) 100%), /* south-east */                        
                        /* metal radial scratches */ 
                        -webkit-repeating-radial-gradient(    50% 50%, 100% 100%, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0) 3%, rgba(0, 0, 0, .1) 2.5%), 
                        -webkit-repeating-radial-gradient(    50% 50%, 100% 100%, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0)   6%, rgba(255, 255, 255, .1) 7.3%), 
                        -webkit-repeating-radial-gradient(    50% 50%, 100% 100%, rgba(255, 255, 255, 0    ) 0%, rgba(255, 255, 255, 0) 1.2%, rgba(255, 255, 255, .2) 2.1%), 
                        /* make the whole knob more light */ 
                        -webkit-radial-gradient(50% 50%, 150% 50%, rgba(230, 230, 230, 1) 6%, rgba(217, 217, 217, 1) 32%, rgba(153, 153, 153, 1) 100%); 
}

So now we added four light reflections, but it will be better to add some dark conical gradients right before and after each light reflection. We will make it more contrast then.

.metal:before, .metal:after { 
    content: ""; 
    top: 0; 
    left: 0; 
    position: absolute; 
    width: 250px; 
    height: 250px; 
    border-radius: 250px; 
    /* dark conical gradients */    
    background-image:     -webkit-radial-gradient(  50%   0%, 10% 50%, rgba(0, 0, 0, .1) 0%, rgba(0, 0, 0, 0) 100%), 
                        -webkit-radial-gradient(  50% 100%, 10% 50%, rgba(0, 0, 0, .1) 0%, rgba(0, 0, 0, 0) 100%), 
                        -webkit-radial-gradient(   0%  50%, 50% 10%, rgba(0, 0, 0, .1) 0%, rgba(0, 0, 0, 0) 100%), 
                        -webkit-radial-gradient( 100%  50%, 50% 06%, rgba(0, 0, 0, .1) 0%, rgba(0, 0, 0, 0) 100%); 
} 
.metal:before {     -webkit-transform: rotate( 65deg); } 
.metal:after {    -webkit-transform: rotate(-65deg); }

Now its time to add a blue pin to our markup, javascript and styles:

<div id="volume-knob" class="metal"> 
                <div id="pin">                    
                </div> 
</div>
#pin { /* this is pin container, so we will rotate it as a radius and actual pin on the end will “draw” a cricle*/ 
    position: absolute; 
    top: -16px; 
    left: 50%; 
    height: 280px; 
    width: 10px; 
    margin-left: -6px; 
    -webkit-transform: rotate(30deg);    
}

#pin:after { /* blue pin itself */ 
    -webkit-border-radius: 10px; 
    background: #3299BB; 
    content: ' '; 
    -webkit-box-shadow: -1px 0 0 rgba(255, 255, 255, 1) inset, 1px 0 0 rgba(0, 0, 0, .5) inset, 0 0 2px rgba(255, 255, 255, .9); 
    -webkit-transform: rotate(45deg); 
    width: 10px; 
    height: 10px; 
    position: absolute; 
    bottom: 30px;    
}

Rotate pin along with the progress bar:

function displayProgress(a){    
    if(a >= 0 && a <= 180){ 
        progressBar.style.clip ="rect(0px, 140px, 280px, 0px)"; 
        progressBar.style.webkitTransform ="rotate(30deg)"; 
        lBar.style.webkitTransform = "rotate(" + -1 * (180 - a)     + "deg)";        
        rBar.style.display = "none";        
        pin.style.webkitTransform = "rotate(" + a + "deg)"; 
    } 
    else if(a >= 0 && a < 300){ 
        progressBar.style.clip ="rect(0px, 280px, 280px, 0px)"; 
        rBar.style.display = "block"; 
        lBar.style.webkitTransform = "rotate(0deg)"; 
        rBar.style.webkitTransform = "rotate(" + a + "deg)"; 
        pin.style.webkitTransform = "rotate(" + a + "deg)"; 
    } 
}

The final step is to prepare control to mobile browser:

1. As I mentioned  in one of my previous posts we need to add the following meta tags to make it fill like an mobile app:

<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0; minimum-scale=1.0; user-scalable=0;" /> 
<meta name="apple-mobile-web-app-capable" content="yes" />

2. As we rely on touchmove event, we need to prevent default mobile webkit browser behavior defined for this event, so user will not drag whole viewport, but just our volume knob:

document.body.addEventListener('touchmove', function(e) { 
      // This prevents native scrolling from happening. 
      e.preventDefault(); 
}, false);

Looks like we’ve done now. Here is github link to the project and demo (don’t forget to use mobile device to access it).