I still stuck and need your help my canvas project. I got the idea of a template, what I want to see there and I want to insert a content now there. From my last question about I have this working canvas template: jsfiddle.net/AbdiasSoftware/LmCwZ/2/ Here is the idea of what I want to have at my first tab. Hopefully with your help creating first main tab, I will carry on expanding example and working by myself. First tab example: http://i.imgur.com/5Anzfny.png
How I can do this for my first tab? Some of the text content should be automatically update by application. Thank you in advance.
As #Ken suggests in his answer to your last question, layout of complex content is usually done with HTML+CSS. A nice tool to give you tabs is jqueryUI's tab control: https://jqueryui.com/tabs/ A production application would use HTML+CSS.
But since you're coding a project for learning purposes, here is how you can create "templates" for your tab content.
JavaScript has a variable called an object. Objects are kind of like arrays because that one object can hold multiple pieces of information. Each piece of information in an object is labeled.
An object that holds info about text you want to include in your template might look like this:
var myTextObject1 = { text:"Hello", x:100, y:20 };
var myTextObject2 = { text:"World", x:100, y:35 };
To make your template, create a contents array and save your objects in that array
var contents=[];
contents.push(myTextObject1);
contents.push(myTextObject2);
Then when you activate this tab you can use the objects to draw content on your tab
for(var i=0;i<contents.length;i++){
drawTextContent( contents[i] );
}
function drawTextContent(text){
ctx.fillText(text.text,text.x,text.y);
}
Of course you will need to create different kinds of objects:
an object that defines text.
an object that defines an image.
an object that defines a background rectangle.
an object that defines a captioned image (image+text).
Here's starting example code and a Demo: http://jsfiddle.net/m1erickson/WNaLn/
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; }
canvas{border:1px solid red;}
</style>
<script>
$(function(){
// get a reference to the canvas and context
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
// the contents[] array will hold individual content objects
// the content objects will be used to later draw the content to the tab
var contents=[];
// load a test image
var house=new Image();
house.onload=start;
house.src="houseIcon.png";
function start(){
// create some test contents
// tab background
addBackgroundRect(0,0,275,275,"red");
// left panel example
addBackgroundRect(10,10,100,250,"lavender");
addImageContent(house,50,15,20,20);
addImageContent(house,75,65,20,20);
addImageContent(house,50,110,20,20);
addImageContent(house,15,65,20,20);
addImageContent(house,40,65,30,30);
// right panel example
addBackgroundRect(110,10,150,100,"white");
addTextContent("Text1",115,20,"red");
addTextContent("Text2",115,40,"red");
addTextContent("Text3",115,60,"red");
addTextContent("Text4",115,80,"red");
addTextImageContent("Caption",house,175,20,60,60);
drawContents(contents);
}
// draw all content in the contents array
function drawContents(contents){
for(var i=0;i<contents.length;i++){
var content=contents[i];
//
switch (content.type){
case "background":
drawBackgroundRect(content);
break;
case "text":
drawTextContent(content);
break;
case "image":
drawImageContent(content);
break;
case "textImage":
drawTextImageContent(content);
break;
default:
break;
}
}
}
// draw contents based on a content object
function drawBackgroundRect(bk){
ctx.fillStyle=bk.color;
ctx.fillRect(bk.x,bk.y,bk.width,bk.height);
}
//
function drawTextContent(text){
ctx.fillStyle=text.color;
ctx.fillText(text.text,text.x,text.y);
}
//
function drawImageContent(img){
ctx.drawImage(img.image,img.x,img.y,img.width,img.height);
}
//
function drawTextImageContent(tImg){
ctx.drawImage(tImg.image,tImg.x,tImg.y,tImg.width,tImg.height);
ctx.fillStyle="black";
ctx.fillRect(tImg.x,tImg.y+tImg.height-15,tImg.width,15);
ctx.fillStyle="white";
ctx.fillText(tImg.text,tImg.x+5,tImg.y+tImg.height-4);
}
// create content objects
function addBackgroundRect(x,y,width,height,color){
contents.push({
type:"background",
x:x,
y:y,
width:width,
height:height,
color:color
});
}
//
function addTextContent(text,x,y,color){
contents.push({
type:"text",
text:text,
x:x,
y:y,
color:color
});
}
//
function addImageContent(imgObject,x,y,width,height){
contents.push({
type:"image",
image:imgObject,
x:x,
y:y,
width:width,
height:height
});
}
//
function addTextImageContent(text,imgObject,x,y,width,height){
contents.push({
type:"textImage",
text:text,
image:imgObject,
x:x,
y:y,
width:width,
height:height
});
}
}); // end $(function(){});
</script>
</head>
<body>
<canvas id="canvas" width=300 height=300></canvas>
</body>
</html>
Related
To summarize, I am changing what canvases are shown via ajax calls and what gets drawn on each as well. The main problem is that my main drawing function fails on getContext and there is other weird behavior like missing canvases (but they are definitely there).
Here is the function I use to draw on my canvases:
function PlotSet(plot_properties){
var p = plot_properties;
var canvas = document.getElementById(p.panel_name);
var spinner_target = document.getElementById(p.spinner_name);
if (!canvas) {
alert('Error: Cannot find the canvas element!');
return;
} else if (!canvas.getContext) {
alert('Error: Canvas context does not exist!');
return;
} else {
var ctx = canvas.getContext('2d');
/*Do the drawing*/
}
}
I have 3 buttons in a section of my page that determine how many and the arrangement of the panels/canvas. When someone clicks one, another php page with that arrangement is loaded.
<div id="panel_single" name="panel_control" class="xs-btn sm-btn-h-grp sm-btn-one-panel"></div>
<div id="panel_split" name="panel_control" class="xs-btn sm-btn-h-grp sm-btn-four-panel"></div>
<div id="panel_rows" name="panel_control" class="xs-btn sm-btn-h-grp sm-btn-list-panel"></div>
<script>
$("#panel_single_settings").hide();
$("div[name=panel_control]").click(function(event) {
var nav_id = $(this).attr("id");
if(nav_id == "panel_single"){
$("#panel_single_settings").show();
}else{
$("#panel_single_settings").hide();
}
//$("span[name=vnav-text]").removeClass("vnav-active");
//$("#" + nav_id).addClass('vnav-active');
refresh_content($(".widget-panel"), nav_id, function(){
side_panel_hide($(".side_panel"), "600px");
});
});
</script>
Everything works when I click on these after loading page. But I have two issues when changing the drawing properties/redrawning. (1) the PlotSet function fails on getContext for everything except the first canvas, when multiple canvases are shown, when this function is used to redraw an already drawn canvas (using a pop-up form with ajax to set what is redrawn). (2) When only one panel is shown, the settings can be changed and the panel can be redrawn, but then when I then load a page with multiple panels, all panels but the first are blank (i.e. this page functions as expected, except when I redrawn a canvas on another page).
Single Panel example:
<script>
var plot_properties = {
//Settings to draw
}
PlotSet(plot_properties);
</script>
example of multi panel configuration:
<canvas class="analytics-graph-medium" id="graph_send"></canvas>
<canvas class="analytics-graph-medium" id="graph_recv"></canvas>
<canvas class="analytics-graph-medium" id="graph_cpu"></canvas>
<canvas class="analytics-graph-medium" id="graph_ram"></canvas>
<script>
var split_send_plot_properties = {
//Settings to draw
}
PlotSet(split_send_plot_properties);
var split_recv_plot_properties = {
//Settings to draw
}
PlotSet(split_recv_plot_properties);
.
.
.
//**************************************************************
//Panel Settings Events
//**************************************************************
$("#cpu_panel_settings").on("click", function(){
var panel_name = $(this).attr('id');
set_side_panel_html($(".side_panel"), "/gui/pages/status/dialogs/panel_settings.php", split_cpu_plot_properties, function(){
side_panel_show($(".side_panel"), "500px");
});
});
.
.
.
</script>
And this is the submit button action for changing the settings:
$("#mod_panel").click(function(){
plot_properties = {
//lots of properties to be drawn
}
PlotSet(plot_properties);
side_panel_hide($(".side_panel"), "600px");
});
Well, I seem to have solved the problem. I still do not understand the problem, but the solution is to add a new canvas with the same name, remove the old canvas and them to re-grab the new canvas with the same old name with getElementById. But only do that when the canvas can be found, but the context does not exist... otherwise use the original context.
function PlotSet(plot_properties){
var p = plot_properties;
var spinner_target = document.getElementById(p.spinner_name);
var canvas = document.getElementById(p.panel_name);
if (!canvas) {
alert('Error: Cannot find the canvas element!');
return;
} else if (!canvas.getContext) {
var new_canvas = document.createElement(p.panel_name);
canvas.parentNode.insertBefore(new_canvas, canvas.nextSibling);
canvas.parentNode.removeChild(canvas);
canvas = document.getElementById(p.panel_name);
}
var ctx = canvas.getContext('2d');
//Draw Something
}
This makes everything work, all the dynamic page loading with multiple canvases on them, plus changing settings/drawing of any canvas, and switching pages after a chane is made.
If anyone has any futher insight into what caused the problem or why this solution worked, I'm eager ears.
The code snippet shown below (HTML5/javascript) loads Microsoft Bing Map (VirtualEarth 6.3), then adds two Shape layers and two sample Pushpins, one per each layer.
QUESTION: What pure javascript function (or solution) to use in order to clear all pushpins from just the 1st layer keeping the other layer intact?
Note: clear layer function should be implemented without deleting the entire layer.
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Bing VE Map w/layers</title>
<script type="text/javascript" src="http://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.3"></script>
<script type="text/javascript">
// VE map
var _map;
// 1st shape layer
var _layer1 ;
// 2nd shape layer
var _layer2;
function MapLoad() {
// load map
_map = new VEMap('Map');
_map.LoadMap();
// center point (Columbus Circle NY)
var _center = new VELatLong(40.7681, -73.9819);
// set center point and initial zoom level
_map.SetCenterAndZoom(_center, 12);
// set Map style
_map.SetMapStyle(VEMapStyle.Shaded);
// add 1st shape layer1 to Map obj
_layer1 = new VEShapeLayer()
_map.AddShapeLayer(_layer1);
// add 2nd shape layer2 to Map obj
_layer2 = new VEShapeLayer()
_map.AddShapeLayer(_layer2);
// add pushpin to layer1
var _pushpin1 = new VEShape(VEShapeType.Pushpin, _center);
_layer1.AddShape(_pushpin1);
// add pushpin (Apple Store on 5th) to layer2
var _pushpin2 = new VEShape(VEShapeType.Pushpin, new VELatLong(40.7639, -73.9725));
_layer2.AddShape(_pushpin2);
// QUESTION: HOW TO CLEAR ALL SHAPES FROM LAYER 1, (BUT NOT DELETING THE ENTIRE LAYER)?
}
</script>
</head>
<body onload="MapLoad();">
<div id="Map" style="position:absolute; top:100px; height:90%; width:100%;"></div>
</body>
</html>
You could use the dedicated method DeleteAllShapes() of the VEShapeLayer class, see the MSDN:
https://msdn.microsoft.com/en-us/library/bb412473.aspx
See the example:
// Delete all shapes within the layer at the selected index.
function DeleteAllShapes()
{
layer = map.GetShapeLayerByIndex(selIndex);
layer.DeleteAllShapes();
IndexChanged(selIndex);
}
Also, I would recommend to use AJAX v7.0 instead of v6.3 since it's now deprecated and due to be out of support on November 30, 2016.
I'm creating a HTML5 game which can be made to run on Android also. I went through few articles and didn't get the solution yet. I have a image which i'm generating through javascript and I want to move this image using touchmove so that I can run it in my Android device. This is the code:
gameCanvas.addEventListener("touchmove", touchXY, true);
function touchXY(e) {
if (!e)
var e = event;
e.preventDefault();
avatarX = e.targetTouches[0].pageX - gameCanvas.offsetLeft;
avatarY = e.targetTouches[0].pageY - gameCanvas.offsetTop;
}
This is not working. I got this code from https://developer.apple.com/library/archive/documentation/AudioVideo/Conceptual/HTML-canvas-guide/AddingMouseandTouchControlstoCanvas/AddingMouseandTouchControlstoCanvas.html
And this is my canvas:
<canvas id="gameCanvas" onclick="setUpGame();" width="400" height="300"></canvas>
This is my image:
avatarImage.src = "img/avatar.png";
gameCanvas.getContext("2d").drawImage(avatarImage, Math.random() * 100, Math.random() * 100);
I just want to move the image inside the canvas.
I wrote a full example, hopefully it's not too verbose.
<!DOCTYPE html>
<html>
<head>
<meta charset='UTF-8'>
</head>
<body>
<canvas id='canvas' width='512' height='512'></canvas>
<script>
var c=document.getElementById('canvas'),
ctx=c.getContext('2d'),
activeBox='none',
//populate the map with objects
box=[
{
x:256,
y:128,
width:32,
height:64
},
{
x:128,
y:64,
width:64,
height:64
},
{
x:32,
y:32,
width:32,
height:32
},
];
function draw(){
//clear the screen, draw population
ctx.clearRect(0,0,c.width,c.height);
for(var i=0;i<box.length;i++){
ctx.fillRect(box[i].x,box[i].y,box[i].width,box[i].height);
}
//repeat at 60fps if possible, pause if window looses focus
requestAnimationFrame(draw);
}
function startTouch(e){
//this makes it easier to write control flow later and keeps XY relative to canvas
var xTouch=e.touches[0].pageX-c.offsetLeft,
yTouch=e.touches[0].pageY-c.offsetTop;
//its best to go through this loop in touchstart, because it only happens once per touch
for(var i=0;i<box.length;i++){
if(xTouch>box[i].x&&xTouch<box[i].x+box[i].width){
if(yTouch>box[i].y&&yTouch<box[i].y+box[i].height){
activeBox=i;
}
}
}
}
function moveTouch(e){
//grab a box by the center
if(activeBox!='none'){
box[activeBox].x=e.changedTouches[0].pageX-box[activeBox].width/2;
box[activeBox].y=e.changedTouches[0].pageY-box[activeBox].height/2;
}
}
function endTouch(){
//clear active so that dragging empty space wont move the last active box
activeBox='none';
}
canvas.addEventListener('touchstart',startTouch);
canvas.addEventListener('touchmove',moveTouch);
canvas.addEventListener('touchend',endTouch);
window.addEventListener('load',draw);
</script>
</body>
</html>
I used fillRect for simplicity, but if you want to replace it with drawImage you'll need to create a new element for each and add a source property to the box object array. Here's a partial example.
//you need a new one of these for every image
var img=new Image();
img.src='http://www.w3schools.com/images/w3logotest2.png';
var box={
source:img,
x:Math.floor((Math.random()*256)+1),
y:Math.floor((Math.random()*256)+1)
};
//make sure the image doesnt load before the script
window.onload=function(){
ctx.drawImage(img,box.x,box.y);
}
I'm working on a simple diagram editor using KineticJS. I would like to use two separate canvases for the palette area (that contains a number of Kinetic.Groups that represent the different nodes of the network I might create), and the diagramming area where I can add nodes from the palette via drag and drop, and then add connections between the various nodes as specific anchor points. I'm having trouble figuring out the drag and drop process from the palette canvas of (stationary) Kinetic.Groups over to the other canvas containing diagramming area. I'm guessing that I need to fire off of the dragstart event for the palette objects (although I don't want these themselves to be draggable), and then do something like create an opague copy of the palette object that can be dragged around, and finally dropped into the diagramming area (with full opacity).
Can groups be dragged outside of a the staging canvases boundaries? Maybe I need to generate an image when I start to drag from the palette, drag that image over, and then create another group when dropping into the diagramming area.
Does any one know of any examples that might point me in the right direction, or who can offer some insight (even code) into the required process. I've searched the KineticJS examples but can't quite find enough to get me going.
Here’s one way to drag nodes from a source palette into a destination group:
A Fiddle: http://jsfiddle.net/m1erickson/xtVyL/
Network nodes are represented by small icons (which are really small kinetic image objects).
The user can drag any icon from the source palette to any destination group.
The groups are just defined areas on the canvas, but could be Kinetc.Groups for more flexibility.
During the dragend event, a new duplicate copy of the dragged icon is created in the destination group.
After the dragend event is complete, the original palette icon is automatically moved from
The newly created duplicate icon can be dragged around the destination group (but not outside that group).
Here is code and a Fiddle: http://jsfiddle.net/m1erickson/xtVyL/
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Prototype</title>
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v4.5.5.min.js"></script>
<style>
#container{
border:solid 1px #ccc;
margin-top: 10px;
width:350px;
height:350px;
}
</style>
<script>
$(function(){
var stage = new Kinetic.Stage({
container: 'container',
width: 350,
height: 350
});
var layer = new Kinetic.Layer();
stage.add(layer);
// image loader
var imageURLs=[];
var imagesOK=0;
var imgs=[];
imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/stackoverflow/tempPC.png");
imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/stackoverflow/tempServer.png");
imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/stackoverflow/tempRouter.png");
loadAllImages();
function loadAllImages(callback){
for (var i = 0; i < imageURLs.length; i++) {
var img = new Image();
imgs.push(img);
img.onload = function(){
imagesOK++;
if (imagesOK==imageURLs.length ) {
start();
}
};
img.src = imageURLs[i];
}
}
// top icon positions
var nextIconX=20;
var nextIconY=20;
// define groups
var groups=[];
groups.push({x:0,y:100,w:175,h:250,fill:"skyblue"});
groups.push({x:175,y:100,w:175,h:250,fill:"cornsilk"});
// add boundary info to each group
// draw colored rect to show group area
for(var i=0;i<groups.length;i++){
var g=groups[i];
g.left=g.x;
g.right=g.x+g.w;
g.top=g.y;
g.bottom=g.y+g.h;
var rect=new Kinetic.Rect({
x:g.x,
y:g.y,
width:g.w,
height:g.h,
fill:g.fill,
stroke:"gray"
});
layer.add(rect);
}
// hittest for each group
function groupHit(x,y){
for(var i=0;i<groups.length;i++){
var g=groups[i];
if(x>g.left && x<g.right && y>g.top && y<g.bottom){return(i);}
}
return(-1);
}
function start(){
makePaletteIcon(imgs[0]);
makePaletteIcon(imgs[1]);
makePaletteIcon(imgs[2]);
layer.draw();
}
function makePaletteIcon(img){
// make an icon that stays in the pallette tray
var fixedIcon=newImage(nextIconX,nextIconY,img,false);
layer.add(fixedIcon);
// make an icon that is dragged from the tray to a group
var dragIcon=makeDraggableIcon(nextIconX,nextIconY,img);
layer.add(dragIcon);
// calc the next icon position
nextIconX+=(img.width+20);
}
function makeDraggableIcon(x,y,img){
var i=newImage(x,y,img,true);
//
i.trayX=x;
i.trayY=y;
//
i.setOpacity(0.50);
i.on("dragend",function(){
var x=this.getX();
var y=this.getY();
// if this pallette icon was not dropped in a group
// put the icon back in the tray and return
var hit=groupHit(x,y);
if(hit==-1){
this.setPosition(this.trayX,this.trayY);
return;
}
// add a copy of this icon to the drop group
var component=newImage(x,y,this.getImage(),true);
// set drag limits
var group=groups[hit];
component.maxDragLeft=group.left;
component.maxDragRight=group.right;
component.maxDragTop=group.top;
component.maxDragBottom=group.bottom;
// limit component dragging to inside the assigned group
component.setDragBoundFunc(function(pos) {
var xx=pos.x;
var yy=pos.y;
var w=this.getWidth();
var h=this.getHeight();
if(pos.x<this.maxDragLeft){xx=this.maxDragLeft;}
if(pos.x+w>this.maxDragRight){xx=this.maxDragRight-w;}
if(pos.y<this.maxDragTop){yy=this.maxDragTop;}
if(pos.y+h>this.maxDragBottom){yy=this.maxDragBottom-h;}
return{ x:xx, y:yy };
});
layer.add(component);
// move the dragIcon back into the pallette tray
this.setPosition(this.trayX,this.trayY);
layer.draw();
});
return(i);
}
// make a new Kinetic.Image
function newImage(x,y,img,isDraggable){
var i=new Kinetic.Image({
image:img,
x: x,
y: y,
width: img.width,
height: img.height,
draggable:isDraggable
});
return(i);
}
}); // end $(function(){});
</script>
</head>
<body>
<p>Drag any icon from top into blue or yellow group</p>
<div id="container"></div>
</body>
</html>
I've got a problem filling 25 canvas elements automatically in a for loop. They are numbered like so: can01 to can25.
I've tried all I knew to draw different images on the canvas and I have spent a lot of time in searching a few articles which are about this problem but I haven't found any.
This is my working code to fill all canvas elements with the same image:
var imageGrass = new Image();
imageGrass.src = 'recources/imagesBG/grass.jpg';
imageGrass.onload = function() {
for (var i = 1; i < 26; i++)
{
if( i < 10 )
{
var task = "can0" + i + "_ctx.drawImage(imageGrass, 0, 0);";
eval(task);
}
else
{
var task = "can" + i + "_ctx.drawImage(imageGrass, 0, 0);";
eval(task);
}
}
}
But I really don't know how to make the imageGrass.src dynamic. For example, the canvas element no. 5 (can05) in this case shall look like stone texture.
I´m really looking forward to read your ideas. I just don't get it.
Here’s how to impliment Dave’s good idea of using arrays to organize your canvases:
Create an array that will hold references to all your 25 canvases (do the same for 25 contexts)
var canvases=[];
var contexts=[];
Next, fill the array with all your canvases and contexts:
for(var i=0;i<25;i++){
var canvas=document.getElementById("can"+(i<10?"0":""));
var context=canvas.getContext("2d");
canvases[i]=canvas;
contexts[i]=context;
}
If you haven't seen it before: i<10?"0":"" is an inline if/else used here to add a leading zero to your lower-numbered canvases.
Then you can fetch your “can05” canvas like this:
var canvas=canvases[4];
Why 4 and not 5? Arrays are zero based, so canvases[0] holds can01. Therefore array element 4 contains your 5th canvas “can05”.
So you can fetch the drawing context for your “can05” like this:
var context=contexts[4];
As Dave says, “evals are evil” so here’s how to fetch the context for “can05” and draw the stone image on it.
var context=contexts[4];
context.drawImage(stoneImage,0,0);
This stone drawing can be shortened to:
contexts[4].drawImage(stoneImage,0,0);
You can even put this shortened code into a function for easy reuse and modification:
function reImage( canvasIndex, newImage ){
contexts[ canvasIndex ].drawImage( newImage,0,0 );
}
Then you can change the image on any of your canvases by calling the function:
reimage( 4,stoneImage );
That’s it!
The evil-evals have been vanquished (warning: never invite them to your computer again!)
Here is example code and a Fiddle: http://jsfiddle.net/m1erickson/ZuU2e/
This code creates 25 canvases dynamically rather than hard-coding 25 html canvas elements.
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; padding:0px; margin:0px;border:0px; }
canvas{vertical-align: top; }
</style>
<script>
$(function(){
var canvases=[];
var contexts=[];
var grass=new Image();
grass.onload=function(){
// the grass is loaded
// now make 25 canvases and fill them with grass
// ALSO !!!
// keep track of them in an array
// so we can use them later!
make25CanvasesFilledWithGrass()
// just a test
// fill canvas#3 with gold
draw(3,"gold");
// fill canvas#14 with red
draw(14,"red");
}
//grass.src="https://dl.dropboxusercontent.com/u/139992952/stackoverflow/grass.jpg";
//grass.src="grass.jpg";
function make25CanvasesFilledWithGrass(){
// get the div that we will fill with 25 canvases
var container=document.getElementById("canvasContainer");
for(var i=0;i<25;i++){
// create a new html canvas element
var canvas=document.createElement("canvas");
// assign the new canvas an id, width and height
canvas.id="can"+(i<10?"0":"")+i;
canvas.width=grass.width;
canvas.height=grass.height;
// get the context for this new canvas
var ctx=canvas.getContext("2d");
// draw the grass image in the new canvas
ctx.drawImage(grass,0,0);
// add this new canvas to the web page
container.appendChild(canvas);
// add this new canvas to the canvases array
canvases[i]=canvas;
// add the context for this new canvas to the contexts array
contexts[i]=ctx;
}
}
// test -- just fill the specified canvas with the specified color
function draw(canvasIndex,newColor){
var canvas=canvases[canvasIndex];
var ctx=contexts[canvasIndex];
ctx.beginPath();
ctx.fillStyle=newColor;
ctx.rect(0,0,canvas.width,canvas.height);
ctx.fill();
}
}); // end $(function(){});
</script>
</head>
<body>
<div id="canvasContainer"></div>
</body>
</html>