I'm trying to use the clip() function in canvas to create this effect, as pictured: there is a background image, and when your mouse hover on it, part of the image is shown. I got it to work as a circle, but I want this gradient effect you see the picture. How do I achieve that?
<!DOCTYPE HTML>
<html>
<head>
<link rel="stylesheet" type="text/css" href="./assets/stylesheet/normalize.css">
<link rel="stylesheet" type="text/css" href="./assets/stylesheet/style.css">
</head>
<body>
<canvas id="canvas" width="2000" height="1200"></canvas>
<script>
var can = document.getElementById('canvas');
var ctx = can.getContext('2d');
can.addEventListener('mousemove', function(e) {
var mouse = getMouse(e, can);
redraw(mouse);
}, false);
function redraw(mouse) {
console.log('a');
can.width = can.width;
ctx.canvas.width = window.innerWidth;
ctx.canvas.height = window.innerHeight;
ctx.drawImage(img, 0, 0);
ctx.beginPath();
ctx.rect(0,0,2000,1200);
ctx.arc(mouse.x, mouse.y, 200, 0, Math.PI*2, true)
ctx.clip();
ctx.fillRect(0,0,2000,1200);
}
var img = new Image();
img.onload = function() {
redraw({x: 0, y: 0})
}
img.src = 'http://placekitten.com/2000/1000';
function getMouse(e, canvas) {
var element = canvas,
offsetX = 0,
offsetY = 0,
mx, my;
// Compute the total offset. It's possible to cache this if you want
if (element.offsetParent !== undefined) {
do {
offsetX += element.offsetLeft;
offsetY += element.offsetTop;
} while ((element = element.offsetParent));
}
mx = e.pageX - offsetX;
my = e.pageY - offsetY;
return {
x: mx,
y: my
};
}
</script>
USING a RADIAL gradient
There are many ways to do that but the simplest is a gradient with an alpha.
First you need to define the size of the circle you wish to show.
var cirRadius = 300;
Then the location (canvas coordinates) where this circle will be centered
var posX = 100;
var posY = 100;
Now define the rgb colour
var RGB = [0,0,0] ; // black
Then an array of alpha values to define what is transparent
var alphas = [0,0,0.2,0.5,1]; // zero is transparent;
Now all you do is render the background image
// assume ctx is context and image is loaded
ctx.drawImage(image, 0, 0, ctx.canvas.width, ctx.canvas.height); // fill the canvas
Then create the gradient with it centered at the position you want and the second circle at the radius you want. The first 3 numbers define the center and radius of the start of the gradient, the last 3 define the center and radius of the end
var grad = ctx.createRadialGradient(posX,posY,0,posX,posY,cirRadius);
Now add the colour stops using the CSS color string rgba(255,255,255,1) where the last is the alpha value from 0 to 1.
var len = alphas.length-1;
alphas.forEach((a,i) => {
grad.addColorStop(i/len,`rgba(${RGB[0]},${RGB[1]},${RGB[2]},${a})`);
});
or for legacy browsers that do not support arrow functions or template strings
var i,len = alphas.length;
for(i = 0; i < len; i++){
grad.addColorStop(i / (len - 1), "rgba(" + RGB[0] + "," + RGB[1] + "," + RGB[2] + "," + alphas[i] + ")");
}
Then set the fill style to the gradient
ctx.fillStyle = grad;
then just fill a rectangle covering the image
ctx.fillRect(0,0,ctx.canvas.width,ctx.canvas.height);
And you are done.
By setting the position with via a mouse event and then doing the above steps 60times a second using window.requestAnimationFrame you can get the effect you are looking for in real time.
Here is an example
// create a full screen canvas
var canvas = document.createElement("canvas");
canvas.style.position = "absolute";
canvas.style.left = "0px";
canvas.style.top = "0px";
canvas.style.zIndex = 10;
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
document.body.appendChild(canvas);
// var to hold context
var ctx;
// load an image
var image = new Image();
image.src = "https://i.stack.imgur.com/C7qq2.png?s=328&g=1";
// add resize event
var resize = function(){
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
ctx = canvas.getContext("2d");
}
// add mouse event. Because it is full screen no need to bother with offsets
var mouse = function(event){
posX = event.clientX;
posY = event.clientY;
}
// incase the canvas size is changed
window.addEventListener("resize",resize);
// listen to the mouse move
canvas.addEventListener("mousemove",mouse)
// Call resize as that gets our context
resize();
// define the gradient
var cirRadius = 300;
var posX = 100; // this will be set by the mouse
var posY = 100;
var RGB = [0,0,0] ; // black any values from 0 to 255
var alphas = [0,0,0.2,0.5,0.9,0.95,1]; // zero is transparent one is not
// the update function
var update = function(){
if(ctx){ // make sure all is in order..
if(image.complete){ // draw the image when it is ready
ctx.drawImage(image,0,0,canvas.width,canvas.height)
}else{ // while waiting for image clear the canvas
ctx.clearRect(0,0,canvas.width,canvas.height);
}
// create gradient
var grad = ctx.createRadialGradient(posX,posY,0,posX,posY,cirRadius);
// add colour stops
var len = alphas.length-1;
alphas.forEach((a,i) => {
grad.addColorStop(i/len,`rgba(${RGB[0]},${RGB[1]},${RGB[2]},${a})`);
});
// set fill style to gradient
ctx.fillStyle = grad;
// render that gradient
ctx.fillRect(0,0,canvas.width,canvas.height);
}
requestAnimationFrame(update); // keep doing it till cows come home.
}
// start it all happening;
requestAnimationFrame(update);
Related
I want to fill a Canvas with an Image and scale it to a certain width beforehand.
I am trying to achieve an effect where an image in the foreground of the canvas can be erased with the mouse to view an image in the background. This is why I need to use a pattern to fill my canvas instead of just using drawImage(). Everything works apart from the scaling of the foreground image. Here is my code for generating the pattern:
var blueprint_background = new Image();
blueprint_background.src = "myfunurl";
blueprint_background.width = window.innerWidth;
blueprint_background.onload = function(){
var pattern = context.createPattern(this, "no-repeat");
context.fillStyle = pattern;
context.fillRect(0, 0, window.innerWidth, 768);
context.fill();
};
This does exactly what it should do, except that the image keeps its original size.
As you see, I want the image to scale to window.innerWidth (which has the value 1920 when logging it).
If needed, I can provide the rest of the code, but since the error is most likely in this snippet, I decided not to post the rest.
EDIT: Here is my full code with the suggested changes. The front ground image now displays over the full width, however the erasing does not work anymore.
JavaScript (Note that I use jQuery instead of $):
jQuery(document).ready(function() {
var cwidth = window.innerWidth;
var cheight = 768;
function createCanvas(parent, width, height) {
var canvas = {};
canvas.node = document.createElement('canvas');
canvas.context = canvas.node.getContext('2d');
canvas.node.width = width || 100;
canvas.node.height = height || 100;
parent.appendChild(canvas.node);
return canvas;
}
function init(canvas, fillColor) {
var ctx = canvas.context;
canvas.isDrawing = true;
jQuery('#canvas').children().css('position:absolute; top: ' + jQuery('#Top_bar').height() + 'px');
// define a custom fillCircle method
ctx.fillCircle = function(x, y, radius, fillColor) {
this.fillStyle = fillColor;
this.beginPath();
this.moveTo(x, y);
this.arc(x, y, radius, 0, Math.PI * 2, false);
this.fill();
};
// bind mouse events
canvas.onmousemove = function(e) {
if (!canvas.isDrawing) {
return;
}
var x = e.pageX - this.offsetLeft;
var y = e.pageY - jQuery('#Top_bar').outerHeight();
var radius = 30;
var fillColor = '#ff0000';
ctx.globalCompositeOperation = 'destination-out';
ctx.fillCircle(x, y, radius, fillColor);
};
}
var container = document.getElementById('canvas');
jQuery('#canvas').css('position:absolute; top: ' + jQuery('#Top_bar').height() + 'px');
var canvas = createCanvas(container, cwidth, cheight);
init(canvas, '#ddd');
var fgimg = document.getElementById("fgimg");
fgimg.width = cwidth;
var context = canvas.node.getContext("2d");
let canvasP = document.getElementById("pattern");
canvasP.width = window.innerWidth;
canvasP.height = 768;
let ctxP = canvasP.getContext("2d");
ctxP.drawImage( fgimg, 0, 0,window.innerWidth,768 );
context.fillStyle = context.createPattern(canvasP,"no-repeat");
context.fillRect(0,0, canvas.width, canvas.height);
});
CSS:
#canvas {
background:url(http://ulmke-web.de/wp-content/uploads/2019/01/Header-6.jpg);
background-repeat: no-repeat;
background-size: cover;
background-position: center center;
width: 100%;
height: 768px;
}
HTML:
<div id="canvas">
<canvas id="pattern">
</div>
<div style="display:none">
<img id="fgimg" src=" http://ulmke-web.de/wp-content/uploads/2019/01/Header-5.jpg">
</div>
I would use two canvases. On the first one you draw your image and you use this canvas as an image to create the pattern. In order to scale the image you scale the size of the first canvas #pattern in my example.
For example you can do this for a 10/10 image:
canvasP.width = 10;
canvasP.height = 10;
ctxP.drawImage( redpoint, 2.5, 2.5 );
or you can do this for a 20/20 image:
canvasP.width = 20;
canvasP.height = 20;
ctxP.drawImage( redpoint, 5, 5,10,10 );
Furthermore, in my example I'm adding a little margin around the image.
let canvasP = document.getElementById("pattern");
if (canvasP && canvasP.getContext) {
let ctxP = canvasP.getContext("2d");
/*canvasP.width = 10;
canvasP.height = 10;
ctxP.drawImage( redpoint, 2.5, 2.5 ); */
canvasP.width = 20;
canvasP.height = 20;
ctxP.drawImage( redpoint, 5, 5,10,10 );
}
let canvas1 = document.getElementById("canvas");
if (canvas1 && canvas1.getContext) {
let ctx1 = canvas1.getContext("2d");
if (ctx1) {
ctx1.fillStyle = ctx1.createPattern(canvasP,"repeat");
ctx1.fillRect(0,0, canvas1.width, canvas1.height);
}
}
canvas{border:1px solid}
<img id="redpoint" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO 9TXL0Y4OHwAAAABJRU5ErkJggg==">
<canvas id="pattern"></canvas>
<canvas id="canvas"></canvas>
I hope it helps.
I am having an issue when I'm trying to render multiple offscreen canvases into onscreen canvas. I do get one offscreen canvas rendered but the problem is that there should be two other rendered before. In other words, only last canvas is rendered. The expected result would be three overlapping rectangles (or squares :) in red, green and blue. Here's the code:
function rectangle(color) {
var offScreenCanvas = document.createElement('canvas');
var offScreenCtx = offScreenCanvas.getContext('2d');
var width = offScreenCanvas.width = 150;
var height = offScreenCanvas.height = 150;
switch(color) {
case 1:
offScreenCtx.fillStyle='rgb(255,0,0)';
break;
case 2:
offScreenCtx.fillStyle='rgb(0,255,0)';
break;
case 3:
offScreenCtx.fillStyle='rgb(0,0,255)';
break;
}
offScreenCtx.fillRect(0,0,width,height);
return offScreenCanvas;
}
function draw(offScreenCanvas, x , y) {
var canvas = document.getElementById('canvas')
var ctx = canvas.getContext('2d');
var width = canvas.width = window.innerWidth;
var height = canvas.height = window.innerHeight;
ctx.drawImage(offScreenCanvas, x, y);
}
var images = [];
var color = 1;
for (var i=0; i<3; i++) {
var img = new rectangle(color);
images.push(img);
color++;
}
var x = 0;
var y = 0;
for (var i = 0; i < images.length; i++) {
draw(images[i], x, y);
x += 100;
y += 100;
}
I did some searching and it seems that I'm not the first with this issue, but I could not get this working properly.
Setting canvas height or width clears the canvas.
The problem with your code is that you are causing the onscreen canvas to be cleared when you set it size in the function draw
Setting the canvas size, even if that size is the same, will cause the canvas context to reset and clear the canvas. All the other canvases are rendered, but erased when you set the onscreen canvas size.
Your draw function
function draw(offScreenCanvas, x , y) {
var canvas = document.getElementById('canvas')
var ctx = canvas.getContext('2d');
// The cause of the problem ===================================
// Either one of the following lines will clear the canvas
var width = canvas.width = window.innerWidth;
var height = canvas.height = window.innerHeight;
//=============================================================
ctx.drawImage(offScreenCanvas, x, y);
}
To avoid this just set the canvas size once. If you need to resize the canvas and keep its content you first need to create a copy of the canvas, then resize it, then render the copy back to the original.
Demo shows 5 offscreen canvases being rendered onto one onscreen canvas.
const colours = ['#f00', '#ff0', '#0f0', '#0ff', '#00f'];
const ctx = can.getContext('2d');
can.width = innerWidth - 4; // sub 4 px for border
can.height = innerHeight - 4;
function createCanvas(color, i) {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
canvas.width = 150;
canvas.height = 150;
ctx.font = "24px arial";
ctx.fillStyle = color;
ctx.fillRect(0, i * 30, canvas.width, 30);
ctx.fillStyle = "black";
ctx.fillText("Canvas "+i,10,(i + 0.75) * 30);
return canvas;
}
colours.forEach((c, i) => {
ctx.drawImage(createCanvas(c, i), 0, 0);
})
canvas {
border: 2px solid black;
position : absolute;
top : 0px;
left : 0px;
}
<canvas id="can"></canvas>
I'm developing web app using canvas and I made three. canvas, canvas_panorama and canvas_image.
First one is something like main canvas, conteiner for the others. canvas_panorama is a background for canvas_image.
After canvas is right clicked, I'm computing angle to rotate canvas_image:
function getAngle( e, pw /*canvas*/ ){
var offset = pw.offset();
var center_x = (offset.left) + ($(pw).width() / 2);
var center_y = (offset.top) + ($(pw).height() / 2);
var mouse_x = e.pageX;
var mouse_y = e.pageY;
var radians = Math.atan2(mouse_x - center_x, mouse_y - center_y);
angle = radians;
}
After I have an angle I'm trying to rotate canvas_image like this:
function redraw(){
var p1 = ctx.transformedPoint(0,0);
var p2 = ctx.transformedPoint(canvas.width,canvas.height);
ctx.clearRect( p1.x, p1.y, p2.x-p1.x, p2.y-p1.y );
canvas_image_ctx.drawImage(image_img, 0, 0, 150, 150);
canvas_panorama_ctx.drawImage(panorama_img, 0, 0, 600, 300);
canvas_panorama_ctx.drawImage(canvas_image, 20, 20);
// rotate panorama_img around its center
// x = x + 0.5 * width
// y = y + 0.5 * height
canvas_panorama_ctx.translate(95, 95);
canvas_panorama_ctx.rotate(angle);
// translate to back
canvas_panorama_ctx.translate(-95, -95);
ctx.drawImage(canvas_panorama, 0, 0);
}
But this rotates both canvas_image and canvas_panorama. It should only rotate canvas_image
JSFiddle to show you my problem
I think you are confusing yourself with this idea of multiple canvases.
Once in the drawImage() method, every of your canvases are just images, and could be just one or even just plain shapes.
Transformation methods do apply to the canvas' context's matrix, and will have effect only if you do some drawing operations when they are set.
Note : To reset your context matrix, you can either use save(); and restore() methods which will also save all other properties of your context, so if you only need to reset the transform, then it's preferred to simply reset the transformation matrix to its default : ctx.setTransform(1,0,0,1,0,0).
Here is a simplified example to make things clearer :
var ctx = canvas.getContext('2d');
// a single shape, with the border of the context matrix
var drawRect = function(){
ctx.beginPath();
ctx.rect(10, 10, 50, 20);
ctx.fill();
ctx.stroke();
ctx.beginPath();
ctx.rect(0, 0, canvas.width, canvas.height);
ctx.stroke();
};
// set the color of our shapes
var gradient = ctx.createLinearGradient(0,0,70,0);
gradient.addColorStop(0,"green");
gradient.addColorStop(1,"yellow");
ctx.fillStyle = gradient;
// here comes the actual drawings
//we don't have modified the transform matrix yet
ctx.strokeStyle = "green";
drawRect();
// here we translate of 100px then we do rotate the context of 45deg
ctx.translate(100, 0)
ctx.rotate(Math.PI/4)
ctx.strokeStyle = "red";
drawRect();
// reset the matrix
ctx.setTransform(1,0,0,1,0,0);
// here we move of 150px to the right and 25px to the bottom
ctx.translate(150, 25)
ctx.strokeStyle = "blue";
drawRect();
// reset the matrix
ctx.setTransform(1,0,0,1,0,0);
<canvas id="canvas" width="500" height="200"></canvas>
In your code, you are setting the transformations on the canvas that does represent your image, and you do draw every of your canvases at each call.
What you want instead, is to set the transformation on the main canvas only, and draw the non-transformed image :
var main_ctx = canvas.getContext('2d');
var img_canvas = canvas.cloneNode();
var bg_canvas = canvas.cloneNode();
var angle = 0;
// draw on the main canvas, and only on the main canvas
var drawToMain = function(){
// first clear the canvas
main_ctx.clearRect(0,0,canvas.width, canvas.height);
// draw the background image
main_ctx.drawImage(bg_canvas, 0,0);
// do the transforms
main_ctx.translate(img_canvas.width/2, img_canvas.height/2);
main_ctx.rotate(angle);
main_ctx.translate(-img_canvas.width/2, -img_canvas.height/2);
// draw the img with the transforms applied
main_ctx.drawImage(img_canvas, 0,0);
// reset the transforms
main_ctx.setTransform(1,0,0,1,0,0);
};
// I changed the event to a simple onclick
canvas.onclick = function(e){
e.preventDefault();
angle+=Math.PI/8;
drawToMain();
}
// a dirty image loader
var init = function(){
var img = (this.src.indexOf('lena')>0);
var this_canvas = img ? img_canvas : bg_canvas;
this_canvas.width = this.width;
this_canvas.height = this.height;
this_canvas.getContext('2d').drawImage(this, 0,0);
if(!--toLoad){
drawToMain();
}
};
var toLoad = 2;
var img = new Image();
img.onload = init;
img.src = "http://pgmagick.readthedocs.org/en/latest/_images/lena_scale.jpg";
var bg = new Image();
bg.onload = init;
bg.src = 'http://www.fnordware.com/superpng/pnggradHDrgba.png';
<canvas id="canvas" width="500" height="300"></canvas>
I'm trying to create a sinusoidal text scrolling animation in HTML5 canvas, but I can't figure out how to animate each letter differently.
I know I can use .split('') to get an array that contains all the characters in the string. I tried using a for loop for (var i = 0; i < chars.length; i++) but that didn't do what I was expecting (all characters in the array were smooshed together). I was hoping somebody with the experience could help me out with the code and write comments in it, so that I can learn this.
What I already have is below. As you can see, it doesn't animate each letter. See this video for what I am trying to do.
// Canvas
var c = document.getElementById('c');
var ctx = c.getContext('2d');
var seconds = Date.now();
var offsetY = 220;
var offsetX = 490;
var chars = 'abc';
var amplitude = 50;
var textcolor ='#fff';
var backgroundcolor = '#000';
// Options
c.height = 500; // Canvas HEIGHT
c.width = 500; // Canvas WIDTH
function animate() {
var y = Math.floor((Date.now() - seconds) / 10) / 30;
var yPos = Math.sin((y)) * amplitude;
ctx.fillStyle = backgroundcolor;
ctx.fillRect(0, 0, c.width, c.height);
ctx.fillStyle = textcolor;
ctx.fillText(chars, offsetX--, offsetY + yPos);
if (offsetX == 0) {
offsetX = 490;
}
// Loop it
requestAnimationFrame(animate);
}
// Start animation
requestAnimationFrame(animate);
<!doctype html>
<html>
<head>
<title>Sinus Scroller</title>
</head>
<body>
<canvas id="c">
</canvas>
</body>
</html>
It's desirable to warp the letters to the sine wave because the distance from one character to the next grows as the slope of the wave increases. If you avoid warping and simply implement the wave with constant speed in x and with y = sin(x) for each letter, you'll see inter-character gaps growing on the steep portions of the sine wave and shrinking near the optima.
At any rate, here is the simple implementation:
var text = 'Savor the delightful flavor of Bubba-Cola',
canvasWidth = 620,
canvasHeight = 200,
rightEdgeBuffer = 50;
WebFont.load({ // Web Font Loader: https://github.com/typekit/webfontloader
google: {
families: ['Source Sans Pro']
},
active: function () { // Gets called when font loading is done.
var canvas = document.getElementsByTagName('canvas')[0],
context = canvas.getContext('2d'),
yZero = canvasHeight / 2, // Set axis position and amplitude
amplitude = canvasHeight / 4, // according to canvas dimensions.
textColor ='#fff',
backgroundColor = '#000';
canvas.width = canvasWidth;
canvas.height = canvasHeight;
context.font = "32px 'Source Sans Pro', monospace";
var pos = canvasWidth; // Split the text into characters.
var units = text.split('').map(function (char) {
var width = context.measureText(char).width,
unit = { char: char, width: width, pos: pos };
pos += width; // Calculate the pixel offset of each character.
return unit;
});
var running = true,
lapTime; // Set this before the first animation call.
function animate() {
var currentTime = Date.now(),
dp = (currentTime - lapTime) / 15; // Displacement in pixels.
lapTime = currentTime;
context.fillStyle = backgroundColor;
context.fillRect(0, 0, canvasWidth, canvasHeight);
units.forEach(function (unit) {
unit.pos -= dp; // Update char position.
if (unit.pos < -unit.width) { // Wrap around from left to right.
unit.pos += canvasWidth + rightEdgeBuffer;
}
var y = Math.sin(unit.pos / 45) * amplitude;
context.fillStyle = textColor;
context.fillText(unit.char, unit.pos, yZero + y);
});
if (running) {
requestAnimationFrame(animate);
}
}
document.getElementById('stopButton').onclick = function () {
running = false;
};
lapTime = Date.now();
requestAnimationFrame(animate);
}
});
<script
src="https://ajax.googleapis.com/ajax/libs/webfont/1.5.18/webfont.js"
></script>
<canvas></canvas>
<button id="stopButton"> stop </button>
Here is a more complete implementation with rectilinearly warped characters:
https://github.com/michaellaszlo/wavy-text
I am using a jQuery carousel to display 38 different magnifications/positions of a large SVG image. I would ideally like to use some sort of loop to go through all the different sizes, draw to an individual canvas and place one in each of the li's in my carousel. Can anyone help me achieve this. Here's what I tried:
function drawSlides() {
for (var i = 1; i <= 38; i++) {
var currentCanvas = 'myCanvas_' + slideNumber;
// initialise canvas element
var canvas_i = document.getElementById('' + currentCanvas + '');
var context = canvas_i.getContext('2d');
// position of SVG – these measurements are subject to change!
var destX_i = -6940;
var destY_i = -29240;
var destWidth_i = 9373;
var destHeight_i = 30000;
context.drawImage('/path/image.svg',
destX_i, destY_i, destWidth_i, destHeight_i);
// white rectangle background – these are constant
var topLeftCornerX_i = 453;
var topLeftCornerY_i = -10;
var width_i = 370;
var height_i = 480;
context.beginPath();
context.rect(topLeftCornerX_i, topLeftCornerY_i, width_i, height_i);
context.fillStyle = "rgba(255, 255, 255, 1)";
context.fill();
// orange vertical line – these elements are constant
context.moveTo(453, 0);
context.lineTo(453, 460);
context.lineWidth = 2;
context.strokeStyle = "#f5d7cb";
context.stroke();
//orange ball – these are constant
var centerX_ball_i = 453;
var centerY_ball_i = 323;
var radius = 99;
context.beginPath();
context.arc(centerX_ball_i, centerY_ball_i, radius, 0, 2 * Math.PI, false);
var grd_ball_i = context.createLinearGradient(224, 354, 422, 552);
grd_ball_i.addColorStop(0, "#f5d7cb"); // light orange
grd_ball_i.addColorStop(1, "#ff4900"); // dark orange
context.fillStyle = grd_ball_i;
context.fill();
}
};
drawSlides();
This should get you moving:
var numCarouselItems = 38;
var myUL = document.getElementById('carousel');
var items = myUL.childNodes;
var img = new Image;
img.onload = function(){
for (var i=0;i<numCarouselItems;++i){
// Find the nth li, or create it
var li = items[i] || myUL.appendChild(document.createElement('li'));
// Find the nth canvas, or create it
var canvas = li.getElementsByTagName('canvas')[0] ||
li.appendChild(document.createElement('canvas'));
canvas.width = 1; // Erase the canvas, in case it existed
canvas.width = 320; // Set the width and height as desired
canvas.height = 240;
var ctx = canvas.getContext('2d');
// Use your actual calculations for the SVG size/position here
ctx.drawImage( img, 0, 0 );
}
}
// Be sure to set your image source after your load handler is in place
img.src = "foo.svg";