three.js dom element makes the whole page gets larger - javascript

I'm trying to build a 3D viewer with three.js, that has full height but leaves space for a side panel. The vertical layout works as expected, but as soon as I append the render's dom element, a horizontal scroll bar appears.
Attached is a minimal working example. I would expect to just see the (black) canvas element and the red body. But after v.append(renderer.domElement), the page gets larger (filled with blue, html element) and a horizontal scroll bar appears. It seems the page is larger than its body.
See https://jsfiddle.net/5jnvt4jh.
Has anybody an idea, what may be happening there? I couldn't find any margin or padding with Chrome and Firefox. Thanks :).
MWE
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<style>
html {
background-color: blue;
}
body {
margin: 0px;
height: 100vh;
background-color: red;
}
#viewer {
height: 100%;
width: 80vw;
background-color: green;
}
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/86/three.min.js"></script>
</head>
<body>
<div id="viewer"></div>
<script>
var v = document.getElementById('viewer');
var renderer = new THREE.WebGLRenderer();
v.append(renderer.domElement);
renderer.setSize(v.clientWidth, v.clientHeight);
</script>
</body>
</html>

Change style of body to:
body {
margin: 0px;
height: 100vh;
background-color: red;
overflow:hidden;
}
jsfiddle: https://jsfiddle.net/raushankumar0717/5jnvt4jh/2/

Related

How can i write text over a canvas animation

So i'm making a online profile for myself, and i was doing research on how to make the landing page as attractive as possible. Came across HTML5 Canvas, did some research and experimentation on making an interactive background, and this is the result (in codepen).
Now, i would like to write my name in the middle of the canvas with the text infront of the animation.
The animation gets called in a recursive loop and the initialization function gets called when the page is resized or refreshed.
Problem is, i can't get the text infront, and for some odd reason, my text shrinks when the page is resized.
Here is my pen
https://codepen.io/hamza-tariq-khan/pen/mzKMNd
<!doctype html5>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Canvas Resize</title>
<style>
canvas{
/* border: 1.5px solid black; */
/* background-color: red; */
display: block;
}
body{
margin: 0;
overflow-x: hidden;
}
.wrapper{
margin : 20px;
}
</style>
</head>
<body>
<canvas></canvas>
<script src="script.js"></script>
<div class="wrapper">
<h1>This is a sample sentence</h1>
</div>
</body>
</html>
and this is an idea of what i want to achieve. (the writing of Mathew williams infront of the moving background)
http://findmatthew.com
If I were you, I would skip rendering text in the canvas and apply some CSS rules to the div to make it show up on top instead. The CSS approach improves performance and also improves accessibility. A blind person using a screen reader will be able to figure out what's in the div, but reading text in the canvas is not supported. Most importantly, it's a lot easier to reason about HTML and CSS than it is to reason about text rendering in a canvas element. How often will you do that? When you come back to change the code in a month, six months, or a year, it will be easier to change the HTML/CSS than it will be to think through the canvas rendering logic all over again!
To do this, use the following CSS for div wrapper:
.wrapper{
position: absolute;
top: 0px;
color: red;
font-size: 60px;
margin : 20px;
}
position: absolute allows the div to overlap the canvas, and properties top, bottom, left and right allow you to control how far the div is offset from the edges of its parent (in this case wrapper is a child of body). I adjusted color and font-size just to make it obvious that it works.
And here is a link to a working example: https://codepen.io/anon/pen/LqoroR
var canvas = document.getElementById("dm_graphs");
var ctx = canvas.getContext("2d");
ctx.fillStyle = "blue";
ctx.fillRect(0, 0, canvas.width, canvas.height);
<style>
body,
canvas,
html {
font: 24px sans-serif;
height: 100hv;
width: 100%;
margin: 0;
padding: 0;
background: #888;
color: #135;
overflow: hidden
}
#fs {
position: relative
}
#txt,
canvas {
position: absolute
}
#txt {
color: yellow;
margin: 50px;
font: 24px subpixel-antialiased Noto Sans Samaritan;
background: transparent
}
</style>
<body>
<div id="fs">
<canvas id="dm_graphs" width="400" height="300"></canvas>
<div id="txt">This is a text over a canvas.</div>
</div>
</body>

Javascript window resize possible race condition

Given the following test case, the expected behaviour is that the lightblue element exactly matches the size of the red parent as the browser window is resized.
<html>
<head>
<script src="https://code.jquery.com/jquery-1.11.1.min.js"/></script>
<style type="text/css">
#viewport{
width: 100%;
height: 30%;
background-color: red;
}
#child{
background-color: lightblue;
}
</style>
</head>
<body>
<div id="viewport"><div id='child'></div></div>
<script>
window.addEventListener( 'resize', function(){
var width = $('#viewport').innerWidth();
var height = $('#viewport').innerHeight();
$('#child').css('height', height+'px');
$('#child').css('width', width+'px');
});
</script>
</body>
</html>
The actual behaviour on chrome 36.0.1985.143 is that sometimes (especially at smaller window sizes) the child element is set exactly 5px less tall and/or 1px less wide than the parent element. The issue stops happening if $('#child').css('width', width+'px'); is commented out.
It has been reported that the issue doesn't occur on firefox.
A similar issue seems to have been picked up on http://thewebivore.com/using-settimeout-win-race-condition-changing-views/ however I haven't been able to mitigate it with a timeout < 10 ms which is not really a solution.
I've plugged your example code into a fiddle and I seem to be having a host of other problems.
However, if I use vh and vw instead of %, I get much better results:
#viewport {
width: 100vw;
height: 30vh;
background-color: red;
}
#child {
background-color: lightblue;
}
fiddle here...

CSS keeping image ratio, not working with Chrome

So the main idea is to keep this black image in the top left corner (with a ratio 16:9) and fill the remaining space with a "tomato" div. the solution I had found works fine on FF and even IE but breaks under Chrome and Opera (webkit). I'm not entirely sure what do I need to change..
Here's a link to jsfiddle (it doesn't work there well, so I'm adding the whole code below as well).
<!DOCTYPE html>
<html lang="en">
<head>
<style>
.body{ margin: 0px; }
.container {
position: fixed;
height: 100%;
width: 100%;}
.imgHor {width:100%; display:block;}
.moreSpaceHor {width: 100%;}
.lessSpaceHor {
background: tomato;
height: 100%;}
.imgVer { height: 100%; }
.moreSpaceVer {display: inline; float:top;}
.lessSpaceVer {
#top: 100%;
width: 100%;
float:top;
height:100%;
display: inline;
background: tomato;
position:absolute;
}
</style>
<script>
var timeout=-1;
function manageResizing(){
window.clearTimeout(timeout);
timeout=setTimeout(resizeView,128);
}
function resizeView(){
var img=document.getElementById("imgResizer");
var typeOrient = (9*window.innerWidth > 16*window.innerHeight);
var typeClass = img.className =="imgVer";
//if class and orientation are the same -> quit
if(typeOrient == typeClass) return;
var mSpace=document.getElementById("moreSpace");
var lSpace=document.getElementById("lessSpace");
img.className = typeClass ? "imgHor" : "imgVer";
lSpace.className = typeClass ? "lessSpaceHor" : "lessSpaceVer";
mSpace.className = typeClass ? "moreSpaceHor" : "moreSpaceVer";
}
</script>
</head>
<body class="body" onload="manageResizing();" onresize="manageResizing();">
<div class="container">
<div id="moreSpace" class="moreSpaceHor">
<div style="position:fixed; top:0px; color:white;">PIOTR</div>
<img class="imgHor" id="imgResizer" src="http://oi62.tinypic.com/j9vsj7.jpg"></img>
</div>
<div id="lessSpace" class="lessSpaceHor">KOZAK</div>
</div>
</body>
</html>
//edit
Some more info, it kind of work on Chrome/Opera, it breaks when you try to resize horizontally.. although when you refresh the window it's back as it should be :/
I get an output similar to yours by calling the javascript outside of an onReady() block. Make sure the javascript is called after the document has loaded.
Ok it's been solved now, I followed the idea here about attaching a new method responsible for making Chrome to redraw the page:
Force DOM redraw/refresh on Chrome/Mac
var forceRedraw = function(element){...}
Now it's fine among all browsers.

How do you capture a click on an HTML element that has a CSS 3D transform away from the screen?

I have a div that rotates around the x-axis, around its center, so that the top half "falls away" from the screen while the bottom half comes toward the screen. When I try to capture the onclick event, I only get it from the div if I click on it below its centre. If I click on it above its center, the containing div receives the onclick event.
I've tried moving the div to the front with z-index and translateZ(), but still the containing div receives the onclick when I click on the top half of the div.
How can I get the div to receive the onclick event, regardless of where on the div it is clicked?
Here's a sample that demonstrates the problem:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script type="text/javascript">
function onMainClick() {
console.log('onMainClick()');
}
function onContainerClick() {
console.log('onContainerClick()');
}
</script>
<title>Click Test</title>
</head>
<body>
<div onclick="onContainerClick()" style="width: 200px; height: 200px; background-color: burlywood">
<div onclick="onMainClick()" style="width:100%; height: 100%; background-color: grey; -webkit-transform: perspective(1000px) rotateX(45deg)"></div>
</div>
</body>
</html>
onMainClick() is not called when clicking the top half of the grey div.
Built the case in a jsfiddle, I don't exactly know what the perspective rotation does, but the solution is to give the other div a z-index of -1...
CSS
#div1 {
width: 200px;
height: 200px;
background-color: burlywood;
z-index: -1;
}
#div2 {
width: 100%;
height: 100%;
background-color: grey;
-webkit-transform: perspective(1000px) rotateX(45deg);
}
Update: correct jsfiddle link...

How to place one element exactly to the same visible position, as another?

I have two elements "src" and "dest"
"src" and "dest" are in different DOM-nodes, that can not have the same parent.
I need to place "src" element in the same visible position, as "dest".
"src" element must also have the same sizes, as "dest".
I have following code for case, when "src" and "dest" having the same parent:
src.css("position", "absolute");
src.css("top", dest.offset().top);
src.css("left", dest.offset().left);
src.width(dest.width());
// Show "src" element, instead of "dest". "src" must be in the same visible position, as "dest"
dest.css("opacity", 0);
src.show();
Unfortunately, it does not works. "src" element has displacement to bottom and left, for that i cannot find the reason.
Maybe, i do something wrong ...
How to do it right for two cases ?
"src" and "dest" having the same grand-parent
"src" and "dest" does't having the same parent. Maybe grand-grand-grand-parent is the common for both.
Update:
I have arranged a simple HMTL document, that does a simple visual swapping of one element with another:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>MacBlog</title>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.4.2.min.js" charset="utf-8"></script>
<style type="text/css" media="screen">
.dest {
background-color: #0cf;
width: 480px;
height: 320px;
}
.src {
background-color: #09c;
width: 1024px;
height: 768px;
}
</style>
<script type="text/javascript" charset="utf-8">
jQuery(function($){
// Common items, to deal with
var src = $(".src");
var dest = $(".dest");
// Setup
src.hide();
// Interaction
dest.click(function(){
src.width(dest.width());
src.height(dest.height());
src.offset(dest.offset());
dest.hide();
src.show();
});
});
</script>
</head>
<body>
<div>
<!--On clicking, this element should visually be swapped by ".src" element -->
<div class="dest"><p>dest</p></div>
<div class="src"><p>src</p></div>
</div>
</body>
</html>
It does not work correctly. After "swapping", "src" element has a strange displacement to top-left direction on ~30 pixels.
I use latest version of Safari 5, if i makes sense.
Update 2:
Unfortunately, this also does not works. I updated my example:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>MacBlog</title>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.4.2.min.js" charset="utf-8"></script>
<style type="text/css" media="screen">
div {
margin: 0;
padding: 0;
}
.holder {
position: relative;
top: 40pt;
left: 40pt;
border: black solid thin;
}
.dest {
background-color: #0cf;
width: 480px;
height: 320px;
}
.src {
background-color: #09c;
width: 1024px;
height: 768px;
}
</style>
<script type="text/javascript" charset="utf-8">
jQuery(function($){
// Common items, to deal with
var src = $(".src");
var dest = $(".dest");
// Setup
src.hide();
// Interaction
dest.click(function(){
src.css("position", "absolute");
src.width(dest.width());
src.height(dest.height());
src.offset(dest.offset());
dest.hide();
src.show();
});
});
</script>
</head>
<body>
<div class="holder">
<!--On clicking, this element should visually be swapped by ".src" element -->
<div class="dest"><p>dest</p></div>
<div class="src"><p>src</p></div>
</div>
</body>
</html>
I tested it here:http://jsfiddle.net/YEzWj/1/
Using your second example make your CSS like this:
div {
position:relative;
margin: 0;
padding: 0;
}
.holder {
position: relative;
top: 40pt;
left: 40pt;
border: black solid thin;
}
.dest {
position:absolute;
background-color: #0cf;
width: 480px;
height: 320px;
}
.src {
background-color: #09c;
width: 1024px;
height: 768px;
}
EDIT: After playing around with it some, it did not work in all circumstances. I decided to change the javascript. Note: My example toggles the display of src and dest within the holder, making holder the same size as dest so the border shows outside the dest and src.
jQuery(function($){
// Common items, to deal with
var src = $(".src");
var dest = $(".dest");
var holder=$(".holder");
holder.width(dest.width());
holder.height(dest.height());
// Setup
src.hide();
// Interaction
dest.click(function(){
src.show();
src.css("position", "absolute");
src.width(dest.width());
src.height(dest.height());
src.offset(dest.offset());
dest.hide();
});
src.click(function(){
dest.show();
src.hide();
});
});
EDIT2: Remove the src.click() event if you wish it to NOT go back to the dest on src click.
You need to make the dest element absolute, otherwise the top and left offsets will not apply.
src.css('position', 'absolute'); // ensure position is set to absolute
src.offset(dest.offset());
Also, elements like p and body will have default stylesheets depending on browser. So try to supply a reset style to make things consistent:
p {
margin: 0;
}
body {
margin: 0;
padding: 0;
}
You can call the offset function to set the offset and handle different parents correctly, like this:
dest.offset(src.offset());

Categories

Resources