SitePoint Sponsor

User Tag List

Results 1 to 16 of 16
  1. #1
    SitePoint Evangelist
    Join Date
    Dec 2005
    Posts
    527
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Gradient in javascript

    Is any way to creating gradient background for a div without using background image ?!

  2. #2
    I meant that to happen silver trophybronze trophy Raffles's Avatar
    Join Date
    Sep 2005
    Location
    Tanzania
    Posts
    4,662
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Yes, with lots of divs.

    http://slayeroffice.com/code/gradient/

    Seems like an awful lot of work when you could just use images and tile them.

  3. #3
    SitePoint Enthusiast
    Join Date
    Jan 2004
    Location
    Edinburgh, Scotland
    Posts
    90
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Wrong Forum ?

    Quote Originally Posted by bakhanbeigi View Post
    Is any way to creating gradient background for a div without using background image ?!
    What is the connection with JavaScript?
    Throw away your Calculator -
    get instant results from www.calcResult.com

  4. #4
    I meant that to happen silver trophybronze trophy Raffles's Avatar
    Join Date
    Sep 2005
    Location
    Tanzania
    Posts
    4,662
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Well, if you wanted to do this for more than one div on a single page it would be quite tedious. It also makes outputting HTML from the server side a lot less hassle, since all you need to do is add something in the class attribute to give this gradient effect.

  5. #5
    SitePoint Wizard bronze trophy
    Join Date
    Jul 2006
    Location
    Augusta, Georgia, United States
    Posts
    4,147
    Mentioned
    16 Post(s)
    Tagged
    3 Thread(s)
    erase
    Last edited by oddz; Jan 1, 2008 at 23:53.

  6. #6
    SitePoint Wizard bronze trophy
    Join Date
    Jul 2006
    Location
    Augusta, Georgia, United States
    Posts
    4,147
    Mentioned
    16 Post(s)
    Tagged
    3 Thread(s)
    erase

  7. #7
    SitePoint Wizard bronze trophy
    Join Date
    Jul 2006
    Location
    Augusta, Georgia, United States
    Posts
    4,147
    Mentioned
    16 Post(s)
    Tagged
    3 Thread(s)
    erase

  8. #8
    SitePoint Wizard bronze trophy
    Join Date
    Jul 2006
    Location
    Augusta, Georgia, United States
    Posts
    4,147
    Mentioned
    16 Post(s)
    Tagged
    3 Thread(s)
    erase

  9. #9
    SitePoint Wizard bronze trophy
    Join Date
    Jul 2006
    Location
    Augusta, Georgia, United States
    Posts
    4,147
    Mentioned
    16 Post(s)
    Tagged
    3 Thread(s)
    The below function was created by me to handle the creation of dynamic gradients.

    Its not necessary that you understanding the workings of the the GRADIENT function. All you need to do is link to it in the html.

    However, in order to use this it is going to take some explanation.

    First, I'm going to start of with the "class" function file.

    javascript class file
    Code:
    function GRADIENT() {
      this.colors = [];
      this.ramp = [];
      this.mid = [];
      this.object;
      this.type;
      
      this.Color = Color;
      function Color(r,g,b) {
        if(arguments.length != 3) return alert('Method Color requires 3 arguments.');
        for(var x=0; x < arguments.length; x++) { if(typeof arguments[x] != 'number') return alert(arguments[x]+' is not a number. RGB values can only be numbers.'); }
        for(var x=0; x < arguments.length; x++) { if(arguments[x] < 0 || arguments[x] > 255) return alert(arguments[x]+' is not a valid rgb value. Values must be between 0 and 255.'); }
        this.colors[this.colors.length] = [r,g,b];
      }
      this.Ramp = Ramp;
      function Ramp(x) {
        if(arguments.length != 1) return alert('Ramp can only be one value.');
        if(typeof x != 'number') return alert('Ramp can only be a number,');
        if(x < 0 || x > 100) return alert('Ramp can only be a number between 0 and 100.');
        for(r in this.ramp) { if(x == this.ramp[r]) return alert('All ramps must have a different value. Each one must be different otherwise the colors will overlap.'); }
        this.ramp[this.ramp.length] = x;
      }
      this.Mid = Mid;
      function Mid(x) {
        if(arguments.length != 1) return alert('Mid can only have one value.');
        if(typeof x != 'number') return alert('Mid must be a number.');
        if(x < 0 || x > 100) return alert('Mid can only be a number equal to or between 0-100.');
        this.mid[this.mid.length] = x;
      }
      this.Object = Object;
      function Object(x) {
        if(!document.getElementById(x)) return alert('A HTML element with the ID '+ x + ' does not exist in the html document.');
        this.object = x;  
      }
      this.Type = Type;
      function Type(x) {
        if(typeof x != 'string') return alert('Type must be a string.');
        if(x != 'v' && x != 'h') return alert('The valid values for type are either v or h.');
        this.type = x;
      }
      
      this.Stop = Stop;
      function Stop(a,b,c,d,e) {
        if(arguments.length != 5) return alert('Method Stop requires 5 arguments.');
        this.Color(a,b,c);
        this.Ramp(d);
        this.Mid(e);
      }
      
      this.Apply = Apply;
      function Apply() {
        if(this.type != 'v' && this.type != 'h') return alert('The gradient type can only be horizontal-h or vertical-v.');
        if(typeof this.object != 'string') return alert('The object type must be a string that point to a valid HTML element.');
        if(this.colors.length != this.ramp.length) return alert('The number of colors in gradient is not equal to the number of ramps.');
        if(this.ramp.length != this.mid.length) return alert('The number of ramps is not equal to the number of mid points.');  
        this.createGradient();
        alert('created');
      }
      this.Generate = Generate;
      function Generate(x) {
        if(arguments.length != 1) return alert('Method Generate can only take on argument.');
        if(typeof x != 'number') return alert(x +' is not a number. Method generate takes a number.');
        this.colors = [];
        this.ramp = [];
        this.mid = [];
        for(var i=0; i< x; i++) {
          var a = Math.floor(Math.random()*256);
          var b = Math.floor(Math.random()*256);
          var c = Math.floor(Math.random()*256);
          
          if(i != x-1) var d = i*(Math.floor(100/x)); else var d = 100;
          var e = 50; //default midpoint
          this.Stop(a,b,c,d,e);
        }
      }
    }// end of Class GRADIENT
    
    GRADIENT.prototype.ComputedStyle = ComputedStyle;
    function ComputedStyle(styleProperty) {
      var computedStyle = null;
      if(typeof this.gradient.object.currentStyle != 'undefined') {
        computedStyle = this.gradient.object.currentStyle;
      } else {
        computedStyle = document.defaultView.getComputedStyle(this.gradient.object, null);
      }
      return computedStyle[styleProperty];
    }
    
    GRADIENT.prototype.createGradient = createGradient;
    function createGradient() {
      alert('Gradient properties are valid.');
      
      if(this.type == 'v') {
        var span = 'width'; var len = 'height';
      } else if(this.type == 'h') {
        var span = 'height'; var len = 'width';
      } else {
        return alert('The element type has not been set or is not equal to v or h.');
      }
      
      if(!document.getElementById) return alert('Your browser does not support the appropriate scripting to make document.getElementById possible.');
      if(!document.getElementById(this.object)) return alert(this.object+' Is not a valid element ID that resides in the html document.');
      this.gradient = new Object();
      this.gradient.object = document.getElementById(this.object);
       
      this.gradient.span = parseFloat(this.ComputedStyle(span));
      this.gradient.len = parseFloat(this.ComputedStyle(len));
      
      if(typeof this.gradient.span != 'number') return alert(this.gradient.span+' Is not a number. Property Span must be a number.');
      if(typeof this.gradient.len != 'number') return alert(this.gradient.len+' is not a number. Property Len must be a number.');
    
      this.gradient.clones = [];
      for(var i=0; i< this.gradient.span; i++) {
        this.gradient.clones[i] = this.gradient.object.cloneNode(false);
        this.gradient.clones[i].width = 1+'px';
        this.gradient.clones[i].height = this.gradient.len+'px';
        this.gradient.clones[i].left = i +'px';
      }
    
      this.gradient.stopDistance = [];
      for(var i=0; i<this.colors.length; i++) {
        this.gradient.stopDistance[i] = Math.round(this.gradient.span * (this.ramp[i]/100));
      }
      
      for(var i=0; i<this.gradient.stopDistance.length; i++) { 
        if(i==0) {
       
          for(var d=0; d<this.gradient.stopDistance[i]; d++) {
            this.gradient.clones[d].newColor = 'rgb('+ this.colors[i][0] + ','+
            this.colors[i][1] +','+ this.colors[i][2] +')';
          }   
          
        } else {
          
          this.gradient.steps = [];
          this.gradient.steps[i] = this.gradient.stopDistance[i] - this.gradient.stopDistance[i-1];
          
          this.gradient.left = [];
          this.gradient.right = [];
          this.gradient.left[i] = Math.round(((this.mid[i-1]/100) * this.gradient.steps[i]));
          this.gradient.right[i] = Math.round((this.gradient.steps[i] - this.gradient.left[i]));
          
          this.gradient.left_increment = [];
          this.gradient.right_increment = [];
          this.gradient.left_increment[i] = this.colorLeft_increment(i);
          this.gradient.right_increment[i] = this.colorRight_increment(i); 
          
          for(var l=0; l<this.gradient.steps[i]; l++) {
            
            if(l < this.gradient.left[i]) {
            
                this.gradient.clones[l+this.gradient.stopDistance[i-1]].newColor = this.color_left(i,l);
            
             } 
             if(l >= this.gradient.left[i]) {
                
                this.gradient.clones[l+this.gradient.stopDistance[i-1]].newColor = this.color_right(i,l);        
             }
           }
        }    
      } 
      this.apply_to_page();
    } // end of createGradient function/method
    
    GRADIENT.prototype.colorLeft_increment = colorLeft_increment;
    function colorLeft_increment(num) {
    
    
      var s = this.gradient.left[num];
    
      this.gradient.incred =
      
      ((this.colors[num][0] - this.colors[num-1][0])/2)/s;
      
      this.gradient.incgreen =
      
      ((this.colors[num][1] - this.colors[num-1][1])/2)/s;
      
      this.gradient.incblue =
      
      ((this.colors[num][2] - this.colors[num-1][2])/2)/s;
                
    
    
      this.gradient.transformation = [];
      this.gradient.transformation[0] = this.roundTo(this.gradient.incred, 2);
      this.gradient.transformation[1] = this.roundTo(this.gradient.incgreen, 2);
      this.gradient.transformation[2] = this.roundTo(this.gradient.incblue, 2);
      return this.gradient.transformation;  
      
    } // end of colorLeft_increment function/method
    
    GRADIENT.prototype.colorRight_increment = colorRight_increment;
    function colorRight_increment(num) {
    
      var s = this.gradient.right[num];
    
      this.gradient.incred =
      
      ((this.colors[num][0] - this.colors[num-1][0])/2)/s;
      
      this.gradient.incgreen =
      
      ((this.colors[num][1] - this.colors[num-1][1])/2)/s;
      
      this.gradient.incblue =
      
      ((this.colors[num][2] - this.colors[num-1][2])/2)/s;
      
      this.gradient.transformation = [];
      this.gradient.transformation[0] = this.roundTo(this.gradient.incred, 2);
      this.gradient.transformation[1] = this.roundTo(this.gradient.incgreen, 2);
      this.gradient.transformation[2] = this.roundTo(this.gradient.incblue, 2);
      return this.gradient.transformation;
      
    } // end of colorRight_increment function/method
    
    GRADIENT.prototype.color_left = color_left;
    function color_left(i,l) {
    
      var swatch = [];
      swatch['red'] = Math.round((this.colors[i-1][0]) + (l * this.gradient.left_increment[i][0]));
      swatch['green'] = Math.round((this.colors[i-1][1]) + (l * this.gradient.left_increment[i][1]));
      swatch['blue'] = Math.round((this.colors[i-1][2]) + (l * this.gradient.left_increment[i][2]));
      var mix = 'rgb('+swatch['red']+','+swatch['green']+','+swatch['blue']+')';
      return mix;
    
    } // end of function/method color_left
    
    GRADIENT.prototype.color_right = color_right;
    function color_right(i,l) {
      
      var swatch = [];
      swatch['red'] = Math.round((((this.colors[i][0] - this.colors[i-1][0])/2)+ this.colors[i-1][0]) + (this.gradient.right_increment[i][0] * (l-this.gradient.left[i])));
      swatch['green'] = Math.round((((this.colors[i][1] - this.colors[i-1][1])/2)+ this.colors[i-1][1]) + (this.gradient.right_increment[i][1] * (l-this.gradient.left[i])));
      swatch['blue'] = Math.round((((this.colors[i][2] - this.colors[i-1][2])/2)+ this.colors[i-1][2]) +(this.gradient.right_increment[i][2] * (l-this.gradient.left[i])));
      var mix = 'rgb('+swatch['red']+','+swatch['green']+','+swatch['blue']+')';
      return mix;
    
    } // end of function/method color_right
    
    GRADIENT.prototype.roundTo = roundTo;
    function roundTo(base, precision) {
      var m = Math.pow(10, precision);
      var a = Math.round(base*m)/m;
      return a;
    } // end of function/method roundTo
    
    GRADIENT.prototype.apply_to_page = apply_to_page;
    function apply_to_page() {  
      if(this.type == 'v') { 
        this.vertical_application();
      } else if(this.type == 'h') {
        this.horizontal_application();  
      } else {
        alert('Something happened and the type property has changed. Please make sure type is a valid string of v or h.');
      }
    
    } // end of function/method apply_to_page
    
    GRADIENT.prototype.vertical_application = vertical_application;
    function vertical_application() {
      for(var i=0; i<this.gradient.clones.length; i++) {
    
        this.gradient.object.appendChild(this.gradient.clones[i]);
        this.gradient.clones[i].position = "absolute";
        this.gradient.clones[i].style.left = this.gradient.clones[i].left;
        this.gradient.clones[i].style.top = 0;
        this.gradient.clones[i].style.width = this.gradient.clones[i].width;
        this.gradient.clones[i].style.height = this.gradient.clones[i].height;
        this.gradient.clones[i].style.backgroundColor = this.gradient.clones[i].newColor;
      }
      
      this.trashCollect();
    
    } // end of function/method vertical_application
    
    GRADIENT.prototype.horizontal_application = horizontal_application;
    function horizontal_application() {
    
      for(var i=0; i<this.gradient.clones.length; i++) {
    
        this.gradient.object.appendChild(this.gradient.clones[i]);
        this.gradient.clones[i].position = "absolute";
        this.gradient.clones[i].style.left = 0;
        this.gradient.clones[i].style.top = this.gradient.clones[i].left;
        this.gradient.clones[i].style.width = this.gradient.clones[i].height;
        this.gradient.clones[i].style.height = this.gradient.clones[i].width;
        this.gradient.clones[i].style.backgroundColor = this.gradient.clones[i].newColor;
      } 
      
      this.trashCollect();
      
    } // end of function/method horizontal_application
    
    GRADIENT.prototype.trashCollect = trashCollect;
    function trashCollect() {
      this.gradient = null;
    } // end of function/method trashCollect
    Now… all you need to to is save that file and link to it in the html.

    Then in a separate javascript file place the onload handler.

    Here is an example of the onload handler.

    javascript
    Code:
    window.onload = function() {
    
    var grad = new GRADIENT()
    grad.Stop(255,0,0,0,50);
    grad.Stop(0,225,0,25,50);
    grad.Stop(0,0,255,50,50);
    grad.Stop(255,0,255,75,50);
    grad.Stop(255,255,0,100,50);
    grad.Type('v');
    grad.Object("box");
    grad.Apply();
    }
    I'll explain this in a few but, this is the base html file.

    html
    Code:
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
      <title>Dynamic Gradient</title>
        <meta http-equiv="content-type"
            content="text/html; charset=utf-8" />
        <script language="javascript" type="text/javascript" src="gradient-class.js"></script>
        <script language="javascript" type="text/javascript" src="gradient-handler.js"></script>
    </head>
    <body>
    
    <div style="position:relative;width:200px;height:500px;background-color:red;" id='wrapper'>
      <div style="position:absolute;top:0;left:0;width:100&#37;;height:100%;background-color:black" id='box'></div> <!-- box div -->
    </div> <!-- end of wrapper -->
    
    </body>
    </html>
    The file with the javascript class is named gradient-class.js. The handler function file is named gradient-handler.js.

    Now, to clarify about the methods appropriate to creating the actually gradient(gradient-handler.js).

    The first thing you need to do is create a gradient.

    Code:
    window.onload = function() {
      var grad = new GRADIENT();
    }
    Next you declare base colors. Base colors are added to the gradient by calling the Stop method.

    Code:
    window.onload = function() {
      var grad = new GRADIENT();
      grad.Stop(255,0,0,0,50); 
    }
    Lets take a loot at the above code. The Stop method takes five arguments. The first three arguments make up the rgb mix. In this case the rgb mix is 255,0,0, which is red. Each value can be any positive integer between 0(including 0) – 256. These three colors make up the rgb mix. The fourth argument set the location of the gradient. The location is a percentage based on the height or width of an object. In this case 0 means the top if the gradient is horizontal or left if the gradient is vertical (more on that later.) The last argument determines the midpoint of two color collisions. This might be a little hard to understand so I'll elaborate.

    In a gradient of just two colors where those colors meet is where the midpoint is. For sake of clarity I'm going to explain some of the theory behind this.

    Say there are two colors in a gradient [0,0,0] – black and [255,255,255] – white;

    The midpoint color will be determined as shown below.

    255-0 = 255

    255/2 = 127.5

    Therefore, The mid color is [127,127,127]

    Now, normally this mid color would reside in the very middle of the object the gradient is applied to. For example, an object with a width of 100 pixels the mid color would be located at 50px(conceptually) – half way or 50%. What the last argument in the Stop method does is allows you to control this midpoint for each color transition in the gradient. In the example(code) above I left the midpoint in the middle. However, you could also set that value to anything from 0 – 100 to essentially control the midpoint of two color transitions in the gradient.

    With that out of the way you may call the Stop method as many times as you wish. each time you call the Stop method a new base color will added to the gradient. You will also need to make sure that no two stops share the same location. The location is the fourth argument in the Stop method.

    With that out of the way I wnet ahead and added some more colors to the gradient.

    Code:
    var grad = new GRADIENT()
    grad.Stop(255,0,0,0,50);
    grad.Stop(0,225,0,25,50);
    grad.Stop(0,0,255,50,50);
    grad.Stop(255,0,255,75,50);
    grad.Stop(255,255,0,100,50);
    }
    Now you should begin to see the use of the fourth and fifth argument. Essentially, the first stop is located at 0. The second stop is lated at 25% of the width of the object the gradient will be applied to. The third 50% – middle. The fourth 75% and the fifth the end 100%. Each stop midpoint(fifth argument) is 50%. However, you can change that from anything between 0–100 to see the effect.

    Now, the next Method sets the type of gradient. A gradient can either be vertical or horizontal. In the below example the gardient is being set to horizontal by supplying a argument of 'h'. In order to create a vertical gradient you would supply a argument value of 'v'.

    Code:
    window.onload = function() {
    
    var grad = new GRADIENT()
    grad.Stop(255,0,0,0,50);
    grad.Stop(0,225,0,25,50);
    grad.Stop(0,0,255,50,50);
    grad.Stop(255,0,255,75,50);
    grad.Stop(255,255,0,100,50);
    grad.Type('v');
    The next Method sets the html object to apply the gradient to. The argument value should be the id of the element. In this example, the id of the element is box.

    Code:
    var grad = new GRADIENT()
    grad.Stop(255,0,0,0,50);
    grad.Stop(0,225,0,25,50);
    grad.Stop(0,0,255,50,50);
    grad.Stop(255,0,255,75,50);
    grad.Stop(255,255,0,100,50);
    grad.Type('v');
    grad.Object("box");
    Finally, to create or paint the gradient on screen you call the Apply() method.

    Code:
    window.onload = function() {
    
    var grad = new GRADIENT()
    grad.Stop(255,0,0,0,50);
    grad.Stop(0,225,0,25,50);
    grad.Stop(0,0,255,50,50);
    grad.Stop(255,0,255,75,50);
    grad.Stop(255,255,0,100,50);
    grad.Type('v');
    grad.Object("box");
    grad.Apply();
    }
    One last method available is Generate. Generate takes one argument–a positive integer. That integer is the number stops. generate does the stop work for you and randomly creates color stops. Here is an example of this method in action (reload it in a browser to see the result.)

    [code]
    Code:
    window.onload = function() {
    
    var grad = new GRADIENT()
    grad.Generate(5);
    grad.Type('v');
    grad.Object("box");
    grad.Apply();
    }

    This may not work in IE I have just tested in firefox and safari. However, it should give you a way to create gradients dynamically in most browsers.

    This entire thing was a case study I did. So it should function well in most circumstances.

  10. #10
    SitePoint Wizard Pepejeria's Avatar
    Join Date
    Jan 2005
    Location
    Too far up north
    Posts
    1,566
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Internet Explorer has a Gradient Filter. But I would personally use an image for this.

  11. #11
    SitePoint Zealot
    Join Date
    Dec 2007
    Posts
    120
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

  12. #12
    I meant that to happen silver trophybronze trophy Raffles's Avatar
    Join Date
    Sep 2005
    Location
    Tanzania
    Posts
    4,662
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    IE doesn't support it.

  13. #13
    SitePoint Wizard Pepejeria's Avatar
    Join Date
    Jan 2005
    Location
    Too far up north
    Posts
    1,566
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Again, an image would be the easiest way to do this. Adding around 100 divs or using IE-only filters or SVG (that doesn't work in IE) is just a pain.

  14. #14
    Programming Since 1978 silver trophybronze trophy felgall's Avatar
    Join Date
    Sep 2005
    Location
    Sydney, NSW, Australia
    Posts
    16,799
    Mentioned
    25 Post(s)
    Tagged
    1 Thread(s)
    For a sample that uses an IE filter and SVG see http://www.felgall.com/gradient.htm

    As you can see even that method still requires quite a bit of code just to avoid using a small image.
    Stephen J Chapman

    javascriptexample.net, Book Reviews, follow me on Twitter
    HTML Help, CSS Help, JavaScript Help, PHP/mySQL Help, blog
    <input name="html5" type="text" required pattern="^$">

  15. #15
    SitePoint Wizard Pepejeria's Avatar
    Join Date
    Jan 2005
    Location
    Too far up north
    Posts
    1,566
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Cool felgall.

    One problem though, I have the IE SVG plugin installed and it gave me a dialog asking me if I wanted to accept the license agreement. It did not display anything after answering yes, it just sits there with no gradient showing up.

  16. #16
    Programming Since 1978 silver trophybronze trophy felgall's Avatar
    Join Date
    Sep 2005
    Location
    Sydney, NSW, Australia
    Posts
    16,799
    Mentioned
    25 Post(s)
    Tagged
    1 Thread(s)
    Quote Originally Posted by Pepejeria View Post
    Cool felgall.

    One problem though, I have the IE SVG plugin installed and it gave me a dialog asking me if I wanted to accept the license agreement. It did not display anything after answering yes, it just sits there with no gradient showing up.
    I guess hiding the <object> in a conditional comment testing that the browser is not IE would fix that but the code is already about 1.5 times the size of an image that produces exactly the same effect and would be even bigger with the conditional comments added.

    Unless there is a way of making significant improvements in the amount of code required it is more efficient to just use a gradient image (plus that will also work on older browsers).
    Stephen J Chapman

    javascriptexample.net, Book Reviews, follow me on Twitter
    HTML Help, CSS Help, JavaScript Help, PHP/mySQL Help, blog
    <input name="html5" type="text" required pattern="^$">


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •