How to translate element to act like a odometer - javascript

I've got code:
<div class="wrap2" id="wrap" data-num="0">
<span>0</span><span>1</span>...
CSS:
.wrap2[data-num="0"] {
transfom:translate(0, 0);
}
.wrap2[data-num="1"] {
transform:translate(0, -30px);
}
https://jsfiddle.net/9t4zsuov/2/
But i want to act like a odometer - numbers have to roll only to top, not bottom. Any ideas, how to do that ?

As #codyThompsonDev said, a rollover area is the best way to implement this. Something I think he missed though, is what happens when you go from a rollover number to a non-rollover number.
For example, let's say that the odometer randomly tries to roll to 4, then 3, then 1. The first time, it can roll to 4 no problem. The second time, it has to roll to "13", in the rollover zone. But then, it tries to roll to "11" which is also in the rollover zone, causing it to roll backwards.
To achieve this effect under those circumstances, you must snap the dial back out of the rollover zone, then roll forward again. I would implement this using window.requestAnimationFrame().
I've made a fiddle to demonstrate this: https://jsfiddle.net/tprobinson/8k125fmz/67/
Add the debugBackground class to dupa2 to see the rollover effect visually.
I would recommend generating the CSS classes with a preprocessor like Sass, as writing them by hand can be error prone as well.
document.getElementById("rand").addEventListener("click", randomize);
const debug = document.getElementById("debug");
const dupa = document.getElementById("cipa");
let animationInProgress = null
function setDebug(num) {
debug.textContent = 'Number is really: ' + num
}
function animateOdometer(newNum) {
// Add the smooth class and set the number to let it roll.
dupa.classList.add('smooth')
setDebug(newNum)
dupa.dataset.num = newNum
// In 1000 ms, remove the smooth class
animationInProgress = window.setTimeout(() => {
dupa.classList.remove('smooth')
animationInProgress = null
}, 1000)
}
function randomize() {
let oldNum = Number.parseInt(dupa.dataset.num)
if (oldNum === undefined || oldNum === null) {
oldNum = 0
}
let newNum = Math.floor(Math.random() * 9) + 0;
// If an animation is already in progress, cancel it
if (animationInProgress) {
window.clearTimeout(animationInProgress)
dupa.classList.remove('smooth')
animationInProgress = null
}
// If the new number is before our old number
// we have to force a roll forwards
if (newNum < oldNum) {
newNum += 10
}
if (oldNum > 9) {
// The dial was already rolled over. We need to
// snap the dial back before rolling again.
// Wait for a frame so we can snap the dial back
dupa.dataset.num = oldNum - 10
setDebug(oldNum - 10)
dupa.classList.remove('smooth')
window.requestAnimationFrame(() => {
// Wait for one frame to let the snapback happen
window.requestAnimationFrame(() => {
// Then roll forward
animateOdometer(newNum)
})
})
return
}
// Roll the dial
animateOdometer(newNum)
}
#rand,
#debug {
margin-top: 50px;
}
.dupa1 {
height: 30px;
width: 30px;
border: 1px solid #000;
overflow: hidden;
}
.dupa2.smooth {
transition: all 1s ease;
}
.dupa2 span {
height: 30px;
width: 30px;
display: block;
text-align: center;
line-height: 30px;
}
.dupa2.debugBackground {
background: linear-gradient(to bottom, #ffffff 0%, #ffffff 50%, #207cca 51%, #207cca 100%);
}
.dupa2[data-num="0"] {
transform: translate(0, 0);
}
.dupa2[data-num="1"] {
transform: translate(0, -30px);
}
.dupa2[data-num="2"] {
transform: translate(0, -60px);
}
.dupa2[data-num="3"] {
transform: translate(0, -90px);
}
.dupa2[data-num="4"] {
transform: translate(0, -120px);
}
.dupa2[data-num="5"] {
transform: translate(0, -150px);
}
.dupa2[data-num="6"] {
transform: translate(0, -180px);
}
.dupa2[data-num="7"] {
transform: translate(0, -210px);
}
.dupa2[data-num="8"] {
transform: translate(0, -240px);
}
.dupa2[data-num="9"] {
transform: translate(0, -270px);
}
.dupa2[data-num="10"] {
transform: translate(0, -300px);
}
.dupa2[data-num="11"] {
transform: translate(0, -330px);
}
.dupa2[data-num="12"] {
transform: translate(0, -360px);
}
.dupa2[data-num="13"] {
transform: translate(0, -390px);
}
.dupa2[data-num="14"] {
transform: translate(0, -420px);
}
.dupa2[data-num="15"] {
transform: translate(0, -450px);
}
.dupa2[data-num="16"] {
transform: translate(0, -480px);
}
.dupa2[data-num="17"] {
transform: translate(0, -510px);
}
.dupa2[data-num="18"] {
transform: translate(0, -540px);
}
.dupa2[data-num="19"] {
transform: translate(0, -570px);
}
<div class="dupa1">
<div class="dupa2" id="cipa" data-num="0">
<span>0</span>
<span>1</span>
<span>2</span>
<span>3</span>
<span>4</span>
<span>5</span>
<span>6</span>
<span>7</span>
<span>8</span>
<span>9</span>
<span>0</span>
<span>1</span>
<span>2</span>
<span>3</span>
<span>4</span>
<span>5</span>
<span>6</span>
<span>7</span>
<span>8</span>
<span>9</span>
</div>
</div>
<div id="debug">
Number is really: 0
</div>
<button id="rand">rand</button>

You can use two sets of numbers and a little bit of extra javascript to achieve this effect.
If the new number is less than the current number, use a second set of numbers (digits 0-9) that are farther down. As the css animation transitions from the first set of numbers to the second, it will appear as if the odometer is "rolling over".
When the animation completes, switch back to the first set of numbers without animating (no transition class).
I've made a working example based off of your original jsfiddle.
NOTE: This makes use of the .classList property of DOM elements, and the tranistionend event. You may have to add vendor prefixes (i.e. webkitTransitionEnd) and implement your own version of .classList, depending on what browsers you need to support.
document.getElementById("rand").addEventListener("click", randomize);
document.getElementById("cipa").addEventListener("transitionend", transitionEnd);
function randomize() {
setNumber(Math.floor(Math.random() * 9));
}
function setNumber(newNumber) {
let dupa = document.getElementById("cipa");
// assumes dupa.dataset.num always be a valid int
let selected = parseInt(dupa.dataset.num);
if (newNumber === selected) return; // if same as existing, don't do anything
// if the new number is less than the old number
// use the second set of numbers to avoid moving "backwards"
if (newNumber < selected) dupa.classList.add("rolledover");
// animate to the new position
dupa.classList.add("transitioning");
dupa.dataset.num = "" + newNumber;
}
function transitionEnd() {
let dupa = document.getElementById("cipa");
// don't animate
dupa.classList.remove("transitioning");
dupa.classList.remove("rolledover");
}
#rand {
margin-top: 50px;
}
.dupa1 {
height: 30px;
width: 30px;
border: 1px solid #000;
overflow: hidden;
}
.dupa2.transitioning {
transition: all 1s ease;
}
.dupa2 span {
height: 30px;
width: 30px;
display: block;
text-align: center;
line-height: 30px;
}
.dupa2[data-num="0"] {
transform: translate(0, 0);
}
.dupa2[data-num="1"] {
transform: translate(0, -30px);
}
.dupa2[data-num="2"] {
transform: translate(0, -60px);
}
.dupa2[data-num="3"] {
transform: translate(0, -90px);
}
.dupa2[data-num="4"] {
transform: translate(0, -120px);
}
.dupa2[data-num="5"] {
transform: translate(0, -150px);
}
.dupa2[data-num="6"] {
transform: translate(0, -180px);
}
.dupa2[data-num="7"] {
transform: translate(0, -210px);
}
.dupa2[data-num="8"] {
transform: translate(0, -240px);
}
.dupa2[data-num="9"] {
transform: translate(0, -270px);
}
.rolledover.dupa2[data-num="0"] {
transform: translate(0, -300px);
}
.rolledover.dupa2[data-num="1"] {
transform: translate(0, -330px);
}
.rolledover.dupa2[data-num="2"] {
transform: translate(0, -360px);
}
.rolledover.dupa2[data-num="3"] {
transform: translate(0, -390px);
}
.rolledover.dupa2[data-num="4"] {
transform: translate(0, -420px);
}
.rolledover.dupa2[data-num="5"] {
transform: translate(0, -450px);
}
.rolledover.dupa2[data-num="6"] {
transform: translate(0, -480px);
}
.rolledover.dupa2[data-num="7"] {
transform: translate(0, -510px);
}
.rolledover.dupa2[data-num="8"] {
transform: translate(0, -540px);
}
.rolledover.dupa2[data-num="9"] {
transform: translate(0, -570px);
}
<div class="dupa1">
<div class="dupa2" id="cipa" data-num="0">
<span>0</span>
<span>1</span>
<span>2</span>
<span>3</span>
<span>4</span>
<span>5</span>
<span>6</span>
<span>7</span>
<span>8</span>
<span>9</span>
<span>0</span>
<span>1</span>
<span>2</span>
<span>3</span>
<span>4</span>
<span>5</span>
<span>6</span>
<span>7</span>
<span>8</span>
<span>9</span>
</div>
</div>
<button id="rand">rand</button>

Thank you a lot.
But I stuck in another problem similar, but with array.
I've made a fiddle for better view to the problem: https://jsfiddle.net/zr2dLbge/
<div class="wrap" id="wrap"></div>
.wrap{
border:1px solid #000;
display: inline-block;
height:30px;
border-right: none;
}
.numbers{
width:30px;
height:30px;
display:inline-block;
overflow: hidden;
border-right: 1px solid #000;
}
.numbers span{
display: block;
width:30px;
height:30px;
line-height: 30px;
text-align: center;
}
.numbers[data-num="0"] div{
transform: translate(0, 0);
transition: all 1s ease;
}
.numbers[data-num="1"] div{
transform: translate(0, -30px);
transition: all 1s ease;
}
.numbers[data-num="2"] div{
transform: translate(0, -60px);
transition: all 1s ease;
}
.numbers[data-num="3"] div{
transform: translate(0, -90px);
transition: all 1s ease;
}
.numbers[data-num="4"] div{
transform: translate(0, -120px);
transition: all 1s ease;
}
.numbers[data-num="5"] div{
transform: translate(0, -150px);
transition: all 1s ease;
}
.numbers[data-num="6"] div{
transform: translate(0, -180px);
transition: all 1s ease;
}
.numbers[data-num="7"] div{
transform: translate(0, -210px);
transition: all 1s ease;
}
.numbers[data-num="8"] div{
transform: translate(0, -240px);
transition: all 1s ease;
}
.numbers[data-num="9"] div{
transform: translate(0, -270px);
transition: all 1s ease;
}
let arr = [];
var numbers = 1234561234;
const wrap = document.getElementById("wrap");
function toArray (val) {
return (val).toString().split('');
}
arr = toArray(numbers);
for (let i = 0; i < arr.length; i++) {
div = document.createElement('div'),
div.className = "numbers";
div.dataset.num = arr[i];
div.dataset.x = i;
div.innerHTML = "<div><span>0</span><span>1</span><span>2</span><span>3</span><span>4</span><span>5</span><span>6</span><span>7</span><span>8</span><span>9</span></div>"
wrap.appendChild(div);
}
setInterval(function(){
arr.forEach( (k) => {
arr[k] = Math.floor(Math.random() * 9) + 0;
})
for (let i = 0; i < arr.length; i++) {
document.querySelector('.numbers[data-x="'+i+'"]').dataset.num = arr[i];
}
}, 1000);
unfortunately window.requestAnimationFrame() doesn't work for me in this case

Related

Freeze the slider on hover

There are sliders on my site. Which keeps sliding using functions and setTimeout. I am currently trying to make my slider freeze on mouse hover. But adding an event listener to the slides doesn't seem to work. What can be the best possible solution?
//quote slider
let qslideIndex = 0;
let qslides = document.getElementsByClassName("quotemySlides");
let qdots = document.getElementsByClassName("quotedot");
//hiding each image through loop
const qhidenLoop = ()=>{
let j;
for (j = 0; j < qslides.length; j++) {
qslides[j].style.display = "none";
}
}
//running the slide
const qautoslideRun = ()=>{
qslideIndex++;
if (qslideIndex > qslides.length) {
qslideIndex = 1;
}
qhidenLoop();
qslides[qslideIndex-1].style.display = "block";
}
qshowSlides();
//all slide functions running here
function qshowSlides() {
qautoslideRun();
setTimeout(qshowSlides, 10000); // Change image every 10 seconds
}
.quoteslideshow-container {
max-width: 40%;
position: relative;
margin: 5% auto 5% auto;
}
.quotemySlides {
display: none;
}
/* Fading + slide in animation */
.slideinfromleft {
animation: slideinfromleft 1.5s ease-in 0s 1 normal forwards;
}
.image {
transition: border, border-radius 1s linear;
}
.image:hover {
border-radius: 20%;
border: 2px solid black
}
#keyframes slideinfromleft {
0% {
-webkit-transform: translateX(-100%);
-moz-transform: translateX(-100%);
-o-transform: translateX(-100%);
-ms-transform: translateX(-100%);
opacity: 0.1;
}
50% {
opacity: .5
}
100% {
-webkit-transform: translateX(0);
-moz-transform: translateX(0);
-o-transform: translateX(0);
-ms-transform: translateX(0);
opacity: 1
}
}
<body>
<div class="container">
<div class="quote">
<div class="quoteslideshow-container">
<!-- Full-width images with number and caption text -->
<div class="quotemySlides slideinfromleft">
<img class="image" src="img/quote1.png" style="width:100%">
</div>
<div class="quotemySlides slideinfromleft">
<img class="image" src="img/quote2.png" style="width:100%">
</div>
<div class="quotemySlides slideinfromleft">
<img class="image" src="img/quote3.png" style="width:100%">
</div>
<div class="quotemySlides slideinfromleft">
<img class="image" src="img/quote4.png" style="width:100%">
</div>
</div>
<br>
</div>
</div>
<script src="tribute.js" type="text/javascript"></script>
<script src="quotetribute.js" type="text/javascript"></script>
</body>
Use a variable to hold setTimeout into it, on mouseover slide clear it, on mouseleave call function slider() again, I change timeout to 3 seconds for test hover.
on mouseleave I call function qshowSlides() after 1 second by setTimeout, you can call it without setTimeout or increase time for setTimeout
//quote slider
let qslideIndex = 0;
let qslides = document.getElementsByClassName("quotemySlides");
let qdots = document.getElementsByClassName("quotedot");
let timeoutHolder = null;
//hiding each image through loop
const qhidenLoop = ()=>{
let j;
for (j = 0; j < qslides.length; j++) {
qslides[j].style.display = "none";
}
}
//running the slide
const qautoslideRun = ()=>{
qslideIndex++;
if (qslideIndex > qslides.length) {
qslideIndex = 1;
}
qhidenLoop();
qslides[qslideIndex-1].style.display = "block";
}
qshowSlides();
//all slide functions running here
function qshowSlides() {
qautoslideRun();
timeoutHolder = setTimeout(qshowSlides, 3000); // Change image every 3 seconds for test hover
}
const disableAutoSlideOnHover = () => {
const container = document.querySelector( ".quoteslideshow-container" );
container.addEventListener( "mouseover", function() {
clearTimeout( timeoutHolder );
timeoutHolder = null;
} );
container.addEventListener( "mouseleave", function() {
setTimeout( () => qshowSlides(), 1000 )
} );
}
disableAutoSlideOnHover();
.quoteslideshow-container {
max-width: 40%;
position: relative;
margin: 5% auto 5% auto;
}
.quotemySlides {
display: none;
}
/* Fading + slide in animation */
.slideinfromleft {
animation: slideinfromleft 1.5s ease-in 0s 1 normal forwards;
}
.image {
transition: border, border-radius 1s linear;
}
.image:hover {
border-radius: 20%;
border: 2px solid black
}
#keyframes slideinfromleft {
0% {
-webkit-transform: translateX(-100%);
-moz-transform: translateX(-100%);
-o-transform: translateX(-100%);
-ms-transform: translateX(-100%);
opacity: 0.1;
}
50% {
opacity: .5
}
100% {
-webkit-transform: translateX(0);
-moz-transform: translateX(0);
-o-transform: translateX(0);
-ms-transform: translateX(0);
opacity: 1
}
}
<body>
<div class="container">
<div class="quote">
<div class="quoteslideshow-container">
<!-- Full-width images with number and caption text -->
<div class="quotemySlides slideinfromleft">
<img class="image" src="https://images.unsplash.com/photo-1497215728101-856f4ea42174?ixlib=rb-1.2.1&ixid=MnwxMjA3fDF8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1170&q=80" style="width:100%">
</div>
<div class="quotemySlides slideinfromleft">
<img class="image" src="https://images.unsplash.com/photo-1586227740560-8cf2732c1531?ixlib=rb-1.2.1&ixid=MnwxMjA3fDF8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1261&q=80" style="width:100%">
</div>
<div class="quotemySlides slideinfromleft">
<img class="image" src="https://images.unsplash.com/photo-1659944975073-453265ccf3a6?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1170&q=80" style="width:100%">
</div>
<div class="quotemySlides slideinfromleft">
<img class="image" src="https://images.unsplash.com/photo-1659830686710-9c6df95f8cf3?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1176&q=80" style="width:100%">
</div>
</div>
<br>
</div>
</div>
<script src="tribute.js" type="text/javascript"></script>
<script src="quotetribute.js" type="text/javascript"></script>
</body>

Why add and remove function is not working at the same time in a function in JavaScript?

I have started learning JS recently and am stuck here. I have created a dice game where images change themselves randomly when a button is clicked.
The images just get changed from one to another. I want to give a rolling effect to them. So, I have added animation for them that they change angles in both X-axis and Y-axis. It works on the first click but later doesn't.
So I had added classList.add() to give the animation and classList.remove() to remove but the remove function doesn't work.
This is HTML code:
function roll() {
document.querySelectorAll("img")[0].classList.add("rollEffect");
document.querySelectorAll("img")[1].classList.add("rollEffect");
var randomNumber1 = Math.floor(Math.random() * 6 + 1);
var randomNumber2 = Math.floor(Math.random() * 6 + 1);
var randomImage1 = "dice" + randomNumber1 + ".png";
var randomImage2 = "dice" + randomNumber2 + ".png";
document.querySelectorAll("img")[0].setAttribute("src", randomImage1);
document.querySelectorAll("img")[1].setAttribute("src", randomImage2);
if (randomNumber1 > randomNumber2)
document.querySelector("h1").innerHTML = "Player1 wins!!!";
else
if (randomNumber2 > randomNumber1)
document.querySelector("h1").innerHTML = "Player2 wins!!!";
else
document.querySelector("h1").innerHTML = "DRAW!!!";
document.querySelectorAll("img")[0].classList.remove("rollEffect");
document.querySelectorAll("img")[1].classList.remove("rollEffect");
}
.btn {
background-color: #8843F2;
border: 0;
border-radius: 20px;
color: #ffffff;
font-family: 'Indie Flower', cursive;
margin: 0 50px;
padding: 1% 2%;
}
.container {
width: 70%;
margin: auto;
text-align: center;
}
.dice {
text-align: center;
display: inline-block;
}
#keyframes rollClick {
9% {
transform: rotateX(30deg) rotateY(30deg)
}
18% {
transform: rotateX(60deg) rotateY(60deg)
}
28% {
transform: rotateX(90deg) rotateY(90deg)
}
37% {
transform: rotateX(120deg) rotateY(120deg)
}
46% {
transform: rotateX(150deg) rotateY(150deg)
}
55% {
transform: rotateX(180deg) rotateY(180deg)
}
65% {
transform: rotateX(210deg) rotateY(210deg)
}
76% {
transform: rotateX(240deg) rotateY(240deg)
}
85% {
transform: rotateX(270deg) rotateY(270deg)
}
90% {
transform: rotateX(300deg) rotateY(300deg)
}
95% {
transform: rotateX(330deg) rotateY(330deg)
}
100% {
transform: rotateX(360deg) rotateY(360deg)
}
}
.rollEffect {
animation-name: rollClick;
animation-duration: 0.1s;
}
body {
background-color: #F9D371;
}
img {
width: 80%;
}
<div class="container">
<h1>Roll us</h1>
<div class="dice">
<p>Player 1</p>
<img class="img1" src="dice6.png">
</div>
<div class="dice">
<p>Player 2</p>
<img class="img2" src="dice6.png">
</div>
<button class="btn" onclick="roll()">Roll</button>
</div>
The javascript code that adds the rolling animation class runs separate from any animation durations.
It will run as quickly as the performance of the device allows.
In your js code it will:
add the .rollEffect class to both images.
set a new image url.
set text with the result of the game
remove the .rollEffect class from both images.
This all happens as fast as possible, we're talking micro/nano seconds.
So the animation does get applied, each time, and gets removed each time. so fast you can't even see the animation.
You have to wait a bit before removing the animation class. so the animation has time to run before it's removed.
This can be achived with setTimeout
For example:
setTimeout(() => {
document.querySelectorAll("img")[0].classList.remove("rollEffect");
document.querySelectorAll("img")[1].classList.remove("rollEffect");
}, 100); // <--- 100 here will execute the code in the callback after 100ms, the same as the animation time.
function roll() {
document.querySelectorAll("img")[0].classList.add("rollEffect");
document.querySelectorAll("img")[1].classList.add("rollEffect");
var randomNumber1 = Math.floor(Math.random() * 6 + 1);
var randomNumber2 = Math.floor(Math.random() * 6 + 1);
var randomImage1 = `http://placekitten.com/g/${50*randomNumber1}/300`;
var randomImage2 = `http://placekitten.com/g/200/${50*randomNumber2}`;
document.querySelectorAll("img")[0].setAttribute("src", randomImage1);
document.querySelectorAll("img")[1].setAttribute("src", randomImage2);
if (randomNumber1 > randomNumber2)
document.querySelector("h1").innerHTML = "Player1 wins!!!";
else
if (randomNumber2 > randomNumber1)
document.querySelector("h1").innerHTML = "Player2 wins!!!";
else
document.querySelector("h1").innerHTML = "DRAW!!!";
setTimeout(() => {
document.querySelectorAll("img")[0].classList.remove("rollEffect");
document.querySelectorAll("img")[1].classList.remove("rollEffect");
}, 100);
}
.btn {
background-color: #8843F2;
border: 0;
border-radius: 20px;
color: #ffffff;
font-family: 'Indie Flower', cursive;
margin: 0 50px;
padding: 1% 2%;
}
.container {
width: 70%;
margin: auto;
text-align: center;
}
.dice {
text-align: center;
display: inline-block;
}
#keyframes rollClick {
9% {
transform: rotateX(30deg) rotateY(30deg)
}
18% {
transform: rotateX(60deg) rotateY(60deg)
}
28% {
transform: rotateX(90deg) rotateY(90deg)
}
37% {
transform: rotateX(120deg) rotateY(120deg)
}
46% {
transform: rotateX(150deg) rotateY(150deg)
}
55% {
transform: rotateX(180deg) rotateY(180deg)
}
65% {
transform: rotateX(210deg) rotateY(210deg)
}
76% {
transform: rotateX(240deg) rotateY(240deg)
}
85% {
transform: rotateX(270deg) rotateY(270deg)
}
90% {
transform: rotateX(300deg) rotateY(300deg)
}
95% {
transform: rotateX(330deg) rotateY(330deg)
}
100% {
transform: rotateX(360deg) rotateY(360deg)
}
}
.rollEffect {
animation-name: rollClick;
animation-duration: 0.1s;
}
body {
background-color: #F9D371;
}
img {
width: 150px;
height: 150px;
}
<div class="container">
<h1>Roll us</h1>
<div class="dice">
<p>Player 1</p>
<img class="img1" src="http://placekitten.com/g/200/300">
</div>
<div class="dice">
<p>Player 2</p>
<img class="img2" src="http://placekitten.com/g/300/200">
</div>
<button class="btn" onclick="roll()">Roll</button>
</div>

Continue animation where ended

I have a 3D cube that completes one of 2 animations depending on what number is selected by math.random. The animation holds its end position after it has ended (due to "forwards") but if the cube is clicked, to run the animation again, it returns back to its original position. How to I make the cube complete the animation starting from the last time's ending position?
.scene {
perspective:200px;
width:100px;
height:100px;
}
.die {
position:relative;
width:100%;
height:100%;
transform-style:preserve-3d;
transform: translateZ(-50px);
transition: transform 1s;
animation:;
}
.face {
position:absolute;
width:100px;
height:100px;
color:white;
top:0;
bottom:0;
left:0;
right:0;
background-color:purple;
}
.one {
transform: rotateY(0deg) translateZ(50px);
}
.two {
transform:rotateY(90deg) translateZ(50px);
}
.three {
transform:rotateY(180deg) translateZ(50px);
}
.four {
transform:rotateY(-90deg) translateZ(50px);
}
.five {
transform:rotateX(90deg) translateZ(50px);
}
.six {
transform:rotateX(-90deg) translateZ(50px);
}
#keyframes one {
0% {transform: translateZ(-5em) rotateY(0deg) rotateX(0deg);}
100% {transform: translateZ(-5em) rotateY(0deg) rotateX(360deg);}
}
#keyframes two {
0% {transform: translateZ(-5em) rotateY(0deg) rotateX(0deg);}
100% {transform: translateZ(-5em) rotateY(-90deg) rotateX(360deg);}
}
<div class="scene">
<div class="die" id="die" onclick="spinDie()">
<div class="face one">one
</div>
<div class="face two">two
</div>
<div class="face three">three
</div>
<div class="face four">four
</div>
<div class="face five">five
</div>
<div class="face six">six
</div>
</div>
</div>
</div>
function spinDie() {
var num = Math.floor(Math.random() * 1) + 1;
if (num === 1) {
document.getElementById("die").style.animation="one 2s forwards"
}
if(num === 2) {
document.getElementById("die").style.animation="two 2s forwards"
}
}
Use transition instead of animation.
Define the transitions inside an Array faces
Get a random face {x: N, y: N}
Addup += spins to the current random face x and y valuex. I.e: x += (360 * randomBetween(n, N))
const EL_dice = document.getElementById("dice");
// https://en.wikipedia.org/wiki/Dice
const faces = [
{x:0, y:0}, // 1 front
{x:0, y:-90}, // 2 right
{x:-90, y:0}, // 3 top
{x:90, y:0}, // 4 bottom
{x:0, y:90}, // 5 left
{x:0, y:180}, // 6 back
];
function spinDice() {
const rand = ~~(Math.random() * 6); // Generate random 0 to 5
const face = faces[rand]; // Get random face
face.x += 360 * (~~(Math.random() * 4) + 1); // Addup some x spins
face.y += 360 * (~~(Math.random() * 4) + 1); // Addup some y spins
console.clear(); console.log(rand + 1);
EL_dice.style.cssText = `
transition: 3s cubic-bezier(0.2, -0.2, 0.5, 1.1);
transform: rotateX(${face.x}deg) rotateY(${face.y}deg);
`;
}
EL_dice.addEventListener("click", spinDice);
.dice-perspective {
display: inline-flex;
perspective: 500px;
margin: 20px;
user-select: none;
}
.dice {
--size: 80px; /* SET HERE THE DESIRED DICE SIZE */
--half: calc(var(--size) / 2);
width: var(--size); height: var(--size);
position: relative;
transform-style: preserve-3d;
}
.dice>div {
height: inherit; width: inherit;
position: absolute;
background: #0bf; color: #fff;
display: flex;
align-items: center;
justify-content: center;
font-size: calc(var(--size) * 1.4);
line-height: 0;
}
.front {transform: rotateY(0deg) translateZ(var(--half));}
.right {transform: rotateY(90deg) translateZ(var(--half));}
.top {transform: rotateX(90deg) translateZ(var(--half));}
.bottom {transform: rotateX(-90deg) translateZ(var(--half));}
.left {transform: rotateY(-90deg) translateZ(var(--half));}
.back {transform: rotateX(180deg) translateZ(var(--half));}
Click dice to spin
<div class="dice-perspective">
<div id="dice" class="dice">
<div class="front">⚀</div>
<div class="right">⚁</div>
<div class="top">⚂</div>
<div class="bottom">⚃</div>
<div class="left">⚄</div>
<div class="back">⚅</div>
</div>
</div>

move element across page with smooth move

I'm trying to move a cockroach through the whole page in a logical and real way.
I wrote this code but it's not working in a good status.
This code is not logical, just put it for clarification
I want his movement to be logical so that he goes through the whole page, to be flexible for all screens
Can anybody help, please?`
$(function(){
var x = $(".container");
setTimeout(function() {
x.addClass("first");
}, 1000);
setTimeout(function() {
$(x).children().css({transition : "2s"});
$(x).css({transition : "4s"});
x.addClass("second");
}, 2000);
setTimeout(function() {
$(x).children().css({transition : "0s"});
$(x).css({transition : "0s"});
x.addClass("third");
}, 4000);
setTimeout(function() {
$(x).children().css({transition : "4s"});
$(x).css({transition : "2s"});
x.addClass("fourth");
}, 6000);
setTimeout(function() {
$(x).children().css({transition : "2s"});
$(x).css({transition : "3s"});
x.addClass("fifth");
}, 8000);
})
.container{
position: fixed;
bottom: 10px;
left: 10px;
transition: transform 1s;
}
.container.first{
transform: translateX(200px) ;
}
img{
width:60px;
height: 60px;
border-radius: 2px;
transition: transform 2s;
}
.container.first img{
transform: translateY(-100px) rotate(-50deg);
}
.container.first.second img{
transform: translateY(-200px) rotate(-135deg);
}
.container.first.second{
transform: translateX(-200px) ;
}
.container.first.second.third img{
transform:translateX(-20px) translateY(-250px) rotate(30deg) ;
}
.container.first.second.third{
transform: translateX(-50px) scale(1 , 1.6);
}
.container.first.second.third.fourth img{
transform: translateY(-450px) rotate(-55deg);
}
.container.first.second.third.fourth{
transform: translateX(400px) ;
}
.container.first.second.third.fourth.fifth img{
transform: translateY(-700px) rotate(-90deg);
}
.container.first.second.third.fourth.fifth{
transform: translateX(250px) ;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<img src="https://i2.wp.com/drkathyobear.com/wp-content/uploads/2015/09/cockroach.jpg" />
</div>
`

appear image selecte div one by one

I have InsertProduct.aspx page that user can upload 6 image in this page for their product...
I want at first in page be 1 div that I define on it fileupload control when users click on Selectimage they can upload their first image when they upload their first image then appear second DIV that they can upload their second image when they upload second image third div will appear and they can select third image it will goes up to 6 image
users can upload 6 image and they can delete their uploaded image...
how I can do it?
Best regards
Neda
You could use one of the many file upload jQuery plugins, but I think the easiest way to implement this is to use HTML5 FileReader.
Please have a look at this jsFiddle. (The demo here at SO is not working because I haven't found the ajax echo service here yet. Maybe I'll fix this later.)
The code is not perfect but it should help you getting started.
You could improve/check the following:
Upload the images immediately. At the moment they're uploaded with an upload all button.
Handling of removing images needs to be improved. No server images are removed, just the currently selected image will be removed.
Initial loading of the previously uploaded server images not implemented.
Uploading takes pretty long in the fiddle, not sure if my files where too large. But you could probably check if binary json is better/faster then base64 encoded images.
CSS styling can be improved.
(function () {
var $app = $('#uploadApp');
var formTemplate = function (id, handler) {
$(document).on('change', '#file_' + id, handler);
var $tmpl = $('<div/>').addClass('productPane').append([
$('<h1/>').text('Image ' + id),
$('<div/>').addClass('imageContainer'),
$('<input type="file"/>').attr('id', 'file_' + id)]);
return $tmpl.clone();
};
// Array Remove - By John Resig (MIT Licensed)
Array.prototype.remove = function(from, to) {
var rest = this.slice((to || from) + 1 || this.length);
this.length = from < 0 ? this.length + from : from;
return this.push.apply(this, rest);
};
var uploader = {
imageCount: 0,
MAX_IMAGES: 6,
images: [],
init: function () {
this.addForm();
$('#uploadAll').click(this.uploadAll.bind(this));
},
addForm: function () {
this.imageCount++;
$app.append(formTemplate(this.imageCount,
$.proxy(this.upload, this)));
},
uploadAll: function () {
if (this.images.length == 0) return; // nothing to upload
var json_obj = {
json: $.toJSON(this.images),
delay: 1
};
Pace.track(function () {
$.ajax({
async: true,
cache: false,
type: 'POST',
url: 'http://jsfiddle.net/echo/json/',
//jsonp: "callback",
data: json_obj,
dataType: 'json', //'jsonp',
success: function (data) {
console.log(data, 'images uploaded');
// just a test to show which images are uploaded
$('#debug').append('<h2>Uploaded images</h2>');
$.each(data, function (index, image) {
$('#debug').append($('<img/>')
.attr('src', image).width(50));
});
}
});
});
},
upload: function (evt) {
//console.log(evt);
evt.preventDefault();
var that = this;
var files = evt.target.files; // FileList object
var curIndex = $(evt.target).attr('id').split('_')[1]
var $productPane = $(evt.target).closest('.productPane');
// files is a FileList of File objects. List some properties.
// var output = [];
//for (var i = 0, f; f = files[i]; i++) {
f = files[0];
var reader = new FileReader();
reader.onload = function (evt) {
var img = new Image();
img.src = evt.target.result;
img.width = 100;
this.images[curIndex - 1] = evt.target.result;;
var $curImg = $productPane.find('.imageContainer').html($(img));
$productPane.append($('<button/>').text('remove')
.click(function () {
$curImg.empty(); // remove image
that.images.remove(curIndex - 1); // delete image from array
f = null; // clear current file object
$('#file_' + curIndex).val(''); // clear file input
$(this).remove(); // delete remove button
}));
}.bind(this);
reader.readAsDataURL(f);
if (this.imageCount < this.MAX_IMAGES && $(evt.target).attr('id').split('_')[1] == this.imageCount) {
// we can add one more image and user clicked on last input
//console.log(this.imageCount);
this.addForm();
}
// if you need file parameters here are some example properties
/*output.push(escape(f.name), '(', f.type || 'n/a', ') - ',
f.size, ' bytes, last modified: ',
f.lastModifiedDate.toLocaleDateString());*/
//}
//$('#debug').append(output);
}
};
uploader.init();
})();
.productPane {
float: left;
width: 200px;
height: 250px;
}
.productPane h1 {
font-size: 1.1em;
}
/*pacejs template follows here -- flash theme */
/* This is a compiled file, you should be editing the file in the templates directory */
.pace {
-webkit-pointer-events: none;
pointer-events: none;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
}
.pace-inactive {
display: none;
}
.pace .pace-progress {
background: #2299dd;
position: fixed;
z-index: 2000;
top: 0;
right: 100%;
width: 100%;
height: 2px;
}
.pace .pace-progress-inner {
display: block;
position: absolute;
right: 0px;
width: 100px;
height: 100%;
box-shadow: 0 0 10px #2299dd, 0 0 5px #2299dd;
opacity: 1.0;
-webkit-transform: rotate(3deg) translate(0px, -4px);
-moz-transform: rotate(3deg) translate(0px, -4px);
-ms-transform: rotate(3deg) translate(0px, -4px);
-o-transform: rotate(3deg) translate(0px, -4px);
transform: rotate(3deg) translate(0px, -4px);
}
.pace .pace-activity {
display: block;
position: fixed;
z-index: 2000;
top: 15px;
right: 15px;
width: 14px;
height: 14px;
border: solid 2px transparent;
border-top-color: #2299dd;
border-left-color: #2299dd;
border-radius: 10px;
-webkit-animation: pace-spinner 400ms linear infinite;
-moz-animation: pace-spinner 400ms linear infinite;
-ms-animation: pace-spinner 400ms linear infinite;
-o-animation: pace-spinner 400ms linear infinite;
animation: pace-spinner 400ms linear infinite;
}
#-webkit-keyframes pace-spinner {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
#-moz-keyframes pace-spinner {
0% {
-moz-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-moz-transform: rotate(360deg);
transform: rotate(360deg);
}
}
#-o-keyframes pace-spinner {
0% {
-o-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-o-transform: rotate(360deg);
transform: rotate(360deg);
}
}
#-ms-keyframes pace-spinner {
0% {
-ms-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-ms-transform: rotate(360deg);
transform: rotate(360deg);
}
}
#keyframes pace-spinner {
0% {
transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
transform: rotate(360deg);
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://jquery-json.googlecode.com/files/jquery.json-2.2.min.js"></script>
<div id="uploadApp">
<button id="uploadAll">Upload images</button>
<br/>
</div>
<div id="debug"></div>
<script>
window.paceOptions = {
//minTime: 2000,
//ghostTime:500,
//startOnPageLoad:false,
//target: '.test1'
}
</script>
<script src="https://raw.github.com/HubSpot/pace/master/pace.js"></script>

Categories

Resources