rotate each letter problem in CSS and JavaScript? - javascript

I am trying to create an animation like I have created an empty h1 element and filled it with span elements by using javascript (each span element contains an individual letter) and when I hover on span it's rotating (as desired) but in order to rotate span Element I have to give display:inline-block; to the span element but by doing this it removes space between the words. I searched it on the internet but didn't get the right answer.
So any anyone tell me how do I rotate the text with proper spacing around each word?
Here is my code you can experiment by uncommenting the display:inline-block; in CSS
let a = document.querySelector("h1")
let txt = "Hello How are you"
let indletter = Array.from(txt)
//console.log(indletter)
for(let i = 0; i < indletter.length;i++){
let span = document.createElement("span")
span.innerText = indletter[i]
a.appendChild(span)
}
body {
background-color: #eee;
text-align: center;
margin-top: 100px;
font-family:arial;
}
h1{
font-size:0;
}
span{
font-size:2rem;
/* display:inline-block; */
transition:.3s alternate;
}
span:hover{
color:red;
cursor:pointer;
transform:rotate(45deg);
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1></h1>
</body>
</html>

Since those spans contain only whitespace, they “collapse” when you make them inline-block. Simply adding white-space: pre; can already fix that.
(And you can add it to all of them, don’t need a special class for the space-spans - they all contain one character each only, so this has no negative effect.)
span{
font-size:2rem;
display:inline-block;
white-space:pre;
transition:.3s alternate;
}

You could just test to see if that letter was a space and apply a special class to it.
if (indletter[i]==" ") span.classList.add('spacer');
and the css
.spacer{
padding:0 5px;
}
Also I changed the transition easing to something it would understand and now the tweening works.
transition:.3s ease-in-out;
let a = document.querySelector("h1")
let txt = "Hello How are you"
let indletter = Array.from(txt)
//console.log(indletter)
for(let i = 0; i < indletter.length;i++){
let span = document.createElement("span")
span.innerText = indletter[i]
if (indletter[i]==" ") span.classList.add('spacer');
a.appendChild(span)
}
body {
background-color: #eee;
text-align: center;
margin-top: 100px;
font-family:arial;
}
h1{
font-size:0;
}
span{
font-size:2rem;
position:relative;
display:inline-block;
transition:.3s ease-in-out;
}
.spacer{
padding:0 5px;
}
span:hover{
color:red;
cursor:pointer;
transform:rotate(45deg);
transition:.3s alternate;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1></h1>
</body>
</html>

Use for space
let a = document.querySelector("h1")
let txt = "Hello I am SHAYAN"
let indletter = Array.from(txt)
//console.log(indletter)
for (let i = 0; i < indletter.length; i++) {
let span = document.createElement("span")
span.innerHTML = indletter[i] === ' ' ? ' ' : indletter[i];
a.appendChild(span)
}
body {
background-color: #eee;
text-align: center;
margin-top: 100px;
font-family: arial;
}
h1 {
font-size: 0;
}
span {
font-size: 2rem;
display: inline-block;
transition: .3s alternate;
}
span:hover {
color: red;
cursor: pointer;
transform: rotate(45deg);
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1></h1>
</body>
</html>

Related

Javascript counter on animation end

how can I make a counter that counts every time animation restarts?
I tried seconds counter, but it didnt synchronize well with my animation.
However, I am trying to make similar website as tacospin.com, but with jumping dog.
The logic in tacospin is quite simple, everytime degree = 0 it counts. But I cant figure out how to do something like that
My animation code:
var seconds = 0;
var el = document.getElementById('seconds-counter');
function incrementSeconds() {
seconds += 1;
el.innerText = "You have been here for " + seconds + " seconds.";
}
var cancel = setInterval(incrementSeconds, 1350);
#center{
display: block;
margin-left: auto;
margin-right: auto;
width: 20%;
}
.centerfloor{
display: block;
margin-left: auto;
margin-right: auto;
margin-top: 193px;
width: 30%;
}
#keyframes jump {
0% {transform: translate3d(0,0,0) scale3d(1,1,1);}
40% {transform: translate3d(0,30%,0) scale3d(1,1,1);}
100% {transform: translate3d(0,100%,0) scale3d(1,1.2,1);}
}
.jump {
transform-origin: 50% 50%;
animation: jump .7s linear alternate infinite;
}
/* For demo: */
<!DOCTYPE html>
<html lang="cz">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Dog jump</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<main>
<div id="dogdiv">
<img class="jump" id="center" src="dogie.png" alt="idk">
</div>
<img class="centerfloor" src="floo.png">
</main>
<div id="seconds-counter"></div>
<script src="script.js"></script>
</body>
</html>
You can rely on animationiteration event, it can be bound to any DOM element which is animated via CSS, and it gets fired everytime the animation repeats.
https://developer.mozilla.org/en-US/docs/Web/API/Element/animationiteration_event
var seconds = 0;
let animations = 0;
let animFlag = false;
var el = document.getElementById('seconds-counter');
const el2 = document.getElementById('anims-counter');
function incrementSeconds() {
seconds += 1;
el.innerText = "You have been here for " + seconds + " seconds.";
}
var cancel = setInterval(incrementSeconds, 1350);
const animated = document.querySelector('.jump');
animated.addEventListener('animationiteration', () => {
animFlag = !animFlag
if (!animFlag) {
animations++
el2.innerText = "Animation ended. Total: " + animations
}
});
#center{
display: block;
margin-left: auto;
margin-right: auto;
width: 20%;
}
.centerfloor{
display: block;
margin-left: auto;
margin-right: auto;
margin-top: 193px;
width: 30%;
}
#keyframes jump {
0% {transform: translate3d(0,0,0) scale3d(1,1,1);}
40% {transform: translate3d(0,30%,0) scale3d(1,1,1);}
100% {transform: translate3d(0,100%,0) scale3d(1,1.2,1);}
}
.jump {
transform-origin: 50% 50%;
animation: jump .7s linear alternate infinite;
}
/* For demo: */
<!DOCTYPE html>
<html lang="cz">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Dog jump</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<main>
<div id="dogdiv">
<img class="jump" id="center" src="dogie.png" alt="idk">
</div>
<img class="centerfloor" src="floo.png">
</main>
<div id="seconds-counter"></div>
<div id="anims-counter"></div>
<script src="script.js"></script>
</body>
</html>

Why isn't this file opening?

Try stuffing this code into files index.html, style.css and app.js, it doesn't open. The browser says that "The webpage was reloaded because a problem occurred" and keeps on loading.I am using an MacBook Air with macOS Big Sur with an M1, if that's of any help. I removed the full HTML code and rewrote it again, and found out it is the javascript that is causing the issue. But I have no idea why, because 1) I think my code is correct and 2) I can't open the console to check for errors because the file doesn't open. Could anybody help me?
My HTML file is:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style.css">
<script src="./app.js" defer></script>
<title>Document</title>
</head>
<body>
<div class="type" contenteditable="true">In .type</div>
<div class="words">In .words</div>
</body>
</html>
My JavaScript file is:
const type = document.querySelector(".type");
const words = document.querySelector(".words");
console.log(type.innerHTML.split(""));
for (let i=0; i < type.innerHTML.split("").length; i++) {
type.innerHTML += `<span>${i}</span>`
}
And my css file is:
#import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono&display=swap');
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background-color: #333;
}
.type, .words {
font-family: 'JetBrains Mono', monospace;
color: #fff;
border: 2px solid #007bff;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: 80%;
height: 200px;
border-radius: 20px;
display: flex;
align-items: center;
padding: 50px;
font-size: 100px;
outline: none;
}
.type {
background-color: transparent;
z-index: 2;
}
.words {
background-color: #333;
z-index: 1;
}
You are running a loop on element type and updating it in loop.
You have created an endless loop my friend.
Try changing this-
for (let i=0; i < type.innerHTML.split("").length; i++) {
type.innerHTML += `<span>${i}</span>`
}
to this-
let typesplit = type.innerHTML.split("")
for (let i=0; i < typesplit.length ; i++) {
type.innerHTML += `<span>${i}</span>`
}
This way it won't update the value of .type every time.
Also try not to use type as variable name as it is a reserved word in Typescript which resembles JavaScript.

When I click the button to change all the another buttons to dark mode, it works just a single time

I made a button to change all the page to dark mode.
I have some dark buttons I want to change it to light when I click the button that change the page to dark mode.
The problem is when I want to change the page to dark mode it works, but with the dark buttons it works just a single time, and the second button doesn't work for the first time.
You will find the code that I write below.
Thanks.
let darkBackground = document.querySelector('body');
let darkModeBtn = document.getElementById('darkModeBtn');
let btnIcon = document.getElementById('btnIcon');
let codeButton = document.getElementsByClassName('btn-dark');
darkModeBtn.addEventListener('click', function() {
darkBackground.classList.toggle('darkbackground');
btnIcon.classList.toggle('fa-sun');
btnIcon.classList.toggle('fa-moon');
for (var i = 0, len = codeButton.length; len > i; i++) {
codeButton[i].classList.toggle('btn-light');
codeButton[i].classList.toggle('btn-dark');
};
});
.darkbackground {
background-color: rgb(46, 45, 49);
transition: .15s;
color: white;
}
.darkmodebtn {
font-size: 1.50rem;
padding: 0.5rem 0.85rem;
background-color: rgba(47, 128, 237, 1);
outline: none;
border: 0;
border-radius: 20px;
color: white;
position: fixed;
bottom: 18px;
right: 18px;
}
.darkmodebtn:focus {
outline: none;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap#4.5.3/dist/css/bootstrap.min.css" rel="stylesheet"/>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.15.1/css/all.css" integrity="sha384-vp86vTRFVJgpjF9jiIGPEEqYqlDwgyBgEF109VFjmqGmIY/Y4HV4d3Gp2irVfcrp" crossorigin="anonymous">
<title>Document</title>
</head>
<body>
Light and Black
Light and Black
Light and Black
<button class="darkmodebtn" id="darkModeBtn"><i id="btnIcon" class="fas fa-moon"></i></button>
</body>
</html>
let darkBackground = document.querySelector('body');
let darkModeBtn = document.getElementById('darkModeBtn');
let btnIcon = document.getElementById('btnIcon');
let codeButton = document.getElementsByClassName('code-btn');
darkModeBtn.addEventListener('click', function() {
darkBackground.classList.toggle('darkbackground');
btnIcon.classList.toggle('fa-sun');
btnIcon.classList.toggle('fa-moon');
for (var i = 0, len = codeButton.length; len > i; i++) {
codeButton[i].classList.toggle('btn-light');
codeButton[i].classList.toggle('btn-dark');
};
});
.darkbackground {
background-color: rgb(46, 45, 49);
transition: .15s;
color: white;
}
.darkmodebtn {
font-size: 1.50rem;
padding: 0.5rem 0.85rem;
background-color: rgba(47, 128, 237, 1);
outline: none;
border: 0;
border-radius: 20px;
color: white;
position: fixed;
bottom: 18px;
right: 18px;
}
.darkmodebtn:focus {
outline: none;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap#4.5.3/dist/css/bootstrap.min.css" rel="stylesheet"/>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.15.1/css/all.css" integrity="sha384-vp86vTRFVJgpjF9jiIGPEEqYqlDwgyBgEF109VFjmqGmIY/Y4HV4d3Gp2irVfcrp" crossorigin="anonymous">
<title>Document</title>
</head>
<body>
Light and Black
Light and Black
Light and Black
<button class="darkmodebtn" id="darkModeBtn"><i id="btnIcon" class="fas fa-moon"></i></button>
</body>
</html>

Add Active Class to Current selected svg using js

the svg id = "map"
the normal path class = "T"
Selected class ="Tactive"
Tcurrent is a active shave by Default
var oMap= document.getElementById("map");
var oRng= document.getElementsByClassName("T");
var Tcurrent
for (var j = 0; j < oRng.length; j++) {
oRng[j].addEventListener("click", function () {
Tcurrent = document.getElementsByClassName("T Tactive");
Tcurrent[0].classList ="T"
this.classList = "T Tactive";
});
}
Hopefully this may help...
$('.svg').click(function() {
$('.svg').removeClass('selected'); // removes initial selected classes.
this.classList.add('selected'); // adds selected class for clicked svg.
});
.svg {
margin: 15px;
padding: 8px;
height: 100px;
width: 100px;
display: inline-block;
background: #eee;
border-radius: 4px;
}
.svg:hover {
cursor: pointer;
}
.selected {
border: 2px solid #333;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>Selected</title>
</head>
<body>
<main>
<div class="svg">a.</div>
<div class="svg">b.</div>
</main>
<script src="https://code.jquery.com/jquery-3.1.0.js"></script>
</body>
</html>

Working with Input + keyup + value and then giphy

I would like to get whatever user search via input after he will stop typing. Then i would like to pass it to giphy api but there i have a problem with passing variable/result. Here is my code :
const mainInput = document.querySelector(".main-input");
mainInput.addEventListener('keyup', getUserQuery);
function getUserQuery(e) {
let timeout = null;
let userQuery;
clearTimeout(timeout);
timeout = setTimeout(function() {
return userQuery = mainInput.value;
},300)
return userQuery;
}
//function makeUrlForSearch(getUserQuery) {
// let a = getUserQuery();
// console.log(a);
//}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
display: flex;
flex-flow: column wrap;
justify-content: center;
align-items: center;
font-size: 10px;
}
.header {
padding: 1rem;
margin: 1rem auto;
}
.header-title {
font-size: 2rem;
}
.main-input {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Wyszkuj Gipha!</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<header class="header"><h1 class="header-title">Wyszukaj Gipha!</h1></header>
<main class="main">
<form class="main-form">
<input type="text" placeholder="Wyszukaj Gipha!" class="main-input" id="main-input">
</form>
</main>
<script src="main.js"></script>
</body>
</html>
the makerUrlForSearch is not working and i've beend siting on it for a while but its not working.
Can anyone help? So that i would get search made by user after 300ms after he stops typing and then use it in giphy api, but i cannot do it :(
There were a couple issues in the code you provided :
In getUserQuery function, you're returning userQuery before the asynchronous setTimeOut sets its value.
The makeUrlForSearch function is calling getUserQuery but is never called. I switched that and made it so getUserQuery calls the makeUrlForSearch function
In getUserQuery, the timeout declaration would always erase previous timeouts. I moved the let timeout = null instruction outside of your getUserQuery function to make it global so that a getUserQuery call can clear a previous timeout.
const mainInput = document.querySelector(".main-input");
mainInput.addEventListener('keyup', getUserQuery);
let timeout;
function getUserQuery(e) {
clearTimeout(timeout);
timeout = setTimeout(function() {
makeUrlForSearch(mainInput.value);
},300);
}
function makeUrlForSearch(getUserQuery) {
//let a = getUserQuery();
console.log(getUserQuery);
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
display: flex;
flex-flow: column wrap;
justify-content: center;
align-items: center;
font-size: 10px;
}
.header {
padding: 1rem;
margin: 1rem auto;
}
.header-title {
font-size: 2rem;
}
.main-input {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Wyszkuj Gipha!</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<header class="header"><h1 class="header-title">Wyszukaj Gipha!</h1></header>
<main class="main">
<form class="main-form">
<input type="text" placeholder="Wyszukaj Gipha!" class="main-input" id="main-input">
</form>
</main>
<script src="main.js"></script>
</body>
</html>
Below you can find a solution to your problem by using debounce function from lodash
I have made changes below. Added a raw debounce function.
function debounce(func, wait, immediate) {
var timeout;
return function() {
var context = this, args = arguments;
var later = function() {
timeout = null;
if (!immediate) func.apply(context, args);
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
};
};
$(document).ready(function(){
function makeUrlForSearch(query) {
let a = query;
console.log(a);
}
function getUserQuery(e) {
makeUrlForSearch(e.target.value);
}
document.querySelector(".main-input").addEventListener('keyup', debounce(getUserQuery, 300));
});
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
display: flex;
flex-flow: column wrap;
justify-content: center;
align-items: center;
font-size: 10px;
}
.header {
padding: 1rem;
margin: 1rem auto;
}
.header-title {
font-size: 2rem;
}
.main-input {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.core.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Wyszkuj Gipha!</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<header class="header"><h1 class="header-title">Wyszukaj Gipha!</h1></header>
<main class="main">
<form class="main-form">
<input type="text" placeholder="Wyszukaj Gipha!" class="main-input" id="main-input">
</form>
</main>
<script src="main.js"></script>
</body>
</html>

Categories