I want to be able to create diagrams and drawings on the fly, using input from the user.
If I have 2 text boxes for width and height, i want to be able to draw a rectangle based on user entered values, if they change the value in the input fields i want the drawing to change.
is canvas capable of this? does it need to work along with javascript?
thanks
Yes, you can listen for text-inputs and issue appropriate canvas drawing commands.
All canvas commands must be issued in javascript...so yes, javascript is required.
Here's annotated code and a Demo: http://jsfiddle.net/m1erickson/f6E6Y/
<!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");
// vars for current width and height of a canvas rectangle
var width=50;
var height=35;
// references to the input-text elements
// used to let user change the rect width & height
var $width=document.getElementById('width');
var $height=document.getElementById('height')
// set the initial input-text values to the width/height vars
$width.value=width;
$height.value=height;
// call the draw command
draw();
// listen for keyup events on width & height input-text elements
// Get the current values from input-text & set the width/height vars
// call draw to redraw the rect with the current width/height values
$width.addEventListener("keyup", function(){
width=this.value;
draw();
}, false);
$height.addEventListener("keyup", function(){
height=this.value;
draw();
}, false);
// draw() clears the canvas and redraws the rect
// based on user input
function draw(){
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.fillRect(40,40,width,height);
}
}); // end $(function(){});
</script>
</head>
<body>
Width:<input type="text" id="width"><br>
height:<input type="text" id="height"><br>
<canvas id="canvas" width=300 height=300></canvas>
</body>
</html>
Related
I want to create an html5 game which contains multiple sprites.
For different elements I want to create an fixed fps.
For example:
Walk - 10 fps, so 10 sprites will be shown within 1 second
Run - 15 fps
Attack - 3 fps
How can I create this with requestAnimationFrame and not using set timeout or setinterval.
You can use the timestamp feature of requestAnimationFrame to trigger animations at different desired frames-per-second
function animate(timestamp){
// timestamp is a representation of the current elapsed time
}
The method is to set individual times when you want each action to be executed:
WalkTriggerTime = timest + 1000/desiredFPS;
Then do the action when the requestAnimationFrame timestamp exceeds this trigger time
if( timestamp > WalkTriggerTime ){
// execute a walk
// and reset the trigger timer
WalkTriggerTime = timest + 1000/desiredFPS;
}
Example Code and a Demo: http://jsfiddle.net/m1erickson/D6SU8/
<!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(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var animations=[]
var fps03={x:20,y:20,fps:03,frameCount:0,triggerTime:null,}
var fps10={x:20,y:40,fps:10,frameCount:0,triggerTime:null,}
var fps15={x:20,y:60,fps:15,frameCount:0,triggerTime:null,}
var stopAnimation=false;
animations.push(fps03,fps10,fps15);
for(var i=0;i<animations.length;i++){
var a=animations[i];
ctx.fillText(a.fps,a.x,a.y)
}
requestAnimationFrame(animate);
function animate(t){
if(!stopAnimation){requestAnimationFrame(animate);}
for(var i=0;i<animations.length;i++){
var a=animations[i];
if(!a.triggerTime){a.triggerTime=t+1000/a.fps;}
if(t>a.triggerTime){
a.triggerTime=t+1000/a.fps;
a.frameCount++;
ctx.clearRect(a.x+20,a.y-15,19,20)
ctx.fillText(a.frameCount,a.x+20,a.y)
ctx.fillRect(a.x+40,a.y-10,a.frameCount,15);
if(a.x+40+a.frameCount>canvas.width-20){stopAnimation=true;}
}
}
}
}); // end $(function(){});
</script>
</head>
<body>
<h4>Using the timestamp feature of RAF to control fps</h4>
<h4>Left#:fps, Mid#:Execution Count</h4>
<canvas id="canvas" width=300 height=300></canvas>
</body>
</html>
I need to set up a background canvas with a load of images drawn on at various places. Nothing changes on this background, so I want to do it all at once. I think I know how to do that. Then each frame I want to copy that background canvas (ultimately just a part of it) to my main screen canvas people see.
I am doing the following:
g_CanvasScreen = document.getElementById("m_Canvas");
g_CanvasScreenContext = g_CanvasScreen.getContext("2d");
g_OffScreenBackground = document.createElement("canvas");
g_OffScreenBackgroundContext = g_CanvasScreen.getContext("2d");
I believe this gets the main screen canvas from the hmtl5 page g_CanvasScreen.
I believe g_OffScreenBackground is a newly created canvas in memory.
Once all images have loaded I then draw all the images in the correct places to the background screen by calling the function:
DrawMapToBackground(g_OffScreenBackground, g_OffScreenBackgroundContext, 2000, 1600);
2000 x 1600 is the size of the offscreen background.
This then leads to the thing I am not sure about. I believe this will blit the background canvas to the main screen:
g_CanvasScreenContext.drawImage(g_OffScreenBackground,
0, 0, g_OffScreenBackground.width, g_OffScreenBackground.height,
screenX, screenY, g_OffScreenBackground.width, g_OffScreenBackground.height);
Is this last function correct? Can I do a canvas to canvas blit? Should I be doing this another way?
Instead of redrawing the background each time, just put 2 canvas’s on top of each other.
First draw the background image once on the bottom canvas.
Then use the top canvas to draw all your “changing” drawings.
Here’s code and a Fiddle: http://jsfiddle.net/m1erickson/pSjEt/
<!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>
#container{
position:relative;
border:1px solid blue;
width:500px;
height:300px;
}
.subcanvs{
position:absolute;
width:100%;
height:100%;
}
</style>
<script>
$(function(){
var bk=document.getElementById("background");
var bkCtx=bk.getContext("2d");
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var bkimg=new Image();
bkimg.onload=function(){
bk.width=bkimg.width;
bk.height=bkimg.height;
canvas.width=bkimg.width;
canvas.height=bkimg.height;
bkCtx.drawImage(bkimg,0,0);
draw();
}
bkimg.src="https://dl.dropboxusercontent.com/u/139992952/stackoverflow/skyGrass.png";
var x=50;
function draw(){
x+=5;
if(x>300){x=50;}
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.beginPath();
ctx.arc(x,100,30,0,Math.PI*2,false);
ctx.strokeStyle="gold";
ctx.fillStyle="yellow";
ctx.lineWidth=5;
ctx.stroke();
ctx.fill();
setTimeout(draw,1000);
}
}); // end $(function(){});
</script>
</head>
<body>
<div id="container">
<canvas id="background" class="subcanvs"></canvas>
<canvas id="canvas" class="subcanvs"></canvas>
</div>
</body>
</html>
What I have so far: http://sem.serialshop.nl/video/
My goal is to manipulate the video pixels to show corresponding information inside the pupil when hovering one of the buttons. Can I delete the pixels inside the pupil, and replace it with an image?
Removing pixels from an mp4 video—removing pixels of an eye pupil
As darma says, you can probably finish your project by just using context.drawImage() to superimpose your image over the pupil. Here's how you do that.
Also, here's how you would remove the pixels of the pupil (as you asked).
Background
You can take an mp4 video and draw it frame-by-frame into a canvas.
The canvas drawing rate is quick enough that the results look as good as the video they were taken from.
More interestingly, you can manipulate each frame as it’s drawn into the canvas. This allows you to take the pixels of the pupil and replace them.
Manipulating pixels:
You manipulate the canvas frame by using context.getImageData() to grab the pixels into a data array.
Then you manipulate the data array in whatever way you wish.
Finally, you put the modified data array back into the canvas using context.putImageData().
The canvas then shows the modified pixels!
Your Solution
To solve your problem, we get the bounding-box containing the pupil. Every time we see a nearly-black pixel in that bounding box, we know it’s the pupil and we can modify that nearly-black pixel. In the following working code, we just change the pixel from nearly-black to pure red. However, you can do whatever you desire to the pupil pixels.
Here is code to draw the video with the pupil pixels colored red:
<!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(){
var centerX=315;
var centerY=150;
var radius=10;
var rx=267;
var ry=98;
var rwidth=101;
var rheight=95;
var video = document.getElementById('vid');
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var cw = 638;
var ch = 358;
canvas.width = cw;
canvas.height = ch;
video.addEventListener('play', function(){
draw(this,ctx,cw,ch);
},false);
function draw(video,context,w,h) {
if(video.paused || video.ended) return false;
context.drawImage(video,0,0,w,h);
// at this point you could also draw a second image
// into the pupil of the eye like this
// context.drawImage(myImage,rx,ry,rwidth,rheight);
// but what we do here is just put a red bounding box
// around the pupil so that we can see we are
// properly focusing on the pupil area
context.fillStyle="blue";
context.strokeStyle="red";
context.lineWidth=2;
context.beginPath();
context.rect(rx,ry,rwidth,rheight);
context.stroke();
extractPupil(context);
setTimeout(draw,150,video,context,w,h);
}
function extractPupil(context){
// get just the bounding rectangle of the pupil
// NOT the whole canvas.
var imgData=context.getImageData(rx,ry,rwidth,rheight);
var data=imgData.data;
for(var i=0;i<data.length;i+=4){
// if the pixel color is nearly black--change it to red
if(data[i]<20 && data[i+1]<20 && data[i+2]<20){
data[i]=255;
data[i+1]=0;
data[i+2]=0;
}
}
// put the modified pixels back into the canvas
// Now the pupil is colored pure red!
context.putImageData(imgData,rx,ry);
}
}); // end $(function(){});
</script>
</head>
<body>
<canvas id="canvas"></canvas>
<video id="vid" controls loop>
<source src="eye.mp4" type=video/mp4>
</video>
</body>
</html>
I tried to create rectangle in canvas, i am bit confused with coordinate system of canvas
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>jQuery UI Dialog - Modal form</title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<style>
body{
background-color: #231F20;
}
#ribbonid{
width:90px;
height: 90px;
}
</style>
</head>
<body>
<canvas id='ribbonid' > </canvas>
<script>
$(document).ready(function(){
var $ribbonid = $('#ribbonid');
// get the canvas element using the DOM
var canvas = document.getElementById('ribbonid');
// Make sure we don't execute when canvas isn't supported
if (canvas.getContext){
// use getContext to use the canvas for drawing
var cts = canvas.getContext('2d');
cts.fillStyle = '#f7911e';
cts.beginPath();
cts.moveTo(0, 0);
cts.lineTo(90, 0);
cts.lineTo(90, 90);
cts.lineTo(0, 90);
cts.lineTo(0, 0);
cts.fill();
cts.closePath();
}
});
</script>
</body>
</html>
http://jsfiddle.net/bkf2e/
i am aware of canvas.rect function, but i need to create some different shape for me.
I created rectangle of size (90,90)(square), but it is creating full square.
I know it may be my simple mistake, but can you please help me on that.
you need to set the size of your canvas using the width and height attributes, if you use css to size it then it will scale the default size rather than becoming the size you want, which is why it was distorted like that.
I've updated your jsfiddle with the attributes set and you'll see that it's now square.
solved problem,
it was silly mistake of width and height attribute
<canvas id='ribbonid' width='90' height='90' > </canvas>
I am working with some image manipulations and I am trying to have a basic canvas and I have a text box now If I enter any text it should change immediately on the canvas and I need that text to move on the canvas and record it's X and Y positions.So how do I do that?
Here is my code:
<!DOCTYPE html>
<html>
<head>
<title>HTML5 Canvas</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script type="text/javascript">
var drawLogo = function () {
var canvas = document.getElementById('my_canvas');
var context = canvas.getContext('2d');
context.font = 'italic 40px sans-serif';
context.textBaseline = 'top';
context.fillText('Some text', 60, 0);
};
$(function () {
var canvas = document.getElementById('my_canvas');
if (canvas.getContext) {
drawLogo();
}
});
</script>
</head>
<body>
<canvas id="my_canvas" width="900" height="300">
Fallback content here
</canvas>
<input id="Text1" type="text" />
</body>
</html>
First, everytime the text changes you'll need to re-draw the ENTIRE canvas.
Do this:
Add a myText, x & y inputs to your drawLogo function: drawLogo(myText, x, y) and change this line to context.fillText(myText, x, y);
To change text on the canvas, add a JS event handler to the textbox and call the new drawLogo function passing all 3 input parameters.
Keep in mind that you cannot modify what's drawn on a Canvas. You can only draw it once so all modifiers have to be done in one pass.
The moving part is not clear but you'll need to calculate your equations of motion in JS beforehand. When you call the new drawLogo(myText, x, y) you'll pass these values from JS.
Watch out for this line context.textBaseline = 'top'; as last time I checked it wasn't supported in Firefox.