DEPRECATED: SnapFoo Demo - Animating a Loop
How do I make an deprecated: snapfoo demo - animating a loop?
An example demo animating an element loop utilizing the SnapFoo library for SVG animation.. What is a deprecated: snapfoo demo - animating a loop? How do you make a deprecated: snapfoo demo - animating a loop? This script and codes were developed by Daniel Yuschick on 25 September 2022, Sunday.
DEPRECATED: SnapFoo Demo - Animating a Loop - Script Codes HTML Codes
<!DOCTYPE html>
<html >
<head> <meta charset="UTF-8"> <title>DEPRECATED: SnapFoo Demo - Animating a Loop</title> <link rel='stylesheet prefetch' href='http://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css'> <link rel="stylesheet" href="css/style.css">
</head>
<body> <div class="container-fluid"> <section class="row content docs"> <div class="row container"> <div class="row docs-container"> <div class="col-md-12 docs-details"> <section id="examples-animate-loop" class="docs-section"> <h3>Animate a Loop</h3> <p>This example demonstrates looping an animation that rotates an element while changing its points. Additionally, it utilizes the <span class="heavy">keyframeDelay</span> value.</p> <pre class="prettyprint"><code>var snapfoo = snapFoo("#loop-animation");
var theValues = { keyframes: [ { values: {transform: "r90,250,75", points: "286.99,111.99 250.426,75 213.01,111.99 249.405,74.467 213.01,38.01 249.405,75 286.99,38.01 286.99,73.958"}, duration: 1000 }, { values: {transform: "r180,250,75", points: "286.99,111.99 250.426,111.99 213.01,111.99 249.405,74.467 213.01,38.01 249.405,75 286.99,38.01 286.99,73.958"}, duration: 1000 }, { values: {transform: "r270,250,75", points: "286.99,111.99 250.426,111.99 213.01,111.99 213.01,74.467 213.01,38.01 249.405,75 286.99,38.01 286.99,73.958"}, duration: 1000 }, { values: {transform: "r360,250,75", points: "286.99,111.99 250.426,111.99 213.01,111.99 213.01,74.467 213.01,38.01 249.405,38.01 286.99,38.01 286.99,73.958"}, duration: 1000 }, { values: {transform: "r0,250,75", points: "286.99,111.99 250.426,75 213.01,111.99 249.405,74.467 213.01,38.01 249.405,75 286.99,38.01 249.405,73.958"}, duration: 1000, easing: mina.backout, options: {keyframeDelay: 500}} ], loop: true
};
snapfoo.animate("#theShape", theValues);</code></pre> <svg version="1.1" id="loop-animation" x="0px" y="0px" viewBox="0 0 500 150" enable-background="new 0 0 500 150"> <polygon id="theShape" fill="#E76026" stroke="#333333" stroke-miterlimit="10" points="286.99,111.99 250.426,75 213.01,111.99 249.405,74.467 213.01,38.01 249.405,75 286.99,38.01 249.405,73.958" /> </svg> </section> </div> </div> </div> </section> <header class="row"> <div class="container"> <div class="col-md-12"> <a href="https://github.com/yuschick/SnapFoo" title="SnapFoo - Home" target="_blank"><img src="https://yuschick.github.io/SnapFoo/lib/img/snapfoo-logo.png" class="the-logo" alt="SnapFoo - SVG Animation Library" /></a> </div> </div> </header>
</div>
<script src="https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js"></script> <script src='http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js'></script>
<script src='http://cdnjs.cloudflare.com/ajax/libs/snap.svg/0.3.0/snap.svg-min.js'></script> <script src="js/index.js"></script>
</body>
</html>
DEPRECATED: SnapFoo Demo - Animating a Loop - Script Codes CSS Codes
@import url(https://fonts.googleapis.com/css?family=Hind:300,600,400);
.light { font-family: 'Hind', sans-serif !important; font-weight: 300 !important;
}
.heavy { font-family: 'Hind', sans-serif !important; font-weight: 600 !important;
}
.container { max-width: 1080px; margin: 0 auto;
}
.container-fluid { padding: 0;
}
header { background: #fff; padding: 25px;
}
header .the-logo { float: left; width: 208px; height: auto; border: 0;
}
header .header-button-container { float: right;
}
header .header-button-container .button { float: left; border: 1px solid #e86025; color: #e86025; text-align: center; margin: 20px 10px;
}
header .header-button-container .button a, header .header-button-container .button a:active, header .header-button-container .button a:visited, header .header-button-container .button a:hover { text-decoration: none; color: #e86025; font-weight: 600; display: block; width: 100%; padding: 10px; background: #fff; -webkit-transition: background 0.15s, color 0.15s; -moz-transition: background 0.15s, color 0.15s; transition: background 0.15s, color 0.15s;
}
header .header-button-container .button a:hover { background: #e86025; color: #fff;
}
.banner { background: url(../img/background-banner.jpg) #e86025; background-size: 100%; height: 300px; display: block; overflow: hidden;
}
.banner .container .text-container h1 { font: 90px/125px 'Hind', sans-serif; font-weight: 600; color: #414042; margin-top: 25px;
}
.banner .container .text-container p { font: 24px/35px 'Hind', sans-serif; color: #333;
}
.banner .container .hiya { width: 100%; height: auto; border: 0; margin: 20px 0;
}
.content { display: block;
}
.content .docs-container { padding: 0 10px;
}
.content .docs-container .docs-tree li li { margin: 0 15px;
}
.content .docs-container .docs-tree a, .content .docs-container .docs-tree a:active, .content .docs-container .docs-tree a:visited { display: block; text-decoration: none; color: #333; background: #fff; padding: 4px 0; -webkit-transition: background 0.15s; -moz-transition: background 0.15s; transition: background 0.15s;
}
.content .docs-container .docs-tree a:hover { background: #f3f3f3;
}
.content .docs-container .docs-details { overflow: hidden; padding: 0 15px;
}
.content .docs-container .docs-details a, .content .docs-container .docs-details a:active, .content .docs-container .docs-details a:visited, .content .docs-container .docs-details a:hover { text-decoration: none; color: #e86025;
}
.content .docs-container .docs-details a.return, .content .docs-container .docs-details a.return:active, .content .docs-container .docs-details a.return:visited, .content .docs-container .docs-details a.return:hover { display: block; text-align: right; text-decoration: none; color: #e86025;
}
.content .docs-container .docs-details .docs-section { padding: 15px 0;
}
.content .docs-container .docs-details .docs-section h3 { color: #e86025; font: 24px/30px 'Hind', sans-serif; font-weight: 600;
}
.content .docs-container .docs-details .docs-section p { margin: 5px 0; color: #333; font: 16px/22px 'Hind', sans-serif;
}
.content .docs-container .docs-details .docs-section li li { margin: 4px 15px;
}
pre code { overflow-x: auto; overflow-y: hidden; display: block; white-space: pre; word-wrap: normal; padding: 10px;
}
.pln { max-height: 1px;
}
.section-header { width: 100%; display: block; padding: 10px 0 3px 0; background: #e86025;
}
.section-header h2 { font: 35px/42px 'Hind', sans-serif; font-weight: 300; color: #fff; text-transform: uppercase;
}
footer { width: 100%; display: block; padding: 10px 0; background: #e86025; overflow: hidden;
}
footer .the-logo { float: left; width: 150px; height: auto; border: 0;
}
footer .footer-button-container { float: right;
}
footer .footer-button-container .button { float: left; border: 1px solid #fff; color: #fff; text-align: center; margin: 10px 10px;
}
footer .footer-button-container .button a, footer .footer-button-container .button a:active, footer .footer-button-container .button a:visited, footer .footer-button-container .button a:hover { text-decoration: none; color: #fff; font-weight: 600; display: block; width: 100%; padding: 5px; background: #e86025; -webkit-transition: background 0.15s, color 0.15s; -moz-transition: background 0.15s, color 0.15s; transition: background 0.15s, color 0.15s;
}
footer .footer-button-container .button a:hover { background: #fff; color: #e86025;
}
DEPRECATED: SnapFoo Demo - Animating a Loop - Script Codes JS Codes
function snapFoo(theSVGContainerID) { "use strict"; var theLoopIntervalIDs = [], thePathLoopIntervalIDs = [], theAnimatingElementsObj = {}; var theIntervalFunctions = { storeIntervalID: function(theID) { /** * Store an interval ID for later use * @param {Number} theID */ theLoopIntervalIDs.push(theID); }, clearIntervalIDs: { /** * Clear loop intervals */ all: function() { var i = 0; while (i < theLoopIntervalIDs.length) { clearInterval(theLoopIntervalIDs[i]); i++ } while (i < thePathLoopIntervalIDs.length) { clearInterval(thePathLoopIntervalIDs[i]); i++ } thePathLoopIntervalIDs = []; theLoopIntervalIDs = []; }, sequences: function() { while (i < theLoopIntervalIDs.length) { clearInterval(theLoopIntervalIDs[i]); i++ } theLoopIntervalIDs = []; }, paths: function() { while (i < thePathLoopIntervalIDs.length) { clearInterval(thePathLoopIntervalIDs[i]); i++ } thePathLoopIntervalIDs = []; } }, clearSpecificInterval: function(theID) { /** * Clear a specific loop interval */ clearInterval(theID); } }, theAnimationFunctions = { stop: { sectionAnimations: function(theSVGContainerID) { /** * Stop all animations inside the provided section SVG container * @param {String} theSVGContainerID */ var s = Snap.select(theSVGContainerID), theElements = s.selectAll("image", "g", "ellipse", "rect", "path", "line"); theIntervalFunctions.clearIntervalIDs(); theElements.forEach(function(el) { el.stop(); }); }, specificAnimation: function(theElement) { /** * Stop a specific Snap animation * @param {String} theElement */ var theParentSVG = "#" + $(theElement).parents("svg").attr("id"), s = Snap.select(theParentSVG), theElements = s.selectAll(theElement); theElements.forEach(function(el) { el.stop(); }); } }, setSVGElementAttrWithSnap: function(theElement, theAttrValues) { /** * Set a Snap element's attributes * @param {String} theElement * @param {Object} theAttrValues */ var s = Snap.select(theSVGContainerID), theSVGElement = s.select(theElement); theSVGElement.attr(theAttrValues); }, animateSingleSVGElementWithSnap: function(theElement, theAnimationValues, theDuration, theEasing, theDelay, theCallback) { /** * Performs an animation of one element in one direction * @param {String} theElement * @param {Object} theAnimationValues * @param {Number} theDuration * @param {Function} theEasing * @param {Number} theDelay * @param {Object} theCallback */ theEasing = theEasing || mina.linear; theDelay = theDelay || 0; theCallback = theCallback || null; var s = Snap.select(theSVGContainerID), theSVGElement = s.select(theElement); setTimeout(function() { theSVGElement.stop().animate(theAnimationValues, theDuration, theEasing, function() { if (theCallback) { if (typeof theCallback === "function") { theCallback(); } else { for (var key in theCallback) { theCallback[key](); } } } }); }, theDelay); if (theElement in theAnimatingElementsObj) { theAnimatingElementsObj[theElement].frameProgress++; if (theAnimatingElementsObj[theElement].frameProgress >= theAnimatingElementsObj[theElement].totalFrames) { if (theAnimatingElementsObj[theElement].doLoop) { theAnimatingElementsObj[theElement].frameProgress = 0; theAnimatingElementsObj[theElement].loopsCompleted++; } } } }, animateSequence: function(theElement, theAnimationValues, thePassedFrame) { /** * Receives an array of animation values and sends them in sequence to animateGroupOfSVGElementsWithSnap * @param {String} theElement * @param {Object} theAnimationValuesArray{keyframes[ values, duration, easing, options { keyframeCallback, keyframeDelay }], stagger, animationDelay, animationCallback, loop, loopCount} * @param {Number} theCurrentFrame * */ var theCurrentFrame = thePassedFrame || 0, doLoop = theAnimationValues.loop || false, totalLoops = theAnimationValues.loopCount || 0, theStagger = theAnimationValues.stagger || 0, theAnimationDelay = theAnimationValues.animationDelay || 0, theAnimationCallback = theAnimationValues.animationCallback || null; if (theCurrentFrame >= theAnimationValues.keyframes.length) { if (doLoop) { if (totalLoops > 0) { if (theAnimatingElementsObj[theElement].loopsCompleted < totalLoops) { theAnimationFunctions.animateSequence(theElement, theAnimationValues, 0); } else { if ((theElement in theAnimatingElementsObj)) { delete theAnimatingElementsObj[theElement]; } return } } else { theAnimationFunctions.animateSequence(theElement, theAnimationValues, 0) } } else { if (theAnimationCallback) { theAnimationCallback(); } if ((theElement in theAnimatingElementsObj)) { delete theAnimatingElementsObj[theElement]; } return } } else { var theKeyframeOptions = theAnimationValues.keyframes[theCurrentFrame].options || {}, theKeyframeValues = theAnimationValues.keyframes[theCurrentFrame].values, theKeyframeDuration = theAnimationValues.keyframes[theCurrentFrame].duration, theKeyframeEasing = theAnimationValues.keyframes[theCurrentFrame].easing || mina.linear, theKeyframeDelay = theKeyframeOptions.keyframeDelay || 0, theKeyframeCallback = theKeyframeOptions.keyframeCallback || null; if (theCurrentFrame == 0 && doLoop && totalLoops != 0 && theAnimatingElementsObj[theElement] == undefined) { theAnimatingElementsObj[theElement] = {}; theAnimatingElementsObj[theElement].loopsCompleted = 0; } if (theCurrentFrame > 0) { theAnimationDelay = 0; } setTimeout(function() { var i = 0; $(theElement).each(function() { if ($(this).parents(theSVGContainerID).length) { if (!$(this).is('[class^="sf"]')) { var theCurrentClass = $(this).attr("class"), theIdentifier = "sf" + i + " " + theCurrentClass; $(this).attr("class", theIdentifier); } else { var theIdentifier = $(this).attr("class"); } theIdentifier = "." + theIdentifier.replace(" ", "."); if (theKeyframeOptions.keyframeCallback) { theKeyframeCallback = { custom: theKeyframeOptions.keyframeCallback, default: theAnimationFunctions.animateSequence.bind(null, theIdentifier, theAnimationValues, theCurrentFrame + 1) }; } else { theKeyframeCallback = { default: theAnimationFunctions.animateSequence.bind(null, theIdentifier, theAnimationValues, theCurrentFrame + 1) } } if (!(theIdentifier in theAnimatingElementsObj)) { theAnimatingElementsObj[theIdentifier] = { frameProgress: 0, totalFrames: theAnimationValues.keyframes.length, values: {}, doLoop: doLoop, loopsCompleted: 0, totalLoops: totalLoops }; } if (theCurrentFrame == theAnimatingElementsObj[theIdentifier].frameProgress) { theAnimationFunctions.animateSingleSVGElementWithSnap(theIdentifier, theKeyframeValues, theKeyframeDuration, theKeyframeEasing, ((theStagger * i) + theKeyframeDelay), theKeyframeCallback); } i++; } }); }, theAnimationDelay); } }, animateSVGElementAlongPath: function(theElement, thePath, theDuration, theEasing, theDelay, theCallback, reversePathDirection, reverseAtEnd, theReverseSettings) { /** * Animates an element along a path * @param {String} theElement * @param {String} thePath * @param {Number} theDuration * @param {function} theEasing * @param {Number} theDelay * @param {Function} theCallback * @param {Boolean} reversePathDirection * @param {Boolean} reverseAtEnd * @param {Object} theReverseSettings */ var s = Snap.select(theSVGContainerID), theSnapElement = s.select(theElement), theSnapPath = s.select(thePath), theLength = theSnapPath.getTotalLength(), thisBox = theSnapElement.getBBox(), curX = thisBox.x + (thisBox.width / 2), curY = thisBox.y + (thisBox.height / 2), theMovePoint, reversePathDirection = reversePathDirection || false, reverseAtEnd = reverseAtEnd || false, theStartPoint = 0, theEndPoint = theLength; if (reversePathDirection) { theStartPoint = theLength; theEndPoint = 0; } setTimeout(function() { Snap.animate(theStartPoint, theEndPoint, function(value) { theMovePoint = theSnapPath.getPointAtLength(value); theSnapElement.attr({ transform: "t" + (theMovePoint.x - curX) + "," + (theMovePoint.y - curY) }); }, theDuration, theEasing, function() { if (theCallback) { theCallback(); } if (reverseAtEnd) { setTimeout(function() { Snap.animate(theEndPoint, theStartPoint, function(value) { theMovePoint = theSnapPath.getPointAtLength(value); theSnapElement.attr({ transform: "t" + (theMovePoint.x - curX) + "," + (theMovePoint.y - curY) }); }, theReverseSettings.duration, theReverseSettings.easing, function() { if (theReverseSettings.callback) { theReverseSettings.callback(); } if ((theElement in theAnimatingElementsObj)) { theAnimatingElementsObj[theElement].loopsCompleted++; if (theAnimatingElementsObj[theElement].totalLoops > 0 && theAnimatingElementsObj[theElement].loopsCompleted == theAnimatingElementsObj[theElement].totalLoops - 1) { theIntervalFunctions.clearSpecificInterval(theAnimatingElementsObj[theElement].intervalID); theAnimationFunctions.stop.specificAnimation(theElement); } } }); }, theReverseSettings.delay); } else { if ((theElement in theAnimatingElementsObj)) { theAnimatingElementsObj[theElement].loopsCompleted++; if (theAnimatingElementsObj[theElement].totalLoops > 0 && theAnimatingElementsObj[theElement].loopsCompleted >= theAnimatingElementsObj[theElement].totalLoops - 1) { theIntervalFunctions.clearSpecificInterval(theAnimatingElementsObj[theElement].intervalID); theAnimationFunctions.stop.specificAnimation(theElement); } } } }); }, theDelay); }, animateAlongAPath: function(theElement, thePath, theDuration, thePathOptions) { /** * Animate an element along a path. * * @param {String} theElement * @param {String} thePath * @param {Number} theDuration * @param {Object} theOptions * @param {Function} theOptions.easing * @param {Function} theOptions.reverseAtEnd * @param {Number} theOptions.stagger * @param {Number} theOptions.delay * @param {Function} theOptions.callback * @param {Boolean} theOptions.reversePathDirection * @param {Boolean} theOptions.loop * @param {Object} theOptions.loopOptions * @param {Number} theOptions.loopOptions.loopCount * @param {Number} theOptions.reverseOptions * @param {Number} theOptions.reverseOptions.duration * @param {Function} theOptions.reverseOptions.easing * @param {Function} theOptions.reverseOptions.callback * @param {Number} theOptions.reverseOptions.delay */ var theOptions = thePathOptions || {}, theEasing = theOptions.easing || mina.linear, theStagger = theOptions.stagger || 0, theDelay = theOptions.delay || 0, theCallback = theOptions.callback || null, reversePathDirection = theOptions.reversePathDirection || false, reverseAtEnd = theOptions.reverseAtEnd || false, doLoop = theOptions.loop || false, theLoopOptions = theOptions.loopOptions || {}, theReverseOptions = theOptions.reverseOptions || {}, theLoopCount = theLoopOptions.loopCount || 0, theLoopIntervalTime = theDuration, loopReverseDuration = theReverseOptions.duration || theDuration, loopReverseEasing = theReverseOptions.easing || mina.linear, loopReverseCallback = theReverseOptions.callback || null, loopReverseDelay = theReverseOptions.delay || 0; var theReverseSettings = { delay: loopReverseDelay, easing: loopReverseEasing, duration: loopReverseDuration, callback: loopReverseCallback }; setTimeout(function() { var i = 0; $(theElement).each(function() { if ($(this).parents(theSVGContainerID).length) { if (!$(this).is('[class^="sf"]')) { var theCurrentClass = $(this).attr("class"), theIdentifier = "sf" + i + " " + theCurrentClass; $(this).attr("class", theIdentifier); } else { theIdentifier = $(this).attr("class"); } theIdentifier = "." + theIdentifier.replace(" ", "."); if (!(theIdentifier in theAnimatingElementsObj)) { theAnimatingElementsObj[theIdentifier] = { loopsCompleted: 0, totalLoops: theLoopCount, intervalID: 0, theDelay: (theStagger * i) }; i++; } theAnimationFunctions.animateSVGElementAlongPath(theIdentifier, thePath, theDuration, theEasing, theAnimatingElementsObj[theIdentifier].theDelay, theCallback, reversePathDirection, reverseAtEnd, theReverseSettings); if (doLoop) { if (reverseAtEnd) { theLoopIntervalTime = theDuration * 2 + theReverseSettings.delay; } thePathLoopIntervalIDs = setInterval(function() { setTimeout(function() { theAnimationFunctions.setSVGElementAttrWithSnap(theIdentifier, { transform: "t0,0" }); theAnimationFunctions.animateSVGElementAlongPath(theIdentifier, thePath, theDuration, theEasing, 0, theCallback, reversePathDirection, reverseAtEnd, theReverseSettings); }, theAnimatingElementsObj[theIdentifier].theDelay); }, theLoopIntervalTime); theIntervalFunctions.storeIntervalID(thePathLoopIntervalIDs); theAnimatingElementsObj[theIdentifier].intervalID = thePathLoopIntervalIDs; } } }); }, theDelay); } }; return { stop: theAnimationFunctions.stop, clear: theIntervalFunctions.clearIntervalIDs, set: theAnimationFunctions.setSVGElementAttrWithSnap, animate: theAnimationFunctions.animateSequence, animatePath: theAnimationFunctions.animateAlongAPath }
}
$(document).ready(function() { var snapfoo = snapFoo("#loop-animation"); var theValues = { keyframes: [{ values: { transform: "r90,250,75", points: "286.99,111.99 250.426,75 213.01,111.99 249.405,74.467 213.01,38.01 249.405,75 286.99,38.01 286.99,73.958" }, duration: 1000 }, { values: { transform: "r180,250,75", points: "286.99,111.99 250.426,111.99 213.01,111.99 249.405,74.467 213.01,38.01 249.405,75 286.99,38.01 286.99,73.958" }, duration: 1000 }, { values: { transform: "r270,250,75", points: "286.99,111.99 250.426,111.99 213.01,111.99 213.01,74.467 213.01,38.01 249.405,75 286.99,38.01 286.99,73.958" }, duration: 1000 }, { values: { transform: "r360,250,75", points: "286.99,111.99 250.426,111.99 213.01,111.99 213.01,74.467 213.01,38.01 249.405,38.01 286.99,38.01 286.99,73.958" }, duration: 1000 }, { values: { transform: "r0,250,75", points: "286.99,111.99 250.426,75 213.01,111.99 249.405,74.467 213.01,38.01 249.405,75 286.99,38.01 249.405,73.958" }, duration: 1000, easing: mina.backout, options: { keyframeDelay: 500 } }], loop: true }; snapfoo.animate("#theShape", theValues);
});
Developer | Daniel Yuschick |
Username | Yuschick |
Uploaded | September 25, 2022 |
Rating | 3 |
Size | 7,618 Kb |
Views | 14,168 |
Find the perfect freelance services for your business! Fiverr's mission is to change how the world works together. Fiverr connects businesses with freelancers offering digital services in 500+ categories. Find Developer!
Name | Size |
IBM PureSystems - PureApp Emulator | 10,595 Kb |
Ripples on the Water - Website Design | 6,101 Kb |
Archer Pirate Virus - Snap SVG Demo | 7,089 Kb |
Flat Surface Shader Earth | 2,075 Kb |
Perrelet Turbine in SVGs | 6,576 Kb |
Pac Manufacturing Ghost Generator | 7,435 Kb |
Responsive Diamond Navigation | 11,560 Kb |
Interactive HTML5 Video Demo | 8,227 Kb |
SnapFoo v2 Demo - Loop a Group of Elements Along a Path | 7,083 Kb |
Jasper is the AI Content Generator that helps you and your team break through creative blocks to create amazing, original content 10X faster. Discover all the ways the Jasper AI Content Platform can help streamline your creative workflows. Start For Free!
Name | Username | Size |
AngularJS Animated Todo List | Ehaase | 2,975 Kb |
Fluid Layout with Float | Jxqr97 | 1,785 Kb |
Hover Animation from UNIQLO | Insprd | 3,772 Kb |
CSS Gem Badge | Orchard | 3,335 Kb |
Pictos font library from CodePen | Jstam | 3,790 Kb |
Savemedia1.1 | EdsonAlcala | 2,148 Kb |
Two joint circles - One element | Berdejitendra | 1,704 Kb |
Highbrow Basic HTML Lesson 8 | Kimlarocca | 2,094 Kb |
Revolving Text Landing Page Trial | TimRuby | 2,976 Kb |
CSS Org Chart | Appirio-ux | 3,882 Kb |
Surf anonymously, prevent hackers from acquiring your IP address, send anonymous email, and encrypt your Internet connection. High speed, ultra secure, and easy to use. Instant setup. Hide Your IP Now!