Trigger Donut Chart animation on scroll - javascript

I've created some Donut charts with a simple fill animation but I'm having trouble triggering the animation on scroll. Would it be a good idea to add in animate.css and wow.js or is there an easier way to trigger the animation inside of the function? Thanks in advance for the help if you are able to help with this issue.
<div class="donut-chart orange" data-percent="72">
<p><span class="counter" data-count="72">0</span>%</p>
<div class="doughnut"></div>
</div>
$(function() {
$('.donut-chart').each(function(index) {
$(this).append('<svg preserveAspectRatio="xMidYMid" xmlns:xlink="http://www.w3.org/1999/xlink" id="donutChartSVG' + index + '"><path d="M100,100"/></svg>');
var p = new Donut_chart({
element: $('#donutChartSVG' + index),
percent: $(this).attr('data-percent')
});
p.animate();
});
});
$('.counter').each(function() {
var $this = $(this),
countTo = $this.attr('data-count');
$({
countNum: $this.text()
}).animate({
countNum: countTo
}, {
duration: 2000,
easing: 'linear',
step: function() {
$this.text(Math.floor(this.countNum));
},
complete: function() {
$this.text(this.countNum);
}
});
});
.donut-chart svg {
pointer-events: none;
height: 100%;
stroke: #19a8ff;
}
.donut-chart svg path {
fill: none;
stroke-width: 35px;
stroke: #19a8ff;
}
.donut-chart {
width: 200px;
height: 200px;
display: inline-block;
left: 20%;
margin-bottom: 30px;
}
.donut-chart p {
margin: 0;
position: absolute;
left: 1%;
top: 25%;
font-family: 'Open Sans', sans-serif;
font-weight: bolder;
color: #222;
width: 100%;
text-align: center;
font-size: 2em;
}
.doughnut {
border: 35px solid #EAECEF;
border-radius: 100px;
height: 200px;
width: 200px;
position: absolute;
top: 0px;
z-index: -1;
}

try this, just check if the user scrolls then include inside if() your event function.
$(window).scroll(function() {
if ($('.donut-chart').is(':visible')) {
// do your stuff here, include function with p.animate();
}
});
but remember that this may slow down the performance of your site. You may refer to this site for improvement, https://johnresig.com/blog/learning-from-twitter/.

Related

Compounding Value within an object used to slide dot across the page incrementally

I am unable to get a variable to function properly as the translateX value within my object. I am wanting to make the dot scroll across the page each time the next button is clicked. My code is only able to move it back and forth for the first step.
I am new to the animation API, and I have already made this work with CSS transitions but I am trying to get a good handle on the API.
html:
<div class="progress__container">
<div class="progress__bar">
<div id="progress__fill" class="step1"></div>
<div class="circ" id="circ__1"></div>
<div class="circ" id="circ__2"></div>
<div class="circ" id="circ__3"></div>
<div class="circ" id="circ__4"></div>
<div id="progress__dot" class="prog__1"></div>
</div>
<div class="backBar"></div>
<div class="flexrow">
<span class="stepName">Account</span>
<span class="stepName">Frequency</span>
<span class="stepName">Amount</span>
<span class="stepName">Taxes</span>
</div>
<div class="button__container">
<button class="buttonStep" id="back">Back</button>
<button class="buttonStep is-active" id="next">Next</button>
</div>
</div>
js:
// give a starting value for the transformation
var startVal = 0;
// define the keyframes
var moveDot = [
{ transform: `translateX(${startVal}px)`},
{ transform: `translateX(${startVal + 190}px)`}
];
// definte the timing
var dotTiming = {
duration: 400,
fill: "forwards",
easing: 'ease-in',
}
// make the animation happen
var movingDot = document.getElementById("progress__dot").animate(
moveDot,
dotTiming
);
// pause the animation until called
movingDot.pause();
// on click fire the animation
document.getElementById('next').addEventListener('click', function() {
movingDot.playbackRate = 1;
if (startVal <= 380) {
movingDot.play();
startVal += 190;
}
});
document.getElementById('back').addEventListener('click', function() {
movingDot.playbackRate = -1;
if (startVal >= 0) {
movingDot.play();
startVal -= 190;
}
});
css:
#progress__fill {
height:2px;
position: absolute;
top: 7px;
left: 0;
background-color: darkred;
}
#progress__dot {
background-color: darkred;
color: #fff;
border-radius: 50%;
height: 8px;
width: 8px;
position: absolute;
text-align:center;
line-height: 8px;
padding: 6px;
top: 0;
font-size: 12px;
}
/* Static Bar Elements */
.progress__container {
width: 600px;
margin: 20px auto;
position: relative;
}
.backBar {
height:2px;
width:96%;
position: absolute;
top: 7px;
left: 2%;
background-color: lightgrey;
}
.progress__bar {
z-index: 100;
position: relative;
width: 96%;
margin: 0 auto;
}
.circ {
background-color: #fff;
border: 2px solid lightgrey;
border-radius: 50%;
height: 12px;
width: 12px;
display: inline-block;
}
#circ__2, #circ__3 {
margin-left: 30%
}
#circ__4 {
float: right;
}
.passed {
background-color: darkred;
border: 2px solid darkred;
}
.hide {
visibility: hidden
}
.flexrow {
display: flex;
flex-direction: row;
justify-content: space-between;
}
/* Buttons */
.buttonStep {
background: grey;
color: #fff;
padding: 10px 25px;
border-radius: 10px;
font-size: 16px;
}
#back {
float: left;
}
#next {
float: right;
}
.is-active {
background: darkred;
}
The way I have it set up, I expect for the translateX values to increment or decrement depending on the click event listeners which would make the circle slide across the page. What is actually happening is that only the first step works. it will not go past the first stop point. If I log moveDot in the console it gives me the values that I am expecting, but it will only start/stop at 0 and 190. the back button functions the same way. link to fiddle
It is animated from and to the same place every time. Move the definition of moveDot into the event listener:
// give a starting value for the transformation
var startVal = 0;
// definte the timing
var dotTiming = {
duration: 400,
fill: "forwards",
easing: 'ease-in',
}
// on click fire the animation
document.getElementById('next').addEventListener('click', function() {
if (startVal > 380){return;}
// define the keyframes
var moveDot = [{transform: `translateX(${startVal}px)`},
{transform: `translateX(${startVal + 190}px)`}];
// make the animation happen
var movingDot = document.getElementById("progress__dot").animate(
moveDot,
dotTiming
);
movingDot.playbackRate = 1;
movingDot.play();
startVal += 190;
});
document.getElementById('back').addEventListener('click', function() {
movingDot.playbackRate = -1;
if (startVal >= 0) {
movingDot.play();
startVal -= 190;
}
});

JS / CSS issue with Div Slider and Display:Table-Cell

I have a Div slider that rotates a set of Divs in and out of focus. Everything was working fine until I tried switching everything to (table / table-cell) in order to keep them all the Divs the same height in CSS. Now they still rotate out but one div remains visible with a reduced width off to the side of the stage. I get a sense that its position related but just can't figure out what's causing the issue.
Affected Page - https://www.harpercollege.edu/dev/blog-slider-test.php
JS Code:
$('.blog-posts').wrapInner('<div class="blog-posts-stage" />');
// Calculate Conditions & Set Vars
// var playTimer = 9,
slideQty = $('.well').length,
slideWidth = $('.well').width(),
stageWidth = $('.blog-posts-stage').width(),
contWidth = $('.blog-posts').width();
if ((slideQty * slideWidth) < contWidth) {
$('.blog-posts-prev').addClass('blog-posts-prev-disabled').removeClass('blog-posts-prev');
$('.blog-posts-next').addClass('blog-posts-next-disabled').removeClass('blog-posts-next');
} else {
$('.blog-posts-prev-disabled').addClass('blog-posts-prev').removeClass('blog-posts-prev-disabled');
$('.blog-posts-next-disabled').addClass('blog-posts-next').removeClass('blog-posts-next-disabled');
}
$(window).resize(function() {
var slideQty = $('.well').length,
slideWidth = $('.well').width(),
stageWidth = $('.blog-posts-stage').width(),
contWidth = $('.blog-posts').width();
if ((slideQty * slideWidth) < contWidth) {
$('.blog-posts-prev').addClass('blog-posts-prev-disabled').removeClass('blog-posts-prev');
$('.blog-posts-next').addClass('blog-posts-next-disabled').removeClass('blog-posts-next');
} else {
$('.blog-posts-prev-disabled').addClass('blog-posts-prev').removeClass('blog-posts-prev-disabled');
$('.blog-posts-next-disabled').addClass('blog-posts-next').removeClass('blog-posts-next-disabled');
}
});
$('.blog-posts-next').on('click', function(event) {
event.preventDefault();
$('.blog-posts-stage').animate({
left: -(slideWidth)
}, 500, function() {
$('.well:first').appendTo('.blog-posts-stage');
$('.blog-posts-stage').css({
left: '0px'
});
});
});
$('.blog-posts-prev').on('click', function(event) {
event.preventDefault();
$('.well:last').prependTo('.blog-posts-stage');
$('.blog-posts-stage').css({
left: -(slideWidth)
});
$('.blog-posts-stage').animate({
left: '0px'
}, 500, function() {});
});
function moveForward() {
$('.blog-posts-stage').animate({
left: -(slideWidth)
}, 500, function() {
$('.well:first').appendTo('.blog-posts-stage');
$('.blog-posts-stage').css({
left: '0px'
});
});
}
var timer = setInterval(moveForward, playTimer);
$('.blog-posts, .blog-posts-prev, .blog-posts-next').hover(function(ev) {
// clearInterval(timer);
}, function(ev) {
// timer = setInterval( moveForward, playTimer);
});
CSS Code:
<style>
.blog-posts {
width: 100%;
background: #eee;
font-size: 0;
position: relative;
}
.blog-posts-prev,
.blog-posts-next {
display: inline-block;
background: #eee;
color: #000;
text-decoration: none;
padding: 10px;
margin: 5px 0;
}
.blog-posts-prev:hover,
.blog-posts-next:hover {
background: #ccc;
}
.blog-posts-prev-disabled,
.blog-posts-next-disabled {
display: inline-block;
background: #eee;
color: #ccc;
text-decoration: none;
padding: 10px;
margin: 5px 0;
}
.blog-posts-stage {
position: relative;
white-space: normal;
width: 100%;
height: 100%;
float: none;
}
.well {
background: #ccc;
box-shadow: inset -1px 0px 0px 0px rgb(255, 255, 255);
width: 100%;
font-size: 12px;
text-align: left;
display: table-cell;
height: 100%;
width: 100%;
}
.well .row .col-sm-12.col-md-12 h2 {
float: left;
margin-top: 0px;
}
</style>
You could just use a lightbox library and save yourself the effort, but if you really want to do this why not try flex?
.blog-posts-stage {
display: flex;
flex-direction: row;
overflow: hidden;
}
.well-large {
flex-shrink: 0;
}

Jquery animate() effect doesn't function well

When hover on the first and second element, some element will animate to the left, it works well if hovered with a normal speed, but will crashed if hovered too fast for some times
(the text won't show or the text won't move back to its original place when mouseoff, checkout the figures below).
Any suggestions would be appreciated.
1.text won't show
2.text won't move back to its original place
$(document).ready(function() {
var flag = false;
$(".tab-ico").hover(function() {
var f = $(this);
f.data('timeout', window.setTimeout(function() {
f.find(".tab-text").stop(true, true).animate({
left: "-=64"
}, 300, function() {
flag = true;
});
}, 300));
}, function() {
clearTimeout($(this).data("timeout"));
if (flag === true) {
$(this).find(".tab-text").stop(true, true).animate({
left: "+=64"
}, 300, function() {
flag = false;
});
}
});
});
.pfm-toolbar-wrap {
height: 100%;
position: fixed;
right: 0;
top: 0;
width: 35px;
z-index: 9990;
}
.pfm-tbar-tab-Spike {
position: relative;
width: 35px;
}
.pfm-toolbar-tabs {
border-right: 5px solid #7a6e6e;
height: 100%;
}
.p-tab div.tab-ico {
background: #7a6e6e;
}
.tab-text {
border-radius: 3px;
color: #fff;
height: 32px;
left: 0px;
line-height: 32px;
position: absolute;
text-align: center;
width: 70px;
padding-right: 5px;
z-index: -1;
background: #7a6e6e;
}
.tab-text a {
color: #fff;
display: block;
}
.p-tab {
left: 0;
margin-top: -100px;
position: absolute;
top: 50%;
width: 35px;
z-index: 9;
text-align: center;
}
.p-tab div.tab-ico:hover {
background: #e20531;
cursor: pointer;
}
.p-tab div.tab-ico:hover .tab-text {
background: #e20531;
}
.tab-ico {
width:35px;
height:35px;
margin-bottom:5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div class="pfm-toolbar-wrap">
<div class="pfm-toolbar-tabs">
<div class="p-tab">
<div class="pfm-tbar-tab-Spike m_b15">
<div class="tab-ico cart"> <i class="cbl-icon"></i> <em class="tab-text"> text</em>
</div>
</div>
<div class="pfm-tbar-tab-group m_b15">
<div class="tab-ico "> <i class="cbl-icon"></i>
<em class="tab-text"> text2</em>
</div>
</div>
</div>
</div>
</div>
you can use css transition-delay property as follows:
transition-delay: 1s; /* delays for 1 second */
-webkit-transition-delay: 1s; /* for Safari & Chrome */
Find more info here.
I suggest that you use CSS transition, here are two links that will help you make that with less code and using CSS transition
https://css-tricks.com/almanac/properties/t/transition/
https://blog.alexmaccaw.com/css-transitions

Javascript: laggy on hover; animate slide

I have this infobox that will slide to show on hover on a arrow connected to that infobox. See the jsfiddle I've linked further down for more insight.
The thing I'm struggling with is that it's sort of laggy. It jumps back and forth really fast as it likes and it bothers me a lot. I've done some research and found out that the .stop(true, false) is the thing messing it up, but that you can't really go without it either. Haven't found any smooth solution yet though...
I would like it, if possible, to...
...when hovered, fully animate the animation even though the mouse leaves.
...animate when #infoboxArrow is hovered and then animate back when the mouse leaves its parent #infocontainer.
$('#infoboxArrow').hover(function() {
$('#infocontainer')
.stop(true, false)
.animate({
right: 250
}, 600);
}, function() {
$('#infocontainer')
.stop(true, false)
.animate({
right: 0
}, 600);
});
#infocontainer{
position:fixed;
background-color: blue;
top: 0em;
right: 0em;
}
#infoboxArrow {
display: inline-block;
background-color: pink;
margin-bottom: 10.1325em;
margin-top: 10.1325em;
height: 7.735em;
}
#infoboxDiv{
display: inline-block;
background-color: yellow;
width: 400px;
height: 28em;
position: absolute;
}
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<div id="infocontainer" class="slideOutTab">
<div id ="infoboxArrow" class="slideOutTab"><img src="http://i61.tinypic.com/qmx8ns.png"/></div>
<div id="infoboxDiv" class="slideOutTab"></div>
</div>
Try listening to mouseenter and mouseleave events instead of hover:
var $infocontainer = $('#infocontainer');
$('#infoboxArrow').on('mouseenter', function() {
$infocontainer
.stop(true, false)
.animate({
right: 250
}, 600);
});
$infocontainer.on('mouseleave', function() {
$infocontainer
.stop(true, false)
.animate({
right: 0
}, 600);
});
var $infocontainer = $('#infocontainer');
$('#infoboxArrow').on('mouseenter', function() {
$infocontainer
.stop(true, false)
.animate({
right: 250
}, 600);
});
$infocontainer.on('mouseleave', function() {
$infocontainer
.stop(true, false)
.animate({
right: 0
}, 600);
});
#infocontainer{
position:fixed;
background-color: blue;
top: 0em;
right: 0em;
}
#infoboxArrow {
display: inline-block;
background-color: pink;
margin-bottom: 10.1325em;
margin-top: 10.1325em;
height: 7.735em;
}
#infoboxDiv{
display: inline-block;
background-color: yellow;
width: 400px;
height: 28em;
position: absolute;
}
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<div id="infocontainer" class="slideOutTab">
<div id ="infoboxArrow" class="slideOutTab"><img src="http://i61.tinypic.com/qmx8ns.png"/></div>
<div id="infoboxDiv" class="slideOutTab"></div>
</div>
Also note you don't need the image. And you are mixing em units with px, so your layout could break if the font size changes. Consider this code:
var $infocontainer = $('#infocontainer');
$('#infoboxArrow').on('mouseenter', function() {
$infocontainer
.stop(true, false)
.animate({
right: 250
}, 600);
});
$infocontainer.on('mouseleave', function() {
$infocontainer
.stop(true, false)
.animate({
right: 0
}, 600);
});
#infocontainer{
position: fixed;
height: 28em;
background-color: blue;
top: 0em;
right: 0em;
}
#infoboxArrow {
display: inline-block;
background-color: pink;
position: relative;
top: 50%;
margin-top: -59px;
border: 59px solid #FFC0CB;
border-right: 100px solid #000000;
border-left: none;
}
#infoboxDiv{
display: inline-block;
background-color: yellow;
width: 400px;
height: 100%;
position: absolute;
}
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<div id="infocontainer" class="slideOutTab">
<div id="infoboxArrow" class="slideOutTab"></div>
<div id="infoboxDiv" class="slideOutTab"></div>
</div>

.stop on .mouseover or .hover

I can't figure out how to stop and resume the slide on a mouseover or hover occurrence. I basically want to stop all the scripts when .mouseover or .hover is triggered. Can anyone help me on this?
Edit: Code should work if you simply copy paste it, it is all hosted externally
<!DOCTYPE html>
<html>
<head>
<script src="http://code.jquery.com/jquery-1.8.2.min.js" type="text/javascript"></script>
<script src="http://static.tumblr.com/jvojroo/DIamwjvp3/jquery.caroufredsel-6.2.0-packed.js" type="text/javascript"></script>
<script type="text/javascript">
$(function() {
$('#slider').carouFredSel({
width: '100%',
align: false,
items: 4,
items: {
width: $('#wrapper').width() * 0.15,
height: 500,
visible: 1,
minimum: 1
},
scroll: {
items: 1,
timeoutDuration: 1000,
onBefore: function(data) {
// find current and next slide
var currentSlide = $('.slide.active', this),
nextSlide = data.items.visible,
_width = $('#wrapper').width();
// resize currentslide to small version
currentSlide.stop().animate({
width: _width * 0.15
});
currentSlide.removeClass('active');
// hide current block
data.items.old.add(data.items.visible).find('.slide-block').stop().fadeOut();
// animate clicked slide to large size
nextSlide.addClass('active');
nextSlide.stop().animate({
width: _width * 0.7
});
},
onAfter: function(data) {
// show active slide block
data.items.visible.last().find('.slide-block').stop().fadeIn();
}
},
onCreate: function(data) {
// clone images for better sliding and insert them dynamacly in slider
var newitems = $('.slide', this).clone(true),
_width = $('#wrapper').width();
$(this).trigger('insertItem', [newitems, newitems.length, false]);
// show images
$('.slide', this).fadeIn();
$('.slide:first-child', this).addClass('active');
$('.slide', this).width(_width * 0.15);
// enlarge first slide
$('.slide:first-child', this).animate({
width: _width * 0.7
});
// show first title block and hide the rest
$(this).find('.slide-block').hide();
$(this).find('.slide.active .slide-block').stop().fadeIn();
}
});
// Handle click events
$('#slider').children().click(function() {
$('#slider').trigger('slideTo', [this]);
});
$('.slide:firstchild').mouseover(function() {
$('.slide:firstchild').stop();
});
$('#slider').children().mouseover(function() {
$('#slider').stop();
});
//$('#slider').children().mouseout(function() {
// $('#slider').trigger( 'slideTo', [this] );
//});
// Enable code below if you want to support browser resizing
$(window).resize(function() {
var slider = $('#slider'),
_width = $('#wrapper').width();
// show images
slider.find('.slide').width(_width * 0.15);
// enlarge first slide
slider.find('.slide.active').width(_width * 0.7);
// update item width config
slider.trigger('configuration', ['items.width', _width * 0.15]);
});
});
</script>
<style type="text/css">
html, body {
height: 100%;
padding: 0;
margin: 0;
}
body {
background: #f9f9f3;
}
body * {
font-family: Arial, Geneva, SunSans-Regular, sans-serif;
font-size: 14px;
color: #222;
line-height: 20px;
}
#wrapper {
height: 100%;
width: 100%;
min-height: 650px;
min-width: 900px;
padding-top: 1px;
}
#slider {
margin: 100px 0 0 0;
height: 500px;
overflow: hidden;
}
#slider .slide {
position: relative;
display: none;
height: 500px;
float: left;
background-position: center right;
cursor: pointer;
border-left: 1px solid #fff;
}
#slider .slide:first-child {
border: none;
}
#slider .slide.active {
cursor: default;
}
#slider .slide-block {
position: absolute;
left: 40px;
bottom: 75px;
display: inline-block;
width: 435px;
background-color: #fff;
background-color: rgba(255, 255, 255, 0.8);
padding: 20px;
font-size: 14px;
color: #134B94;
border: 1px solid #fff;
overflow: hidden;
border-radius: 4px;
}
#slider .slide-block h4 {
font-size: 36px;
font-weight: bold;
margin: 0 0 10px 0;
line-height: 1;
}
#slider .slide-block p {
margin: 0;
}
#donate-spacer {
height: 0;
}
#donate {
border-top: 1px solid #999;
width: 750px;
padding: 50px 75px;
margin: 0 auto;
overflow: hidden;
}
#donate p, #donate form {
margin: 0;
float: left;
}
#donate p {
width: 650px;
color: #999;
}
#donate form {
width: 100px;
}
</style>
</head>
<body>
<div id="wrapper">
<div id="slider">
<div class="slide">
<img src="http://farm4.staticflickr.com/3821/10956569263_92a647e267_o.png">
<div class="slide-block">
<h4>Ice Age</h4>
<p>Heading south to avoid a bad case of global frostbite, a group of migrating misfit creatures embark on a hilarious quest to reunite a human baby with his tribe.</p>
</div>
</div>
<div class="slide">
<img src="http://farm8.staticflickr.com/7444/10956575693_94fd773731_o.png">
<div class="slide-block">
<h4>For The Birds</h4>
<p>For the Birds is an animated short film, produced by Pixar Animation Studios released in 2000. It is shown in a theatrical release of the 2001 Pixar feature film Monsters, Inc.</p>
</div>
</div>
<div class="slide">
<img src="http://farm4.staticflickr.com/3789/10956504824_4845433ff6_o.png">
<div class="slide-block">
<h4>UP</h4>
<p>A comedy adventure in which 78-year-old Carl Fredricksen fulfills his dream of a great adventure when he ties thousands of balloons to his house and flies away to the wilds of South America.</p>
</div>
</div>
<div class="slide">
<img src="http://farm6.staticflickr.com/5464/9449526762_ed5339251e_o.jpg">
<div class="slide-block">
<h4>Ice Age</h4>
<p>Heading south to avoid a bad case of global frostbite, a group of migrating misfit creatures embark on a hilarious quest to reunite a human baby with his tribe.</p>
</div>
</div>
</div>
</div>
</body>
</html>
You can trigger a custom event named "stop" on carouFredSel component If you want to stop the slider.
$('#slider').trigger("stop");
And trigger a custom event named "play" with a extra parameter true to resume the slider
$("#slider").trigger("play",true);
For example:
<script>
$(function(){
$("#slider").carouFredSel({
items: 4
});
$("#slider > div.slide").hover(
function(){
$("#slider").trigger("stop");
},
function(){
$("#slider").trigger("play",true);
}
);
});
</script>
Hope this is helpful for you.

Categories

Resources