I've looked at all the questions on here asking the same thing and tried every suggestion, none of it is working for me.
I want to layer two dynamically created canvas elements on top of each other, inside the div with an id of "plotPlaceholder".
It continues to just show one below the other, like so:
// grab elements from form
var wid = document.getElementById("wid").value;
var hei = document.getElementById("hei").value;
// grab div container and create canvas elements
var canvasPlaceholder = document.getElementById("plotPlaceholder");
var baseCanvas = document.createElement("canvas");
var canvasElement = document.createElement("canvas");
canvasElement.width = wid;
canvasElement.height = hei;
baseCanvas.width = wid;
baseCanvas.height = hei;
baseCanvas.style.zIndex = "1";
canvasElement.style.zIndex = "2";
baseCanvas.id = "canvasToHoldGrid";
canvasElement.id = "plottingCanvas";
canvasPlaceholder.appendChild(baseCanvas);
canvasPlaceholder.appendChild(canvasElement);
canvas {
border: 2px solid #27a3ea;
position: absolute;
top: 0;
left: 0;
}
#plotPlaceholder {
position: relative;
}
<div id="plotPlaceholder"></div>
I found out what was happening - there was an extra div being created (parent of the canvas elements) with a class of 'canvas-container'. The position property was being overwritten.
.canvas-container {
position: absolute !important;
top: 0;
left: 0;
}
That !important fixed it, although I'm sure it's not best practice in most circumstances.
Related
I'm trying to add an overlay using canvas. It needs to disable clicks so all elements above the overlay should be unclickable, except the element that I send to openOverlay function.
In addition, there is a button that I want to make it clickable. This button is sent to openOverlay function.
How can I do it?
This is my code:
https://codepen.io/anon/pen/QQqQae
The button needs to be clickable but not the div
I tried something like: ctx.clearRect in order to cut the piece that is found above the button:
function openOverlay(elem) {
var loc = elem.getBoundingClientRect();
var canvas = document.createElement("canvas");
canvas.className = "highlight";
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
var ctx = canvas.getContext("2d");
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.clearRect(loc.left - padding, loc.top - padding, loc.width + padding * 2, loc.height + padding * 2);
document.body.appendChild(canvas);
window.overlayCanvas = canvas;
}
Set z-index for "canvas" to -1 :
canvas{
z-index: -1;
}
But, the above method will make all the elements in the canvas clickable.
So, you can set the following style on the button to make it clickable :
button{
position: absolute; //or, relative
left: 0px;
top: 0px;
z-index: 2;
}
All the other elements in the canvas won't be clickable unless they have position absolute (or, relative) and higher z-index.
First, ctx.clearRect doesn't really have any effect on the mouse click event.
In the future, you may be able to use canvas hit regions, but they have limited support for now. See MDN AddHitRegion
But for now, you can put any button that is supposed to be clickable at a higher z-index than the overlay and give it either relative or absolute positioning.
function openOverlay(elem) {
var canvas = document.createElement("canvas");
canvas.className = "highlight";
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
canvas.zIndex = 100;
var ctx = canvas.getContext("2d");
ctx.fillRect(4, 4, 300, 150);
elem.classList.add("clickable");
document.body.appendChild(canvas);
window.overlayCanvas = canvas;
}
var element= document.getElementById("button1")
openOverlay(element)
body{
background-color: grey;
}
.clickable{
position: relative;
z-index:200;
}
canvas{
z-index: 100;
position: absolute;
display: block;
top: 0;
left: 0;
background-color:blue;
opacity: 0.6;
}
<button id="button1" onclick="window.alert('Clicked button1')">Click Me</button>
<button id="button2" onclick="window.alert('Clicked button 2')">Don't Click Me</button>
$(this).css({
position: 'absolute',
left: Math.random() * ($('.parentcontainer').width() - $(this).width()),
top: Math.random() * ($('.parentcontainer').height() - $(this).height())
});
I got this each loop that will randomly place elements within a div. The problem with this is that the elements will overlap each other sometimes because they are absolute positioned. Is there anyway to go around this in js to check position? or maybe rewrite this with margin values? Thanks a ton!
There's a few different ways you can do to achieve this. I find it easiest to try to define the problem in one sentence:
New square's position must be at least X distance from current square positions
Using this sentence, we can make some simple theories as to how the code will work.
Assuming all squares are 50x50 pixels, we can write some checks.
Here are some pseudo code steps we could follow:
Generate a random position for newSquare
Compare the x and y positions of newSquare to all existing squares
If either of the x and y positions of newSquare are further away from the other squares, newSquare can be placed
Otherwise, try again
var container = $('#container');
var squareSize = 50;
var containerSize = 500;
for (var i = 0; i < 20; i++) {
var foundSpace = false;
while (!foundSpace) {
// Generate random X and Y
var randX = Math.floor(Math.random() * (containerSize - squareSize));
var randY = Math.floor(Math.random() * (containerSize - squareSize));
var hitsSquare = false;
var squares = container.children();
squares.each(function(index, square) {
var square = $(square);
// parseInt() because .css() returns a string
var left = parseInt(square.css('left'));
var top = parseInt(square.css('top'));
// Check boundaries
var hitsSquareX = Math.abs(left - randX) < squareSize;
var hitsSquareY = Math.abs(top - randY) < squareSize;
// Will overlap a square
if (hitsSquareX && hitsSquareY) {
hitsSquare = true;
// jQuery break .each()
return false;
}
});
// If doesn't overlap any square
if (!hitsSquare) {
foundSpace = true;
var newSquare = $('<div class="square">');
newSquare.offset({
left: randX,
top: randY
});
container.append(newSquare);
}
}
}
#container {
position: relative;
}
.square {
position: absolute;
background-color: red;
width: 48px;
/* border adds 2px */
height: 48px;
/* border adds 2px */
border: 1px solid black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
</div>
You should look for collision detection.
In my opinion this is a great tutorial: https://www.youtube.com/watch?v=XYzA_kPWyJ8, but there are several other great ones out there.
Good luck :)
I modified the code of the best answer of another question (which aimed to detect from which side the mouse entered a div) in order to make it detect from which side the mouse left a div.
Here is the my code. I changed the log to display in the console. But somehow the results are always being "right" or "bottom" and no "top" or "left".
Any advise, please?
I've been working a bit on the code and I've modified some stuff.
Since you're positioning your div with absolute position, you need to check the position on a different way.
First, I'm using getBoundingClientRect() which returns the position of the element (left, top, right and bottom).
Then I get the mouse coordinates and I calculate from which edge is closest.
You can see an example of my code here:
document.querySelector('#content').onmouseleave = function(mouse) {
var edge = closestEdge(mouse, this);
console.log(edge);
}
function closestEdge(mouse, elem) {
var elemBounding = elem.getBoundingClientRect();
var elementLeftEdge = elemBounding.left;
var elementTopEdge = elemBounding.top;
var elementRightEdge = elemBounding.right;
var elementBottomEdge = elemBounding.bottom;
var mouseX = mouse.pageX;
var mouseY = mouse.pageY;
var topEdgeDist = Math.abs(elementTopEdge - mouseY);
var bottomEdgeDist = Math.abs(elementBottomEdge - mouseY);
var leftEdgeDist = Math.abs(elementLeftEdge - mouseX);
var rightEdgeDist = Math.abs(elementRightEdge - mouseX);
var min = Math.min(topEdgeDist,bottomEdgeDist,leftEdgeDist,rightEdgeDist);
switch (min) {
case leftEdgeDist:
return "left";
case rightEdgeDist:
return "right";
case topEdgeDist:
return "top";
case bottomEdgeDist:
return "bottom";
}
}
#content {
width: 100px;
height: 100px;
background: lightblue;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
<div id="content"></div>
I hope that helps you.
Cheers!
I'm creating and element in JavaScript to append it as a child of
another div:
var a = document.querySelector(".a");
var b = document.createElement("div");
b.style.position = "relative";
b.style.height = a.offsetHeight+"px";
b.style.width = a.offsetWidth+"px";
b.style.background = "blue";
b.style.top="0px";
a.appendChild(b);
But I want to position the "b" element completely over the "a" element.
I know that I should do something like that to achieve the effect:
b.style.top = -b.offsetTop+"px";
But there is no way I can find the offsetTop that will be taken by "b" since it has no been added to the document yet.
This is what I have so far:
http://jsfiddle.net/a36eLwu3/
How can I position a relative element in the same coordinates
of his parent in the document?
The simplest way I know of to place two objects directly on top of one another is to put them both in the same container, make the container be position: relative and then make both objects (which are siblings in this structure) be position: absolute with the same top and left. You can do all of this without any calculation and can specify everything via CSS.
Structurally, it looks like this:
Container (position: relative; height: xxx; width: yyy;)
Child A (position: absolute; left: 0; top: 0;)
Child B (position: absolute; left: 0; top: 0;)
I have used this structure for a slideshow where I'm cross fading (fading out one image and fading in the other image).
If the element has to be relatively positioned, you could set a negative top value equal to the height of the parent element:
b.style.top = -Math.abs(a.offsetHeight) + 'px';
Updated Example
var a = document.querySelector(".a");
var b = document.createElement("div");
b.style.position = "relative";
b.style.height = a.offsetHeight+"px";
b.style.width = a.offsetWidth+"px";
b.style.background = "blue";
b.style.top = -Math.abs(a.offsetHeight) + 'px';
a.appendChild(b);
If you can absolutely position the element, it would be easier to absolutely position it relative to the parent. Then give position it to cover the parent using top: 0; right: 0; bottom: 0; left: 0;. In doing so, it will be the same size with the same coordinates of the parent.
Example Here
.a {
background:red;
height: 100px;
position: relative;
}
.a > div {
position: absolute;
top: 0; right: 0;
bottom: 0; left: 0;
}
This would be a safer, more reliable approach compared to the first JS option.
I went through the initial tutorial for making a user radar on Zigfu's website. I am having trouble getting this radar to work in the canvas element.
I want to using the drawing methods in canvas, so I don't want it in the container.
Here is my code so far taken directly from the tutorial. Thanks so much for reading!
function loaded() {
var radardiv = document.getElementById('container');
var radar = {
onuserfound: function (user) {
var userdiv = document.createElement('div');
userdiv.className = 'user';
user.radarelement = userdiv;
radardiv.appendChild(user.radarelement);
},
onuserlost: function (user) {
radardiv.removeChild(user.radarelement);
},
ondataupdate: function (zigdata){
for (var userid in zigdata.users){
var user = zigdata.users[userid];
var pos = user.position;
//console.log(pos);
var el = user.radarelement;
var parentElement = el.parentNode;
var zrange = 2000;
var xrange = 700;
var pixelwidth = parentElement.offsetWidth;
var pixelheight = parentElement.offsetHeight;
var heightscale = pixelheight / zrange;
var widthscale = pixelwidth / xrange;
el.style.left = (((pos[0] / xrange) + 0.5) * pixelwidth - (el.offsetWidth / 2)) + "px";
el.style.top = ((pos[2] / zrange) * pixelheight - (el.offsetHeight / 2)) - 150 + "px";
}
}
};
zig.addListener(radar);
}
document.addEventListener('DOMContentLoaded', loaded, false);
<body>
<div id = 'container'></div>
</body>
</html>
<style>
div#container {
width: 800px;
height: 600px;
border: 1px solid black;
overflow: hidden;
}
div.user {
position: relative;
width: 10px;
height: 10px;
background-color: red;
}
It seems you are missing tags around the javascript, as well as some css for the users radar. Also - your 'container' div is missing a >
Try copying the code from the bottom of http://zigfu.com/en/zdk/tutorials/, or - check out http://zigfu.com/en/zdk/recipes/#omercy16 for a cleaner implementation of the users radar.
The radar used in the tutorial makes use of DOM div placement and positioning.
Unfortunately this can't be used inside the canvas element.
There are ways to overlay over the canvas and other workarounds. See: Placing a <div> within a <canvas>
You can also take the data directly from the plugin and draw to the canvas yourself.
Here is a demo using three.js and zigfu to draw the skeleton onto a canvas:
http://blog.kinect.tonkworks.com/post/30569123887/kinect-online-app-javascript-dev-tutorial-1