Como os anticipe, al final de mi página canvas
, tenía que hacer esta página, combinándo la etiqueta canvas, con animaciones implementadas, con un poco de javascript
, ya que esta es una de las principales virtudes del elemento canvas.
Ejemplos de canvas animados de este sitio
que os voy a ir mostrándo en contenedores de código, que he construido, como un web component
, en los que podeís exáminar todo el código del ejemplo y la propia demo.
Para este canvas se emplean los eventos mousemove
y mouseout
, ya sabeís, similar al :hover
, de CSS.
<body style="margin: 0;">
<canvas id="canvas"></canvas>
</body>
var canvas = document.getElementById("canvas");
var c = canvas.getContext("2d");
var radius = 15;
function drawCircle(mouseX, mouseY){
// Resize to the screen
if(canvas.width != window.innerWidth || canvas.width != window.innerWidth){
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
// Limpia el background
c.clearRect(0, 0, canvas.width, canvas.height);
// Dibuja el circulo
c.beginPath();
c.arc(mouseX, mouseY, radius, 0 , 2 * Math.PI, false);
// Relleno del circulo
c.fillStyle = '#00F0FF';
c.fill();
// Borde (stroke) del circulo
c.lineWidth = 2;
c.strokeStyle = 'black';
c.stroke();
}
// función que va redibujando el circulo al movimiento del ratón (cursor)
canvas.addEventListener('mousemove',function(e){
drawCircle(e.clientX, e.clientY);
});
// Limpia el canvas cuando el ratón sale del canvas
canvas.addEventListener('mouseout',function(e){
c.clearRect(0, 0, canvas.width, canvas.height);
});
// Dibuja un circulo en el centro inicialmente
drawCircle(canvas.width / 2, canvas.height / 2);
<body>
<canvas id="canvas"></canvas>
<script src="../js/requestAnimFrame.js"></script>
</body>
var canvas = document.getElementById("canvas");
var c = canvas.getContext("2d");
var radius = 32;
var lineWidth = 4;
var gravity = 0.1;
var dampening = 0.995;
var mousePullStrength = 0.005;
var animate = false;
var mouse = {
x : 0,
y : 0,
down: false
};
var circle = {
x : canvas.width/2,
y : canvas.height/2,
vx: 0, // 'v' stands for 'velocity'
vy: 0
};
function executeFrame(){
if(animate)
requestAnimFrame(executeFrame);
incrementSimulation();
c.clearRect(0, 0, canvas.width, canvas.height);
drawBox();
drawCircle();
if(mouse.down)
drawLineToMouse();
}
function incrementSimulation(){
// Pull the circle toward the mouse
if(mouse.down){
var dx = mouse.x - circle.x,
dy = mouse.y - circle.y,
distance = Math.sqrt(dx*dx + dy*dy),
unitX = dx / distance,
unitY = dy / distance,
force = distance * mousePullStrength;
circle.vx += unitX * force;
circle.vy += unitY * force;
}
// Execute gravity
circle.vy += gravity;
// Execute dampening (slowing down)
circle.vx *= dampening;
circle.vy *= dampening;
// Increment the position by the velocity
circle.x += circle.vx;
circle.y += circle.vy;
// Bounce off the floor
if(circle.y + radius > canvas.height){
circle.y = canvas.height - radius;
circle.vy = - Math.abs(circle.vy);
}
// Bounce off the ceiling
else if(circle.y - radius < 0){
circle.y = radius;
circle.vy = Math.abs(circle.vy);
}
// Bounce off the right wall
if(circle.x + radius > canvas.width){
circle.x = canvas.width - radius;
circle.vx = - Math.abs(circle.vx);
}
// Bounce off the left wall
else if(circle.x - radius < 0){
circle.x = radius;
circle.vx = Math.abs(circle.vx);
}
}
function drawBox(){
// Resize to the screen
if(canvas.width != window.innerWidth || canvas.width != window.innerWidth){
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
c.lineWidth = 1;
c.strokeRect(0.5, 0.5, canvas.width - 1, canvas.height - 1);
}
function drawCircle(){
c.beginPath();
c.arc(circle.x, circle.y, radius - lineWidth/2, 0 , 2 * Math.PI, false);
c.fillStyle = '00F0FF';
c.fill();
c.lineWidth = 4;
c.strokeStyle = 'black';
c.stroke();
}
function drawLineToMouse(){
c.lineWidth = 2;
c.moveTo(circle.x, circle.y);
c.lineTo(mouse.x, mouse.y);
c.stroke();
}
canvas.addEventListener('mousedown',function(e){
mouse.down = true;
mouse.x = e.pageX;
mouse.y = e.pageY;
});
canvas.addEventListener('mousemove', function(e){
mouse.x = e.pageX;
mouse.y = e.pageY;
});
canvas.addEventListener('mouseup', function(e){
mouse.down = false;
});
// Start animating when the mouse enters the canvas
canvas.addEventListener('mouseover', function(e){
animate = true;
executeFrame();
});
// Stop animating when the mouse exits the canvas
canvas.addEventListener('mouseout', function(e){
mouse.down = false;
animate = false;
});
// Draw the initial scene once, so something
// is displayed before animation starts.
executeFrame();
<body>
<canvas id="canvas"></canvas>
<script src="../js/requestAnimFrame.js"></script>
</body>
var canvas = document.getElementById("canvas");
var c = canvas.getContext("2d");
var gravity = 0.1;
var radius = 20;
var numCircles = 10;
var dampeningFactor = 0.99;
var circles = [];
var i, j, circle, circle2;
var mouse = {
x: 0,
y: 0,
down: false
};
var circleUnderMouse;
var ballMouseY, ballMouseX, pullForceY, pullForceX;
var r, g, b;
var animate = false;
initializeCircles();
function executeFrame(){
if(animate)
requestAnimFrame(executeFrame);
iterateSimulation();
c.fillStyle = 'rgba(255,255,255,0.3)';
c.fillRect(0,0,canvas.width,canvas.height);
drawCircles();
}
function initializeCircles(){
circles = [];
for(i = 0; i < numCircles; i++){
circle = {
x: Math.random() * canvas.width,
y: Math.random() * canvas.height,
velocity:{x:0, y:0}
};
circles.push(circle);
}
}
function drawCircles(){
// Resize to the screen
if(canvas.width != window.innerWidth || canvas.width != window.innerWidth){
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
initializeCircles();
iterateSimulation();
}
// draw rectangle border
c.lineWidth = "3";
c.strokeRect(0,0,canvas.width,canvas.height);
// draw circles
for(i = 0; i < numCircles; i++){
circle = circles[i];
r = i*5;
g = i*10;
b = i*15;
// draw connecting line from ball to mouse
if(circle == circleUnderMouse){
c.beginPath();
c.moveTo(circle.x, circle.y);
c.lineTo(mouse.x, mouse.y);
c.lineWidth = "2";
c.strokeStyle="black";
c.stroke();
}
c.beginPath();
c.arc(circle.x, circle.y, radius, 0, 2 * Math.PI);
if(circle == circleUnderMouse){
c.fillStyle = "C1FF24";
c.lineWidth = "5";
c.stroke();
}
else{
c.fillStyle = 'rgb('+r+', '+g+', '+b+')';
}
c.fill();
}
}
function iterateSimulation(){
for(i = 0; i < numCircles; i++){
circle = circles[i];
// pull ball to mouse
pullBallToMouse();
// Add gravity
circle.velocity.y += gravity;
// slows things down
circle.velocity.x *= dampeningFactor;
circle.velocity.y *= dampeningFactor;
// Add velocity to position
circle.x += circle.velocity.x;
circle.y += circle.velocity.y;
// Make them bounce off the floor
if(circle.y > canvas.height - radius){
circle.y = canvas.height - radius;
circle.velocity.y = - Math.abs(circle.velocity.y);
} // bounce off ceiling
if(circle.y < radius){
circle.y = radius;
circle.velocity.y = Math.abs(circle.velocity.y);
} // bounce off right wall
if(circle.x > canvas.width - radius){
circle.x = canvas.width - radius;
circle.velocity.x = -Math.abs(circle.velocity.x);
} // bounce off left wall
if(circle.x < radius){
circle.x = radius;
circle.velocity.x = Math.abs(circle.velocity.x);
}
// REPULSION between circles
for(j = i + 1; j < numCircles; j++){
circle2 = circles[j];
var dx = circle2.x - circle.x;
var dy = circle2.y - circle.y;
var d = Math.sqrt(dx*dx + dy*dy);
if(d < 2*radius){
if(d === 0){
d = 0.1;
}
var unitX = dx/d;
var unitY = dy/d;
var force = -2;
var forceX = unitX * force;
var forceY = unitY * force;
circle.velocity.x += forceX;
circle.velocity.y += forceY;
circle2.velocity.x -= forceX;
circle2.velocity.y -= forceY;
}
}
}
}
function pullBallToMouse(){
if(circle == circleUnderMouse){
ballMouseY = mouse.y - circle.y;
ballMouseX = mouse.x - circle.x;
pullForceY = ballMouseY * 0.02;
pullForceX = ballMouseX * 0.02;
circle.velocity.y += pullForceY;
circle.velocity.x += pullForceX;
}
}
canvas.addEventListener("mousemove", function(e){
mouse.x = e.x;
mouse.y = e.y;
});
canvas.addEventListener("mousedown", function(e){
mouse.down = true;
mouse.x = e.x;
mouse.y = e.y;
for(i = 0; i < circles.length; i++){
var circle = circles[i]; // get circle out of array
var dx = mouse.x - circle.x;
var dy = mouse.y - circle.y;
var d = Math.sqrt(dx*dx + dy*dy);
if(d < radius){
circleUnderMouse = circle;
break; // break (stop) the for loop
}
}
});
canvas.addEventListener("mouseup", function(e){
mouse.down = false;
circleUnderMouse = null;
});
canvas.addEventListener("mouseout", function(e){
mouse.down = false;
circleUnderMouse = null;
});
// Kick off the animation when the mouse enters the canvas
canvas.addEventListener('mouseover', function(e){
animate = true;
executeFrame();
});
// Pause animation when the mouse exits the canvas
canvas.addEventListener("mouseout",function(e){
animate = false;
});
// Draw the first frame to start animation
executeFrame();
<body>
<canvas id="canvas" width="300" height="300"></canvas>
</body>
var canvas = document.getElementById("canvas");
var c = canvas.getContext("2d");
var centerX = canvas.width / 2;
var trunkHeight = 100;
var branchLengthRatio = 0.75;
var branchAngleDifference = 0.27;
var branchingDepth = 10;
function drawTree(x1, y1, x2, y2, branchLength,
branchAngle, depth){
if(depth == 0)
return;
else{
c.beginPath();
c.moveTo(x1, y1);
c.lineTo(x2, y2);
c.closePath();
c.stroke();
branchLength *= branchLengthRatio;
function branch(angle){
var branchX2 = x2 + branchLength * Math.cos(angle);
var branchY2 = y2 + branchLength * Math.sin(angle);
drawTree(x2, y2, branchX2, branchY2, branchLength,
angle, depth - 1);
}
// Right branch
branch(branchAngle + branchAngleDifference);
// Left branch
branch(branchAngle - branchAngleDifference);
}
}
function redrawTree(){
c.clearRect(0,0, canvas.width, canvas.height);
var x1 = centerX;
var y1 = canvas.height;
var x2 = centerX;
var y2 = canvas.height - trunkHeight;
drawTree(x1, y1, x2, y2, trunkHeight,
- Math.PI / 2, branchingDepth);
}
canvas.addEventListener("mousemove",function(e){
branchLengthRatio = e.x / 300;
branchAngleDifference = e.y / canvas.height * Math.PI;
redrawTree();
console.log("branchLengthRatio = "+branchLengthRatio);
console.log("branchAngleDifference = "+branchAngleDifference);
});
redrawTree();
<body>
<canvas id="canvas"></canvas>
<button type="button" class="btn" id="fullscr">Go Fullscreen</button>
<script src="../js/requestAnimFrame.js"></script>
<script src="../js/fullscreen.js"></script>
</body>
#canvas {
width: 100%;
height: 100%;
}
.btn {
position: fixed;
bottom: 5%;
right: 0px;
transform: translateX(-50%);
border: 1px solid #000;
border-radius: 5px;
font-size: 0.9rem;
padding: 0.5rem 0.7em;
background-color: transparent;
color: #ffffff;
font-family: Verdana, Geneva, Tahoma, sans-serif;
-webkit-font-smoothing: antialiased;
cursor: pointer;
transition: all .3s;
z-index: 100;
}
.btn:hover {background: #1B1734; color: #ffffff;}
var canvas = document.getElementById("canvas");
var c = canvas.getContext("2d");
var numStars = 1000;
var radius = 1;
var focalLength = canvas.width;
var centerX, centerY;
var stars = [], star;
var i;
var animate = false;
initializeStars();
function executeFrame(){
if(animate)
requestAnimFrame(executeFrame);
moveStars();
drawStars();
}
function initializeStars(){
centerX = canvas.width / 2;
centerY = canvas.height / 2;
stars = [];
for(i = 0; i < numStars; i++){
star = {
x: Math.random() * canvas.width,
y: Math.random() * canvas.height,
z: Math.random() * canvas.width
};
stars.push(star);
}
}
function moveStars(){
for(i = 0; i < numStars; i++){
star = stars[i];
star.z--;
if(star.z <= 0){
star.z = canvas.width;
}
}
}
function drawStars(){
var pixelX, pixelY, pixelRadius;
// Condición para cuando se redimensione la ventana
if(canvas.width != window.innerWidth || canvas.height != window.innerHeight){
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
initializeStars();
}
c.fillStyle = "black";
c.fillRect(0,0, canvas.width, canvas.height);
c.fillStyle = "white";
for(i = 0; i < numStars; i++){
star = stars[i];
pixelX = (star.x - centerX) * (focalLength / star.z);
pixelX += centerX;
pixelY = (star.y - centerY) * (focalLength / star.z);
pixelY += centerY;
pixelRadius = radius * (focalLength / star.z);
c.beginPath();
c.arc(pixelX, pixelY, pixelRadius, 0, 2 * Math.PI);
c.fill();
}
}
canvas.addEventListener("mousemove",function(e){
focalLength = e.x;
});
// Animación cuando el ratón entre en el canvas
canvas.addEventListener('mouseover', function(e){
animate = true;
executeFrame();
});
// Para la animación cuando el ratón sale del canvas
canvas.addEventListener("mouseout",function(e){
// mouseDown = false;
animate = false;
});
// Dibuja el primer frame y comienza la animación
executeFrame();
Este simulador de ondas esta basado ecuación de onda
<body>
<canvas id="canvas"></canvas>
<script src="../js/requestAnimFrame.js"></script>
</body>
var canvas = document.getElementById("canvas");
var c = canvas.getContext("2d");
var pullStrength = 0.01;
var dampeningFactor = 0.99;
var initialHeight = 0.5;
var cells = [];
var gridSize = 100;
var conservationOfMassCorrection = 0;
var cellWidth = 1 / (gridSize-1) * canvas.width;
var mouseX, mouseY, mouseDown;
var animate = false;
// This function executes once per animation frame
function executeFrame(){
if(animate)
requestAnimFrame(executeFrame);
clearCanvas();
drawCells();
iterateSimulation();
executeMouseInteraction();
}
// Initialize the water height
for(var i = 0; i < gridSize; i++){
cells.push({
// for a still initial surface
//height: 0.5,
// for an initial wave:
height: i === Math.floor(gridSize*1/4) ? 1 : initialHeight,
velocity: 0
});
}
function clearCanvas(){
// resizes to full screen
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
cellWidth = 1 / (gridSize-1) * canvas.width;
}
function drawCells(){
c.beginPath();
c.moveTo(canvas.width, canvas.height);
c.lineTo(0, canvas.height);
for(var i = 0; i < gridSize; i++){
var cell = cells[i];
var x = i / (gridSize-1) * canvas.width;
var y = canvas.height - cell.height * canvas.height;
c.lineTo(x,y);
}
c.closePath();
c.fill();
}
// Increment the wave simulation:
// Neighboring cells pull on one another.
function iterateSimulation(){
var avgHeight = 0;
for(var i = 0; i < gridSize; i++){
// center cell
var c = cells[i];
// left neighbor
var l = cells[((i - 1) + gridSize) % gridSize];
// right neighbor
var r = cells[(i + 1) % gridSize];
// pull toward neighbors
c.velocity += pullStrength * (l.height - c.height);
c.velocity += pullStrength * (r.height - c.height);
// increment velocity
c.height += c.velocity;
// ensure conservation of mass
c.height += conservationOfMassCorrection;
// apply dampening
c.velocity *= dampeningFactor;
avgHeight += c.height;
}
avgHeight /= (gridSize - 1);
conservationOfMassCorrection = initialHeight - avgHeight;
}
// Pull the wave cell closest to the mouse
function executeMouseInteraction(){
if(mouseDown){
for(var i = 0; i < gridSize; i++){
var x = i / (gridSize-1) * canvas.width;
if(Math.abs(x - mouseX) < cellWidth){
var cell = cells[i];
cell.height = 1 - mouseY/canvas.height;
cell.velocity = 0;
}
}
}
}
// Record when the mouse is pressed
canvas.addEventListener("mousedown",function(e){
mouseDown = true;
mouseX = e.clientX;
mouseY = e.clientY;
});
// Record when the mouse is moved
canvas.addEventListener("mousemove",function(e){
mouseX = e.clientX;
mouseY = e.clientY;
});
// Record when the mouse is released
canvas.addEventListener("mouseup",function(e){
mouseDown = false;
});
// Kick off the animation when the mouse enters the canvas
canvas.addEventListener('mouseover', function(e){
animate = true;
executeFrame();
});
// Pause animation when the mouse exits the canvas
canvas.addEventListener("mouseout",function(e){
mouseDown = false;
animate = false;
});
// Draw the first frame
executeFrame();
Este simulador de ondas esta basado ecuación de onda
<body>
<canvas id="canvas"></canvas>
<script src="../js/requestAnimFrame.js"></script>
</body>
var canvas = document.getElementById("canvas");
var c = canvas.getContext("2d");
var pullStrength = 0.005;
var dampeningFactor = 0.98;
var initialHeight = 0.5;
var cells = [];
var gridSize = 50;
var conservationOfMassCorrection = 0;
var cellWidth = 1 / (gridSize-1) * canvas.width;
var cellHeight = 1 / (gridSize-1) * canvas.height;
var mouseX, mouseY, mouseDown;
var animate = false;
function executeFrame(){
if(animate)
requestAnimFrame(executeFrame);
clearCanvas();
drawCells();
iterateSimulation();
executeMouseInteraction();
};
// Store the color strings as an object re-use optimization.
// (otherwise new string objects would be created for each color each frame)
var grayStrings = [];
for(var gray = 0;gray < 255; gray++){
// this transforms strings from 'rgb(255,190,201)' to '#FF564B'
c.fillStyle = 'rgb('+gray+','+gray+','+gray+')';
// store the colors of the form '#FF564B'
grayStrings.push(c.fillStyle);
}
for(var i = 0; i < gridSize; i++){
for(var j = 0; j < gridSize; j++){
// Raise a single cell so the simulation is
// initialized with something that looks interesting
var isRaisedCell = false;
if(i === Math.floor(gridSize*1/4))
if(j === Math.floor(gridSize*1/4))
isRaisedCell = true;
cells.push({
// for a still initial surface
//height: 0.5,
// for an initial wave:
height: isRaisedCell ? 4 : initialHeight,
velocity: 0
});
}
}
function clearCanvas(){
// resizes to full screen
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
cellWidth = 1 / (gridSize-1) * canvas.width;
cellHeight = 1 / (gridSize-1) * canvas.height;
}
function drawCells(){
for(var i = 0; i < gridSize; i++){
for(var j = 0; j < gridSize; j++){
var cell = cells[i + j * gridSize];
var x = i / (gridSize-1) * canvas.width;
var y = j / (gridSize-1) * canvas.height;
var gray = Math.floor(cell.height * 255);
gray = gray > 255 ? 255 : gray < 0 ? 0 : gray;
// This commented method of defining the colors
// would create lots of new String objects.
// Better to re-use existing objects so that
// no memory is allocated/released each frame.
//c.fillStyle = 'rgb('+gray+','+gray+','+gray+')';
c.fillStyle = grayStrings[gray];
c.fillRect(x,y,cellWidth+1,cellHeight+1);
}
}
}
function iterateSimulation(){
var avgHeight = 0;
for(var i = 0; i < gridSize; i++){
for(var j = 0; j < gridSize; j++){
// center cell
var c = cells[i + j * gridSize];
for(var di = -1; di <= 1; di++){
for(var dj = -1; dj <= 1; dj++){
if(di !== 0 || dj !== 0){
var ni = ((i + di) + gridSize) % gridSize;
var nj = ((j + dj) + gridSize) % gridSize;
var neighbor = cells[ni + nj * gridSize];
// pull toward neighbors
c.velocity += pullStrength * (neighbor.height - c.height);
}
}
}
// increment velocity
c.height += c.velocity;
// ensure conservation of mass
c.height += conservationOfMassCorrection;
// apply dampening
c.velocity *= dampeningFactor;
avgHeight += c.height;
}
}
avgHeight /= Math.pow(gridSize - 1,2);
conservationOfMassCorrection = initialHeight - avgHeight;
}
function executeMouseInteraction(){
if(mouseDown){
var i = Math.floor((gridSize-1) * mouseX / canvas.width);
var j = Math.floor((gridSize-1) * mouseY / canvas.height);
var cell = cells[i + j * gridSize];
cell.height = 2;
cell.velocity = 0;
}
}
canvas.addEventListener("mousedown",function(e){
mouseDown = true;
mouseX = e.offsetX;
mouseY = e.offsetY;
});
canvas.addEventListener("mousemove",function(e){
mouseX = e.offsetX;
mouseY = e.offsetY;
});
canvas.addEventListener("mouseup",function(e){
mouseDown = false;
});
// Kick off the animation when the mouse enters the canvas
canvas.addEventListener('mouseover', function(e){
animate = true;
executeFrame();
});
// Pause animation when the mouse exits the canvas
canvas.addEventListener("mouseout",function(e){
mouseDown = false;
animate = false;
});
// Iterate the simulation a couple of times
// so the program shows something before animation starts.
for(var i = 0; i < 7; i++)
iterateSimulation();
// Draw the first frame
executeFrame();
<body>
<canvas id="canvas"></canvas>
<script src="../js/requestAnimFrame.js"></script>
</body>
var canvas = document.getElementById('canvas');
var c = canvas.getContext('2d');
canvas.width = innerWidth;
canvas.height = innerHeight;
c.fillRect(0,0,canvas.width, canvas.height);
var paintColors = {};
var mouseId = 'mouse';
var mouseDown = false;
function addMouseListeners(){
canvas.addEventListener('mousemove', function(e){
if(mouseDown){
c.fillStyle = paintColors[mouseId];
drawCircle(e.clientX, e.clientY);
}
});
canvas.addEventListener('mousedown', function(e){
mouseDown = true;
setRandomPaintColor(mouseId);
});
canvas.addEventListener('mouseup', function(e){
mouseDown = false;
});
canvas.addEventListener('dblclick', function(e){
c.fillStyle = 'black';
c.fillRect(0,0,canvas.width, canvas.height);
});
}
function setRandomPaintColor(id){
function rand255(){ return Math.floor(Math.random()*255);}
paintColors[id] = 'rgb('+rand255()+','+rand255()+','+rand255()+')';
}
function drawCircle(x, y){
c.beginPath();
c.arc(x, y, 3, 0, 2 * Math.PI);
c.fill();
}
function addMultiTouchListeners(){
canvas.addEventListener('touchmove',function(e){
var i, touch;
setRandomPaintColor();
for(i = 0; i < e.targetTouches.length; i++){
touch = e.targetTouches[i];
c.fillStyle = paintColors[touch.identifier];
drawCircle(touch.pageX, touch.pageY);
}
});
canvas.addEventListener('touchstart',function(e){
var i, touch;
for(i = 0; i < e.changedTouches.length; i++){
touch = e.changedTouches[i];
setRandomPaintColor(touch.identifier);
}
});
canvas.addEventListener('touchend',function(e){
var i, touch;
for(i = 0; i < e.changedTouches.length; i++){
touch = e.changedTouches[i];
console.log("removing "+touch.identifier);
delete paintColors[touch.identifier];
}
});
}
// prevent scrolling
document.body.addEventListener('touchmove', function(event) {
event.preventDefault();
}, false);
addMouseListeners();
addMultiTouchListeners();
Si has llegado hasta aquí, y has leido el código de los ejemplos que he mostrado, observarás que para trabajar con canvas, hay que aprender javascript
, los eventos
, los diferentes métodos para manejar y controlar el ancho (width)
y el alto (height), tanto de la ventana (window), como de los elementos html
, en nuestro caso canvas.