Canvas layers and positioning - javascript

I'm having hard time on figuring out how should i do in order to set a proper size to the following canvases
<div id="canvasesdiv" style="height: 100%; width: 100%; display: table-cell; position: relative; width:578px; height:415.5px">
<canvas id="c1" style="z-index: 1; position:absolute; left: 80px; width="680" height="435"></canvas>
<canvas id="c2" style="z-index: 2; position:absolute; left: 80px; width="680" height="435"></canvas>
<canvas id="c3" style="z-index: 3; position:absolute; left: 80px; width="680" height="435"></canvas>
<canvas id="c4" style="z-index: 4; position:absolute; left: 80px; width="680" height="435"></canvas>
<canvas id="c5" style="z-index: 5; position:absolute; left: 80px; width="680" height="435"></canvas>
Cleary width and height are parsed wrongly (html is expecting : and the values in px) but somehow the canvases are drawn in their full dimension. Instead if i use something like:
<canvas id="c1" style="z-index: 1; position:absolute; left: 80px; "></canvas>
<canvas id="c2" style="z-index: 2; position:absolute; left: 80px; "></canvas>
<canvas id="c3" style="z-index: 3; position:absolute; left: 80px; "></canvas>
<canvas id="c4" style="z-index: 4; position:absolute; left: 80px; "></canvas>
<canvas id="c5" style="z-index: 5; position:absolute; left: 80px; "></canvas>
or with
... width: 500px; height: 500px;"
The canvases are all cropped down to 300x150 (chrome default) no matter what.
The problem is that position:absolute is a must in order to have layers. How can i do in order to define a dimension without ruin the canvas quality and make it so it stays in the given boundary?
See this example, can you fix it so that the position is absolute but the size is whatever you want and centered? See here.
If I add position:absolute, the overlay works but it is out of the div bound, see here.

You are inserting HTML width and height attributes in the style attributes, which should hold css. If you check the dev tools, you will see the relevent rules are striked through. Just use css to style them. Even better, place them in the <style/> tag or in an external stylesheet
Not good:
<canvas style="... width="680" height="435"></canvas>
Good:
<canvas style="... width: 680px; height: 435px;"></canvas>
Or: just close the double quote, and use the attributes anyway (although css is the better solution)

Related

Issue positioning input on a canvas

I would like to make a program to find the third side of a right-angled rectangle based on the two others. My idea was to draw a triangle and to put input boxes next to the three diferent sides. However I'm having trouble making them stick to the sides (they move when you zoom). Here's the code:
<html>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta charset="UTF-8">
<head>
<title>Triangle rectangle</title>
<style>
.triangle {
position: relative;
text-align: center;
}
</style>
</head>
<body align="center">
<h2> Triangle rectangle </h2>
<div class="triangle">
<form autocomplete="off">
<input style="position: absolute; top: 50%; right: 65%; width: 3%" type="text" name="a" id="a" placeholder='a' >
<input style="position: absolute; top: 260px; right: 950px; width: 3%" type="text" name="b" id="b" autofocus='on' placeholder='b' >
<input style="position: absolute; top: 100px; right: 850px; width: 5%" type="text" name="hypo" id="hypo" placeholder='Hypothénuse' >
</form>
<canvas id="myCanvas" width="500" height="250" >Your browser does not support the HTML5 canvas tag.</canvas>
</div>
<script>
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(500, 250);
ctx.moveTo(0, 0);
ctx.lineTo(0, 250);
ctx.moveTo(0, 250);
ctx.lineTo(500, 250);
ctx.stroke();
</script>
</body>
</html>
Here's a site with the code: http://rightangledrectangleirl.bitballoon.com/
Edit: Managed to fix it:
<div style="position:relative; width:500px;height:250px; margin: 0 auto;" align="center">
<canvas id="myCanvas" width="500" height="250">Your browser does not support the HTML5 canvas tag.</canvas>
<form autocomplete="off">
<input style="position: absolute; top: 125px; left: 10px; width: 50px" type="text" name="a" id="a" autofocus='on' placeholder='a' >
<input style="position: absolute; top: 220px; right: 180px; width: 50px" type="text" name="b" id="b" autofocus='on' placeholder='b' >
<input style="position: absolute; top: 90px; right: 90px; width: 80px" type="text" name="hypo" id="hypo" autofocus='on' placeholder='Hypothénuse' >
</form>
</div>
Absolute positioning works relative to the last container which has the position attribute explicitly defined. In this case the triangle div has position:relative, so the input boxes will be absolutely positioned relative to that.
With this in mind it's important to note that when the size of the page changes, the size of your triangle div also changes, so the absolute positioning also changes. In order to fix this you should give the triangle container a fixed sized (or at least a predictable one). Making it match the size of your canvas seems like a good choice.
Giving it a fixed size unfortunately makes the way you centered it horizontally break, but that can be fixed by using margin : auto.
Lastly you should redo your top, left, bottom, right percentages. Keep in mind you can use pixels as well. I don't know exactly where you want the items positioned, but perhaps the following code will get you on track:
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(500, 250);
ctx.moveTo(0, 0);
ctx.lineTo(0, 250);
ctx.moveTo(0, 250);
ctx.lineTo(500, 250);
ctx.stroke();
.triangle {
position: relative;
text-align: center;
width : 500px;
height : 250px;
margin : auto;
}
#a {
position: absolute;
top: 50%;
left: 0px;
width: 3%;
}
#b {
position: absolute;
bottom: 0px;
right: 50%;
width: 3%
}
#hypo {
position: absolute;
top: 45%;
left: 40%;
width: 100px;
}
<body align="center">
<h2> Triangle rectangle </h2>
<div class="triangle">
<form autocomplete="off">
<input type="text" name="a" id="a" placeholder='a'>
<input type="text" name="b" id="b" autofocus='on' placeholder='b'>
<input type="text" name="hypo" id="hypo" placeholder='Hypothénuse'>
</form>
<canvas id="myCanvas" width="500" height="250">Your browser does not support the HTML5 canvas tag.</canvas>
</div>
</body>
The problem was that your .triangle div didn't have a set width or height:
.triangle {
position: relative;
text-align: center;
width: 500px;
height: 250px;
margin: 0 auto;
}
.h {
position: absolute;
top: 120px;
right: 100px;
width: 100px;
}
.b {
position: absolute;
bottom: -35px;
left: 210px;
width: 50px;
}
.a {
position: absolute;
top: 120px;
left: -70px;
width: 50px;
}
<h2> Triangle rectangle </h2>
<div class="triangle">
<form autocomplete="off">
<input class="a" type="text" name="a" id="a" placeholder='a' >
<input class="b" type="text" name="b" id="b" autofocus='on' placeholder='b' >
<input class="h" type="text" name="hypo" id="hypo" placeholder='Hypothénuse' >
</form>
<canvas id="myCanvas" width="500" height="250" >Your browser does not support the HTML5 canvas tag.</canvas>
</div>
<script>
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(500, 250);
ctx.moveTo(0, 0);
ctx.lineTo(0, 250);
ctx.moveTo(0, 250);
ctx.lineTo(500, 250);
ctx.stroke();
</script>

Adjustable image on top of an another image using CSS

I would like for the image B to be fluid like the Image A, while mainlining it's center position of Image A.
Here is my sample code:
<div class="container">
<img id="imgA" src="A.png" />
<img id="imgB" src="B.png" />
</div>
CSS:
#imgA{
display: block;
width: 100%;
height: auto;
position: relative;
}
#imgB{
position: absolute;
top: 50%;
left: 50%;
margin-left: -200px;
margin-top: -100px;
width: 400px;
height: 200px;
}
With above code, I only can achieve image B to be the center of Image A while the resolution is high enough, but when it gets lower, image A will adjust to it's screen but image B remains the same. What do I need to add for image B to be fluid and be the center of image A at any resolution?
You need to calculate the offset of the second image in %, not in pixels, and make sure their sizes are relative to the container div. I created a js fiddle with an example: http://jsfiddle.net/BX6u7/
<div class="container">
<img id="imgA" src="http://placehold.it/350x150" />
<img id="imgB" src="http://placehold.it/150x50" />
</div>
and css:
.container {
margin: 0 auto;
position:relative;
width: 50%;
background-color:yellow;
}
#imgA{
display: block;
width:100%;
max-width:100%;
height:auto;
border:none;
}
#imgB{
top: 28.6%;
left: 21.6%;
width: 57%;
max-width: 57%;
border:1px solid white;
position: absolute;
}
You should not be using hard-coded px units, instead go for %.
Replace margin,width and height attributes with respective % values. '%' to be determined as per your image sizes and your requirement.

render one div and it's interactive content by clicking on another div

<div id="1" class="aaa" style="position: relative; left: 50px; top: 50px; width: 300px; height: 200px; border: solid 1px; background: #dddddd; overflow: hidden;">
<div style="position: relative; left: 30px; top: 25px; width: 100px; height: 50px; background: blue;" onmouseenter="this.style.background='red';"></div>
<div style="position: relative; left: 160px; top: 70px; width: 100px; height: 50px; background: blue;" onmouseenter="this.style.background='orange';"></div>
</div>
<div id="2" class="bbb" style="position: relative; left: 250px; top: 100px; width: 50px; height: 20px; border: solid 1px; background: #cccccc; text-align: center; overflow: hidden;">click</div>
http://jsfiddle.net/FWyBQ/
I have one div (id="1" class="aaa") which contains multiple interactive divs. State of this interactive content should be able to be rendered as image (gif?) with the click on the other div (id="2" class="bbb").
That image should preferably be opened in a new tab or window. Or maybe just right click > save as in place.
p.s. I am aware of scripts like html2canvas and phantomjs, but I have no idea how to implement them in my case.
edit:
Now I'm trying to implement this solution, which with a little tweaking should work with processing.js (http://cloud.github.com/downloads/processing-js/processing-js/processing-1.4.1.min.js).
I guess I just need the right jquery code with processing.js in order to achieve the functionality I need. I've tried this and it doesn't work:
$('.bbb').click(function (e) {
var canvas = document.getElementById("1"),
img = canvas.toDataURL("image/png");
$('.aaa').document.write('<img src="'+img+'"/>');
});
You could use html2canvas for this; include the html2canvas library in your page and try something like this:
//element would be your aaa div
html2canvas(element, {
onrendered: function(canvas) {
// canvas is the resulting canvas generated from the element
var url = canvas.toDataURL("image/png");
}
});
You would then need to post the value of 'url' to a PHP script like in one of the answers to this question.
EDIT
The reason your new code doesn't work is because the element with an id of "1" is not a canvas element. Its a div.
Canvas methods like toDataUrl() can only be called on Canvas elements (which is why I suggested using html2canvas to change your div into a Canvas.)
I've forked your jsfiddle to show how the code could work if the element with id "1" was a canvas:
http://jsfiddle.net/_Pez/cksGt/1/
_Pez
If I was in your pants, I'd start by switching the first div to SVG notation. It's not that different and there are a ton of ways to export an svg object to png.
This should get you started
<svg id="1" class="aaa" width="400" height="250">
<g>
<rect id="svg_0" height="200" width="300" y="50" x="50" stroke-width="1" stroke="#000000" fill="#dddddd"/>
<rect id="svg_1" height="50" width="100" y="75" x="80" stroke-width="5" fill="blue"/>
<rect id="svg_2" height="50" width="100" y="120" x="210" stroke-width="5" fill="blue"/>
</g>
</svg>
<div id="2" class="bbb" style="position: relative; left: 250px; top: 100px; width: 50px; height: 20px; border: solid 1px; background: #cccccc; text-align: center; overflow: hidden;">click</div>

Making a div always on top of a canvas that always write something

I am continuously drawing some lines in my canvas using kinetic.js and I want a div-text to appear on top of this canvas. Using relative and absolute trick I can place a div in the middle of my canvas but the problem is as I am continuously drawing lines, these lines are being drawn on top of my div-texts which I dont want to happen!
Basic template:
<div id="div-text" style="background-color:#00baba; position: absolute; margin-top: 50%; margin-left: 50%;">
greatTexts
</div>
<div id="container" style="position: relative; width: 100%; height: 100%;">
<canvas></canvas>
</div>
I believe you could also just set a z-index value on both #container and #div-text.
Like this:
<div id="div-text" style="background-color:#00baba; position: absolute; margin-top: 50%; margin-left: 50%;z-index:999;">
greatTexts
</div>
<div id="container" style="position: relative; width: 100%; height: 100%;z-index:990;">
<canvas id="myCanvas" height="500" width="500"></canvas>
</div>
This shows an example.
A canvas if by default empty, meaning you can see elements behind it.
Since you placed your <div> before the <canvas>, in the code, the <div> is rendered under the <canvas>.
Solution? Switch the divs around a little:
<div>
<canvas style="position:absolute; width:100%; height:100%; background:red"></canvas>
<div id="div-text" style="background-color:#00baba; position:absolute; margin-top:50%; margin-left:50%;">
greatTexts
</div>
</div>
Just place the div with text after the container div like this
<div id="container" style="position: relative; width: 100%; height: 100%;">
<div id="div-text" style="background-color:#00baba; position: absolute; margin-top: 50%; margin-left: 50%;">
greatTexts
</div>
There's no need to create a canvas element, because as you've mentioned, KineticJS automatically creates those for you.

Save many canvas element as image

I have 3 layers of canvas - 1 is matrix, 2 & 3 is graphics, how to preserve them in one image?
<div style="position: relative;">
<canvas id="matix" width="100" height="100"
style="position: absolute; left: 0; top: 0; z-index: 0;"></canvas>
<canvas id="layer1" width="100" height="100"
style="position: absolute; left: 0; top: 0; z-index: 0;"></canvas>
<canvas id="layer2" width="100" height="100"
style="position: absolute; left: 0; top: 0; z-index: 1;"></canvas>
</div>
You can draw one canvas into another with ctx.drawImage(other_canvas,0,0)
If you do that in the right order, you will have all the canvas contents correctly layered in one of them.
If you want to save the image, you can call canvas.toDataURL() to get the contents as a base64 encoded PNG file.

Categories

Resources