i'm trying to do a simple task of moving a div's position when the mouse is clicked. While style.left isn't working, style.backgroundColor is working. Google hasn't been helpful, please help
`body {
background-color: aquamarine;
}
.box {
height: 120px;
width: 120px;
border-radius: 60px;
background-color: black;
}`
const moving = document.querySelector(".box");
function move() {
let x = 100;
moving.style.left = 10 + "px";
console.log("hi");
moving.style.backgroundColor = "white";
}
moving.addEventListener("click", move);
by default div have a static position
static
The element is positioned according to the normal flow of the
document.
The top, right, bottom, left, and z-index properties have no
effect. This is the default value.
https://developer.mozilla.org/fr/docs/Web/CSS/position
an idea can be to set the position of your box in relative or absolute
const moving = document.querySelector(".box");
function move() {
let x = 100;
moving.style.left = 10 + "px";
console.log("hi");
moving.style.backgroundColor = "white";
}
moving.addEventListener("click", move);
body {
background-color: aquamarine;
}
.box {
height: 120px;
position: relative;
width: 120px;
border-radius: 60px;
background-color: black;
}
`
<div class="box"></div>
Related
I'm looking for a soultion when a section is out of viewport, Locomotive scroll will change the css attributes on another element and when is in viewport, it reverts that back.
I couldn't find a soulution or a topic. basic knowledge of JS. So, appreaciate if someone can help me out to figure this out.
This function from https://stackoverflow.com/a/57279138/3807365 is pretty simple to incorporate on scroll.
function isInView(el) {
const box = el.getBoundingClientRect();
return box.top < window.innerHeight && box.bottom >= 0;
}
Lets try
function isInView(el) {
const box = el.getBoundingClientRect();
return box.top < window.innerHeight && box.bottom >= 0;
}
var div1 = document.querySelector(".div1")
var div2 = document.querySelector(".div2")
window.onscroll = function() {
if (isInView(div1)) {
div2.classList.add("active");
} else {
div2.classList.remove("active");
}
if (isInView(div2)) {
div1.classList.add("active");
} else {
div1.classList.remove("active");
}
}
body {
height: 1000px;
}
.div {
width: 50px;
height: 50px;
}
.div1 {
margin-top: 100px;
background: aqua;
margin-bottom: 100px;
}
.div2 {
background: magenta;
}
.active {
border: 2px solid red;
}
<body>
<div class="div div1"></div>
<div class="div div2"></div>
</body>
I'm trying to resize rotated (transformed with css) object with vanilla js. Object origin is center and can't be changed.
I've found a function here which should do the thing, however still it doesn't looks ideal - left top corner change its position (half of pixels or so).
Here is a simplified codepen example.
What code modifications I need to do at getCorrection to keep left top corner position always same?
UPDATE:
As per comments below, the calculation is accurate but browser just can't deal with fractions of a pixel perfectly which seems like a technical limitation? Any ideas how to fix?
If you apply the transforms relative to the top left corner (transform-origin: top left), then you don't need to calculate that correction factor. You can then wrap all the shapes if you need to position them on the page:
const obj = document.querySelector('.object');
const btn = document.querySelector('button');
let h = 100;
let w = 100;
btn.addEventListener('click', () => {
h += 5;
w += 5;
updateElement();
});
function updateElement() {
obj.style.width = w + 'px';
obj.style.height = h + 'px';
}
updateElement();
body {
margin: 0;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
overflow-y: scroll;
overflow-x: hidden;
}
button {
margin: 8px;
padding: 8px;
font-family: monospace;
border: 2px solid black;
background: transparent;
}
.container {
position: relative;
width: 100%;
height: 100%;
}
.object-initial {
position: absolute;
top: 16px;
left: 30%;
outline: 1px dashed black;
transform: rotate(20deg);
transform-origin: top left;
width: 100px;
height: 100px;
}
.object {
position: absolute;
top: 16px;
left: 30%;
outline: 1px solid black;
transform: rotate(20deg);
transform-origin: top left;
}
<button>Increase width and height</button>
<div class="container">
<div class="object"></div>
<div class="object-initial"></div>
</div>
Finally I was able to resolve issue with sub-pixels rendering. I've changed an approach slightly - instead of updating left & top coordinates with offset, I've used css translate() to apply the same offset. Works very well.
Seems transform has much better sub-pixels rendering optimizations.
Here is a codepen example.
function updateElement() {
obj.style.left = l + 'px';
obj.style.top = t + 'px';
obj.style.width = w + 'px';
obj.style.height = h + 'px';
obj.style.transform = 'rotate(' + r + 'deg) translate(' + ox + 'px, ' + oy + 'px)';
}
Same formula might be reused with slight adjustments to preserve any of rectangle corners.
I'm using a small script to follow the cursor with a div element.
This script makes the element strictly follow the cursor.
What I'm trying to do is to add some kind of duration to the process of "following" the cursor. I tried CSS transitions but the animation always ended up breaking. Can somebody please help me with this?
Let's say mouse is somewhere, and then it changes position by around 100px. I want to specify the duration like if i was using CSS... But the thing is that I can not use any transitions but only some javascript magic instead...
document.body.addEventListener("mousemove", function(e) {
var curX = e.clientX;
var curY = e.clientY;
document.querySelector('mouse').style.left = curX - 10 + 'px';
document.querySelector('mouse').style.top = curY - 10 + 'px';
});
body {
background: #333;
height: 500px;
width: 500px;
}
mouse {
display: block;
position: fixed;
height: 20px;
width: 20px;
background: #fff;
border-radius: 50%;
}
<body>
<mouse></mouse>
</body>
I was wondering how to add a transition without using the CSS but I'm not the most advanced when it comes to JavaScript.
[edit] : I don't wanna use window.setTimeout.
[edit 2] : I wanted to use transition: 0.1s; but as I said it broke the effect when user moved the mouse too quickly.
There's a whole bunch of ways to do this, as you can see in the other answers, each with its own "feel". I'm just adding one more, where the dot approaches the cursor by a percentage of the remaining distance.
let curX = 0, curY = 0, elemX = null, elemY = null;
document.body.addEventListener("mousemove", function(e) {
curX = e.clientX;
curY = e.clientY;
if (elemX === null) [ elemX, elemY ] = [ curX, curY ];
});
let amt = 0.1; // higher amount = faster tracking = quicker transition
let elem = document.querySelector('mouse');
let frame = () => {
requestAnimationFrame(frame);
elemX = (elemX * (1 - amt)) + (curX * amt);
elemY = (elemY * (1 - amt)) + (curY * amt);
elem.style.left = `${elemX}px`;
elem.style.top = `${elemY}px`;
};
frame();
body {
position: absolute;
background: #333;
left: 0; top: 0; margin: 0; padding: 0;
height: 100%;
width: 100%;
}
mouse {
display: block;
position: absolute;
height: 20px; margin-left: -10px;
width: 20px; margin-top: -10px;
background: #fff;
border-radius: 50%;
}
<body>
<mouse></mouse>
</body>
You can use setTimeout() function, to introduce a delay:
document.body.addEventListener("mousemove", function(e) {
var delay=250 //Setting the delay to quarter of a second
setTimeout(()=>{
var curX = e.clientX;
var curY = e.clientY;
document.querySelector('mouse').style.left = curX - 10 + 'px';
document.querySelector('mouse').style.top = curY - 10 + 'px';
},delay)
});
body {
background: #333;
height: 500px;
width: 500px;
}
mouse {
display: block;
position: fixed;
height: 20px;
width: 20px;
background: #fff;
border-radius: 50%;
}
<body>
<mouse></mouse>
</body>
Or, to avoid trailing, use an interval and move the cursor to the correct direction (change ratio to set the speed ratio):
var curX,curY
document.body.addEventListener("mousemove", function(e) {
curX = e.clientX;
curY = e.clientY;
});
setInterval(()=>{
var ratio=5
var x=document.querySelector('mouse').offsetLeft+10
var y=document.querySelector('mouse').offsetTop+10
document.querySelector('mouse').style.left=((curX-x)/ratio)+x-10+"px"
document.querySelector('mouse').style.top=((curY-y)/ratio)+y-10+"px"
},16)
body {
background: #333;
height: 500px;
width: 500px;
}
mouse {
display: block;
position: fixed;
height: 20px;
width: 20px;
background: #fff;
border-radius: 50%;
}
<body>
<mouse></mouse>
</body>
Hey guys I’m trying to make simple point & click game, in background will be some nice landscape which will be moved by arrows on the left and right (same like slider works), I want object to move only within the lower div (#boxMap), I tried to build contructor to main object but together with friend who helps me, we wrote it in way below. The problem is that this object still doesn’t move how it should be, idea is that when game starts, and when I click right arrow, object appears on the left, if I click left arrow object appears on the left side of the div. When I click the mouse, object should moves to position I clicked. I’m kinda desperate as I have ideas how to make It work later but I totally cannot manage this positioning and movement of the object.
I found some nice yt tutorial about moving objects and tried to set statements to move only within the div without getting outside the edge, unfortunately now it moves only on the bottom edge of div.
So I created new object with class .hero inside the boxMap, and set it’s starting position with css properties, then with function getClickPosition I try to manage it’s movement, I try also set that if object is clicked outside the frame of div, it set it’s position on particular value. Unfortunately now it moves only through the bottom edge, right side it doesn’t exceed the edge, left side it does.
Hope I was able to more or less explain what I try to achieve and what I have already done.
Any idea how to set position and some simple movement in much simpler way?
I would be grateful for any tips
HTML
<body>
<div id="emptySpace">
<span class="left"></span>
<span class="right"></span>
</div>
<div id="boxMap">
</div>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"
integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
<script src="js/app.js"></script>
</body>
CSS
body {
margin: 0;
padding: 0;
background-color: antiquewhite;
#emptySpace {
width: 100%;
height: 70vh;
background-color: azure;
position: relative;
.left {
position: absolute;
left: 10px;
top: 40vh;
border-top: 40px solid transparent;
border-bottom: 40px solid transparent;
border-right:40px solid blue;
//display: none;
}
.right {
position: absolute;
right: 10px;
top: 40vh;
border-top: 40px solid transparent;
border-bottom: 40px solid transparent;
border-left: 40px solid green;
//display: none;
}
}
#boxMap {
width: 100%;
height: 30vh;
border: 1px solid black;
background-color: #d8fffa;
position: relative;
.hero {
position: absolute;
width: 50px;
height: 50px;
display: inline-block;
border: 1px solid black;
border-radius: 50%;
background-color: blue;
transform: translate3d(0px, -45px, 0);
transition: 2s linear;
}
}
}
Javascript
function Game() {
this.hero = new Hero();
this.counter = 0;
var self = this;
this.boxMap = document.querySelector("#boxMap");
// Placing hero on the map
this.showHero = function () {
var heroElement = document.createElement('div');
heroElement.classList.add('hero');
console.log(self, self.boxMap);
self.boxMap.appendChild(heroElement);
$(heroElement).css({top: 130, left: 30})
}
}
var game = new Game();
game.showHero();
var heroMovement = document.querySelector(".hero");
var boxMap = document.querySelector("#boxMap");
boxMap.addEventListener("click", getClickPosition, false);
// Set position on hero and set movement
function getClickPosition(e) {
var xPosition = e.clientX;
var maxWidth = 1350;
var minWidth = -20;
if (xPosition < minWidth) {
xPosition = minWidth;
} else if (xPosition > maxWidth) {
xPosition = maxWidth
} else {
var xPosition = e.clientX - (heroMovement.offsetWidth + 3);
}
var yPosition = e.clientY;
var maxHeight = 60;
var minHeight = -130;
if (yPosition < minHeight) {
yPosition = minHeight;
} else if (yPosition > maxHeight) {
yPosition = maxHeight
} else {
var yPosition = e.clientY - (heroMovement.offsetHeight + 558);
}
console.log(xPosition, yPosition);
var translate3dValue = "translate3d(" + xPosition + "px" + "," + yPosition + "px, 0)";
console.log(translate3dValue);
heroMovement.style.transform = translate3dValue;
}
My code allows scrolling vertically in the bottom section to control scrolling horizontally in the top section.
My jsfiddle
You'll see the colors shift through a gradient. Works pretty well. Problem is that I can't quite seem to get the inverse to work. Scrolling horizontally in the top controls scrolling in the bottom.
Any ideas?
Here's the script that makes it work:
// Add event listener for scrolling
$("#bottom").on("scroll", function bottomScroll() {
var scrolledleft = parseInt($("#bottom").scrollTop()) * 1;
console.log(scrolledleft + scrolledright)
$("#top").scrollLeft(scrolledleft + scrolledright)
})
//Move right column to bottom initially
$("#top").scrollLeft($("#top").height())
//Get actual distance scrolled
var scrolledright = parseInt($("#top").scrollLeft())
Your event handlers need to temporarily cancel each other so that they don't both fire at once. You want to calculate your position percentage based on the current scrollLeft / (width of child div - width of container), then apply that percentage to the other element, and likewise for top/height. Also I changed the height of #top to 50% in CSS.
var handler = function (e) {
var src = e.target;
// the first element that triggers this function becomes the active one, until it's done
if (!activeScroller) activeScroller = src.id;
else if (activeScroller != src.id) return;
var $b = $("#bottom");
var $t = $("#top");
var scrollH = $("#bottom-content").height() - $b.height();
var scrollW = $("#top-content").width() - $t.width();
var scrollPct = 0;
if (src.id == "top") {
if (scrollW > 0) {
scrollPct = $t.scrollLeft() / scrollW;
}
$b.scrollTop(scrollH * scrollPct);
} else {
if (scrollH > 0) {
scrollPct = $b.scrollTop() / scrollH;
}
$t.scrollLeft(scrollW * scrollPct);
}
// give all animations a chance to finish
setTimeout(function () { activeScroller = ""; }, 100);
};
var activeScroller = "";
$("#top,#bottom").on("scroll", handler);
#top {
position: absolute;
margin: auto;
top: 0;
right: 0;
left: 0;
width: 100%;
height: 50%;
position: fixed;
overflow: auto;
background: red;
}
#top-content {
height: 100%;
width: 2000px;
background: linear-gradient(90deg, red, blue);
}
#bottom {
position: absolute;
margin: auto;
right: 0;
bottom: 0;
left: 0;
width: 100%;
height: 50%;
position: fixed;
overflow: auto;
background: green;
z-index: 100;
}
#bottom-content {
height: 2000px;
width: 100%;
background: linear-gradient(0deg, orange, green);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="top">
<div id="top-content"></div>
</div>
<div id="bottom">
<div id="bottom-content"></div>
</div>
Check out this:
https://jsfiddle.net/1p7gp72h/1/
I'm not sure what your end goal is here.
$("#top").on("scroll", function topScroll() {
var scrolledleft = parseInt($("#top").scrollTop()) * 1;
$("#bottom").scrollLeft(scrolledleft + scrolledright)
});
#top {
top: 0;
right: 0;
left: 0;
width: 5000px;
height: 100%;
overflow: auto;
background: red;
overflow-x: scroll;
overflow-y: hidden;
white-space:nowrap;
}
Scroll to left ::
$('div').scrollLeft(1000);
Scroll back to normal/ scroll to right ::
$('div.slick-viewport').scrollLeft(-1000);