Javascript, CSS, jQuery - my canvas moves to where it shouldnt be - javascript

Problem is in title. It used to do it on the odd occasion. Then i added the jQuery rotate.js plugin to spin my heading 360 degrees and now it is constantly placed to the right of where it should be. It may be interesting to note that i got the offset of the canvas with
var rect = gameController.canvas.getBoundingClientRect();
var offset = {
x: rect.left,
y: rect.top
};
And that still has coordinates of 0,0 in the top left corner of where it should be ( which is correct and how it should be when the canvas has not moved).
#canvas {
z-index: 1;
position: absolute;
margin-top: 52px;
margin-left: 44px;
background-image:url(images/background.jpg);
}
If the position is absolute, it is removed from the document and nothing will make it move. Strange.

getBoundingClientRect() returns the sum of the canvas and its css border-boxes.
Maybe check the canvas with getClientRects() to see exactly where it is.

I'm not sure why it moved, i probably have a css error somewhere..but i had my canvas as position absolute, relative to a div that it was inside. I placed my canvas right at the top of the body tag so it was absolute, relative to the whole page, then changed the placement of it with top and bottom to get it correct. Now nothing will move it. It works fine with the rotate.js plugin. Thanks for having a look at my question.

Related

HTML5 Canvas Set Top/Left

I can easily set the canvas.width and canvas.height properties. I cannot find the right JavaScript syntax to set the offset of the canvas using top and left. I have tried setting these properties on the canvas directly and on the bounding rectangle.
I would like to be able to set the top and left offset so that I can reposition the canvas when a user clicks on a point.
If canvas.width = 600 works just fine; why doesn't canvas.top = 80 work? I am confused. Thx for your help.
In order to set the top position of the canvas, you need to wrap the canvas inside of another div with absolute positioning. Then set the position of the canvas to be relative to its wrapping div. Finally, you can set the style of the canvas.
Make sure you provide units e.g. px, em, rem, %, etc...
var panel = document.getElementById('panel');
panel.width = 600;
panel.height = 200;
panel.style.top = '80px'; // Must specify unit.
.container {
position: absolute;
background: #0FF;
}
#panel {
position: relative;
background: #F00;
}
<div class="container">
<canvas id="panel"></canvas>
</div>
The docs state:
The effect of top depends on how the element is positioned (i.e., the value of the position property):
When position is set to absolute or fixed, the top property specifies the distance between the element's top edge and the top edge of its containing block. (Containing block needs to have property position: relative)
When position is set to relative, the top property specifies the distance the element's top edge is moved below its normal position.
When position is set to sticky, the top property behaves like its position is relative when the element is inside the viewport, and like its position is fixed when it is outside.
When position is set to static, the top property has no effect.
Please try canvas.style.top = "80px";
Make sure you have set position to relative or absolute. Have Look at the example below.
<!DOCTYPE html>
<html>
<body>
<canvas id="myCanvas" width="200" height="100" style="border:1px solid #d3d3d3;top: 80px; position: absolute;">
Your browser does not support the HTML5 canvas tag.</canvas>
<script>
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.moveTo(0, 0);
ctx.lineTo(200, 100);
ctx.stroke();
</script>
</body>
</html>
In short, width and height are html attributes and can therefore be set using element.width and element.height. However, top is a css proberty, not an html attribute - therefore it can only be set using element.style.top.
Also, as already pointed out in the other answers, the css position proberty has to be either fixed or absolute in order for top and left to work.

Angular SVG Path Not Visible

I am working on a project where I have a page that lists job positions and I need to visually show progression (how to get from one job to another) using lines/arrows so the user can follow along. I created a page that contains all the data for this and now I am trying to use SVG paths to create lines on top of the data and draw paths.
I found some code in another answer that I converted to pure JS and removed the jQuery references to be able to use it in my project.
Here is the working fiddle with one path example:
http://jsfiddle.net/x4nmqkLj/
Here is my attempt:
http://jsfiddle.net/szrdb263/
My issue that I am facing is that the SVG and Path appear to be created BUT, I am unable to see the line/path on the DOM. However if I view the elements in the web tools, I can see the SVG element and path element and they appear to be in the correct location to where the path would be drawn from the starting and ending position.
My rendered path is as follows:
<path class="path" id="path1" d="M449.953125 512.34375 V568.03125 A55.6875 55.6875 0 0 0 505.640625 623.71875 H765.515625 A55.6875 55.6875 0 0 1 821.203125 679.40625 V1055.3203125"></path>
Here is the SVG Element:
Here is the Path Element:
The path should be drawing a line from the first box 1A to the bottom row, second box 2D. The path appears to be where its expected, the bottom center of the first box to the top center of the bottom box where the arrow would be drawn.
CSS:
#svgContainer {
z-index: -10;
opacity: 0.5;
margin: 2.5em 2.5em;
position: absolute;
background-color: #999;
}
path {
fill: none !important;
stroke: #000 !important;
stroke-width: 0.7em !important;
}
Is anything angular specific that I am missing causing this to not show up?
I am not terribly familiar with SVG but seeing both the SVG element and Path element in the DOM makes me think its pretty close. I can't imagine the arrow is outside of the DOM anywhere but I may be wrong.
Update:
I pasted my path code in a few "validator" sites for SVG to see if it would draw it and I am not getting any visual indication. This would suggest that there is something wrong with the coordinates that it is using to create the path. However, the same code is being used on the working example so I am wondering if this is an angular quirk after all with manipulating the DOM of sorts.
Update 2:
I believe I have solved the issue. I had to change how I was getting the ending coordinates in the JS.
Before:
// calculate path's end (x,y) coords
var endX = endCoord.offsetLeft + 0.5 * endElem.offsetWidth - svgLeft;
var endY = endCoord.offsetTop - svgTop;
After:
// calculate path's end (x,y) coords
var endX = endCoord.getBoundingClientRect().left + 0.5 * endElem.offsetWidth - svgLeft;
var endY = endCoord.getBoundingClientRect().top - svgTop;
New Fiddle: http://jsfiddle.net/8dumowvt/
I got your example working by doing the following:
Replaced offsetTop and offsetLeft by getBoundingClientRect().top and getBoundingClientRect().left in connectElements()
Adjusted style of svgContainer to give it a positive z-index, so that the svg is drawn over the other elements
Added pointer-events: none; to the svgContainer so that you can still interact with the elements behind it
Here's the updated Fiddle.

In Javascript, why does getBoundingClientRect() sometimes return floating point values?

I'm trying to work with an HTML5 canvas element. One thing i'm trying to do is set up a mousemove event to track the mouse on the canvas for drawing and other purposes. I have not been able to find a definitive answer on how to get the exact coordinates of the pixel in the canvas the mouse is over. I found a tutorial on the web that had this html (I added the background-color to the canvas to make it obvious on the rendered page):
<!DOCTYPE HTML>
<html>
<head>
<style>
body {
margin: 0px;
padding: 0px;
}
#myCanvas {
background-color: cornflowerblue;
}
</style>
</head>
<body>
<canvas id="myCanvas" width="578" height="200"></canvas>
<script>
function writeMessage(canvas, message) {
var context = canvas.getContext('2d');
context.clearRect(0, 0, canvas.width, canvas.height);
context.font = '18pt Calibri';
context.fillStyle = 'black';
context.fillText(message, 10, 25);
}
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
canvas.addEventListener('mousemove', function(evt) {
var mousePos = getMousePos(canvas, evt);
var message = 'Mouse position: ' + mousePos.x + ',' + mousePos.y;
writeMessage(canvas, message);
}, false);
</script>
</body>
</html>
When the page is loaded, you see the canvas as a blueish rectangle in the upper left corner of the page. Move the mouse over it and the text in the canvas changes to show the mouse position as two ints, one each for X and Y.
I then modified the canvas style by adding a top and left margin, and left the rest of the page unchanged.
#myCanvas {
background-color: cornflowerblue;
margin-left: 30px;
margin-top: 30px;
}
When I rendered the page now, the blue rectangle of the canvas was offset from the top and left of the page as I expected. But passing my mouse over the canvas now had the X and Y mouse coordinates that were being displayed in the canvas coming up as floats with many decimal places. Tracing through the code a bit, it seems that getBoundingClientRect() is returning a rect where the values top and left are floats.
I assume I could do something like truncate or round the values being returned by getBoundingClientRect(), but that feels like the wrong way to go about it to me.
Am i somehow using getBoundingClientRect() incorrectly, or is it expected that it should return float values?
And is there a clear cut way to get the exact X and Y coordinates of the mouse over the canvas when listening for various mouse events?
tldr; you did zoom/unzoom in your browser.
The problem
margin-left: 30px;
In this jsfiddle thats mimics your problem it does not works as you said on my computer when navigator zoom is set to 100% (normal). But if you zoom inside your browser you will notice such behavior.
margin-left: 11%;
Instead if you use % margin like in this jsfiddle you will notice it does returns floating mouse position wether zoom is on or not.
The answer
The thing is mouse position is computed as it appears on the screen : it may only have entire position coordinates since it is pixel based.
However getBoundingClientRect returns what browser computes to be "Bounding Client Rect of the element" after applying margins, zoom and others modifiers but before telling the GPU to render it. In short it returns the real position of the element which is later approximated by the GPU to be rendered within a matrix of pixels. If you use pixel margins/sizes/paddings/etc then elements positions remains integer based, but if you zoom or use em/% positioning values then it may result floating positions.
The solutions
round bounds
assume it is indeed a floating position and it's just the GPU that needs to round it in order to make it fit on the screen
Edit : The forgotten solutions

How can I translate with webkit-transform enough so that

I am using webkit-transform: scale(zoomFactor,zoomFactor) in css to zoom the contents of an iframe. When I zoom it to the proper size to fit inside the iframe, the positioning of the elements is offset like this:
I cannot figure out how to find the x and y I would need to offset it to get it so that the contents of the iframe appear to be in the same corner as before it was scaled. The amount the contents are offset depend on how large or small the scalefactor is. Does anyone know how I can get this to work?
by using transforms you can set the transform origin.
In your case you want to scale to the top left.
so the origin should not be default (center) but at 0px left and 0px top.
-webkit-transform-origin:0px 0px;

position canvas on top of Scrollbar

I am simulation a projectile motion path. I've one div with css overflow property and a curve drawn using canvas. I want the motion path to appear at top of everything. But curve gets cut at the position where the scroll bar is. If i change the canvas z-index to maximum or something similar to make canvas to appear at top then the scrollbar doesnt work... here is a jsfiddle demo of my problem JSFIDDLE Demo
Following is my javascript code:
var canvas = document.getElementById('canvasTron');
var context = canvas.getContext('2d');
context.beginPath();
context.moveTo(100, 150);
context.lineTo(350, 50);
context.stroke();
Is there any way to do that ???
If you have no situation, but to go with what you have mentioned, here is the solution.
Addition in CSS:
#canvasTron{position:absolute; clip: rect(48px, 351px, 151px, 99px);}
With canvas, you cannot get the scroll to work effectively. As it will occupy the area of that div below it and will not make the scroll work.
The provided solution has to be purely applied in case of WORST CASE SCENARIO, where you are left with no option and have to do it under the existing circumstances. Otherwise, it is NOT POSSIBLE.
Instead of using canvas, You can do this :
<div id="canvasTron"></div>
canvasTron
{
position:absolute;
width:0px;
height:200px;
border:2px solid black;
transform:rotate(50deg);
-webkit-transform:rotate(50deg);
-ms-transform:rotate(50deg);
-o-transform:rotate(50deg);
-moz-transform:rotate(50deg);
left:180px;
}
Remains light weight and scrolling is also working fine.

Categories