Positioning a canvas below overlapping canvases - javascript

I have two canvases that overlap intentionally, to draw a ball falling on top of the other canvas. I want to put a third canvas below those two overlapping ones on the page, without any overlap. When the div element that holds the overlapping canvases has a relative position, it does not prevent other elements from overlapping it. As I understand it, that div must be positioned relatively so that the canvases inside it can be positioned absolutely and overlap.
Here is my HTML:
<div id="box" style="position: relative;"></div>
<div id="countdiv"></div>
Here is the JavaScript:
boxCanvas = document.createElement("canvas");
// the margins on the page are 3%
boxCanvas.width = window.innerWidth - (window.innerWidth * .06);
boxCanvas.height = document.getElementById("height").value;
boxCanvas.style = "border: 1px solid #808080; position: absolute; left: 0; top: 0; z-index: 0";
document.getElementById("box").appendChild(boxCanvas);
// second canvas for drawing balls falling
ballCanvas = document.createElement("canvas");
ballCanvas.width = boxCanvas.width;
ballCanvas.height = boxCanvas.height;
ballCanvas.style = "border: 1px solid #808080; position: absolute; left: 0; top: 0; z-index: 1";
document.getElementById("box").appendChild(ballCanvas);
And here is the JavaScript for the third canvas:
countCanvas = document.createElement("canvas");
countCanvas.width = window.innerWidth - (window.innerWidth * .06);
countCanvas.height = 100;
countCanvas.style = "border: 1px solid #808080;";
document.getElementById("box").appendChild(countCanvas);
countctx = countCanvas.getContext("2d");
ballCanvas.height = boxCanvas.height;
ballCanvas.style = "border: 1px solid #808080; position: absolute; left: 0; top: 0; z-index: 1";
document.getElementById("countdiv").appendChild(ballCanvas);
The problem can be seen here when you click drawbox() and then "show hitcounts". Thanks for the help! Let me know if I could provide any more information.

I must admit I’m not exactly sure what you’re asking.
I think you want to have 2 overlapping canvases on top followed by a separate canvas on the bottom.
And you want to do the styling in javascript instead of CSS.
Here is code and a Fiddle: http://jsfiddle.net/m1erickson/hgHBw/
<!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>
#box{
border:1px solid blue;
}
.subcanvs{
border: 1px solid green;
}
#countCanvas{
border: 1px solid gold;
}
</style>
<script>
$(function(){
var w=300;
var h=200;
var boxDiv=document.getElementById("box");
boxDiv.style.width=w+"px";
boxDiv.style.height=h+"px";
boxDiv.style.position="relative";
var box=document.getElementById("boxCanvas");
var boxCtx=box.getContext("2d");
box.width=w;
box.height=h;
box.style.position="absolute";
box.style.left=0;
box.style.top=0;
var ball=document.getElementById("ballCanvas");
var ballCtx=ball.getContext("2d");
ball.width=w;
ball.height=h;
ball.style.position="absolute";
ball.style.left=0;
ball.style.top=0;
var counter=document.getElementById("countCanvas");
var countCtx=counter.getContext("2d");
counter.width=w;
counter.height=100;
test(boxCtx,20,30,"red");
test(ballCtx,100,30,"green");
test(countCtx,30,30,"blue");
function test(ctx,x,y,color){
ctx.beginPath();
ctx.fillStyle=color;
ctx.rect(x,y,50,50);
ctx.fill();
}
}); // end $(function(){});
</script>
</head>
<body>
<div id="box">
<canvas id="boxCanvas" class="subcanvs"></canvas>
<canvas id="ballCanvas" class="subcanvs"></canvas>
</div>
<canvas id="countCanvas"></canvas>
</body>
</html>
One thing to note:
// this sets the canvas drawing area to 100px wide
myCanvas.width=100;
// this styles the canvas element to be 100px wide on the page
// if this isn't == myCanvas.width then the image will be horizontally distorted
myCanvas.style.width="100px";

Related

How to cut things using CSS or HTML or JavaScript

So I'm working on my website and I have made quite a progress with it. However as it is it's plain.
So I decided to make a few JavaScript animations that would bring my website to life.
However in JavaScript I only know to use specific resolutions given inside the canvas tag in html.
( Is it possible to do something like using percentages of the page
height and width like in css? )
So my JavaScript animation has a set resolution and I want to put it on my animation on a gradient rectangle on which I have some text.
So here is my problem. How can I put my animation on that rectangle without having to change the resolution on the canvas and without distorting the JS animation.
const cvs = document.getElementById("myCanvas");
const ctx = cvs.getContext("2d");
let position = {
x:0,
y:cvs.height/4
};
function resize() {
// Our canvas must cover full height of screen
// regardless of the resolution
var height = window.innerHeight;
// So we need to calculate the proper scaled width
// that should work well with every resolution
var ratio = cvs.width/cvs.height;
var width = height * ratio;
cvs.style.width = width+'px';
cvs.style.height = height+'px';
}
window.addEventListener('load', resize, false);
window.addEventListener('resize', resize, false);
ctx.fillStyle = "#66ccff";
ctx.fillRect(0,0,cvs.width,cvs.height);
function animation(){
ctx.fillStyle = "black";
ctx.fillRect(position.x,position.y,10,30);
position.x+=5;
if(position.x>cvs.width){
position.x = 0;
}
window.requestAnimationFrame(animation);
}
animation();
#group{
position:relative;
background-color:#5c85d6;
position: absolute;
top:0;
bottom: 0;
left: 0;
right: 0;
width:100%;
height:30%;
margin-left: auto;
margin-right:auto;
}
.some_text{
position:absolute;
text-align:center;
top:1%;
left:0;
right:0;
margin-left: auto;
margin-right: auto;
font-size:5vw;
font-family: 'Baloo Bhai', cursive;
}
#myCanvas{
position:absolute;
position: absolute;
top:0;
bottom: 0;
left: 0;
right: 0;
margin-left: auto;
margin-right:auto;
top:-30%;
}
.some_other_text{
position:absolute;
top:30%;
font-size:5vw;
font-family: 'Baloo Bhai', cursive;
text-align:center;
left:0;
right:0;
margin-left: auto;
margin-right: auto;
}
<html>
<head>
<link href="https://fonts.googleapis.com/css?family=Baloo+Bhai" rel="stylesheet">
</head>
<body>
<div id ="group">
<canvas id = "myCanvas" width = "1000" height ="1500"></canvas>
<h1 class = "some_text">Some text here</h1>
</div>
<h1 class = "some_other_text">Some more text that I want to see without the blue of my js animation</h1>
</body>
</html>
Yes I could add a background to my second text that would cover the JavaScript animation so I can see only what I need however that would still render that covered part, slowing down the web-page loading time (I think).

Why isn't the div width/height changing after loading?

I'm trying to create an online image cropper where the user uploads a photo and it is displayed with a box (frame) that is changeable via buttons. Crops the photo and sends it back to the user.
I have a basic template of form uploader in php (working). It then displays the image in a div with another transparent div above it with a border marking the cropping area.
The initial values for the divs are set in the css section via php as the page is sent to the user. I'm trying to adjust the size of the frame div, as the width given is the image width +2 px for the frame (same for height) and it should just be the images width (-2 px).
This code should be working, but when the alerts pop up, they show that the frame width/height has not changed the original values, and it appears as though the frame does not change.
<!DOCTYPE html>
<head>
<style type="text/css">
html, body {
width: 500px;
height: 334px;
background-color: black;
}
.top {
margin-top: 0px;
margin-bottom: 0px;
margin-left: 0px;
margin-right: 0px;
width: 500px;
height: 334px;
position: absolute;
background-color: transparent;
border-width: 1px;
border-style: solid;
border-color: white;
z-index: 999;
}
.bottom {
top: 0px;
left: 0px;
position absolute;
width: 500px;
height: 334px;
background-color: green;
// background-image: url(uploads/1505002267.jpg);
z-index: 998;
}
</style>
<script type="text/javascript">
function myOnLoad() {
var w = 500;
var h = 334;
var frame = document.getElementsByClassName('top')[0];
w = w - 2;
h = h - 2;
//frame.setAttribute("style", "width: " + w + "px;");
//frame.setAttribute("style", "height: " + h + "px;");
frame.style.width = w + "px;";
frame.style.height = h + "px;";
alert(frame.offsetWidth);
alert(frame.offsetHeight);
}
</script>
<title>Test Website</title>
</head>
<body onload="myOnLoad()">
<div class="wrapper">
<div class="bottom" id="image">
<div class="top" id="frame">
</div>
</div>
</div>
</body>
</html>
I am aware that I can change the value php gives to the css section, but I'm going to need to change the crop ratio in the next step anyway, so I need this way to work. Please help, I've been looking at this code for way too long.
Remove the semicolon in the quotes.
frame.style.width = w + "px";
frame.style.height = h + "px";
Also, offsetHeight and offsetWidth takes border into consideration. Since your border width is 1px, it adds 2px to both height and width of the image canceling out the subtraction with 2.
Read more about offset width and height on MDN.

how to make clickable circles using javascript?

Basically, I'm trying to create a game in which circles will spawn on a canvas and the user has to click them as fast as possible. The circles should spawn randomly on the canvas and have a certain radius. Once the user clicks a circle, they are awarded points based on the time it took them to click the circle (less time = more points). After the user clicks the circle, it disappears, and another circle randomly spawns somewhere on the canvas, and the user keeps doing this until 100 circles are clicked overall.
The whole point of this game is to help improve accuracy and reflex for FPS games. I decided I would create a game like this to help myself mainly, and for anyone else because I couldn't find a game like this online that fit my needs.
Anyway, here's the code for the game I have so far. If anyone could help me in the direction of further developing this game or even completing it, it would be much appreciated.
HTML:
var mainCanvas = document.querySelector("#myCanvas");
var mainContext = mainCanvas.getContext("2d");
var canvasWidth = mainCanvas.width;
var canvasHeight = mainCanvas.height;
function spawnTarget() {
}
* {
margin: 0;
padding: 0;
}
body {
background-color: rgb(0, 0, 255);
text-align: center;
}
#header {
display: inline-block;
background-color: rgb(255, 255, 255);
margin: 64px auto;
border-radius: 16px;
}
h1 {
font-family: Arial;
font-size: 128px;
color: rgb(0, 0, 0);
}
#myCanvas {
width: 1800px;
height: 900px;
border: 4px solid rgb(0, 0, 0);
}
<!DOCTYPE html>
<html>
<head>
<title>Aim Practice</title>
<link href="stylesheet.css" type="text/css" rel="stylesheet" />
<script src="script.js" type="text/javascript"></script>
</head>
<body>
<div id="header">
<h1>Aim Practice</h1>
</div>
<div id="container">
<canvas id="myCanvas">
</canvas>
</div>
</body>
</html>
because the circles won't be actual DOM elements, you will have to listen for click events on the canvas, and compare the screenX and screenY on the click event to the canvas coordinates of he circle in question. Remember to add in the offset of the canvas relative to the screen. You will also have to manually calculate whether the click is inside the circle or not.

jquery, resize a canvas without scaling

I was trying to put a canvas in a container. I wanted the canvas to have the same size as the container. To do this I used JQuery, however, this turned out to scale my canvas. This was not my intention, especially because I draw after resizing. Doing seemingly the same thing in good old fashion JavaScript gives me the expected result.
I personally did not expect the JQuery result and it took some time before I figured out the problem. Does anybody know why they opted for this implementation and why it gives a different result? I hope by sharing this I can save some people a lot of time!
Thanks for anybody willing to research this further of fix this!
Here is some example code:
<html>
<head>
<title>Canvas resizing</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<style type="text/css">
#container1{
background-color: green;
width: 100px;
height: 100px;
margin: 50px auto;
}
#container2{
background-color: red;
width: 100px;
height: 100px;
margin: 50px auto;
}
</style>
</head>
<body>
<div id="container1">
<canvas></canvas>
</div>
<div id="container2">
<canvas></canvas>
</div>
<script type="text/javascript">
function draw (canvas) {
var context=canvas.getContext("2d");
context.lineWidth = 5;
context.rect(25,25,50,50);
context.stroke();
}
$(document).ready(function () {
//javascript
var container = document.getElementById('container1');
var canvas = container.childNodes[1];
canvas.width = 100;
canvas.height = 100;
draw(canvas);
//jquery
var container = $('#container2');
var canvas = container.children()[0];
$(canvas).width(100);
$(canvas).height(100);
draw(canvas);
});
</script>
</body>
</html>
The jQuery width and height methods are shorthand aliases for setting the CSS width and height properties. Sizing a canvas using CSS causes the scaled, distorted look you're seeing. Your pure javascript version of the code is setting the width and height attributes of the canvas element. To achieve the same in jQuery you can use:
$(canvas).prop('width', 100)
$(canvas).prop('height', 100)
JSFiddle

How to put img in front of svg tag

I'm using snap.svg
I have index.html
<!Doctype>
<html>
<head>
<title>MAP_TEST</title>
<meta charset="utf-8">
<script type = "text/javascript" src = "JS/jquery.js"></script>
<script type = "text/javascript" src = "JS/init.js"></script>
<script type = "text/javascript" src = "JS/snap.svg.js"></script>
</head>
<body>
<div class="comm_cont">
<div id = "svgborder">
<svg id = 'svgmain'></svg>
</div>
</div>
</body>
</html>
And init.js
$( document ).ready(function() {
var s = Snap("#svgmain");
var g = s.group();
Snap.load("SVGFILES/3k1e-test.svg",function(lf)
{
g.append(lf);
//trying to load picture... Scale button in future
$('<img />', {
src: 'PNG/plus.png',
width: '30px',
height: '30px',
id: 'buttoninrk'
}).appendTo($('.comm_cont'));
//this button must be on picture
//but in front of the picture svg element
//And i can't click the button
});
});
I played with z-indexes of #svgborder and #buttoninkr but it didn't help me.
How to put button in front of svg element?
#buttoninkr, #svgborder
{
position: absolute;
}
#svgborder
{
border:5px solid black;
z-index: 0;
margin-left:auto;
border-radius: 5px;
display: inline-block;
}
#buttoninkr
{
z-index: 1;
}
Added css code with z-indexes.
There is a reason why i'm not using svg buttons instead jquery image button.
Ok, as you can see #svgmain in front of plus.png
http://jsfiddle.net/3wcq9aad/1/
Any ideas?
Solved
#svgborders
{
position: absolute;
background-color: #535364;
border:5px solid black;
z-index: 0;
margin-left:auto;
border-radius: 5px;
display: inline-block;
}
#buttoninrk, #buttondekr, #home_btn
{
position: inherit;
top:0;
margin:10px;
z-index: 1;
}
#buttoninrk
{
right:0px;
}
#buttondekr
{
right:60px
}
EDIT: It wasn't the position of the div that made the difference, but simply adding a width and height. So the original HTML works fine as long as you add a width and height to svgborder in the CSS:
http://jsfiddle.net/3wcq9aad/4/
(Note that sometimes, the position of an element within a document can make a difference to how z-index works.)
If you put the svgborder div before the svg, then z-index will work, but you'll need to know the width and height of your SVG and set it on the svgborder div.
<body>
<div class="comm_cont">
<div id="svgborder"></div>
<svg id='svgmain'></svg>
</div>
</body>
#svgborder
{
z-index: 2;
width:330px;
height:150px;
...
}
Fiddle: http://jsfiddle.net/3wcq9aad/3/
svg does not support z-index
Use element position instead:
$('element').css('position', 'absolute');
Is there a way in jQuery to bring a div to front?

Categories