HTML5 Canvas reset when adding to the body with Javascript - javascript

So, I am currently working on an HTML5 game that uses a canvas element as a "point bucket", a visual gauge to the number of points the user has gained. But, something strange happens to the canvas when I add an element to the HTML document body
So, when writing to the body with javascript (document.body.innerHTML = "whatever";), the canvas will erase everything within itself and reset. Here is a quick and dirty example that I have whipped up to show you what I mean:
<!DOCTYPE HTML>
<html>
<body>
<canvas id="a"></canvas>
<script type = "text/javascript">
function addToBody()
{
document.body.innerHTML += "<p>I am adding to the body</p>";
}
var can = document.getElementById("a");
var con = can.getContext("2d");
//Draw rectangle on canvas
con.fillRect(0,50,100,100);
//Add text to body after 5 seconds
setTimeout("addToBody()",5000);
</script>
</body>
</html>
I know the traditional way to reset a canvas is to assign the canvas width like so:
canvas.width = canvas.width;
Is this another way to achieve the same effect or just a bug? Can someone give me some insight about this? Thanks.

Doing innerHTML += something means that the contents are retrieved as a string, something is added to that string, then the whole lot is assigned to the body, whereupon (the layout of) it is all recalculated. (and event listeners are dropped - unless they're inline handlers)
You should use the object-oriented functions to do achieve the same.
I.e
var newElem = document.createElement('p');
newElem.appendChild( document.createTextNode('I am adding to the body') );
document.body.appendChild(newElem);
This will leave your canvas untouched.

Related

Canvas clears on parent element attribute change

I create a canvas on the fly from a video. This works great and the canvas is correct and shall never be changed. So what I do I wrap the canvas in 2 divs. Now I change any attribute, even when I call element.setAttribute('test',''), via js on one of the 3 elements and the canvas clears.
I have sadly no clue why this is happening. I only want to set the positioning of the direct canvas parent, and its parent shall toggle between display: none and display: block
Any idea why this is happening and how I can prevent it?
[EDIT] I found the problem:
To append the canvas at the correct position I changed
container.innerHTML = ''
container.appendChild(canvas)
to
container.innerHTML = canvas.outerHTML
The later is initially fine, however when I change something on any attribute of the canvas, the container or parent the canvas content clears.
Why is this? Shouldn't the code do the same thing?
Tested in Firefox, Chrome & Chromium
It's not the attribute that causes the problem, but the canvas you create by doing
container.innerHTML = canvas.outerHTML
is not the same canvas anymore, but an entirely new canvas element, which doesn't have any context initialized, and which will be fully transparent.
const canvas = document.createElement('canvas');
const output = document.getElementById('output');
output.append( canvas );
console.log(
'same canvas with append?',
document.querySelector('#output>canvas') === canvas
); // true
document.getElementById('output').innerHTML = canvas.outerHTML;
console.log(
'same canvas with innerHTML?',
document.querySelector('#output>canvas') === canvas
); // false
<div id="output"></div>
So if you want to keep the drawings of your canvas, you need to keep that same element in the DOM, and for this you need to append it.

Canvas to be same height to left column

I am new to JavaScript and I found a codepen which allowed me to create a canvas with confettis falling with javascript. I added the javascript to my project but it seems that the canvas height to way too long. I want the canvas height to be the same as the column on the left (Body). It seems that the canvas' height is set using Javascript but I am still a beginner to the language and hence not sure how to modify it to the way I want. Would appreciate any help thanks.
<canvas id="confeti" class="active" width="100%" height="100%">
</canvas>
Codepen: https://codepen.io/anon/pen/gomLNV
one solution would be to call this onload :
function fixSize(){
var confeti = document.getElementById("confeti");
var leftSide = document.getElementById("leftSide");
confeti.style.height = leftSide.clientHeight + 'px';
}
Ofcourse you have to add the id leftSide to the element which you want to use as max height.
To be fair this is really ugly and simple.
code similar to what spaceninja posted.
i didn't mess with any of your css, its just three lines of js, close to what he responded with:
let b = document.getElementById('b');
let c = document.getElementById('confeti');
c.style.height = b.clientHeight+'px';
https://codepen.io/anon/pen/dJvNQb

Unable to target child element of Canvas

Here is my code
javascript: (function() {
var canvas = document.getElementById("app-view").children[1];
var img = canvas.toDataURL("image/png");
window.open(img);
})();
and here is the app element where I wish to target the second canvas element "children1" but it's not working for some reason and always gets stuck at the first element. A solution will be much appreciated, thanks in advance!
In the picture it always targets the first canvas in yellow but I need the one displayed in blue. You can test the code by saving the script as a bookmark in your browser.
Haven't worked out why toDataURL gets the data of the left canvas, but if you wanted to save the canvas, you can isolate it with
var can = document.getElementById("app-view").children[1];
jQuery("body > *").remove();
jQuery("body").append(can) ;
and then now you can right click and save the canvas
This works for me:
document.getElementById('app-view').childNodes[1]

Raphael Javascript

I am new to Raphael and am trying to do something very simple, but failing miserably. Does anyone know how to create a Raphael canvas and set the background color (ex: green)? This is what I have so far, but when I open it in a browser it displays nothing....
<html>
<head><title></title>
<script src="raphael-min.js"></script>
</head>
<body>
<script type="text/javascript">
//all your javascript goes here
var paper = Raphael(15,40,320,300);
</script>
</body>
</html>
When I put this code inside the js script it displays a circle correctly...
var circle = paper.circle(50,10,10);
circle.attr("fill","#0f0");
But again, my issue is trying to set the background color. Any help would be appreciated.
Thanks
RaphaelJS doesn't provide a default background styling, since its event system relies on being object-driven. However, you can designate a particular DIV and style it accordingly:
<div
id="my_paper_div"
style="background-color:limegreen;width:400px;height:400px"
></div>
Make sure you don't call either the DIV or variable paper. Give them different names, otherwise you'll run into some IE incompatibility.
Redeclare your paper javascript like so:
// declare outside the startup scope, so you can do fancy things later
var my_paper;
// raphaeljs' version of onload
Raphael( function() {
my_paper = Raphael("my_paper_div", 400, 400);
});
Since RaphaelJS rendering doesn't interfere with the background, you can technically mix and match HTML and SVG/VML. For example, see this jsfiddle: http://jsfiddle.net/NQtU5/
You could also draw a rectangle the size of the canvas:
var paper = Raphael("my_paper_div", 600, 400),
placemat = paper.rect(0,0,paper.width,paper.height).attr({"fill" : "#99FF99" });
I usually start this way with Raphael projects because I find it useful to have an object in the background to which to attach events, like a click event that closes all open tooltips.
See example.

Programmatically Clip/Cut image using Javascript

Are there any documents/tutorials on how to clip or cut a large image so that the user only sees a small portion of this image? Let's say the source image is 10 frames of animation, stacked end-on-end so that it's really wide. What could I do with Javascript to only display 1 arbitrary frame of animation at a time?
I've looked into this "CSS Spriting" technique but I don't think I can use that here. The source image is produced dynamically from the server; I won't know the total length, or the size of each frame, until it comes back from the server. I'm hoping that I can do something like:
var image = getElementByID('some-id');
image.src = pathToReallyLongImage;
// Any way to do this?!
image.width = cellWidth;
image.offset = cellWidth * imageNumber;
This can be done by enclosing your image in a "viewport" div. Set a width and height on the div (according to your needs), then set position: relative and overflow: hidden on it. Absolutely position your image inside of it and change the position to change which portions are displayed.
To display a 30x40 section of an image starting at (10,20):
<style type="text/css">
div.viewport {
overflow: hidden;
position: relative;
}
img.clipped {
display: block;
position: absolute;
}
</style>
<script type="text/javascript">
function setViewport(img, x, y, width, height) {
img.style.left = "-" + x + "px";
img.style.top = "-" + y + "px";
if (width !== undefined) {
img.parentNode.style.width = width + "px";
img.parentNode.style.height = height + "px";
}
}
setViewport(document.getElementsByTagName("img")[0], 10, 20, 30, 40);
</script>
<div class="viewport">
<img class="clipped" src="/images/clipped.png" alt="Clipped image"/>
</div>
The common CSS properties are associated with classes so that you can have multiple viewports / clipped images on your page. The setViewport(…) function can be called at any time to change what part of the image is displayed.
In answer to :
Alas, JavaScript simply isn't capable of extracting the properties of the image you'd require to do something like this. However, there may be salvation in the form of the HTML element combined with a bit of server-side scripting.
...
< ? (open php)
$large_image = 'path/to/large_image';
$full_w = imagesx($large_image);
$full_h = imagesy($large_image);
(close php) ? >
This can be done in Javascript, just google a bit :
var newimage = new Image();
newimage.src = document.getElementById('background').src;
var height = newimage.height;
var width = newimage.width;
This generates a new image from an existing one and captures this way in java script the original height and width properties of the original image (not the one id'ed as background.
In answer to :
The width/height properties of the document's image object are read only. If you could change them, however, you would only squish the frames, not cut the frames up like you desire. The kind of image manipulation you want can not be done with client-side javascript. I suggest cutting the images up on the server, or overlay a div on the image to hide the parts you do not wish to display.
...
var newimage = new Image();
newimage.src = document.getElementById('background').src;
var height = newimage.height;
var width = newimage.width;
newimage.style.height = '200px';
newimage.style.width = '200px';
newimage.height = '200px';
newimage.width = '200px';
and if wanted :
newimage.setAttribute('height','200px');
The doubled newimage.style.height and newimage.height is needed in certain circumstances in order to make sure that a IE will understand in time that the image is resized (you are going to render the thing immediately after, and the internal IE processing is too slow for that.)
Thanks for the above script I altered and implemented on http://morethanvoice.net/m1/reader13.php (right click menu... mouseover zoom lent) correct even in IE , but as you will notice the on mousemove image processing is too fast for the old styled IE, renders the position but only once the image. In any case any good idea is welcome.
Thanks to all for your attention, hope that the above codes can help someone...
Claudio Klemp
http://morethanvoice.net/m1/reader13.php
CSS also defines a style for clipping. See the clip property in the CSS specs.
The width/height properties of the document's image object are read only. If you could change them, however, you would only squish the frames, not cut the frames up like you desire. The kind of image manipulation you want can not be done with client-side javascript. I suggest cutting the images up on the server, or overlay a div on the image to hide the parts you do not wish to display.
What spriting does is essentially position a absolutely-positioned DIV inside another DIV that has overflow:hidden. You can do the same, all you need to do is resize the outer DIV depending on the size of each frame of the larger image. You can do that in code easily.
You can just set the inner DIV's style:
left: (your x-position = 0 or a negative integer * frame width)px
Most JavaScript Frameworks make this quite easy.
Alas, JavaScript simply isn't capable of extracting the properties of the image you'd require to do something like this. However, there may be salvation in the form of the HTML <canvas> element combined with a bit of server-side scripting.
PHP code to go about extracting the width and height of the really large image:
<?php
$large_image = 'path/to/large_image';
$full_w = imagesx($large_image);
$full_h = imagesy($large_image);
?>
From here, you'd then load the image into a <canvas> element, an example of which is documented here. Now, my theory was that you may be able to extract pixel data from a <canvas> element; assuming that you can, you would simply make sure to have some form of definite divider between the frames of the large image and then search for it within the canvas. Let's say you found the divider 110 pixels from the left of the image; you would then know that each "frame" was 110 pixels wide, and you've already got the full width stored in a PHP variable, so deciphering how much image you're working with would be a breeze.
The only speculative aspect to this method is whether or not JavaScript is capable of extracting color data from a specified location within an image loaded into a <canvas> element; if this is possible, then what you're trying to accomplish is entirely feasible.
I suppose you want to take a thumbnail for your image. You can use ImageThumbnail.js that created from prototype library in this way:
<script type="text/javascript" src="prototype.js"></script>
<script type="text/javascript" src="ImageThumbnail.js"></script>
<input type="file" id="photo">
<img src="empty.gif" id="thumbnail" width="80" height="0">
<script type="text/javascript">
<!--
new Image.Thumbnail('thumbnail', 'photo');
//-->
</script>
for more information
try use haxcv library haxcv js by simple functions
go to https://docs.haxcv.org/Methods/cutImage to read more about his library
var Pixels = _("img").cutImage (x , y , width , height );
_("img").src (Pixels.src);
// return cut image
but try to include library first

Categories

Resources