Anime.js Moving Letters - Multiple Text Lines - javascript

I am working on implementing the following anime.JS effect on my site and having trouble manipulating the javascript to accommodate multiple lines of text. My desired output is that line one animates then fades out, line 2 animates etc.
https://tobiasahlin.com/moving-letters/#11
<script>
// Wrap every letter in a span
var textWrapper = document.querySelector('.ml11 .letters');
textWrapper.innerHTML = textWrapper.textContent.replace(/([^\x00-\x80]|\w)/g, "<span class='letter'>$&</span>");
anime.timeline({loop: true})
.add({
targets: '.ml11 .line',
scaleY: [0,1],
opacity: [0.5,1],
easing: "easeOutExpo",
duration: 700
})
.add({
targets: '.ml11 .line',
translateX: [0, document.querySelector('.ml11 .letters').getBoundingClientRect().width + 10],
easing: "easeOutExpo",
duration: 700,
delay: 100
}).add({
targets: '.ml11 .letter',
opacity: [0,1],
easing: "easeOutExpo",
duration: 600,
offset: '-=775',
delay: (el, i) => 34 * (i+1)
}).add({
targets: '.ml11',
opacity: 0,
duration: 1000,
easing: "easeOutExpo",
delay: 1000
});
</script>
I'd like the output to look something like this where 3 separate lines are displayed one after another - https://codepen.io/dsr/pen/mdJXEdP
How should I manipulate the JS code and what HTML classes I am using to get this effect?

you can do it with interval function, here is the example:
https://jsfiddle.net/3ux2jkpq/
<h1 class="ml11">
<span class="text-wrapper">
<span class="line line1"></span>
<span class="letters">Hello</span>
<span class="letters">Goodbye</span>
</span>
</h1>
<script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/2.0.2/anime.min.js"></script>
<style>
.ml11 {
font-weight: 700;
font-size: 3.5em;
}
.ml11 .text-wrapper {
position: relative;
display: inline-block;
padding-top: 0.1em;
padding-right: 0.05em;
padding-bottom: 0.15em;
}
.ml11 .line {
opacity: 0;
position: absolute;
left: 0;
height: 100%;
width: 3px;
background-color: #fff;
transform-origin: 0 50%;
}
.ml11 .line1 {
top: 0;
left: 0;
}
.ml11 .letter {
display: inline-block;
line-height: 1em;
}
</style>
<script>
var i = 0;
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
var textWrapper = document.getElementsByClassName('letters');
textWrapper[0].style.display="none";
textWrapper[1].style.display="none";
setInterval( function() {
// Wrap every letter in a span
textWrapper[0].style.display="none";
textWrapper[1].style.display="none";
textWrapper[i].style.display="block";
textWrapper[i].innerHTML = textWrapper[i].textContent.replace(/([^\x00-\x80]|\w)/g, "<span class='letter'>$&</span>");
anime.timeline({loop: true})
.add({
targets: '.ml11 .line',
scaleY: [0,1],
opacity: [0.5,1],
easing: "easeOutExpo",
duration: 700
})
.add({
targets: '.ml11 .line',
translateX: [0, document.querySelector('.ml11 .letters').getBoundingClientRect().width + 10],
easing: "easeOutExpo",
duration: 700,
delay: 100
}).add({
targets: '.ml11 .letter',
opacity: [0,1],
easing: "easeOutExpo",
duration: 600,
offset: '-=775',
delay: (el, i) => 34 * (i+1)
}).add({
targets: '.ml11',
opacity: 0,
duration: 1000,
easing: "easeOutExpo",
delay: 1500
});
if(i==0){i=1;}
else{i=0;}
},1800);
</script>

Related

Anime js does not recognise or follow svg path

I am using animejs for the first time. I tried out a few tutorials from the documentation which worked file. I then tried to use an SVG with a div that followed the SVG's path exactly as shown in this Codepen how for some reason the div does not move at all.
Note: I am using animejs from a cdn. I have also tried downloading the file and using it, but I get the same problem.
Here is my code...
window.onload = () => {
var path = anime.path("path");
anime({
targets: "div",
translateX: path,
translateY: path,
rotate: path,
duration: 3000,
loop: true,
easing: "linear",
});
anime({
targets: "path",
opacity: 0,
duration: 6000,
loop: true,
direction: "alternate",
easing: "easeInOutExpo",
});
}
body {
background: grey;
}
div,
.green {
position: absolute;
background: green;
top: 0.5rem;
left: 0.5rem;
width: 1rem;
height: 1rem;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/3.2.1/anime.js"></script>
<body>
<section>
<article>
<svg>
<path
fill="#000"
stroke="#000"
d="M8,56 C8,33.90861 25.90861,16 48,16 C70.09139,16 88,33.90861 88,56 C88,78.09139 105.90861,92 128,92 C150.09139,92 160,72 160,56 C160,40 148,24 128,24 C108,24 96,40 96,56 C96,72 105.90861,92 128,92 C154,93 168,78 168,56 C168,33.90861 185.90861,16 208,16 C230.09139,16 248,33.90861 248,56 C248,78.09139 230.09139,96 208,96 L48,96 C25.90861,96 8,78.09139 8,56 Z"
/>
</svg>
<div class="green"></div>
</article>
</section>
</body>
The path variable returned from anime.path("selector"); is function. As described in docs you should call it with "x", "y" or "angle"
var path = anime.path("path");
anime({
targets: "div",
translateX: path("x"),
translateY: path("y"),
rotate: path("angle"),
duration: 3000,
loop: true,
easing: "linear",
});

How to fix the problem with 3D animation CSS on iOS (Safari / Chrome)

I have something like browser game.
On click user throw dices. Dices fall through shadow, but there are different block and dice has z-index : 3 and shadow z-index : 2;
This problem only on iOS.
For animation use library anime.js.
Maybe someone had the same problem.
Try to add screenshot for show the problem:
.dice {
width: 144px;
height: 144px;
left: -200px;
top: -450px;
z-index: 3;
transform-style: preserve-3d;
backface-visibility: hidden;
transform: translateZ(-72px) rotateX(313deg) rotateY(226deg) scale3d(0.35, 0.35, 0.35);
z-index: 3;
.cube_face {
width: 144px;
height: 143px;
border: 1px solid #f5f3e6;
border-radius: 15px;
}
}
<div class="diceShadow"></div>
<div class="dice">
<div class="cube_face cube_face_front"></div>
<div class="cube_face cube_face_back big-shadow"></div>
<div class="cube_face cube_face_right"></div>
<div class="cube_face cube_face_left shadow"></div>
<div class="cube_face cube_face_top"></div>
<div class="cube_face cube_face_bottom"></div>
</div>
anime({
targets: dices[count],
left: [{
value: '-200px',
duration: 0
},
{
value: dicePositions[count].x - 56,
duration: duration / 2,
easing: 'easeInCubic'
},
{
value: dicePositions[count].x + 15,
duration: duration / 10,
easing: 'easeOutQuad'
},
{
value: dicePositions[count].x + 30,
duration: duration / 10,
easing: 'easeInQuad'
},
{
value: dicePositions[count].x + 84,
duration: duration / 5,
easing: 'easeOutQuad'
},
],
top: [{
value: '-850px',
duration: 0
},
{
value: dicePositions[count].y - 30,
duration: duration / 2,
easing: 'easeInCubic'
},
{
value: dicePositions[count].y - 95,
duration: duration / 10,
easing: 'easeOutQuad'
},
{
value: dicePositions[count].y + 10,
duration: duration / 10,
easing: 'easeInQuad'
},
{
value: dicePositions[count].y + 50,
duration: duration / 5,
easing: 'easeOutQuad'
},
],
translateZ: [{
value: '-72px',
duration: 0
}, ],
rotateX: [{
value: dicePositions[count].rotateX + 132,
duration: 0
},
{
value: dicePositions[count].rotateX + 32,
duration: duration / 2,
easing: 'easeInOutQuad'
},
{
value: dicePositions[count].rotateX,
duration: duration / 4,
delay: duration / 10,
easing: 'easeOutCubic',
},
],
rotateY: [{
value: dicePositions[count].rotateY - 100,
duration: 0
},
{
value: dicePositions[count].rotateY - 39,
duration: duration / 2,
easing: 'easeInOutQuad'
},
{
value: dicePositions[count].rotateY,
duration: duration / 4,
delay: duration / 10,
easing: 'easeOutQuad',
},
],
rotateZ: [{
value: dicePositions[count].rotateZ,
duration: 0
}, ],
scaleX: [{
value: 0.35,
duration: 0
}, ],
scaleY: [{
value: 0.35,
duration: 0
}, ],
scaleZ: [{
value: 0.35,
duration: 0
}, ],
});
Problem solved! I had DOM elements that were outside parent`s block. When I positioned them to parent block area and add opacity, to hide them - my dices fell into place.
Example:
were :
#train {
width: 158px;
height: 146px;
transition: all 0.4s ease-in;
background: url('../img/train.png') no-repeat center;
background-size: cover;
&[data-show='false'] {
left: -100%;
top: -100%;
}
&[data-show='true'] {
left: 9%;
top: 14%;
}
}
now:
#train {
width: 158px;
height: 146px;
transition: all 0.4s ease-in;
background: url('../img/train.png') no-repeat center;
background-size: cover;
&[data-show='false'] {
left: 0%;
top: 17px;
opacity: 0;
}
&[data-show='true'] {
left: 9%;
top: 14%;
opacity: 1;
}
}

fullpage.js - After resposive is triggered, jQuery.position() and .offset() still return 0,0

Trying to use ScrollMagic with fullpage.js - I have searched and only found that it is suggested to use scrollBar: true or autoScrolling: false to enable jQuery positioning or offsets, however, upon responsive (which turns the page into a normal scrolling site), the position still remains at that (0,0) position.
This seems a bit confusing, as in my mind, if I say:
autoScrolling: true,
but
responsiveWidth: 991
and, via the documentation:
A normal scroll (autoScrolling:false) will be used under the defined width in pixels ... For example, if set to 900, whenever the browser's width is less than 900 the plugin will scroll like a normal site.
So why wouldn't my $('.fp-section').position() work after checking for Responsive in afterResponsive(isResponsive)?
example:
Codepen
jQuery('#main').fullpage({
//Navigation
lockAnchors: false,
navigation: true,
navigationPosition: 'left',
showActiveTooltip: false,
slidesNavigation: false,
//Scrolling
scrollingSpeed: 700,
autoScrolling: true,
fitToSection: false,
fitToSectionDelay: null,
scrollBar: false,
easingcss3: 'ease',
scrollHorizontally: true,
offsetSections: false,
resetSliders: false,
touchSensitivity: 15,
normalScrollElementTouchThreshold: 5,
bigSectionsDestination: 'top',
dragAndMove: 'fingersonly',
//Accessibility
keyboardScrolling: true,
animateAnchor: true,
recordHistory: false,
//Design
sectionsColor: ['#ccc', 'black', '#ccc'],
responsiveWidth: 991,
//Custom selectors
sectionSelector: '.section',
lazyLoading: true,
afterResponsive: function(isResponsive) {
var scene = [];
var parallaxTween = [];
var box = jQuery('.moveme');
var parallax = new TimelineMax();
var controller = new ScrollMagic.Controller({
globalSceneOptions: {
triggerHook: .5,
duration: window.innerHeight + 50
}
});
for (var i = 0; i < box.length; i++) {
var yPer = -100;
var yEnd = 100;
//reset scene on responsive
if (scene[i])
scene[i].destroy(true);
parallaxTween[i] = null;
scene[i] = null;
console.log(box.closest('.section').position());
parallaxTween[i] = parallax.fromTo(jQuery('.container').eq(i), 1, {
yPercent: yPer
}, {
yPercent: yEnd,
ease: Linear.easeNone
}, 0);
scene[i] = new ScrollMagic.Scene({
triggerElement: jQuery(box[i]).closest('.section'),
})
.setTween(parallaxTween[i])
.addIndicators()
.addTo(controller);
}
}
});
.section {
position: relative;
}
.container {
position: absolute;
background: blue;
color: white;
width: 100px;
height: 100px;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.moveme {
margin: 0;
line-height: 100px;
text-align: center;
}
<main class="site-main fullpage-wrapper" id="main" role="main" style="height: 100%; position: relative; transform: translate3d(0px, 0px, 0px); transition: none;">
<div class="section">
<div class="container">
<p class="moveme">i should move
<p>
</div>
</div>
<div class="section">
<div class="container">
<p class="moveme">i should move
<p>
</div>
</div>
<div class="section">
<div class="container">
<p class="moveme">i should move
<p>
</div>
</div>
</main>
<script src='https://cdnjs.cloudflare.com/ajax/libs/gsap/latest/TweenMax.min.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/fullPage.js/2.9.7/jquery.fullpage.extensions.min.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/ScrollMagic/2.0.5/ScrollMagic.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/ScrollMagic/2.0.5/plugins/jquery.ScrollMagic.js'></script>
<script src='https://s3-us-west-2.amazonaws.com/s.cdpn.io/1295227/animation.gsap.js'></script>
<script src='https://s3-us-west-2.amazonaws.com/s.cdpn.io/1295227/debug.addIndicators.js'></script>

jquery circle progress | change colour when exceeds 100%

I am using the jquery circle progress library. I need to have the full progress represent as 100%, however the actual value placed on is 150%.
I need to change the colour of that extra 50%.
Here is the HTML:
<div id="circle"></div>
Here is the JS:
$('#circle').circleProgress({
value: 1.50,
size: 100,
fill: { color: "#ff1e41" }
});
The following is a fiddle: https://jsfiddle.net/2pekq9zw/
How can I change the colour of that extra 50% ?
This is not exactly what you want (because you can't use number > 1 in the value), but the final view is what you are looking for:
https://jsfiddle.net/vz9dr78a/2/
I created two circles that overlap each other, the first is 100% and the second is 50%.
Once the animation of the first circle is done - the animation of the second circle will start:
$('#circle1').circleProgress({
value: 1,
size: 100,
fill: { color: "#ff1e41" }
}).on('circle-animation-end', function() {
$('#circle2').circleProgress({
value: 0.5,
size: 100,
fill: { color: "#00ff00" },
emptyFill: 'rgba(0, 0, 0, 0)'
})
});
here is a snippet:
$('#circle1').circleProgress({
value: 1,
size: 100,
fill: { color: "#ff1e41" }
}).one('circle-animation-end', function() {
$('#circle2').circleProgress({
value: 0.5,
size: 100,
fill: { color: "#00ff00" },
emptyFill: 'rgba(0, 0, 0, 0)'
})
});
.circle-container {
position: relative;
}
.circle-container .circle {
position: absolute;
top: 0;
left: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-circle-progress/1.2.0/circle-progress.js"></script>
<div class="circle-container">
<div id="circle1" class="circle"></div>
<div id="circle2" class="circle"></div>
</div>
Basically the same as the other attempts, though I tried to eliminate the lagging feel of the second circle starting so it feels more natural.
// js
$('#circle1').circleProgress({
value: 1,
size: 100,
animation: { duration: 1200, easing: "linear" },
fill: { color: "#ff1e41" }
});
$('#circle1').on('circle-animation-end', () => {
$('#circle2').circleProgress({
value: .50,
animation: { duration: 1200, easing: "linear"},
size: 100,
fill: { color: "#00FF00" },
emptyFill: 'rgba(0, 0, 0, 0)'
});
})
// css
#circle1 {
position: absolute;
}
#circle2 {
position: absolute;
}
// html
<div id="circle1"></div>
<div id="circle2"></div>
https://jsfiddle.net/2pekq9zw/10/
If you notice, my circles blend together a bit nicer than the other answers
By creating a second, smaller circle overlayed on the first you could show the extra, for example:
$('#circle').circleProgress({
value: 1,
size: 100,
fill: { color: "#ff1e41" }
});
$('#circle2').circleProgress({
value: 0.50,
size: 94,
fill: { color: "darkred" }
});
#circle { position:absolute; top:0;left:0}
#circle2 { position:absolute;top: 3px; left: 3px }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-circle-progress/1.2.0/circle-progress.js"></script>
<div id="circle"></div>
<div id="circle2"></div>

Angular Animate with Greensock

I am having difficulty converting this working greensock animation into an angular animation. Can anyone suggest how I can do this? This was going to be tied to an angular modal wizard so this does need to be an angular animation.
I was hoping to add an animation class to the html that could be used by the javascript. I don't care if it is addClass/removeClass, enter/leave, etc. I have tried a few times and I am having difficulty coming up with a fairly simple solution.
function percentToPixel(perc) {
return ($(".stepNavContainer").outerWidth() / 100) * parseFloat(perc);
}
var cursor = document.getElementById('cursor'),
step1 = document.getElementById('joinModalNavStep1'),
step2 = document.getElementById('joinModalNavStep2'),
step3 = document.getElementById('joinModalNavStep3'),
step4 = document.getElementById('joinModalNavStep4'),
step5 = document.getElementById('joinModalNavStep5');
TweenMax.set(cursor, {
x: percentToPixel("0") + "px",
xPercent: -50,
yPercent: -50
});
TweenMax.set(step1, {
x: percentToPixel("0") + "px",
xPercent: -50,
yPercent: -50
});
TweenMax.set(step2, {
x: percentToPixel("25") + "px",
xPercent: -50,
yPercent: -50
});
TweenMax.set(step3, {
x: percentToPixel("50") + "px",
xPercent: -50,
yPercent: -50
});
TweenMax.set(step4, {
x: percentToPixel("75") + "px",
xPercent: -50,
yPercent: -50
});
TweenMax.set(step5, {
x: percentToPixel("100") + "px",
xPercent: -50,
yPercent: -50
});
var tlStepNavAnimation = new TimelineMax({
paused: true
});
tlStepNavAnimation.to(cursor, 1, {
x: percentToPixel("0") + "px",
xPercent: -50,
yPercent: -50,
ease: Back.easeInOut
});
tlStepNavAnimation.addPause();
tlStepNavAnimation.to(cursor, 1, {
x: percentToPixel("25") + "px",
xPercent: -50,
yPercent: -50,
ease: Back.easeInOut
});
tlStepNavAnimation.addPause();
tlStepNavAnimation.to(cursor, 1, {
x: percentToPixel("50") + "px",
xPercent: -50,
yPercent: -50,
ease: Back.easeInOut
});
tlStepNavAnimation.addPause();
tlStepNavAnimation.to(cursor, 1, {
x: percentToPixel("75") + "px",
xPercent: -50,
yPercent: -50,
ease: Back.easeInOut
});
tlStepNavAnimation.addPause();
tlStepNavAnimation.to(cursor, 1, {
x: percentToPixel("100") + "px",
xPercent: -50,
yPercent: -50,
ease: Back.easeInOut
});
$("#nextBtn").on("click", navigateToNextStep);
$("#previousBtn").on("click", navigateToPreviousStep);
function navigateToNextStep() {
tlStepNavAnimation.play();
}
function navigateToPreviousStep() {
tlStepNavAnimation.reverse();
}
html,
body {
overflow: hidden;
}
body {
background-color: white;
margin: 0;
padding: 0;
}
.stepNavContainer {
position: relative;
height: 50px;
width: 50%;
left: 25%;
border: 1px solid red;
}
.circle {
display: block;
position: absolute;
width: 50px;
height: 50px;
border-radius: 50%;
}
#cursor {
display: block;
position: absolute;
width: 50px;
height: 50px;
background: #c32026;
border-radius: 50%;
}
.step {
background: #999999;
}
.btn {
width: 100px;
height: 50px;
border: 1px solid black;
}
<html>
<head>
<title>Title of the document</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div id="previousBtn" class="btn">
<span>Previous</span>
</div>
<div id="nextBtn" class="btn">
<span>Next</span>
</div>
<div class="stepNavContainer">
<span id="joinModalNavStep1" class="circle step"></span>
<span id="joinModalNavStep2" class="circle step"></span>
<span id="joinModalNavStep3" class="circle step"></span>
<span id="joinModalNavStep4" class="circle step"></span>
<span id="joinModalNavStep5" class="circle step"></span>
<span id="cursor" class="circle"></span>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.18.2/TweenMax.min.js"></script>
<script src="script.js"></script>
</body>
</html>

Categories