clearTimeout setInterval not working. But does in other script? - timer

I wish for this animation to loop over and over throughout the page duration, But for some reason the clearTimer is not fulfilling the job. or i have got the looping wrong thinking that clearing the timers would produce a loop as the function is granted.
<script>
(function () {
var a1;
a1 = setTimeout(anim1,9000);
var a2;
a2 = setTimeout(anim2,10000);
var a3;
a3 = setTimeout(anim3,11000);
var a4;
a4 = setTimeout(anim4,12000);
function anim1() {
document.getElementById("tx1").animate([
{ transform: "translateY(0px)"},
{ transform: "translateY(-10px)"},
{ transform: "translateY(0px)"}
], {
duration: 1000,
})
}
function anim2() {
document.getElementById("tx2").animate([
{ transform: "translateY(0px)"},
{ transform: "translateY(-10px)"},
{ transform: "translateY(0px)"}
], {
duration: 1000,
})
}
function anim3() {
document.getElementById("tx3").animate([
{ transform: "translateY(0px)"},
{ transform: "translateY(-10px)"},
{ transform: "translateY(0px)"}
], {
duration: 1000,
})
}
function anim4 () {
clearTimeout(a1);
clearTimeout(a2);
clearTimeout(a3);
clearTimeout(a4);
}
})();
</script>
I can see no problems, and the same script runs in another file...
I just want the animation to loop over basically. but it runs once, then dies, i assume that the cleartimeout is not the problem. ???

Found a Workaround Allthough im still not sure if im clearing the timers correctly. But its done the job so must be ok now... Thanks for your help folks...
heres the script..
<script>
window.onload=function start() {
var a1 = setTimeout(anim1,9000);
var a2 = setTimeout(anim2,10000);
var a3 = setTimeout(anim3,11000);
var a4 = setTimeout(anim4,12000);
function anim1() {
document.getElementById("tx1").animate([
{ transform: "translateY(0px)"},
{ transform: "translateY(-10px)"},
{ transform: "translateY(0px)"}
], {
duration: 1000,
})
}
function anim2() {
document.getElementById("tx2").animate([
{ transform: "translateY(0px)"},
{ transform: "translateY(-10px)"},
{ transform: "translateY(0px)"}
], {
duration: 1000,
})
}
function anim3() {
document.getElementById("tx3").animate([
{ transform: "translateY(0px)"},
{ transform: "translateY(-10px)"},
{ transform: "translateY(0px)"}
], {
duration: 1000,
})
}
function anim4() {
clearTimeout("a3")
clearTimeout("a1");
clearTimeout("a2");
clearTimeout("a4");
start();
}
}
</script>

You should pass the value returned from setTimeout to clearTimeout function.
In your case, it should be clearTimeout(a1) instead of clearTimeout(anim1) and so on.

Related

Highcharts | Network Graph - Is there a way to expand leaf nodes on click of the Parent node?

Highcharts | Network Graph - Is there a way to expand leaf nodes on click of the Parent node?
Sample Code`Highcharts.addEvent(
Highcharts.Series,
'afterSetOptions',
function (e) {
var colors = Highcharts.getOptions().color
i = 0,
nodes = {};
if (
this instanceof Highcharts.seriesTypes.networkgraph &&
e.options.id === 'lang-tree'
) {
e.options.data.forEach(function (link) {
if (link[0] === 'Parent') {
nodes['Parent'] = {
id: 'Parent',
marker: {
radius: 20
}
};
nodes[link[1]] = {
id: link[1],
marker: {
radius: 10
},
color: colors[i++]
};
} else if (nodes[link[0]] && nodes[link[0]].color) {
nodes[link[1]] = {
id: link[1],
color: nodes[link[0]].color
};
}
});
e.options.nodes = Object.keys(nodes).map(function (id) {
return nodes[id];
});
}
}
);`
Currently, this feature is not available to achieve from the API options without any customization.
Please take a look at this demo where you can find some custom functions to collapse the child nodes on the click event: https://jsfiddle.net/BlackLabel/9mv0ny3j/
point: {
events: {
click: function() {
var point = this;
point.linksFrom.forEach(link => {
if (link.toNode.isHidden) {
link.graphic.show();
link.toNode.graphic.css({
opacity: 1
});
link.toNode.dataLabel.css({
opacity: 1
})
link.toNode.isHidden = false;
} else {
link.graphic.hide();
link.toNode.graphic.css({
opacity: 0
});
link.toNode.dataLabel.css({
opacity: 0
})
link.toNode.isHidden = true;
}
})
}
}
},
API: https://api.highcharts.com/highcharts/series.line.events.click

Chartist graphs get re-drawn everytime I click on any button or resize window

I really like this library, but I can't seem to control this issue somehow. If any event occurs the graphs are being re-drawn every time.
I am using React.js and this is how I am creating and displaying the Chartist graphs:
const dailyComplaintsChart = {
data: {
labels: ["M", "T", "W", "T", "F", "S", "S"],
series: [whichType.seriesDaily]
},
options: {
lineSmooth: Chartist.Interpolation.cardinal({
tension: 0
}),
low: 0,
high: highestValue.highestValueDaily, // creative tim: we recommend you to set the high sa the biggest value + something for a better look
chartPadding: {
top: 0,
right: 0,
bottom: 0,
left: 0
}
},
// for animation
animation: {
draw: function (data) {
if (data.type === "line" || data.type === "area") {
data.element.animate({
d: {
begin: 600,
dur: 700,
from: data.path
.clone()
.scale(1, 0)
.translate(0, data.chartRect.height())
.stringify(),
to: data.path.clone().stringify(),
easing: Chartist.Svg.Easing.easeOutQuint
}
});
} else if (data.type === "point") {
data.element.animate({
opacity: {
begin: (data.index + 1) * delays,
dur: durations,
from: 0,
to: 1,
easing: "ease"
}
});
}
}
}
};
return(
<div className="daily-graph">
<ChartistGraph
className="ct-chart-background-daily-complaints"
data={dailyComplaintsChart.data}
type="Line"
options={dailyComplaintsChart.options}
listener={dailyComplaintsChart.animation}
/>
<div className={classes.line}>
<p>Daily Complaints</p>
</div>
</div>
)
This problem is caused by the use of animation, So you have to put all the animate function in an if statement and set a counter outside of draw function.
let animated = 0;
draw(data) {
if (animated <= label.length) {
// animate
data.element.animate(...)
animated++;
}
}

AngularJS Material Slide Left to Right CSS3 Animation

I am trying to "translate" this AngularJS slide left / right example to an AngularJS Material one.
The latter link consists of the following code snippets:
HTML code:
<div ng-controller="ExampleController" ng-app="switchExample">
<!--<select ng-model="slide" ng-options="item as item.name for item in slides">
</select>-->
<code>slide={{slide}}</code>
<code>moveToLeft={{mtl}}</code>
<md-button ng-click="prev()"><</md-button>
<md-button ng-click="next()">></md-button>
<div class="">
<div class="ngSwitchItem" ng-if="slide.name == 'first'" ng-class="{'moveToLeft' : mtl}">
<div class="firstPage page" md-swipe-left="selectPage(1)">
first
</div>
</div>
<div class="ngSwitchItem" ng-if="slide.name == 'second'" ng-class="{'moveToLeft' : mtl}">
<div class="secondPage page" md-swipe-right="selectPage(0)" md-swipe-left="selectPage(2)">
second
</div>
</div>
<div class="ngSwitchItem" ng-if="slide.name == 'third'" ng-class="{'moveToLeft' : mtl}">
<div class="thirdPage page" md-swipe-right="selectPage(1)" md-swipe-left="selectPage(3)">
third
</div>
</div>
<div class="ngSwitchItem" ng-if="slide.name == 'fourth'" ng-class="{'moveToLeft' : mtl}">
<div class="fourthPage page" md-swipe-right="selectPage(2)">
fourth
</div>
</div>
</div>
</div>
JS code
(function(angular) {
'use strict';
angular.module('switchExample', ['ngMaterial', 'ngAnimate'])
.controller('ExampleController', ['$scope', function($scope) {
$scope.slides = [
{ index: 0, name: 'first' },
{ index: 1, name: 'second' },
{ index: 2, name: 'third' },
{ index: 3, name: 'fourth' }
];
$scope.selectPage = selectPage;
/**
* Initialize with the first page opened
*/
$scope.slide = $scope.slides[0];
$scope.prev = () => {
if ($scope.slide.index > 0) {
selectPage($scope.slide.index - 1);
}
}
$scope.next = () => {
if ($scope.slide.index < 3) {
selectPage($scope.slide.index + 1);
}
}
/**
* #name selectPage
* #desc The function that includes the page of the indexSelected
* #param indexSelected the index of the page to be included
*/
function selectPage(indexSelected) {
if ($scope.slides[indexSelected].index > $scope.slide.index) {
$scope.mtl = false;
} else {
$scope.mtl = true;
}
$scope.slide = $scope.slides[indexSelected];
}
}]);
})(window.angular);
CSS code
body {
overflow-x: hidden;
}
.ngSwitchItem {
position: absolute;
top: 50px;
bottom: 0;
right: 0;
left: 0;
animation-duration: 10.30s;
animation-timing-function: ease-in-out;
-webkit-animation-duration: 10.30s;
-webkit-animation-timing-function: ease-in-out;
}
.page {
position: inherit;
top: 0;
right: inherit;
bottom: inherit;
left: inherit;
}
.firstPage {
background-color: blue;
}
.secondPage {
background-color: red;
}
.thirdPage {
background-color: green;
}
.fourthPage {
background-color: yellow;
}
/* When the page enters, slide it from the right */
.ngSwitchItem.ng-enter {
animation-name: slideFromRight;
-webkit-animation-name: slideFromRight;
}
/* When the page enters and moveToLeft is true, slide it from the left(out of the user view) to the right (left corner) */
.ngSwitchItem.moveToLeft.ng-enter {
animation-name: slideFromLeft;
-webkit-animation-name: slideFromLeft;
}
/* When the page leaves, slide it to left(out of the user view) from the left corner,
in other words slide it from the left(out of the view) to the left corner but in reverse order */
.ngSwitchItem.ng-leave {
animation-name: slideFromLeft;
animation-direction: reverse;
-webkit-animation-name: slideFromLeft;
-webkit-animation-direction: reverse;
}
/* When the page leaves, slide it to the right(out of the user view) from the the left corner,
in other words, slide it from the right but in reverse order */
.ngSwitchItem.moveToLeft.ng-leave {
animation-name: slideFromRight;
animation-direction: reverse;
-webkit-animation-name: slideFromRight;
-webkit-animation-direction: reverse;
}
#keyframes slideFromRight {
0% {
transform: translateX(100%);
}
100% {
transform: translateX(0);
}
}
#keyframes slideFromLeft {
0% {
transform: translateX(-100%);
}
100% {
transform: translateX(0);
}
}
#-webkit-keyframes slideFromRight {
0% {
-webkit-transform: translateX(100%);
}
100% {
-webkit-transform: translateX(0);
}
}
#-webkit-keyframes slideFromLeft {
0% {
-webkit-transform: translateX(-100%);
}
100% {
-webkit-transform: translateX(0);
}
}
As seen, however, the second one doesn't behave as the first one, WHEN slide direction has changed.
For instance:
I slide to left the first one --> second slide loads with the correct animation
Then, I slide to right the second one --> it is supposed the first slide to start appearance from the left side, while the second one to start disappearance to to the right side. Instead, as you may see, the second one start to disappear to the left and from the right side a white slide is shown. At some point, the first slide starts its appearance from the middle of the content.
Please note, I deliberately delay the animations on the second example, just to see the undesired side effect mode clearly.
Actually, after a few more research hours, I found where the problem was buried - it seems, I have to move scope variable change for the next tick, to give time ng-class change to make its "magic".
Long story short - adding the following is what made the thing work:
$timeout(() => {
$scope.slide = $scope.slides[indexSelected];
}, 0)
Here is the updated example and the code snippet below:
JS code
(function(angular) {
'use strict';
angular.module('switchExample', ['ngMaterial', 'ngAnimate'])
.controller('ExampleController', ['$scope', '$timeout', function($scope, $timeout) {
$scope.slides = [
{ index: 0, name: 'first' },
{ index: 1, name: 'second' },
{ index: 2, name: 'third' },
{ index: 3, name: 'fourth' }
];
$scope.selectPage = selectPage;
/**
* Initialize with the first page opened
*/
$scope.slide = $scope.slides[0];
$scope.prev = () => {
if ($scope.slide.index > 0) {
selectPage($scope.slide.index - 1);
}
}
$scope.next = () => {
if ($scope.slide.index < 3) {
selectPage($scope.slide.index + 1);
}
}
/**
* #name selectPage
* #desc The function that includes the page of the indexSelected
* #param indexSelected the index of the page to be included
*/
function selectPage(indexSelected) {
if ($scope.slides[indexSelected].index > $scope.slide.index) {
$scope.mtl = false;
} else {
$scope.mtl = true;
}
// this will move a scope variable change to the next tick,
// hence will give time $scope.mtl to be handled by ng-class
$timeout(() => {
$scope.slide = $scope.slides[indexSelected];
}, 0)
}
}]);
})(window.angular);

How to loop an animation for multiple appended divs?

I made a div wich I animate with jquery.
The loop goes like this: to the right, then down, to the left, and down again.
When the start button is pressed, the first div starts the animation loop. The next div is appended at a random interval, same for the next one etc.
BUT when a second div is appended, the whole animation loop goes nuts.
What I'm trying to accomplish:
If a second div is appended, the first one should just complete it's animtion loop.
And the second one and the ones after that also complete their loop.
Can you help me with this? Should I add counters for the classes or something?
(By the way I disabled the random appending code in this jsfiddle, so you can see the right animation loop first. Please enable to see the crazy effect)
Demo
HTML
<div id="arena">
<div id="start">start</div>
</div>
jQuery
var counter = 0;
$("#start").on('click', function () {
$("#arena").append('<div class="b"></div>');
bbLoop();
$("#start").hide();
});
function bbLoop() {
bbRight();
}
function bbLeft() {
$(".b").animate({
left: "-=300"
}, 1500, "swing", bbLeftDown);
}
function bbRight() {
$(".b").animate({
left: "+=300"
}, 1500, "swing", bbRightDown);
}
function bbLeftDown() {
$(".b").animate({
bottom: "-=30"
}, 300, "swing", bbRight);
}
function bbRightDown() {
$(".b").animate({
bottom: "-=30"
}, 300, "swing", bbLeft);
}
/*
function doSomething() {}
(function loop() {
var rand = Math.round(Math.random() * (3000 - 500)) + 500;
setTimeout(function () {
doSomething();
$("#arena").append('<div class="b"></div>');
loop();
}, rand);
}());
*/
Try this
It makes use of passing the same object through each function so that the appended elements can be animated separately from the first
$("#start").on('click', function () {
$("#arena").append('<div class="b"></div>');
bbLoop($('.b:eq(0)'));
$("#start").hide();
(function loop() {
var rand = Math.round(Math.random() * (3000 - 500)) + 500;
setTimeout(function () {
var elem = $('<div class="b"></div>');
$("#arena").append(elem);
bbRight(elem);
doSomething();
loop();
}, rand);
}());
});
function bbLoop(obj) {
bbRight(obj);
}
function bbLeft(obj) {
obj.animate({
left: "-=300"
}, 1500, "swing", bbLeftDown(obj));
}
function bbRight(obj) {
obj.animate({
left: "+=300"
}, 1500, "swing", function() { bbRightDown(obj) });
}
function bbLeftDown(obj) {
obj.animate({
top: "+=300"
}, 300, "swing");
}
function bbRightDown(obj) {
obj.animate({
top: "+=300"
}, 300, "swing", bbLeft(obj));
}
function doSomething() {}
Or if you want them removed at the end, check here. .animate works in quirky ways sometimes, thus the approximation of the end animation time in the setTimeout is necessary

Can not export renderer text using highcharts/highstock when click range selector

I have a question related the chart export.
Please see Jsfiddle here
I added a text label using chart.renderer.text on the Yaxis for the latest value of series.
If I directly click button "Export Image". There is no problem, the label can be displayed. I'm using the following way to export image. draw_labels() is a function to draw yaxis label.
$("#b").click(function () {
chart.exportChart(null, {
chart: {
backgroundColor: '#FFFFFF',
width: 972,
height: 480,
events: {
load: function () {
draw_labels(this);
}
}
}
});
});
The problem is after I clicked range selector or change Xaxis range. When I try to export the
chart to image, there is no labels are drawn. The following is the complete code.
The following is the complete code:
$(function () {
var chart;
$.getJSON('http://www.highcharts.com/samples/data/jsonp.php?filename=aapl-c.json&callback=?', function (data) {
chart = new Highcharts.StockChart({
chart: {
renderTo: 'container',
events: {
load: function () {
draw_labels(this);
$("#b").click(function () {
chart.exportChart(null, {
chart: {
backgroundColor: '#FFFFFF',
width: 972,
height: 480,
events: {
load: function () {
draw_labels(this);
}
}
}
});
});
}
}
},
series: [{
name: 'AAPL',
id: 'test',
data: data,
tooltip: {
valueDecimals: 2
}
}],
navigator: {
enabled: false
},
yAxis: {
tickWidth: 0,
id: 'value_axis',
type: 'linear',
gridLineColor: '#EEE',
lineColor: '#D0CDC9',
lineWidth: 0,
minorTickInterval: null,
opposite: true,
offset: 0
},
xAxis: {
events: {
afterSetExtremes: function (e) {
console.log('test');
$('[id="test_text"]').remove();
draw_labels(chart);
}
}
}
});
});
function draw_labels(chart) {
$(chart.series).each(function (i, serie) {
var s_id = serie.options.id;
var temp_id = s_id;
var point = serie.points[serie.points.length - 1];
if (point) {
var pre, post;
if (point.y) {
var last_value_dis = (point.y).toFixed(1);
yaxis_name = 'value_axis';
//Get Yaxis position
var y_axis = chart.get(yaxis_name);
offsite_yaxis = 0;
element_text = chart.renderer.text(
//the text to render
'<span style="font-size:10px;font-weight:bold;color:' + serie.color + ';">' + last_value_dis + '</span>',
//the 'x' position
y_axis.width + y_axis.offset,
//the 'y' position
chart.plotTop + point.plotY + 3).attr({
id: temp_id + '_text',
zIndex: 999
}).add();
}
}
});
}
});
Here, I have fixed it for you. Here is a saved image:
Following changes have been done:
Added a redraw event to your exportchart
redraw: function () {
$("#test_text").remove() ;
draw_labels(this);
}
Changed this line in afterSetExtremes
$('[id="test_text"]').remove();
to
$("#test_text").remove() ;
Earlier one was not working as expected, so I had to change it.
Problem with disappearing text is related with id, when I removed it, label appears. But then I came across second issue, wrong y position. So i declare global variable, then when you call your function, set position of label, and use in chart exporting this variable. As a result label is exported correct.
http://jsfiddle.net/UGbpJ/11/

Resources