well, this time I'd like to write about a nice class implemented using mootools libraries used to paint shadows around blocks. His name is mooCanvasShadow, written by Arian Stolwijk, and here the link to the project. This class uses the mooCanvas class of ibolmo's.
When I used this class for some projects I encountered some difficulties and some strange behavioures, so I tried to reniew this class which was shared under the MIT license. There was a problem when applying a shadow to a container div which was centered in the page when resizing the browser window. The problem was that while resizing the browser window the container centered is moved in order to keep the centered position, but the canvas area painted in order to get the shadow was static and positioned absolute relative to the body, so couldn't follow the container in motion. The solution is to paint the canvas area relative to the container we want to apply shadows to (changes made to the method createCanvasDiv). This way if it moves than the canvas follows it.
Another adjustment was made in a regular expression matching colors, it didn't consider not capital letters and so always put the default color if you write colors codes this way: #ffffff (like me).
Above the major things, now the code:
//AbiCanvasShadow, Mootools Canvas Dropshadow Abidibo extended
/*
Script: CanvasShadow.js
Contains the Canvas class.
Dependencies:
MooTools, <http: mootools.net="">
Element, and its dependencies
Element.Dimensions
MooCanvas, <http: ibolmo.com="" moocanvas="" projects="">
Canvas,
Paths
Author:
Arian Stolwijk, <http: www.aryweb.nl="">
Adjusted by
Abidibo, <http: abidibo.otto.to.it="">
License:
MIT License, <http: en.wikipedia.org="" mit_license="" wiki="">
*/
var AbiCanvasShadow = new Class({
/**
* This function creates a new canvas element of MooCanvas
* The elements will be placed at the right position, so the
* canvas element is right behind the to-shadow element
*
* @param {Object} shadowDiv this div will get a shadow
* @param {Object} options the options:
* size: The size of the shadow
* radius: the radius of the shadow corners
* opacity: The opacity of the shadow
* color: The shadow color, this should be like #FF9900,
* or an array with the rgb colors [255,0,255]
* overwrite: if the canvas element already exists,
* it wil dispose that element and create a new one
*/
initialize: function(shadowDiv,options){
// Set shadow div
this.shadowDiv = shadowDiv;
// Get the coordinates of the element
this.position = shadowDiv.getCoordinates();
// Set some options
this.size = options.size;
var radius = options.radius;
var opacity = options.opacity;
if($(shadowDiv.get('id')) == false){
this.giveId(shadowDiv);
}
// Dispose the already existing element, if needed
if ($type(options.overwrite) == 'boolean' && options.overwrite == true) {
if ($type($(shadowDiv.get('id') + '_mooShadow')) == 'element') {
$(shadowDiv.get('id') + '_mooShadow').dispose();
}
}
// Create a new Canvas object, of MooCanvas
this.canvas = new Canvas({
'width': this.position.width + (this.size * 2),
'height': this.position.height + (this.size * 2),
'id': shadowDiv.get('id')+'_mooShadow'
});
// Create a div and put the canvas element in it to set it at the right position
this.createCanvasDiv();
// Create the context
var ctx = this.canvas.getContext("2d");
// Create the shadow color
if(options.color.test(/#[0-9A-Za-z]{6}|[0-9A-Za-z]{3}/)){
options.color = options.color.hexToRgb(true);
}
if($type(options.color) == 'array' && $type(options.color[2]) != 'undefined'){
var color = options.color[0]+','+options.color[1]+','+options.color[2];
}else{
var color = '0,0,0';
}
// Create the retangles/ the actual shadow
for (var i = this.size; i >= 0; i--) {
this.roundedRect(ctx,
i,
i,
(this.position.width-(i*2)+2*this.size),
(this.position.height-(2*i)+2*this.size),
radius
);
ctx.fillStyle = "rgba("+color+", "+opacity/(this.size-i)+")";
ctx.fill();
}
},
/**
* This function creates a div where the canvas element is in inserted
* This element will position behind the to-shadow div
*/
createCanvasDiv: function(){
this.canvasDiv = new Element('div',{
styles:{
'width': this.position.width+(this.size*2),
'height': this.position.height+(this.size*2),
'z-index': -1,
'position': 'absolute',
'left': '-'+this.size+'px',
'top': '-'+this.size+'px'
}
}).adopt(this.canvas).inject(this.shadowDiv);
},
/**
* This method creates a rounded rectangle
* @param {Object} ctx the canvas context
* @param {Object} x the upper left x-axis position
* @param {Object} y the upper left y-axis positoin
* @param {Object} width the retangle width
* @param {Object} height the retangle height
* @param {Object} radius the corner radius
*/
roundedRect: function (ctx,x,y,width,height,radius){
ctx.beginPath();
ctx.moveTo(x,y+radius);
ctx.lineTo(x,y+height-radius);
ctx.quadraticCurveTo(x,y+height,x+radius,y+height);
ctx.lineTo(x+width-radius,y+height);
ctx.quadraticCurveTo(x+width,y+height,x+width,y+height-radius);
ctx.lineTo(x+width,y+radius);
ctx.quadraticCurveTo(x+width,y,x+width-radius,y);
ctx.lineTo(x+radius,y);
ctx.quadraticCurveTo(x,y,x,y+radius);
},
/**
* This method set an random ID to an element
* @param {Object} div
*/
giveId: function(div){
div.set('id',$rand()+'_mooShadow');
}
});
/**
*
* @param {Object} options: the same options as the mooCanvasShadow() class
*/
Element.implement({
AbiCanvasShadow: function (options){
new AbiCanvasShadow(this,options);
return this;
}
});
/*
Script: CanvasShadow.js
Contains the Canvas class.
Dependencies:
MooTools, <http: mootools.net="">
Element, and its dependencies
Element.Dimensions
MooCanvas, <http: ibolmo.com="" moocanvas="" projects="">
Canvas,
Paths
Author:
Arian Stolwijk, <http: www.aryweb.nl="">
Adjusted by
Abidibo, <http: abidibo.otto.to.it="">
License:
MIT License, <http: en.wikipedia.org="" mit_license="" wiki="">
*/
var AbiCanvasShadow = new Class({
/**
* This function creates a new canvas element of MooCanvas
* The elements will be placed at the right position, so the
* canvas element is right behind the to-shadow element
*
* @param {Object} shadowDiv this div will get a shadow
* @param {Object} options the options:
* size: The size of the shadow
* radius: the radius of the shadow corners
* opacity: The opacity of the shadow
* color: The shadow color, this should be like #FF9900,
* or an array with the rgb colors [255,0,255]
* overwrite: if the canvas element already exists,
* it wil dispose that element and create a new one
*/
initialize: function(shadowDiv,options){
// Set shadow div
this.shadowDiv = shadowDiv;
// Get the coordinates of the element
this.position = shadowDiv.getCoordinates();
// Set some options
this.size = options.size;
var radius = options.radius;
var opacity = options.opacity;
if($(shadowDiv.get('id')) == false){
this.giveId(shadowDiv);
}
// Dispose the already existing element, if needed
if ($type(options.overwrite) == 'boolean' && options.overwrite == true) {
if ($type($(shadowDiv.get('id') + '_mooShadow')) == 'element') {
$(shadowDiv.get('id') + '_mooShadow').dispose();
}
}
// Create a new Canvas object, of MooCanvas
this.canvas = new Canvas({
'width': this.position.width + (this.size * 2),
'height': this.position.height + (this.size * 2),
'id': shadowDiv.get('id')+'_mooShadow'
});
// Create a div and put the canvas element in it to set it at the right position
this.createCanvasDiv();
// Create the context
var ctx = this.canvas.getContext("2d");
// Create the shadow color
if(options.color.test(/#[0-9A-Za-z]{6}|[0-9A-Za-z]{3}/)){
options.color = options.color.hexToRgb(true);
}
if($type(options.color) == 'array' && $type(options.color[2]) != 'undefined'){
var color = options.color[0]+','+options.color[1]+','+options.color[2];
}else{
var color = '0,0,0';
}
// Create the retangles/ the actual shadow
for (var i = this.size; i >= 0; i--) {
this.roundedRect(ctx,
i,
i,
(this.position.width-(i*2)+2*this.size),
(this.position.height-(2*i)+2*this.size),
radius
);
ctx.fillStyle = "rgba("+color+", "+opacity/(this.size-i)+")";
ctx.fill();
}
},
/**
* This function creates a div where the canvas element is in inserted
* This element will position behind the to-shadow div
*/
createCanvasDiv: function(){
this.canvasDiv = new Element('div',{
styles:{
'width': this.position.width+(this.size*2),
'height': this.position.height+(this.size*2),
'z-index': -1,
'position': 'absolute',
'left': '-'+this.size+'px',
'top': '-'+this.size+'px'
}
}).adopt(this.canvas).inject(this.shadowDiv);
},
/**
* This method creates a rounded rectangle
* @param {Object} ctx the canvas context
* @param {Object} x the upper left x-axis position
* @param {Object} y the upper left y-axis positoin
* @param {Object} width the retangle width
* @param {Object} height the retangle height
* @param {Object} radius the corner radius
*/
roundedRect: function (ctx,x,y,width,height,radius){
ctx.beginPath();
ctx.moveTo(x,y+radius);
ctx.lineTo(x,y+height-radius);
ctx.quadraticCurveTo(x,y+height,x+radius,y+height);
ctx.lineTo(x+width-radius,y+height);
ctx.quadraticCurveTo(x+width,y+height,x+width,y+height-radius);
ctx.lineTo(x+width,y+radius);
ctx.quadraticCurveTo(x+width,y,x+width-radius,y);
ctx.lineTo(x+radius,y);
ctx.quadraticCurveTo(x,y,x,y+radius);
},
/**
* This method set an random ID to an element
* @param {Object} div
*/
giveId: function(div){
div.set('id',$rand()+'_mooShadow');
}
});
/**
*
* @param {Object} options: the same options as the mooCanvasShadow() class
*/
Element.implement({
AbiCanvasShadow: function (options){
new AbiCanvasShadow(this,options);
return this;
}
});
and how to use it:
window.addEvent('domready',function(){
// 'mainContainer' is the ID of the element
$('mainContainer').AbiCanvasShadow({
opacity: 0.2,
size: 14,
radius: 10,
color: '#333333'
});
}.delay(800));
// 'mainContainer' is the ID of the element
$('mainContainer').AbiCanvasShadow({
opacity: 0.2,
size: 14,
radius: 10,
color: '#333333'
});
}.delay(800));
The html structure must be this way:
<div id="mainContainer">
<div id="container">
your site, your content
</div>
</div>
<div id="container">
your site, your content
</div>
</div>
that because of... guess it? IE. Si seƱores, another self behaviour for IE7 and IE6 and I don't know if IE8 too. Whit these horrible browsers using only one container causes the below canvas area to affect the background of the element even if a color was setted. So some points:
- Use two container and apply the effect to the outer
- Very important: set the position property of mainContainer as relative, that because the canvas is positioned absolute relative to it
- Set the width of 'mainContainer' equal to the width of 'container'
- Set a background color for 'container'
- Pay attention if using padding or margins, that is properties affecting the position of the element
window.onload = function ()...
but in this case the interval between the appearence of the element and its shadow is grater, especially if the element contains iframe or heavy elements.That's all guys, hasta la proxima!
No comments:
Post a Comment