I'm trying to to change dynamically a context.clip(); in a HTML5 canvas, drawing a shape with different values from an array. The idea is to get different parts of a board-game illuminated one after the other, clipping a darker version of the board to see just a square of the clearer version.
That's the code I'm struggling with, based in other questions from this very site, but I really cannot find the error:
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>HTML5 Trivial</title>
<script type="text/javascript">
var strings = new Array();
strings[0] = "context.moveTo(134,487);context.lineTo(169,435);context.lineTo(200,449);context.lineTo(172,508);";
strings[1] = "context.moveTo(102,461);context.lineTo(142,414);context.lineTo(169,434);context.lineTo(133,485);";
strings[2] = "context.moveTo(71,434);context.lineTo(120,394);context.lineTo(143,414);context.lineTo(99,461);";
strings[3] = "context.moveTo(49,403);context.lineTo(101,370);context.lineTo(121,394);context.lineTo(70,435);";
strings[4] = "context.moveTo(19,340);context.lineTo(78,320);context.lineTo(99,370);context.lineTo(48,404);context.lineTo(31,375);";
strings[5] = "context.moveTo(172,507);context.lineTo(198,449);context.lineTo(231,458);context.lineTo(211,522);";
strings[6] = "context.moveTo(259,531);context.lineTo(267,466);context.lineTo(230,460);context.lineTo(213,521);";
strings[7] = "context.moveTo(257,531);context.lineTo(266,468);context.lineTo(300,470);context.lineTo(334,466);context.lineTo(347,531);context.lineTo(302,534);";
var images = new Array();
function draw(i){
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
var img = new Image();
img.src = 'board_dark.jpg';
img.onload = function() {
context.drawImage(img,0,0);
}
images[i] = new Image();
images[i].onload = function() {
eval(strings[Math.floor(Math.random()*6)]);
context.closePath();
context.clip();
context.drawImage(images[i],0,0);
i = i + 1;
window.setTimeout(function(){draw(i)},100);
}
images[i].src = 'board.jpg';
}
</script>
</head>
<body onLoad="draw(0);">
<canvas id="myCanvas" width="1024" height="1024"></canvas>
</body>
</html>
Am I coding terribly? I've been changing ways of writing, trying not to use the eval(), etc., without success...
Thank you for your help, as always!
Ramon
PD- Sorry for my English!
Your code is really really strange. I've redone some of it to give you a better idea of how to go about coding this (without using eval, for one!)
http://jsfiddle.net/p6tXv/
Now there is a general function that will draw from a list of points that you give it (they are the same points you supplied).
You almost certainly don't want to use clip and a dark image, instead you should be drawing over the board with semi-transparent black.
I wrote the code in such a way that it will black out the spots. If you want to black out everything except the spots then you will have to write a pat that is a little more complex, but it shouldn't be that hard.
Just a comment on the coding style; the use of eval() to call your context.moveTo logic is all kinds of bad. Check Google for various reasons on "why eval is bad"; it's been mentioned elsewhere numerous times.
Instead of storing commands, store the coordinates as polygon-style objects, and iterate through the points in order to achieve the desired result.
I realize that this could be a simple demo written to illustrate a specific purpose, but if you're sharing the code at all, then you'll be sharing bad code. Consider revising.
Related
I'm two days into js,html and css programming. So very newbie!
Following and building upon this TUTORIAL
Q1: How can I add this male into the background (see figuere 1.) and prohibit any strokes outside of the borders?
Adding image to background was no biggy!
function make_base()
{
base_image = new Image();
base_image.src = 'img/bmapFront.gif';
base_image.onload = function(){
context.drawImage(base_image, 0,0);
}
}
There is a context.clip function, not sure if I can use pixel form as clipping path. Making tons of "image substractions" isn't the best way.
Any suggestions
Edit:
Did the Job for me: VeryHelpful
var frontPath = new Path2D ("M 133.41,17.00 C 141.37,2.41 160.66, !VERY LONG! ")
context.clip(frontPath);
Messy strokes!
He should look like this. Then I want to save him.
Although there is such a thing as ctx.clip(), this is sometimes not what's wanted as it's impractical to use a path.
The solution that I like involves creating a virtual empty canvas onto which you draw your pixel image. Through various manipulations, like using ctx.getImageData and similar to make sure you only get one kind of color or apply other filters only once, you can obtain an image that seems to be empty (alpha of 0, mostly) in the places where you want to clip other images or paths out.
At that point, you'd use ctx.globalCompositeOperation = 'source-atop', or pick another one you might want to use from mdn's list of globalCompositeOperations.
At this point, you can just draw this virtual canvas image onto the main canvas
So I have a semi-complex canvas drawing someone gave me. It draws an image vertically (i.e., top-down). Let's assume its a stick figure with facial features.
This is done in Javascript and Canvas. i.e.: ctx.beginPath(), ctx.moveTo(x,y), ctx.lineTo(1,1), etc.
I want the stick figure to move towards some point (x,y) and to face that direction while moving toward it. For example, if the x,y is near the bottom right, I want the stick figure to be oriented in a way such that its feet are facing towards the bottom right while it is moving.
The main question is, how would I go about doing this (i.e changing the stickman), knowing that I have a "hardcoded" drawing (in this example, stickman) that has been given to me?
You can render the received image on a separate canvas (doesn't need to be displayed) and use ctx.canvas.toDataURL() to convert it to an image. You could then embed the resulting image in your canvas and apply transforms to it more easily.
I mentioned this in a comment on the question but it sounded like fun, so I implemented a proof of concept.
var canvasObject = function(ctx) {
ctx.beginPath();
ctx.moveTo(0,0);
ctx.arc(30,30,15,0,2*Math.PI);
ctx.fillStyle='red';
ctx.fill();
return ctx;
}
var myCtx = document.querySelector('canvas').getContext('2d');
var objCtx = document.createElement('canvas').getContext('2d');
var renderedObjUrl = canvasObject(objCtx).canvas.toDataURL();
var renderedObj = document.createElement('img');
renderedObj.setAttribute('src', renderedObjUrl);
myCtx.drawImage(renderedObj, 30, 10);
<canvas id="myCanvas" width="600" height="400"></canvas>
I'm new to HTML5, and I'm planning to create a tool to demonstrate how a character was written by hand in correct order.
I've this code to create a Chinese character with canvas, but is there a way to draw it step by step until the whole character is complete? Using Javascript is welcome, I don't want to use gif or flash to draw so many frames.
Any idea? Thanks.
<!DOCTYPE html>
<html>
<head>
<title>Canvas beginePath example</title>
<script>
function beginDemo() {
var canvas = document.getElementById("demo")
var ctx = canvas.getContext('2d');
ctx.font = "52pt 楷体";
ctx.fillText("字", 220, 200);
}
</script>
</head>
<body onload="beginDemo();">
<canvas id="demo" width="800" height="800"></canvas>
</body>
</html>
The zhongwen development tool (GPL) includes a large text file with stroke animation data. I remember that it was fairly easy to render the stroke shapes using Pixi, but animating them seemed challenging. At the time I made a mental note to find out from the zdt people if the data could be used and then make something to animate it nicely, but never did. Someone else had a similar idea which is really quite nicely done. Code is MIT license. Maybe you can use that, or at least get some ideas from it. Assuming three years on this might still be relevant to you.
I am faced with a problem that slows down animation on a canvas, as various pictures move left, right, up and down. I need advice on how to optimize the animation.
It is important that the animation works on all main browsers, in particular: Chrome, Firefox and Internet Explorer.
Is it possible to optimize the animation? Maybe put a delay on the drawing? Thank you in advance.
In javascript you can use the setInterval and setTimeout functions to create delays and throttle the frame rate.
for instance if you wanted to make your drawing loop approximately 30 FPS you could have some code that looks like this:
function draw(){
var canvas = document.getElementById('myCanvas');
//create the image object
var img = new Image();
//set the image object's image file path
var img.src = "images/myImage.png"
//check to see that our canvas exists
if( canvas.getContext )
{
//grab the context to draw to.
var ctx = cvs.getContext('2d');
//clear the screen to a white background first
//NOTE to make this faster you can clear just the parts
//of the canvas that are moving instead of the whole thing
//every time. Check out 'Improving HTML5 Canvas Performance'
//link mention in other post
ctx.fillStyle="rgb(255,255,255)";
ctx.fillRect (0, 0,512, 512);
//DO ALL YOUR DRAWING HERE....
//draw animation
ctx.drawImage(img, 0, 0);
}
//Recalls this draw update 30 times per second
setTimeout(draw,1000/30);
}
This will help you control how much processing time the animation is taking. Thus if you find that your animation is going too slow you can increase the frame rate by changing the denominator '30' to something like '60' fps or anything that really works well for your program.
As far as optimizing goes in addition to setTimeout() the way you draw your animations is critical too. Try to load all your images before you render them this is called "Preloading". That is if you have a bunch of different images for each animated cell then before you call your draw function load all the images into an array of images like so:
var loadedImages = new Array();
loadedImages[0] = new Image();
loadedImages[0].src = "images/animationFrame1.png";
loadedImages[1] = new Image();
loadedImages[1].src = "images/animationFrame2.png";
loadedImages[2] = new Image();
loadedImages[2].src = "images/animationFrame3.png";
loadedImages[3] = new Image();
loadedImages[3].src = "images/animationFrame4.png";
you could even put them in a hash if it makes sense for you app where instead of
loadedImages[0] = new Image();
loadedImages[0].src = "images/animationFrame1.png";
you do this
loadedImages['frame1'] = new Image();
loadedImages['frame1'].src = "images/animationFrame1.png";
once you have all your images loaded you references them for drawing by doing calling them like so:
//Using the integer array
ctx.drawImage(loadedImages[0], 0, 0);
//OR
//Using the stringed hash
ctx.drawImage(loadedImages['frame1'], 0, 0);
You want to separate your loading process from your rendering process because loading images is process intensive thus will slow your animations down if you are loading things while rendering.
That is not to say that you can't ever load anything while rendering, but instead just be conscience that this will slow animation speed down.
Here is an article on preloading images.
There is another post on here which talks about consistent animation speed on all browsers here
Note the link posted by the green checked answer
Other things to be noted are making sure to only clearing and redrawing bounding boxes as mentioned in the post with HTML 5 canvas optimization. That link has some really good techniques to be conscience of while developing canvas animations.
Here are some frame works as well which might come in handy to cross compare what you are doing to what other engines are doing.
Hope some of this helps. I am new to javascript (only started coding with it about 2 weeks ago) and so there could be better ways to do things but these are the things I have found thus far.
window.requestAnimationFrame() is one sure way to make your animation run smoother.
https://developer.mozilla.org/en/DOM/window.mozRequestAnimationFrame
(cross browser http://paulirish.com/2011/requestanimationframe-for-smart-animating/ )
However it doesn't fix the possible problems with your drawing code which was missing from the question.
So, I'm using this function getImageData on the "context" variable that I've made inside of the <script> part, and when I do something such as draw a rectangle then do ctx.getImageData.data[0] it will show the red value of that rectangle that I drew on the canvas. But, when I import an image and draw it onto the canvas, and try to use the getImageData.data[0] all I get is 0, which makes no sense, I'm not sure why it is not reading the image correctly. I've tried tutorials on this but they're all vague and only have segments written together.
So, when I draw the rectangle, its color value comes out just fine, but again, when I draw the image, even without drawing the rectangle on the canvas, I never get the value of that particular pixel on the image.
Can someone help me? Here's my currrent code:
<html>
<head>
<title>
Color Test :)
</title>
</head>
<body>
<canvas id = "ColorTest" width = "500" height = "500">
please don't use shitty browsers :)
</canvas>
<script>
//netscape.security.PrivilegeManage…
var canvas = document.getElementById("ColorTest")
, ctx = canvas.getContext("2d")
, image = new Image()
image.onload = function(){
ctx.drawImage(image,0,0)
}
image.src = 'Pikachu.gif'
ctx.fillStyle = "rgb(123,40,170)"
ctx.fillRect(0,0,100,100)
var imagedata = ctx.getImageData(0,0,100,100)
, spot = 0
while(imagedata.data[spot] == 0){
spot++
}
console.log(imagedata.data[0])
</script>
</body>
</html>
Does the following alert anything sensible?
image.onload = function() {
ctx.drawImage(image, 0, 0);
var id = ctx.getImageData(0,0,canvas.width,canvas.height);
alert([id.data[0], id.data[1], id.data[2], id.data[3]].join(", "));
}
It could be that the image is transparent. Try with a single color non-transperent image.
What browser are you using? Using getImageData when loading an image from another domain is not allowed (security issue), and if I remember correctly there is some browsers that have problems determining the domain when running scripts localy