How to stop transition and keep current translate - javascript

following is my code, I wanna stop transtion but keep its current translateY, but following code stop transition and set translateY 0, I expect a way can get current translateY when transition
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<!--mobile friendly-->
<meta name="viewport" content="width=device-width, user-scalable=yes">
<style>
.it {
width: 300px;
height: 300px;
background-color: pink;
transition: transform 1s cubic-bezier(0.19, 1, 0.22, 1) 0s;
}
</style>
</head>
<body>
<div class="it">
</div>
<script type="module">
var it = document.querySelector(".it")
setTimeout(() => {
it.style.transform = "translateY(500px)"
}, 100)
setTimeout(() => {
it.style.transform = null
}, 1000)
</script>
</body>
</html>

I wrote a method I don't know if it will satisfy you
<style>
.it {
width: 300px;
height: 300px;
background-color: pink;
transition: transform 1s cubic-bezier(0.19, 1, 0.22, 1) 0s;
}
.it-class {
transform: translateY(500px) ;
}
</style>
</head>
<body>
<div class="it">
</div>
<button>stop</button>
<script>
var it = document.querySelector(".it")
const button = document.querySelector("button")
button.onclick = () => {
it.classList.toggle('it-class')
}
</script>

I find solution, use getBoudingRectClient().y and window.scrollY can get element abs pos y in document;
so get parent abs_pos_y and element abs_pos_y to get current element pos y from parent top border(rel_pos_y),
cur_translateY = rel_pos_y - element.offsetTop
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<!--mobile friendly-->
<meta name="viewport" content="width=device-width, user-scalable=yes">
<style>
.c {
position: relative;
border: 5px solid black;
width: 300px;
height: 300px;
}
.it {
margin-top: -200px;
width: 300px;
height: 300px;
background-color: pink;
transition: 2s cubic-bezier(0.19, 1, 0.22, 1) 0s;
}
</style>
</head>
<body>
<div class="c">
<div class="it">
</div>
</div>
<script type="module">
var it = document.querySelector(".it")
// offsetTop don't calc translateY, so use following get element abs pos y in document
var getPos = (e) => {
var rect = e.getBoundingClientRect()
return {
x: rect.x + window.scrollX,
y: rect.y + window.scrollY
}
}
setTimeout(() => {
it.style.transform = "translateY(300px)"
}, 100)
//
setTimeout(() => {
var c = document.querySelector(".c")
var cy = getPos(c).y
console.log(`cy:${cy}`)
var iy = getPos(it).y
console.log(`iy:${iy}`)
it.style.transform = `translateY(${iy - cy - it.offsetTop}px)` // iy - cy is element dist from parent top border, - it.offsetTop get translateY
}, 800)
</script>
</body>
</html>

Related

TypeError: Attempted to assign to readonly property - Vanilla Javascript Mouse Position

My expected result is for the image to move within the container according to the calculations made on the x-axis mouse position. That is why Xratio ranges from -1 to 1.
I am not sure what is the readonly property here?
I used console.log(typeof Xratio) and got "number".
I also used console.log(typeof easeOutExpo) and saw "function".
Could this be a simple mistake I am not understanding with assigning?
const bxImg = document.querySelector('.bx-pic');
document.addEventListener('mousemove', (e) => {
const xRatio = (e.clientX / window.innerWidth) * 2 - 1;
console.log(typeof xRatio);
const xRatioEased = 0;
if (xRatio >= 0) {
xRatioEased = easeOutExpo(xRatio);
} else {
xRatioEased = easeOutExpo(-xRatio * -1)
}
bxImg.style.transform = `scale(1.2) translate3D(${-xRatioEased * 10}px, ${0}, ${0})`;
})
function easeOutExpo(n) {
if (n === 1) {
return 1;
} else {
return 1 - Math.pow(2, -10 * n);
}
}
console.log(typeof easeOutExpo);
html, body {
width: 100%;
height: 100%;
}
body {
background-color: #FDFDFD;
}
img {
width: 100%;
height: 100%;
object-fit: cover;
}
.bx-wp {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
overflow: hidden;
width: 350px;
height: 350px;
outline: 30px solid royalblue;
}
.bx {
position: relative;
transform: scale(1.2);
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title></title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="bx-wp">
<img src="https://images.unsplash.com/photo-1641113994135-a9f230b1f9b0?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2670&q=80" alt="A Mountain" class="bx bx-pic">
</div>
<script src="script.js"></script>
</body>
</html>
You've declared xRatioEased as a const, so it can only be set on initialisation. Replace const xRatioEased with let xRatioEased and it should all work.
xRatioEased is a constant. Constants can be changed only on initialization. If you declare xRatioEased as a variable (with let or var), you can fix the issue.
If you want to know more about constants and when to use them, you can head over to this link

Having issue's on image position after user selects reset

I have some image assets (folders in this example), where I can drag around and then use the "reset" button to essentially clean them up. However, after you reset the positions and try to drag again, it takes you all the way back to where you dragged it previously? Odd right??? Any help is greatly appreciated!
Again, looking to just solve for:
Let the user drag a folder/image
Let the user reset/clean-up
Let the user drag again, but starting from "reset"
"use strict";
// Reset Folder position on Clean Up
$(".reset-position").click(function () {
// Reset position
$(".resize-drag").removeAttr("style").css("transition", ".5s");
setTimeout(function () {
$(".resize-drag").removeAttr("style");
}, 600);
});
interact(".resize-drag")
.draggable({
onmove: window.dragMoveListener,
})
.resizable({
preserveAspectRatio: false,
edges: { left: false, right: false, bottom: false, top: false },
})
.on("resizemove", function (event) {
var target = event.target,
x = parseFloat(target.getAttribute("data-x")) || 0,
y = parseFloat(target.getAttribute("data-y")) || 0;
// update the element's style
target.style.width = event.rect.width + "px";
target.style.height = event.rect.height + "px";
// translate when resizing from top or left edges
x += event.deltaRect.left;
y += event.deltaRect.top;
target.style.webkitTransform = target.style.transform =
"translate(" + x + "px," + y + "px)";
target.setAttribute("data-x", x);
target.setAttribute("data-y", y);
target.textContent = event.rect.width + "×" + event.rect.height;
});
function dragMoveListener(event) {
var target = event.target,
// keep the dragged position in the data-x/data-y attributes
x = (parseFloat(target.getAttribute("data-x")) || 0) + event.dx,
y = (parseFloat(target.getAttribute("data-y")) || 0) + event.dy;
// translate the element
target.style.webkitTransform = target.style.transform =
"translate(" + x + "px, " + y + "px)";
// update the posiion attributes
target.setAttribute("data-x", x);
target.setAttribute("data-y", y);
}
:root {
--font-color: #000;
--font-size: 13px;
}
html,
body {
overflow: hidden;
background:white;
}
p {
font-size: var(--font-size);
text-align: center;
padding-top: 5px;
color: var(--font-color) !important;
}
.folder-container-1 {
width: 82px;
position: absolute;
right: 30px;
top: 10%;
cursor: pointer;
}
#folders {
width: 82px;
display: flex;
align-content: center;
justify-content: center;
}
#folders:active {
opacity: 0.7;
transform: rotate(4deg);
background: rgba(0, 0, 0, 0.5);
border-radius: 4px;
border: 1px solid grey;
}
.resize-drag {
box-sizing: border-box;
touch-action: none !important;
user-select: none !important;
}
.resize-container {
width: 100%;
height: 240px;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<title>Folder Reset Position</title>
<!-- Bootstrap core CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css" />
<link rel="stylesheet" href="/style.css" />
</head>
<body>
<div class="folder-container-1">
<div class="folder-1 resize-drag projects-folder" data-target="#myProjects">
<img src="https://i.ibb.co/C2W4qR0/folder.png" id="folders" title="folder" alt="folder" />
<p>Folder 1</p>
</div>
<div class="folder-1 resize-drag components-folder" data-target="#myComponents">
<img src="https://i.ibb.co/C2W4qR0/folder.png" id="folders" title="folder" alt="folder" />
<p>Folder 2</p>
</div>
<div class="folder-1 resize-drag about-folder" data-target="#aboutMe">
<img src="https://i.ibb.co/C2W4qR0/folder.png" id="folders" title="folder" alt="folder" />
<p>Folder 3</p>
</div>
<button class="reset-position">Reset</button>
</div>
</body>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/interact.js/1.2.6/interact.min.js"></script>
<script src="/script.js"></script>
<script src="/drag.js"></script>
</html>
You have the data-x/data-y attribute still attached to the draggable even after reset. Try removing that and it should work fine.
I'm quite not sure why you need setTimeout to remove the style attribute though. I have added an extra statement to remove data-x and data-y. Maybe you can clean that up to a single statement
$(".reset-position").click(function () {
// Reset position
$(".resize-drag").removeAttr("style").css("transition", ".5s");
$(".resize-drag").removeAttr('data-x data-y');
setTimeout(function () {
$(".resize-drag").removeAttr("style");
}, 600);
});

Scrollbar height indicator to execute function

I'm using jQuery to get user's current height, and after he reaches that height, there will be animation function (Such as reactive websites, when user scroll down he has animation in different part of the page).
Yet, I can't really figure out why exactly the following code doesn't work.
$(window).scroll(function() {
var height = $(window).scrollTop();
if(height > 200) {
$("#project").animate({
bottom: '250px',
opacity: '0.5',
height: '1000px',
width: '100%'
});
}
});
CSS:
/* About Page */
.about{
width: 100%;
height: 1000px;
background-color: blue;
}
/* Projects Page */
.project{
background-color: red;
}
HTML:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="stylesheet" type="text/css" href="css/style.css" />
<script src="jquery-3.4.1.min.js"></script>
<script src="myscripts.js"></script>
<title>My Portfolio</title>
</head>
<body>
<div id="about" class="about">
</div>
<div id="project" class="project">
</div>
</body>
</html>
How can I use scrolling height indicator to activate functions such as animation?
You need to take into account the height of each section and calculate the scrollBottom position instead, which might be more useful if you want to trigger an animation once you reach some element:
const $about = $('#about');
const $projects = $('#projects');
const $services = $('#services');
// Calculate the top offset of each section (number of sections above it * 1000px each).
// We want to expand them when we are 50px above them, so we substract that.
let projectTop = 1000 - 50;
let servicesTop = 2000 - 50;
$(window).scroll(() => {
requestAnimationFrame(() => {
// Calculate the scrollBottom by summing the viewport's height:
const scrollBottom = $(window).scrollTop() + $(window).height();
if (scrollBottom >= projectTop) {
$projects.animate({ height: '1000px' });
}
if (scrollBottom >= servicesTop) {
$services.animate({ height: '1000px' });
}
});
});
body {
margin: 0;
}
.about {
background: red;
width: 100%;
height: 1000px;
}
.projects {
background: green;
width: 100%;
}
.services {
background: blue;
width: 100%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="about" class="about"></div>
<div id="projects" class="projects"></div>
<div id="services" class="services"></div>

How to make an bouncing of element smooth onclick (only using vanilla JS)?

I want to make something that is like this:
http://www.lessmilk.com/imgtut/FB1/3.gif
But my square dosen't seem to bounce up properly (it should move up to a certain distance then fall back. Like that in example), especially when it is falling, it stops for in same position on first click and then requires second click to move up . What did I do wrong or is it not just tuned properly? Can it be done in some other way? Need help and suggestions.
Here is my code.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Bounce</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
.container {
background-color: aqua;
height: 300px;
width: 500px;
position: relative;
}
.square {
height: 25px;
position: absolute;
width: 25px;
background-color: brown;
}
</style>
</head>
<body>
<div class="container" onclick="accelerateUp()">
<div class="square" style="top:0; left:20px"></div>
</div>
<script>
var square = document.querySelector('.square');
var updateInterval, gravitySpeed = 0, gravity = 0.05;
function accelerateUp() {
clearInterval(updateInterval)
gravity = -0.2;
setTimeout(() => { gravity = 0.05 }, 100)
updateInterval = setInterval(() => accelerateDown(), 5)
}
function accelerateDown() {
let topValue = parseInt(square.style.top);
let leftValue = parseInt(square.style.left);
gravitySpeed += gravity;
square.style.top = topValue + gravitySpeed + 'px';
hitBottom();
}
function hitBottom() {
if (parseInt(square.style.top) > 250 || parseInt(square.style.top) < 0) {
gravitySpeed = 0;
}
}
updateInterval = setInterval(() => accelerateDown(), 5);
</script>
</body>
</html>
Instead of having an "accelerateUp" you should just consider setting the velocity to a specific/set value on each click OR changing the velocity by a set amount.
I think part of the problem is trying to manage how the acceleration changes as a result of the click hitting the square up, and I think it's just easier to change the velocity and let the acceleration remain constant.
const square = document.querySelector('.square');
const frameRate = 60; // fps
const yAcceleration = .5; // change in px / frame
const hitUpForce = -10;
let yVelocity = 0; // px / frame
let yPosition = 0; // px
function timeStep() {
// velocity changes position
const willHitGround = yPosition + yVelocity > 275
yPosition = willHitGround ? 275 : yPosition + yVelocity;
// accerlation changes velocity
yVelocity = willHitGround ? 0 : yVelocity + yAcceleration;
square.style.top = `${yPosition}px`
}
function hitUp() {
// just set contant velocity as result of hit
yVelocity = hitUpForce; // Or possibly yVelocity += hitUpForce
}
updateInterval = setInterval(timeStep, 1000/frameRate);
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Bounce</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
.container {
background-color: aqua;
height: 300px;
width: 500px;
position: relative;
}
.square {
height: 25px;
position: absolute;
width: 25px;
background-color: brown;
}
</style>
</head>
<body>
<div class="container" onclick="hitUp()">
<div class="square" style="top:0; left:20px"></div>
</div>
</body>
</html>
Ok, I just figured it out that I have to reset the gravitySpeed variable to 0 on click (because when falling it's value is negative and that was stoping the ball from jumping on first click). So resetting the variable helped me. I posted the answer here so that it can help someone.
function accelerateUp() {
clearInterval(updateInterval);
gravitySpeed = 0;
gravity = -0.2;
setTimeout(() => { gravity = 0.05 }, 100)
updateInterval = setInterval(() => accelerateDown(), 5)
}

How to move an drag and drop item to a certain position, when located over canvas?

I am working on a Tablet-environment with draggable objects.
The drag & drop works, it is even possible to drag several objects at once, when implemented.
References are :
Reference 1 & Reference 2
This is how the current version of my code looks like:
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="utf-8">
<meta
name='viewport'
content='width=50px, initial-scale=1.0, maximum-scale=1.0, user-scalable=0,'
/>
<!--
Refernces:
* https://wiki.selfhtml.org/wiki/JavaScript/Tutorials/Drag_and_Drop
* https://mobiforge.com/design-development/touch-friendly-drag-and-drop
-->
<style>
#container {
width: 200px;
height: 200px;
position: relative;
background: yellow;
top: 100px
}
main1 {
position: relative;
}
div1 {
position: absolute;
top: 0px;
left: 100px;
height: 72px;
width: 72px;
background: red;
border: 0px solid #666;
margin: 0;
padding: 0;
}
</style>
<title>Clean up</title>
</head>
<body>
<div id ="container">
</div>
<main1 id="main1">
<div1 class="draggable" id="d1-0""></div1>
</main1>
<script>
var nodeList = document.getElementsByClassName('draggable');
for(var i=0;i<nodeList.length;i++) {
var obj = nodeList[i];
obj.addEventListener('touchmove', function(event) {
var touch = event.targetTouches[0];
// Place element where the finger is
event.target.style.left = touch.pageX + 'px';
event.target.style.top = touch.pageY + 'px';
event.preventDefault();
}, false);
}
</script>
</body>
</html>
The idea is, that the red box (div1) can be moved, dragged and dropped everywhere on the screen. But it needs to be moved to its very initial starting position, when it enters the yellow canvas. (The idea is to "clean up" and "move objects back to where they came from".)
You should use jQuery UI's draggable and touch punch for mobile friendliness
Let me know if this is close to what you're looking for and we can adjust as needed
$(document).ready(function() {
$('#div1').draggable();
$('#container').droppable({
drop: function( event, ui ) {
alert("You dropped the red on the yellow");
}
});
$(document).on("click", "#animateBtn", function() {
//Simple animate w/ just specifying the offsets
//$('#div1').animate({top:"250px", left:"250px"});
//Other animate options
$('#div1').animate({
top:"15px",
left:"15px"
}, {
duration:555, //Animation time in pixels
easing:"easeOutQuart" //See https://api.jqueryui.com/easings/
});
});
});
#container {
width: 200px;
height: 200px;
position: relative;
background: yellow;
top: 100px
}
body {
position: relative;
}
#div1 {
position: absolute;
top: 0px;
left: 100px;
height: 72px;
width: 72px;
background: red;
border: 0px solid #666;
margin: 0;
padding: 0;
}
#animateBtn {
position:fixed;
right:10px;
bottom:10px;
display:inline-block;
padding:3px 5px;
background-color:green;
color:white;
border-radius:6px
}
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="utf-8">
<meta
name='viewport'
content='width=50px, initial-scale=1.0, maximum-scale=1.0, user-scalable=0,'
/>
<title>Drag and Drop</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui-touch-punch/0.2.3/jquery.ui.touch-punch.min.js"></script>
</head>
<body>
<div id="container"></div>
<div class="draggable" id="div1"></div>
<div id="animateBtn">Animate</div>
</body>
</html>
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="utf-8">
<meta
name='viewport'
content='width=50px, initial-scale=1.0, maximum-scale=1.0, user-scalable=0,'
/>
<title>Drag and Drop</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui-touch-punch/0.2.3/jquery.ui.touch-punch.min.js"></script>
<style>
#container {
width: 200px;
height: 200px;
position: relative;
background: yellow;
top: 100px
}
body {
position: relative;
}
#div1 {
position: absolute;
top: 100px;
left: 100px;
height: 72px;
width: 72px;
background: red;
border: 0px solid #666;
margin: 0;
padding: 0;
}
</style>
<title>Clean up</title>
</head>
<body>
<div id="container"></div>
<div class="draggable" id="div1"></div>
<!--<div id="animateBtn">Animate</div>-->
<script>
$(document).ready(function() {
$('#div1').draggable();
$('#container').droppable({
drop: function() {
$('#div1').animate({top:"100px", left:"100px"});
}
});
});
</script>
</body>
</html>
I didn't see a mention of jQuery but w3schools has a working example that goes without. Could you some touchup though:
/**
* Make object draggable
* #param {Element} element
*/
const addDraggable = (element)=> {
let pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
const dragMouseDown = e => {
e = e || window.event;
e.preventDefault();
// get the mouse cursor position at startup:
[pos3, pos4] = [e.clientX, e.clientY];
document.onmouseup = closeDragElement;
document.onmousemove = elementDrag;
};
const elementDrag = e => {
console.log(e.clientX, e.clientY);
e = e || window.event;
e.preventDefault();
// calculate the new cursor position:
[pos1, pos2] = [pos3 - e.clientX, pos4 - e.clientY];
[pos3, pos4] = [e.clientX, e.clientY];
// set the element's new position:
[element.style.top, element.style.left] =
[(element.offsetTop - pos2) + "px", (element.offsetLeft - pos1) + "px"];
};
const closeDragElement = _ => {
// stop moving when mouse button is released:
document.onmouseup = null;
document.onmousemove = null;
};
element.onmousedown = dragMouseDown;
}
document.addEventListener("DOMContentLoaded", event=> {
_('#logo-top').addEventListener('click', event=> {
event.stopPropagation();
_('#logo-top').classList.toggle('active');
_('nav').forEach( n=> n.classList.toggle('collapsed') );
_('main').classList.toggle('extended');
});
addDraggable( _('#help-text') );
_( '#help' ).addEventListener( 'click', ()=>{ _('#help-text').classList.toggle('active')} );
_( '#help-text-close' ).addEventListener( 'click', ()=>{_('#help-text').classList.toggle('active')} );
});
Another way would be to use the Drag Operations

Categories