How do I get a CSS object to move using Javascript? - javascript

I am trying to make a JavaScript game and I need a CSS object with an animation to move in place of an object I originally made using JavaScript. Basically, what I want to happen is have my "sword" CSS object move with my player object when I have it Unsheathed. I have been looking for a while and they only give me a result as to were it will be when the page is loaded. I need the sword to always be moving with the player. If my code is needed, tell me, and I will provide it. If you have any questions, feel free to ask. I am pretty new so go easy on the terrible JavaScript that may be provided.
PLEASE USE AN EXAMPLE RELATED TO MY CODE!
if you don't I probably wont understand what is going on....
Thank You in Advance

Focusing the the following element of your example I am only going to address CSS here...
....
<div class="player"></div>
<div id="swordl"></div>
<div id="swordr"></div>
....
To move #swordl and #swordr along with .player you can take advantage of a feature of the CSS position attribute.
When a containing element has CSS position: relative; children of that element with the CSS position: absolute; are positioned with reference to the top-left corner of the parent.
In the following example #player would be the parent, and #swordl and #swordr would be the children...
....
<div id="player">
<div id="swordl"></div>
<div id="swordr"></div>
</div>
....
/* CSS */
#player {
position: relative;
}
#swordl, #swordr {
position: absolute;
}
#swordl {
left: 4px;
top: 2px;
}
#swordr {
left: 12px;
top: 2px;
}
Note the change of class to id in 'player'
Now, whenever you animate the position of #player the two #swords will maintain their position relative to the top-left corner of their containing parent element: you will not have to animate the position of #swords explicitly.
Hope that helps. ;)
CSS position # MDN

You can use the transistion. I have included a couple examples. One example is just JavaScript, the other is not just JavaScript.
//Get Element By Id of 'movingdiv'
var div = document.getElementById('movingdiv');
//Create the timeout (not required)
setTimeout(function() {
//Change the style.top to 50%, You can also do this in px
div.style.top = '50%';
//Change the style.top to 50%, You can also do this in px
div.style.left = '50%';
//Add the transform so it can be centered in the viewport
div.style.transform = 'translate(-50%,-50%)';
//Add the timeout below in milliseconds.
}, 1000)
#movingdiv {
width: 100px;
height: 100px;
background: black;
position: absolute;
top: 10px;
left: 10px;
transition: all 2s;
}
<div id='movingdiv'></div>
//Create a div
var div = document.createElement('div');
//Give the div some style. IMPORTANT: notice the transition
div.style = 'width: 100px; height: 100px; background: black; position: absolute; top: 10px; left: 10px; transition: all 2s;';
//Append the div to the body
document.body.appendChild(div);
//Create a timeout for the div to move
setTimeout(function() {
//Change the style.top to 50%, You can also do this in px
div.style.top = '50%';
//Change the style.top to 50%, You can also do this in px
div.style.left = '50%';
//Add the transform so it can be centered in the viewport
div.style.transform = 'translate(-50%,-50%)';
//Add the timeout below in milliseconds.
}, 1000)

Related

Centre Lottie SVG to a Header element

I have an animation from Lottiefiles (in JSON format), which is then converted into an animated SVG document by the Lottie framwork. However, I can't seem to position the SVG document with the header tag. I'd like it to be beside the text.
I tried to search existing threads for similar things, but none of these worked, except for one (sort of). This included adding the SVG into a div, inside the header itself. However, when I tried this, the SVG document is fixed in place, so while it worked for shorter text (less than 6 characters), if the text was longer, the SVG would appear underneath, instead of moving to the end of the text.
I also have to manually assign the style to the SVG file through Javascript in a timeout, because the SVG document doesn't exist initially.
This is the actual header code (in PugJS).
h1(class="channel-header" style="margin-bottom: 36px; width: 96px; margin: auto;") #{channel}
if premium
div(id="bodyanim" class="badge baseline")
Here is the SASS for the header and inner div tag:
.badge
display: inline-flex
align-self: center
height: 70%
.badge svg, .badge img
height: 1em
width: 1em
fill: currentColor
z-index: -1
position: absolute
left: 0
top: 0
.badge.baseline svg, .badge img
top: .125em
position: relative
.channel-header
margin: 0 0 16px 0
padding: 0
line-height: 1
font-weight: normal
position: relative
height: 45px
And here's the JS setting the SVG object, and setting its CSS after a timeout.
var animData = {
wrapper: document.getElementById('bodyanim'),
animType: 'svg',
loop: true,
prerender: true,
autoplay: true,
path: '/anims/4768-trophy.json'
};
var anim = bodymovin.loadAnimation(animData);
setTimeout(function () {
var svg = animData.wrapper.getElementsByTagName("svg")[0];
svg.style.position = "absolute";
svg.style.left = "0";
svg.style.top = "0";
svg.style.zIndex = -1;
svg.style.marginLeft = "65%";
}, 100);
When I run the site with this code, the header works for any text shorter than 7 characters, but if there's more, the header tries to "push" itself above the SVG document, and the SVG remains in position behind it instead of moving along with the text.
You can see an example of this on this site (you can either edit the endpoint, i.e. /channel/anythinghere or edit the tag client-side):
http://themadgamers.co.uk:3000/channel/ItsMike
Why do you set a fixed width for your h1?
h1(class="channel-header" style="margin-bottom: 36px; width: 96px; margin: auto;")
If you remove the 96px width restriction, longer strings no longer push the trophy below the user names.
As for the manual need to style the SVG via JavaScript...
setTimeout(function () {
var svg = animData.wrapper.getElementsByTagName("svg")[0];
svg.style.position = "absolute";
svg.style.left = "0";
svg.style.top = "0";
svg.style.zIndex = -1;
svg.style.marginLeft = "65%";
}, 100);
Consider adding a new class to your CSS.
.mySvg {
position: absolute;
left: 0;
top: 0;
z-index: -1;
margin-left: 65%;
}
Then you should be able to simplify the JavaScript to:
setTimeout(function () {
var svg = animData.wrapper.getElementsByTagName("svg")[0];
svg.className = "mySvg";
}, 100);

Clipping a site display with an overlay div in a given viewport

I am querying how it is possible to have a site, for arguments sake StackOverflow, where an overlay div can hide all of the content apart from what is inside the div. I suppose like a camera, you can only see whats in the viewfinder, not outside of it. I want for the moment for the viewfinder to be fixed.
I found: Fiddle
which is close, but not quite. I have tried to google and ask friend devs but no luck in the resource department. Anyone got any ideas to get me started?
<html>
<div class="content">
<h1>All the page content divs</h1>
</div>
<div id="viewport-window"></div>
</html>
You can do this by applying a clip-path style to the main element you want the overlay to be over (for instance body if you want the whole page). You could possibly also use clip for more browser support, but do keep in mind it is being deprecated.
Demo
Has a static clip-path, but when moving mouse around it will change to a 200x200 viewport that follows the mouse
jQuery(document).mousemove(function(e){
var width = jQuery(document).width();
var height = jQuery(document.body).height();
var viewW = 200;
var viewH = 200;
var top = e.pageY - (viewH/2);
var right = (width-e.pageX) - (viewW/2);
var bottom = (height-e.pageY) - (viewH/2);
var left = e.pageX - (viewW/2);
var style = "inset("+top+"px "+right+"px "+bottom+"px "+left+"px)";
jQuery(document.body).css({
"-webkit-clip-path":style,
"-moz-clip-path":style,
"clip-path":style
});
});
body {
-webkit-clip-path:inset(20px 200px 200px 40px);
-moz-clip-path:inset(20px 200px 200px 40px);
clip-path:inset(20px 200px 200px 40px);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<img src="https://placekitten.com/g/500/500" />
Actually, you can do this without an "overlay" element.
Just use a giant box-shadow and a high z-index.
In this example I've used a :hover and the 'overlay` is slightly transparent.
.wrapper {
width: 80%;
margin: auto;
text-align: center;
}
.box {
width: 100px;
height: 100px;
margin: 1em;
display: inline-block;
vertical-align: top;
background: plum;
position: relative;
}
.box:hover {
box-shadow: 0 0 0 10000px rgba(0, 0, 0, 0.75);
z-index: 9999;
}
<div class="wrapper">
<div class="box">Lorem ipsum.</div>
<div class="box">Lorem ipsum.</div>
<div class="box">Lorem ipsum.</div>
</div>
Of course, this effect is purely visual the other elements are still accessible.
You can also do that in 2 steps for example:
First, create a div to overlay entire page and hide everything.
Second, create a clone of your div(to be shown) with absolute position which has the same coordinates of the original location, and increase its z-index.
So, the logic is to hide everyting and show what you want over it. You could also visualize it with css or jquery animations.

Adjusting a div based on the size of the container

I have an HTML video player with Javascript generated controls(with background images of SVG graphics). I'm having an issue using the css calc() function, and need to resize the div's based on the video controls bar. So when the window is expanded/contracted, the controls need to adjust accordingly.
The controls div:
//Controls Wrapper
videoObj.controlsWrapper = document.createElement("div");
videoObj.controlsWrapper.className = "video-controls";
The controls are generated dynamically, so for instance, the play button is generated by this:
videoObj.playBtn = document.createElement("button");
videoObj.playBtn.className = "play btn";
So the question is how to adjust the size of the play button(which is a background of an SVG graphic), to a percentage(about 25%) of the height of the controls wrapper div.
jsfiddle
This is the easiest way... try resizing the box :)
The parent is relative. The child is absolute. Setting the top, left, right and bottom all to 0 will actually create a spider web effect ( or stretch effect ). I used different pixels so you could see the reaction. otherwise the child will cover the parent. Hope this helps.
http://jsfiddle.net/m5wm1rLs/
.parent{
position: relative;
width: 100px;
height: 100px;
background-color: red;
}
.child{
position: absolute;
top: 3px;
bottom: 20px;
left: 3px;
right: 20px;
background-color: green;
}
<div class="parent">
<div class="child"></div>
</div>
To test that this works, you can make parent resizable:
$('.parent').resizable();
Resizing it to 25% of the parent div height is relatively easy, but only doable with a scripting language. As far as CSS has come by allow calc(), it has no support for pulling the sizes of designated elements.
Here's a simple script I threw together for you:
window.onload = function() {
resize();
}
window.onresize = function() {
resize();
}
function resize() {
document.getElementsByClassName('play')[0].style.width = (document.getElementsByClassName('timeline')[0].offsetHeight * .25) + 'px';
}
JSFiddle: http://jsfiddle.net/zq2vzkk5/
I recommend you use ids to identify the elements you want to pull the values from, but if the positions of the elements won't change on the page, then classes are fine. You just have to update which instance of the class you want to pull the value from if it does change.
If you want a jQuery variation, I can supply that, too.
I hope this helps.
Edit:
Here's the jQuery variation:
$(function() {
resize();
$(window).resize(function() {
resize();
});
});
function resize() {
$('.play').first().width($('.timeline').first().outerHeight() * .25);
}
JSFiddle: http://jsfiddle.net/s51vrca2/
You can do this without JS :
.play {
height: 25%;
}

JQuery Mousemove div class e.pageX positions

I am using this code:
$('.my_img').mousemove(function(e){
$('.mycls').css("left",e.pageX-20+"px");
$('.mycls').css("top",e.pageY-10+"px");
});
then...
<div class="mycls">I Move</div>
then...
<img class="my_img" src="myimg.png" />
My problem is that if I add any div's above these divs the position changes and mycls is no longer at mouse position.
So if I was to add to extra div's after the body like this:
<div>ONE</div>
<div>TWO</div>
...then the rest of the code...I will lose the position :o/
Any ideas on how to sort this?
Since e.pageX and e.pageY values are relative to the entire page, your code shouldn't be affected by adding new elements. If you set top and left to an element, it defines its distance from the top and left of the page.
The only case where it could be problematic is if you have position:relative set on any parent elements of the mycls div. Remove that position:relative, so that top and left refer to the entire page and not the parent element.
simply add a CSS position:absolute; to your movable element .mycls
var img = document.getElementById("my_img");
var cls = document.getElementById("mycls");
img.onmousemove = function(e){
cls.style.left = e.clientX-20 + "px";
cls.style.top = e.clientY-10 + "px";
};
#mycls {
background-color: rgba(255,255,255,0.8);
position: fixed;
left: 0;
top: 0;
font-family: sans-serif;
padding: 10px;
border-radius: 5px;
border: 1px solid rgba(0,0,0,0.8);
}
#my_img {
width: 420px;
height: 200px;
background-color: #333; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="my_img">
<div id="mycls">
Your message here
</div>
</div>
Here's an example of how I have done this in the past ... importantly
the div that is moving is a child of the container so that a any mousemove events it triggers are bubbled to the parent for handling

CSS absolute positioning elements inside a div

I have a .wall div with a some .toy divs inside it. I want to arrange the toys inside the wall. float:left property has done it for me nicely.
Now the problem is I want to add position:absolute for the toy divs to make it draggable later. How can I do this either via Javascript or via CSS?
Applying position:absolute, all toys will come to the top left corner of the wall overlying and hiding each other.
The width and height of the wall is constant but the width and height of the toys is variable, also the number of toy divs is dynamic and as the number increases toys need to arrange as rows.
Any suggessions will be helpful, please note the I can not avoid the use of position:absolute for dragging.
<script type="text/javascript" src="jquery-1.4.2.min.js"></script>
<style>
body{
text-align:center;
}
.clearfix{
clear:both;
}
.wall {
border: 5px solid #cde;
margin:auto;
width:200px;
padding:10px;
}
.toy{
background-color: #BBCCEE;
border:1px solid #8899BB;
margin:5px;
width: auto;
padding:5px;
float:left;
}
.tall{
padding-top:10px;
}
</style>
<script>
$(document).ready(function() {
$('.toy').each(function(index) {
var position = $(this).offset();
var prevPosition = $(this).prev().offset();
$(this).css({
//top: position.top,
//left:position.left,
//position:'absolute',
});
});
});
</script>
<div class='wall'>
<div class='toy'>T1</div>
<div class='toy'>T2</div>
<div class='toy'>T3333333</div>
<div class='toy'>T4</div>
<div class='toy'>T5</div>
<div class='toy tall'>T6</div>
<div class='toy'>T7</div>
<div class='toy'>T8</div>
<div class='clearfix'></div>
</div>
Here is the code at JSBin.
Add
position:relative
To the wall div
I am working on a website that does exactly that (sorry for the non-english stuff):
http://moveit.canassa.com/cartao/4/
The link is now broken but here is a jsFiddle that shows what I am talking about:
http://jsfiddle.net/canassa/Z9N3L/
The "toy" div is using a position absolute:
.toy{
width: 100px;
height: 25px;
position: absolute;
z-index: 0;
}
The problem with the position absolute is that the toy will be relative to page and not the "wall" container, in order to fix that you must make the wall container relative:
#wall{
position: relative;
overflow: hidden;
}
The overflow:hidden is also a nice trick that I found. It makes the draggable objects go "under" the wall container.
There is no big secret to make it draggable, using jQuery:
// Creates a toy div inside the wall
$(MV.wallId).append('<div class="toy" id="' + this.getId() + '"></div>');
box = this.getBox(); // return the "toy" that I've just created.
$('#' + this.getId()).draggable(); // make it draggable
This would be a lot easier if you just used the jQueryUI .draggable(). It doesn't require the elements to be positioned.
If you're dead set on using this plugin, then you have the right idea. Let the elements flow into place and then calculate their position and set position: absolute and whatever the left and top end up being at runtime.
Set the .wall to be position: relative. Then:
var tPos;
$('.toy').each(function(index) {
tPos = $(this).position();
$(this).css({
left: tPos.left,
top: tPos.top
});
};
$('.toy').css({
position: absolute
});
The height of the .wall and the width of each .toy collapse when the toys are absolutely positioned but you can just add a few more lines to get/set their width and height in the above .each loops.
This obviously doesn't work if new toys can be added dynamically without a page reload as you suggest. To handle that you could switch them back to position: relative, add the new one, get the position of the new one in the flow, then set the position and switch back to position: absolute. Any elements that had been dragged out of place would be gaps in the flow, but I don't see any easy way around that.
the element in that the absolute should be positioned, must have the style position:relative.
(must be a parent of the target element)
The container div for every .toy must have position:relative set. That way, the position 0 for its children elements becomes its top left corner. Like this:
<div class="parent">
<div class="child">Blah.</div>
<div class="child">Blah.</div>
</div>
And:
.parent {
position: relative;
}
.child {
position: absolute;
left: 10px; /* This is 10 pixels from the parents left side */
top: 10px; /* This is 10 pixels from the parents top side */
}
Good luck.

Categories