Skip to content

Instantly share code, notes, and snippets.

@insidegui
Created June 6, 2011 21:35
Show Gist options
  • Save insidegui/1011179 to your computer and use it in GitHub Desktop.
Save insidegui/1011179 to your computer and use it in GitHub Desktop.
Extensões úteis para trabalhar com canvas
// frameRate padrão será 25fps
CanvasRenderingContext2D.prototype.frameRate = 1000/25
// setFrameRate(rate)
// @rate: frame rate a ser utilizado (em quadros por segundo - fps -) (ex: 30)
CanvasRenderingContext2D.prototype.setFrameRate = function(rate)
{
// transforma o frame rate passado de quadros por segundo para ms
this.frameRate = Math.round(1000/rate);
return this.frameRate;
}
// roundRect(x, y, width, height, radius)
// desenha um retângulo com cantos arredondados
// @x: posição X no canvas para desenhar o retângulo (ex: 10)
// @y: posição Y no canvas para desenhar o retângulo (ex: 10)
// @width: largura do retângulo
// @height: altura do retângulo
// @radius: quantidade de "arredondamento"
CanvasRenderingContext2D.prototype.roundRect = function(x, y, width, height, radius)
{
this.beginPath()
this.moveTo(x + radius, y)
this.lineTo(x + width - radius, y)
this.quadraticCurveTo(x + width, y, x + width, y + radius)
this.lineTo(x + width, y + height - radius)
this.quadraticCurveTo(x + width, y + height, x + width - radius, y + height)
this.lineTo(x + radius, y + height)
this.quadraticCurveTo(x, y + height, x, y + height - radius)
this.lineTo(x, y + radius)
this.quadraticCurveTo(x, y, x + radius, y)
this.closePath()
}
// size()
// retorna objeto contendo o tamanho do contexto e o centro na horizontal e na vertical (x/y)
CanvasRenderingContext2D.prototype.size = function()
{
return {
width : this.canvas.width,
height : this.canvas.height,
centerX : this.canvas.width / 2,
centerY : this.canvas.height / 2
};
}
// animatedSprite(imageFile, totalFrames, frameWidth, x, y, loop, clearAtEnd)
// anima um sprite, que deve ser uma imagem com os diferentes frames distribuídos horizontalmente, a proporção do frame deve ser de 1:1
// @imageFile: url da imagem que será utilizada como sprite animado (ex: "animation.png")
// @totalFrames: número de frames da animação (ex: 5)
// @frameWidth: largura do frame (ex: 75)
// @x: posição X no canvas para desenhar o sprite (ex: 10)
// @y: posição Y no canvas para desenhar o sprite (ex: 10)
// @loop: número de vezes para repetir a animação ou "bounce" para ir e voltar
// -1 ou true -> a animação repetirá infinitamente
// 0 ou 1 -> a animação será executada somente uma vez
// "bounce" -> quando chegar ao final, a animação irá "rebobinar" e reproduzir novamente
// @clearAtEnd: limpar o canvas quando a animação terminar (só se aplica se não houver loop)
CanvasRenderingContext2D.prototype.animatedSprite = function(imageFile, totalFrames, frameWidth, x, y, loop, clearAtEnd) {
// cria a imagem
var image = new Image()
image.setAttribute("src", imageFile)
// inicializa as variáveis
var timer = 0 // timer da animação
var currentFrame = 1 // frame atual
ctx = this // contexto do canvas
var rewind = false // define se está reproduzindo de trás pra frente
var i = 0 // contador de repetição
var imageData = ctx.getImageData(0, 0, ctx.canvas.width, ctx.canvas.height)
// renderiza um quadro da imagem
var renderFrame = function(frame)
{
// limpa o context
ctx.clearRect(x, y, frameWidth, frameWidth)
// insere o que estava "por trás" da animação primeiro
ctx.putImageData(imageData, 0, 0)
// pega o quadro atual da imagem com base no frame passado e no frameWidth e desenha no canvas
context.drawImage(image, frame*frameWidth, 0, frameWidth, frameWidth, x, y, frameWidth, frameWidth)
}
// executado quando a imagem é carregada pelo browser
image.onload = function()
{
// pega informações de tamanho do context
ctxSize = ctx.size()
// inicializa o timer da animação
timer = setInterval(function(){
// renderiza o quadro atual
renderFrame(currentFrame)
// cálculos de loop
// se não estiver rebobinando ...
if(rewind === false) {
// ... incrementa o frame atual em 1
currentFrame++
// se tiver chegado ao final da animação
if(currentFrame == totalFrames-1) {
// verifica qual o tipo de loop especificado
// se for do tipo bounce...
if(loop == "bounce") {
// ... "rebobina" a animação
rewind = true
// se não, verifica se o parametro loop é um número...
} else if(parseInt(loop) != "NaN") {
// ... se for um número, volta para o primeiro quadro da animação
currentFrame = 1
// incrementa o contador
i++
// se o parametro loop for -1 ou true, a animação repetirá infinitamente
// caso não seja...
if(loop != -1 && loop !== true) {
// ... se i for maior ou igual que o número de vezes que é para repetir...
if(i >= loop) {
// ... pára o timer da animação
clearInterval(timer)
// se for para limpar o quadro no final ...
if(clearAtEnd === true) {
// ... limpa o canvas
context.clearRect(0, 0, ctxSize.width, ctxSize.height)
// restaura imagem que estava no canvas antes da animação
ctx.putImageData(imageData, 0, 0)
}
}
}
} else {
clearInterval(timer)
}
}
}
// se estiver rebobinando...
if(rewind === true) {
// subtrai 1 do currentFrame
currentFrame--
// se o frame atual for o primeiro ...
if(currentFrame == 1) {
// ... passa a reproduzir para frente como antes
rewind = false
}
}
}, ctx.frameRate)
}
}
// checkerboard(color, size)
// preenche o canvas com um padrão checkerboard
// @color: a cor dos quadrados (opcional / default "#CCC") (ex: "red" / "#F00" / "rgba(255,0,0,1)")
// @size: o tamanho dos quadrados (opcional / default 10) (ex: 20)
CanvasRenderingContext2D.prototype.checkerboard = function(color, size)
{
if(typeof(color) == "undefined") {
color = "#CCC"
size = 10
}
x = 0
y = 0
width = this.canvas.width
height = this.canvas.height
for(var h = 0; h < (height/size); h++) {
if(h % 2 == 0) {
var increment = 0
} else {
var increment = size
}
for(var i = 0; i < (width/size); i++) {
if(i%2==0) {
var theColor = color
} else {
var theColor = "white"
}
this.fillStyle = theColor
this.fillRect(x+increment+size*i,y+size*h,size,size)
}
}
}
// fadedSphere(x,y,radius,color)
// desenha uma esfera "desbotada"
// @x: posição x onde desenhar a esfera (centro da esfera) (ex: 50)
// @y: posição y onde desenhar a esfera (centro da esfera) (ex: 50)
// @radius: raio da esfera (default 5) (ex: 10)
// @color: array com cor da esfera (default [255,255,255,0.5]) (ex: [255,0,0,1])
CanvasRenderingContext2D.prototype.fadedSphere = function(x,y,radius,color)
{
this.save()
if(typeof(radius) == "undefined") radius=5
if(typeof(color) == "undefined") color = new Array(255, 255, 255, 0.5)
var grad = this.createRadialGradient(x, y, 1, x, y, radius)
grad.addColorStop(0, this.arrayToRGBA(color))
if(color.length == 4) color.pop()
color.push(0)
grad.addColorStop(1, this.arrayToRGBA(color))
this.fillStyle = grad
this.roundRect(x-radius, y-radius, radius*2, radius*2, radius)
this.globalCompositeOperation = "lighter";
this.fill()
this.restore()
}
// arrayToRGBA(colorArray)
// transforma um array em cor no formato rgba para ser usada em fillStyle, strokeStyle ou gradientes
// @colorArray: array contendo as cores r,g,b e (opcionalmente) a.
// EXEMPLOS:
// var color = new Array(123,200,129)
// ctx.arrayToRGBA(color) // retornará "rgba(123,200,129,1)"
//
// var color = new Array(100,0,100, 0.5)
// ctx.arrayToRGBA(color) // retornará "rgba(100,0,100, 0.5)"
CanvasRenderingContext2D.prototype.arrayToRGBA = function(colorArray)
{
var output = "rgba("
output += colorArray[0]
output += ","+colorArray[1]
output += ","+colorArray[2]
if(colorArray.length == 3) {
output += ",1)"
} else {
output += ","+colorArray[3]+")"
}
return output
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment