HTML preprocessors can make writing HTML more powerful or convenient. For instance, Markdown is designed to be easier to write and read for text documents and you could write a loop in Pug.
In CodePen, whatever you write in the HTML editor is what goes within the <body>
tags in a basic HTML5 template. So you don't have access to higher-up elements like the <html>
tag. If you want to add classes there that can affect the whole document, this is the place to do it.
In CodePen, whatever you write in the HTML editor is what goes within the <body>
tags in a basic HTML5 template. If you need things in the <head>
of the document, put that code here.
The resource you are linking to is using the 'http' protocol, which may not work when the browser is using https.
CSS preprocessors help make authoring CSS easier. All of them offer things like variables and mixins to provide convenient abstractions.
It's a common practice to apply CSS to a page that styles elements such that they are consistent across all browsers. We offer two of the most popular choices: normalize.css and a reset. Or, choose Neither and nothing will be applied.
To get the best cross-browser support, it is a common practice to apply vendor prefixes to CSS properties and values that require them to work. For instance -webkit-
or -moz-
.
We offer two popular choices: Autoprefixer (which processes your CSS server-side) and -prefix-free (which applies prefixes via a script, client-side).
Any URLs added here will be added as <link>
s in order, and before the CSS in the editor. You can use the CSS from another Pen by using its URL and the proper URL extension.
You can apply CSS to your Pen from any stylesheet on the web. Just put a URL to it here and we'll apply it, in the order you have them, before the CSS in the Pen itself.
You can also link to another Pen here (use the .css
URL Extension) and we'll pull the CSS from that Pen and include it. If it's using a matching preprocessor, use the appropriate URL Extension and we'll combine the code before preprocessing, so you can use the linked Pen as a true dependency.
JavaScript preprocessors can help make authoring JavaScript easier and more convenient.
Babel includes JSX processing.
Any URL's added here will be added as <script>
s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.
You can apply a script from anywhere on the web to your Pen. Just put a URL to it here and we'll add it, in the order you have them, before the JavaScript in the Pen itself.
If the script you link to has the file extension of a preprocessor, we'll attempt to process it before applying.
You can also link to another Pen here, and we'll pull the JavaScript from that Pen and include it. If it's using a matching preprocessor, we'll combine the code before preprocessing, so you can use the linked Pen as a true dependency.
Search for and use JavaScript packages from npm here. By selecting a package, an import
statement will be added to the top of the JavaScript editor for this package.
Using packages here is powered by esm.sh, which makes packages from npm not only available on a CDN, but prepares them for native JavaScript ESM usage.
All packages are different, so refer to their docs for how they work.
If you're using React / ReactDOM, make sure to turn on Babel for the JSX processing.
If active, Pens will autosave every 30 seconds after being saved once.
If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.
If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.
Visit your global Editor Settings.
<div class="slider-wrapper">
<div class="rotatescroll" id="rotatescroll">
<div class="viewport">
<ul class="overview">
<li>
<a href="http://www.baijs.com"><img src="https://lh3.googleusercontent.com/-qYs3ZOJX-xg/VcoW14eR7uI/AAAAAAAADII/yAy7HLAr-ds/s800-Ic42/Southend-on-Sea-England_350x350.jpg" alt="" /></a>
</li>
<li>
<a href="http://www.baijs.com"><img src="https://lh3.googleusercontent.com/-vZR6Rjpv3Uw/VcoW01PFRiI/AAAAAAAADII/F4N3YtK0mTA/s800-Ic42/Kylemore_County-Galway_Ireland_350x350.jpg" alt="" /></a>
</li>
<li>
<a href="http://www.baijs.com"><img src="https://lh3.googleusercontent.com/-6twGYRW9qec/VcoW1E5Fj2I/AAAAAAAADII/xzsBLnCTuIs/s800-Ic42/Kidwelly-Carmarthen-Wales_350x350.jpg" alt="" /></a>
</li>
<li>
<a href="http://www.baijs.com"><img src="https://lh3.googleusercontent.com/-TFeJJDYwyYw/VcoW1ATUTyI/AAAAAAAADII/GHVafrqce-c/s800-Ic42/Guernsey-coast-at-Gouffre_Channel-Islands_350x350.jpg" alt="" /></a>
</li>
<li>
<a href="http://www.baijs.com"><img src="https://lh3.googleusercontent.com/-87WIsl0qnqE/VcoW2euL1PI/AAAAAAAADII/FFnVShlNvCY/s800-Ic42/Vest-Agder_Lindesnes_350x350.jpg" alt="" /></a>
</li>
<li>
<a href="http://www.baijs.com"><img src="https://lh3.googleusercontent.com/-rcW7QNlhexM/VcoW1E9f5qI/AAAAAAAADII/zDpGAwGUuoE/s800-Ic42/Prins-Hendrikkade-Amsterdam-Holland_350x350.jpg" alt="" /></a>
</li>
<li>
<a href="http://www.baijs.com"><img src="https://lh3.googleusercontent.com/-MF0cIdb1OtY/VcoW23sXmHI/AAAAAAAADII/MFHcCy-vSOI/s800-Ic42/bridges-Meuse-Sambre-Namur-Belgium_350x350.jpg" alt="" /></a>
</li>
<li>
<a href="http://www.baijs.com"><img src="https://lh3.googleusercontent.com/-iamZ6JKpjJI/VcoW1SfQxyI/AAAAAAAADII/zTQU2uKVY6w/s800-Ic42/Sorrento-Naples-Italy_350x350.jpg" alt="" /></a>
</li>
</ul>
</div>
<!-- /.viewport -->
<div class="dot"></div>
<div class="overlay overlay-interaction" id="overlayInteraction"></div>
<div class="overlay overlay-static"></div>
<div class="overlay overlay-active" id="overlayActive"></div>
<div class="thumb"></div>
</div>
<!-- /.rotatescroll -->
</div>
<!-- /.slider-wrapper -->
*,
*:before,
*:after {
/* outline: 1px dotted salmon; */
box-sizing: inherit;
}
html,
body {
height: 100%;
background-color: #303634;
}
body {
font: 100%/1.5 AvenirNext-Medium, Corbel, "Segoe Ui", "Trebuchet Ms", sans-serif;
margin: 0;
box-sizing: border-box;
min-height: 100%;
overflow: hidden;
}
img {
border: 0;
max-width: 100%;
height: auto;
}
.slider-wrapper {
/* width: 390px; */
max-width: 24.375em;
margin: 2em auto 0;
}
.rotatescroll img {
vertical-align: middle;
border: 9px solid #26d9a0;
}
.rotatescroll img,
.rotatescroll .overview li {
border-radius: 50%;
}
/* Tiny Circleslider */
.rotatescroll {
position: relative;
height: 390px;
width: 390px;
padding: 40px;
overflow: hidden;
}
.rotatescroll .viewport {
/* width: 390px; */
height: 390px;
position: relative;
margin: 0 auto;
overflow: hidden;
pointer-events: none;
background-color: #26d9a0;
}
.rotatescroll .overview {
/* position: absolute; */
position: relative;
width: 798px;
list-style: none;
left: 0;
top: 0;
margin: -20px 0 0 -20px;
padding: 0;
z-index: 0;
}
.rotatescroll .overview li {
height: 342px;
width: 342px;
float: left;
position: relative;
padding: 15px;
margin: 4px 0 0 4px;
}
.rotatescroll .overlay {
pointer-events: none;
position: absolute;
left: 0;
top: 0;
height: 390px;
width: 390px;
/* standalone SVG: https://gist.github.com/atelierbram/2f7e675dc7d65acab65d#file-bg-scroll-active_390x390-svg */
background: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 390 390'%3E%3Cg%3E%3Cpath fill='rgb(48,54,52)' d='M195,0H0v195C0,87.305,87.305,0,195,0z'/%3E%3Cpath fill='rgb(48,54,52)' d='M195,390h195V195C390,302.696,302.695,390,195,390z'/%3E%3Cpath fill='rgb(48,54,52)' d='M0,195v195h195C87.305,390,0,302.696,0,195z'/%3E%3Cpath fill='rgb(48,54,52)' d='M195,0c107.695,0,195,87.305,195,195V0H195z'/%3E%3C/g%3E%3Cg%3E%3Cpath fill='rgb(64,191,151)' d='M195,0C87.304,0,0,87.305,0,195s87.304,195,195,195c107.695,0,195-87.305,195-195S302.695,0,195,0z M195,345c-82.926,0-150-67.074-150-150c0-82.925,67.074-150,150-150c82.926,0,150,67.075,150,150C345,277.926,277.926,345,195,345 z'/%3E%3C/g%3E%3Cg%3E%3Cpath fill='rgb(240,250,247)' d='M195,3C88.919,3,3,88.92,3,195s85.919,192,192,192c106.08,0,192-85.92,192-192S301.08,3,195,3z M195,345 c-82.926,0-150-67.074-150-150c0-82.925,67.074-150,150-150c82.926,0,150,67.075,150,150C345,277.926,277.926,345,195,345z'/%3E%3C/g%3E%3Cg%3E%3Cpath fill='rgb(38,217,160)' d='M195,43c-84.003,0-152,67.998-152,152c0,84.002,67.997,152,152,152c84.002,0,152-67.998,152-152 C347,110.998,279.002,43,195,43z M195,345c-82.926,0-150-67.074-150-150c0-82.925,67.074-150,150-150c82.926,0,150,67.075,150,150 C345,277.926,277.926,345,195,345z'/%3E%3C/g%3E%3Cg%3E%3Cpath fill='rgb(38,217,160)' d='M137.375,56.438C155.096,49.08,174.598,45,195,45s39.697,4.018,57.417,11.375l16.792-40.458 C246.524,6.489,221.106,1,195,1c-26.107,0-51.759,5.447-74.443,14.875L137.375,56.438z'/%3E%3C/g%3E%3C/svg%3E") 0 0 no-repeat;
}
.rotatescroll .overlay-interaction {
background: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 390 390'%3E%3Cg%3E%3Cpath fill='rgb(185,255,153)' d='M137.375,56.438C155.096,49.08,174.598,45,195,45s39.697,4.018,57.417,11.375l16.792-40.458 C246.524,6.489,221.106,1,195,1c-26.107,0-51.759,5.447-74.443,14.875L137.375,56.438z'/%3E%3C/g%3E%3C/svg%3E") 0 0 no-repeat;
z-index: 0;
}
.rotatescroll [class*="-hovered"] {
z-index: 1;
}
/* https://mathiasbynens.be/notes/css-escapes */
.rotatescroll .slideno\(1\),
.is-slide2-hovered {
transform: rotate(45deg);
}
.rotatescroll .slideno\(2\),
.is-slide3-hovered {
transform: rotate(90deg);
}
.rotatescroll .slideno\(3\),
.is-slide4-hovered {
transform: rotate(135deg);
}
.rotatescroll .slideno\(4\),
.is-slide5-hovered {
transform: rotate(135deg);
transform: rotate(180deg);
}
.rotatescroll .slideno\(5\),
.is-slide6-hovered {
transform: rotate(225deg);
}
.rotatescroll .slideno\(6\),
.is-slide7-hovered {
transform: rotate(270deg);
}
.rotatescroll .slideno\(7\),
.is-slide8-hovered {
transform: rotate(315deg);
}
.rotatescroll .thumb {
touch-action: none;
-ms-touch-action: none;
position: absolute;
top: -3px;
cursor: pointer;
/* left: 137px; */
left: 200px;
width: 24px;
height: 24px;
z-index: 200;
background: #fff;
border: 2px solid #40bf97;
border-radius: 50%;
}
.rotatescroll .dot {
left: inherit !important;
top: 0 !important;
z-index: 100;
text-align: center;
overflow: hidden;
position: absolute;
/* top: 0; */
right: 0;
width: 50%;
height: 50%;
transform-origin: 0% 100%;
}
.rotatescroll .dot span {
/* display: none; */
}
.rotatescroll .dot:after {
content: '';
position: absolute;
top: 2px;
left: 0;
border-left: 2px solid #40b590;
height: 42px;
/* display: table-cell; */
}
.rotatescroll .text {
padding-top: 20px;
}
.rotatescroll .flip.text {
padding-top: 30px;
}
.rotatescroll .flip.text span {
top: 5px;
}
.rotatescroll .active .flip.text span {
top: 18px !important;
}
.rotatescroll .active h1 div.text {
/* background-color: #26d9a0; */
color: #fff;
padding: 20px;
height: 8px !important;
text-shadow: 0 0 1px #303634,2px 1px 1px hsla(160, 6%, 20%,.5);
font-family: AvenirNext-DemiBold, Corbel, "Segoe Ui", "Trebuchet Ms", sans-serif;
}
.rotatescroll .active h1 div.text:hover {
color: #303634;
text-shadow: none;
}
.rotatescroll h1 span {
line-height: 0.65;
white-space: pre;
overflow: visible;
padding: 0px;
}
.rotatescroll .flip {
transform: rotate(180deg)
}
.rotatescroll .active {}
.rotatescroll .dot h1 {
position: absolute;
left: -100%;
width: 200%;
height: 200%;
transform: skewY(45deg) rotate(22.5deg);
margin: 0;
cursor: pointer;
text-align: center;
font-size: 12px;
line-height: 0;
font-weight: bold;
text-transform: uppercase;
color: #303634;
}
.rotatescroll .dot-1 {
transform: rotate(337.5deg) skewY(-45deg);
}
.rotatescroll .dot-2 {
transform: rotate(22.5deg) skewY(-45deg);
}
.rotatescroll .dot-3 {
transform: rotate(67.5deg) skewY(-45deg);
}
.rotatescroll .dot-4 {
transform: rotate(112.5deg) skewY(-45deg);
}
.rotatescroll .dot-5 {
transform: rotate(157.5deg) skewY(-45deg);
}
.rotatescroll .dot-6 {
transform: rotate(202.5deg) skewY(-45deg);
}
.rotatescroll .dot-7 {
transform: rotate(247.5deg) skewY(-45deg);
}
.rotatescroll .dot-8 {
transform: rotate(292.5deg) skewY(-45deg);
}
// Avoid `console` errors in browsers that lack a console.
(function() {
var method;
var noop = function() {};
var methods = [
'assert', 'clear', 'count', 'debug', 'dir', 'dirxml', 'error',
'exception', 'group', 'groupCollapsed', 'groupEnd', 'info', 'log',
'markTimeline', 'profile', 'profileEnd', 'table', 'time', 'timeEnd',
'timeStamp', 'trace', 'warn'
];
var length = methods.length;
var console = (window.console = window.console || {});
while (length--) {
method = methods[length];
// Only stub undefined methods.
if (!console[method]) {
console[method] = noop;
}
}
}());
// Place any jQuery/helper plugins in here.
/*global jQuery */
/*!
* Lettering.JS 0.6.1
*
* Copyright 2010, Dave Rupert http://daverupert.com
* Released under the WTFPL license
* http://sam.zoy.org/wtfpl/
*
* Thanks to Paul Irish - http://paulirish.com - for the feedback.
*
* Date: Mon Sep 20 17:14:00 2010 -0600
*/
(function($) {
function injector(t, splitter, klass, after) {
var text = t.text(),
a = text.split(splitter),
inject = '';
if (a.length) {
$(a).each(function(i, item) {
inject += '<span class="' + klass + (i + 1) + '" aria-hidden="true">' + item + '</span>' + after;
});
t.attr('aria-label', text)
.empty()
.append(inject)
}
}
var methods = {
init: function() {
return this.each(function() {
injector($(this), '', 'char', '');
});
},
words: function() {
return this.each(function() {
injector($(this), ' ', 'word', ' ');
});
},
lines: function() {
return this.each(function() {
var r = "eefec303079ad17405c889e092e105b0";
// Because it's hard to split a <br/> tag consistently across browsers,
// (*ahem* IE *ahem*), we replace all <br/> instances with an md5 hash
// (of the word "split"). If you're trying to use this plugin on that
// md5 hash string, it will fail because you're being ridiculous.
injector($(this).children("br").replaceWith(r).end(), r, 'line', '');
});
}
};
$.fn.lettering = function(method) {
// Method calling logic
if (method && methods[method]) {
return methods[method].apply(this, [].slice.call(arguments, 1));
} else if (method === 'letters' || !method) {
return methods.init.apply(this, [].slice.call(arguments, 0)); // always pass an array
}
$.error('Method ' + method + ' does not exist on jQuery.lettering');
return this;
};
})(jQuery);
/*global jQuery */
/*!
* FitText.js 1.1
*
* Copyright 2011, Dave Rupert http://daverupert.com
* Released under the WTFPL license
* http://sam.zoy.org/wtfpl/
*
* Date: Thu May 05 14:23:00 2011 -0600
*/
(function($) {
$.fn.fitText = function(kompressor, options) {
// Setup options
var compressor = kompressor || 1,
settings = $.extend({
'minFontSize': Number.NEGATIVE_INFINITY,
'maxFontSize': Number.POSITIVE_INFINITY
}, options);
return this.each(function() {
// Store the object
var $this = $(this);
// Resizer() resizes items based on the object width divided by the compressor * 10
var resizer = function() {
$this.css('font-size', Math.max(Math.min($this.width() / (compressor * 10), parseFloat(settings.maxFontSize)), parseFloat(settings.minFontSize)));
};
// Call once to set.
resizer();
// Call on resize. Opera debounces their resize by default.
$(window).on('resize', resizer);
});
};
})(jQuery);
/*
* CircleType 0.36
* Peter Hrynkow
* Copyright 2014, Licensed GPL & MIT
*
*/
$.fn.circleType = function(options) {
var self = this,
settings = {
dir: 1,
position: 'relative',
};
if (typeof($.fn.lettering) !== 'function') {
console.log('Lettering.js is required');
return;
}
return this.each(function() {
if (options) {
$.extend(settings, options);
}
var elem = this,
delta = (180 / Math.PI),
fs = parseInt($(elem).css('font-size'), 10),
ch = parseInt($(elem).css('line-height'), 10) || fs,
txt = elem.innerHTML.replace(/^\s+|\s+$/g, '').replace(/\s/g, ' '),
letters,
center;
elem.innerHTML = txt
$(elem).lettering();
elem.style.position = settings.position;
letters = elem.getElementsByTagName('span');
center = Math.floor(letters.length / 2)
var layout = function() {
var tw = 0,
i,
offset = 0,
minRadius,
origin,
innerRadius,
l, style, r, transform;
for (i = 0; i < letters.length; i++) {
tw += letters[i].offsetWidth;
}
minRadius = (tw / Math.PI) / 2 + ch;
if (settings.fluid && !settings.fitText) {
settings.radius = Math.max(elem.offsetWidth / 2, minRadius);
} else if (!settings.radius) {
settings.radius = minRadius;
}
if (settings.dir === -1) {
origin = 'center ' + (-settings.radius + ch) / fs + 'em';
} else {
origin = 'center ' + settings.radius / fs + 'em';
}
innerRadius = settings.radius - ch;
for (i = 0; i < letters.length; i++) {
l = letters[i];
offset += l.offsetWidth / 2 / innerRadius * delta;
l.rot = offset;
offset += l.offsetWidth / 2 / innerRadius * delta;
}
for (i = 0; i < letters.length; i++) {
l = letters[i]
style = l.style
r = (-offset * settings.dir / 2) + l.rot * settings.dir
transform = 'rotate(' + r + 'deg)';
style.position = 'absolute';
style.left = '50%';
style.marginLeft = -(l.offsetWidth / 2) / fs + 'em';
style.webkitTransform = transform;
style.MozTransform = transform;
style.OTransform = transform;
style.msTransform = transform;
style.transform = transform;
style.webkitTransformOrigin = origin;
style.MozTransformOrigin = origin;
style.OTransformOrigin = origin;
style.msTransformOrigin = origin;
style.transformOrigin = origin;
if (settings.dir === -1) {
style.bottom = 0;
}
}
if (settings.fitText) {
if (typeof($.fn.fitText) !== 'function') {
console.log('FitText.js is required when using the fitText option');
} else {
$(elem).fitText();
$(window).resize(function() {
updateHeight();
});
}
}
updateHeight();
if (typeof settings.callback === 'function') {
// Execute our callback with the element we transformed as `this`
settings.callback.apply(elem);
}
};
var getBounds = function(elem) {
var docElem = document.documentElement,
box = elem.getBoundingClientRect();
return {
top: box.top + window.pageYOffset - docElem.clientTop,
left: box.left + window.pageXOffset - docElem.clientLeft,
height: box.height
};
};
var updateHeight = function() {
var mid = getBounds(letters[center]),
first = getBounds(letters[0]),
h;
if (mid.top < first.top) {
h = first.top - mid.top + first.height;
} else {
h = mid.top - first.top + first.height;
}
elem.style.height = h + 'px';
}
if (settings.fluid && !settings.fitText) {
$(window).resize(function() {
layout();
});
}
if (document.readyState !== "complete") {
elem.style.visibility = 'hidden';
$(window).load(function() {
elem.style.visibility = 'visible';
layout();
});
} else {
layout();
}
});
};;
(function(factory) {
if (typeof define === 'function' && define.amd) {
define(['jquery'], factory);
} else if (typeof exports === 'object') {
module.exports = factory(require("jquery"));
} else {
factory(jQuery);
}
}
(function($) {
var pluginName = "tinycircleslider",
defaults = {
interval: false,
intervalTime: 3500,
dotsSnap: false,
dotsHide: true,
radius: 140,
start: 0,
slides: []
};
function Plugin($container, options) {
/**
* The options of the carousel extend with the defaults.
*
* @property options
* @type Object
* @default defaults
*/
this.options = $.extend({}, defaults, options);
/**
* @property _defaults
* @type Object
* @private
* @default defaults
*/
this._defaults = defaults;
/**
* @property _name
* @type String
* @private
* @final
* @default 'tinycircleslider'
*/
this._name = pluginName;
var self = this,
$viewport = $container.find(".viewport"),
$overview = $container.find(".overview"),
$slides = $overview.children(),
$thumb = $container.find(".thumb"),
$dots = $container.find(".dot"),
$links = $slides.find("a")
, containerSize = {
width: $container.outerWidth(true),
height: $container.outerHeight(true)
}, slideSize = {
width: $slides.first().outerWidth(true),
height: $slides.first().outerHeight(true)
}, thumbSize = {
width: $thumb.outerWidth(true),
height: $thumb.outerHeight(true)
}, dotSize = {
width: $dots.outerWidth(),
height: $dots.outerHeight()
}
, intervalTimer = null, animationTimer = null, touchEvents = 'ontouchstart' in window, isTouchEvent = false, hasRequestAnimationFrame = 'requestAnimationFrame' in window;
/**
* When dotsSnap is enabled every slide has a corresponding dot.
*
* @property dots
* @type Array
* @default []
*/
this.dots = [];
/**
* The index of the current slide.
*
* @property slideCurrent
* @type Number
* @default 0
*/
this.slideCurrent = 0;
/**
* The current angle in degrees
*
* @property angleCurrent
* @type Number
* @default 0
*/
this.angleCurrent = 0;
/**
* The number of slides the slider is currently aware of.
*
* @property slidesTotal
* @type Number
* @default 0
*/
this.slidesTotal = $slides.length;
/**
* If the interval is running the value will be true.
*
* @property intervalActive
* @type Boolean
* @default false
*/
this.intervalActive = false;
/**
* @method _initialize
* @private
*/
function _initialize() {
_setDots();
$overview
.append($slides.first().clone())
.css("width", slideSize.width * ($slides.length + 1));
_setEvents();
_setCSS(0);
self.move(self.options.start, self.options.interval);
return self;
}
/**
* @method _setEvents
* @private
*/
function _setEvents() {
if (touchEvents) {
$container[0].ontouchstart = _startDrag;
$container[0].ontouchmove = _drag;
$container[0].ontouchend = _endDrag;
}
$thumb.bind("mousedown", _startDrag);
var snapHandler = function(event) {
event.preventDefault();
event.stopImmediatePropagation();
self.stop();
self.move($(this).attr("data-slide-index"));
return false;
};
if (touchEvents) {
$container.delegate(".dot", "touchstart", snapHandler);
}
$container.delegate(".dot", "mousedown", snapHandler);
}
/**
* @method _setTimer
* @private
*/
function _setTimer(slideFirst) {
intervalTimer = setTimeout(function() {
self.move(self.slideCurrent + 1, true);
}, (slideFirst ? 50 : self.options.intervalTime));
}
/**
* @method _toRadians
* @private
* @param {Number} [degrees]
*/
function _toRadians(degrees) {
return degrees * (Math.PI / 180);
}
/**
* @method _toDegrees
* @private
* @param {Number} [radians]
*/
function _toDegrees(radians) {
return radians * 180 / Math.PI;
}
/**
* @method _setDots
* @private
*/
function _setDots() {
var docFragment = document.createDocumentFragment();
$dots.remove();
$slides.each(function(index, slide) {
var $dotClone = null,
angle = parseInt($(slide).attr("data-degrees"), 10) || (index * 360 / self.slidesTotal),
position = {
top: -Math.cos(_toRadians(angle)) * self.options.radius + containerSize.height / 2 - dotSize.height / 2,
left: Math.sin(_toRadians(angle)) * self.options.radius + containerSize.width / 2 - dotSize.width / 2
};
if ($dots.length > 0) {
$dotClone = $dots.clone();
$dotClone
.addClass($(slide).attr("data-classname"))
.css(position);
docFragment.appendChild($dotClone[0]);
}
self.dots.push({
"angle": angle,
"slide": slide,
"dot": $dotClone
});
});
self.dots.sort(function(dotA, dotB) {
return dotA.angle - dotB.angle;
});
$.each(self.dots, function(index, dot) {
// custom
if ($(dot.dot).length > 0) {
if (index === 4) {
$(dot.dot)
.addClass("dot-" + (index + 1))
.attr('data-slide-index', index)
.html("<h1><div class='flip text'>" + options.slides[index] + "</div><div class='flip-curve curve'> </div></h1>");
} else {
$(dot.dot)
.addClass("dot-" + (index + 1))
.attr('data-slide-index', index)
.html("<h1><div class='text'>" + options.slides[index] + "</div></h1>");
}
}
});
$container.append(docFragment);
// custom
$('h1').each(function(i, text) {
if ($(this).find('div').html() === "Norway") {
$(this).find('div.text').circleType({
radius: 220,
dir: -1
});
} else {
$(this).find('div.text').circleType({
radius: 220
});
}
});
$dots = $container.find(".dot");
}
/**
* If the interval is stopped start it.
*
* @method start
* @chainable
*/
this.start = function(first) {
if (self.options.interval) {
self.intervalActive = true;
_setTimer(first);
}
return self;
};
/**
* If the interval is running stop it.
*
* @method stop
* @chainable
*/
this.stop = function() {
self.intervalActive = false;
clearTimeout(intervalTimer);
return self;
};
/**
* @method _findShortestPath
* @private
* @param {Number} [angleA]
* @param {Number} [angleB]
*/
function _findShortestPath(angleA, angleB) {
var angleCW, angleCCW, angleShortest;
if (angleA > angleB) {
angleCW = angleA - angleB;
angleCCW = -(angleB + 360 - angleA);
} else {
angleCW = angleA + 360 - angleB;
angleCCW = -(angleB - angleA);
}
angleShortest = angleCW < Math.abs(angleCCW) ? angleCW : angleCCW;
return [angleShortest, angleCCW, angleCW];
}
/**
* @method _findClosestSlide
* @private
* @param {Number} [angle]
*/
function _findClosestSlide(angle) {
var closestDotAngleToAngleCCW = 9999,
closestDotAngleToAngleCW = 9999,
closestDotAngleToAngle = 9999,
closestSlideCCW = 0,
closestSlideCW = 0,
closestSlide = 0;
$.each(self.dots, function(index, dot) {
var delta = _findShortestPath(dot.angle, angle);
if (Math.abs(delta[0]) < Math.abs(closestDotAngleToAngle)) {
closestDotAngleToAngle = delta[0];
closestSlide = index;
}
if (Math.abs(delta[1]) < Math.abs(closestDotAngleToAngleCCW)) {
closestDotAngleToAngleCCW = delta[1];
closestSlideCCW = index;
}
if (Math.abs(delta[2]) < Math.abs(closestDotAngleToAngleCW)) {
closestDotAngleToAngleCW = delta[2];
closestSlideCW = index;
}
});
return [
[closestSlide, closestSlideCCW, closestSlideCW],
[closestDotAngleToAngle, closestDotAngleToAngleCCW, closestDotAngleToAngleCW]
];
}
/**
* Move to a specific slide.
*
* @method move
* @chainable
* @param {Number} [index] The slide to move to.
*/
this.move = function(index) {
var slideIndex = Math.max(0, isNaN(index) ? self.slideCurrent : index);
if (slideIndex >= self.slidesTotal) {
slideIndex = 0;
}
var angleDestination = self.dots[slideIndex] && self.dots[slideIndex].angle,
angleDelta = _findShortestPath(angleDestination, self.angleCurrent)[0],
angleStep = angleDelta > 0 ? -2 : 2;
self.slideCurrent = slideIndex;
_stepMove(angleStep, angleDelta, 50);
self.start();
return self;
};
/**
* @method _sanitizeAngle
* @private
* @param {Number} [degrees]
*/
function _sanitizeAngle(degrees) {
return (degrees < 0) ? 360 + (degrees % -360) : degrees % 360;
}
/**
* @method _stepMove
* @private
* @param {Number} [angleStep]
* @param {Number} [angleDelta]
* @param {Boolean} [stepInterval]
*/
function _stepMove(angleStep, angleDelta, stepInterval) {
var angleStepNew = angleStep,
endAnimation = false;
if (Math.abs(angleStep) > Math.abs(angleDelta)) {
angleStepNew = -angleDelta;
endAnimation = true;
} else if (hasRequestAnimationFrame) {
requestAnimationFrame(function() {
_stepMove(angleStepNew, angleDelta + angleStep);
});
} else {
animationTimer = setTimeout(function() {
_stepMove(angleStepNew, angleDelta + angleStep, stepInterval * 0.9);
}, stepInterval);
}
self.angleCurrent = _sanitizeAngle(self.angleCurrent - angleStepNew);
_setCSS(self.angleCurrent, endAnimation);
}
/**
* @method _page
* @private
* @param {Object} [event]
*/
function _page(event) {
return {
x: isTouchEvent ? event.targetTouches[0].pageX : (event.pageX || event.clientX),
y: isTouchEvent ? event.targetTouches[0].pageY : (event.pageY || event.clientY)
};
}
/**
* @method _drag
* @private
* @param {Object} [event]
*/
function _drag(event) {
var containerOffset = $container.offset(),
thumbPositionNew = {
left: _page(event).x - containerOffset.left - (containerSize.width / 2),
top: _page(event).y - containerOffset.top - (containerSize.height / 2)
};
self.angleCurrent = _sanitizeAngle(
_toDegrees(
Math.atan2(thumbPositionNew.left, -thumbPositionNew.top)
)
);
if (!hasRequestAnimationFrame) {
_setCSS(self.angleCurrent);
}
return false;
}
/**
* @method _setCSS
* @private
* @param {Number} [angle]
* @param {Function} [fireCallback]
*/
function _setCSS(angle, fireCallback) {
closestSlidesAndAngles = _findClosestSlide(angle);
closestSlides = closestSlidesAndAngles[0];
closestAngles = closestSlidesAndAngles[1];
$overview.css("left", -(closestSlides[1] * slideSize.width + Math.abs(closestAngles[1]) * slideSize.width / (Math.abs(closestAngles[1]) + Math.abs(closestAngles[2]))));
$thumb.css({
top: -Math.cos(_toRadians(angle)) * self.options.radius + (containerSize.height / 2 - thumbSize.height / 2),
left: Math.sin(_toRadians(angle)) * self.options.radius + (containerSize.width / 2 - thumbSize.width / 2)
});
if (fireCallback) {
/**
* The move event will trigger when the carousel slides to a new slide.
*
* @event move
* custom
*/
$container.trigger("move", [$slides[self.slideCurrent], self.slideCurrent]);
var slideno = _findClosestSlide(self.angleCurrent)[0][0];
$('.dot').removeClass('active');
$('.dot:eq(' + slideno + ')').addClass('active');
$('#overlayActive').removeClass('slideno(0) slideno(1) slideno(2) slideno(3) slideno(4) slideno(5) slideno(6) slideno(7)').addClass('slideno(' + slideno + ')');
$('.dot-1').mouseover(function() {
$('#overlayInteraction').addClass('is-slide1-hovered');
});
$('.dot-1').mouseout(function() {
$('#overlayInteraction').removeClass('is-slide1-hovered');
});
$('.dot-2').mouseover(function() {
$('#overlayInteraction').addClass('is-slide2-hovered');
});
$('.dot-2').mouseout(function() {
$('#overlayInteraction').removeClass('is-slide2-hovered');
});
$('.dot-3').mouseover(function() {
$('#overlayInteraction').addClass('is-slide3-hovered');
});
$('.dot-3').mouseout(function() {
$('#overlayInteraction').removeClass('is-slide3-hovered');
});
$('.dot-4').mouseover(function() {
$('#overlayInteraction').addClass('is-slide4-hovered');
});
$('.dot-4').mouseout(function() {
$('#overlayInteraction').removeClass('is-slide4-hovered');
});
$('.dot-5').mouseover(function() {
$('#overlayInteraction').addClass('is-slide5-hovered');
});
$('.dot-5').mouseout(function() {
$('#overlayInteraction').removeClass('is-slide5-hovered');
});
$('.dot-6').mouseover(function() {
$('#overlayInteraction').addClass('is-slide6-hovered');
});
$('.dot-6').mouseout(function() {
$('#overlayInteraction').removeClass('is-slide6-hovered');
});
$('.dot-7').mouseover(function() {
$('#overlayInteraction').addClass('is-slide7-hovered');
});
$('.dot-7').mouseout(function() {
$('#overlayInteraction').removeClass('is-slide7-hovered');
});
$('.dot-8').mouseover(function() {
$('#overlayInteraction').addClass('is-slide8-hovered');
});
$('.dot-8').mouseout(function() {
$('#overlayInteraction').removeClass('is-slide8-hovered');
});
}
}
/**
* @method _endDrag
* @private
* @param {Object} [event]
*/
function _endDrag(event) {
if ($(event.target).hasClass("dot")) {
return false;
}
self.dragging = false;
event.preventDefault();
$(document).unbind("mousemove mouseup");
$thumb.unbind("mouseup");
if (self.options.dotsHide) {
$dots.stop(true, true).fadeOut("slow");
}
if (self.options.dotsSnap) {
self.move(_findClosestSlide(self.angleCurrent)[0][0]);
}
}
function _dragAnimationLoop() {
if (self.dragging) {
_setCSS(self.angleCurrent);
requestAnimationFrame(function() {
_dragAnimationLoop();
});
}
}
/**
* @method _startDrag
* @private
* @param {Object} [event]
*/
function _startDrag(event) {
event.preventDefault();
isTouchEvent = event.type == 'touchstart';
self.dragging = true;
if ($(event.target).hasClass("dot")) {
return false;
}
self.stop();
$(document).mousemove(_drag);
$(document).mouseup(_endDrag);
$thumb.mouseup(_endDrag);
if (self.options.dotsHide) {
$dots.stop(true, true).fadeIn("slow");
}
if (hasRequestAnimationFrame) {
_dragAnimationLoop();
}
}
return _initialize();
}
/**
* @class tinycircleslider
* @constructor
* @param {Object} options
@param {Boolean} [options.dotsSnap=false] Shows dots when user starts dragging and snap to them.
@param {Boolean} [options.dotsHide=true] Fades out the dots when user stops dragging.
@param {Number} [options.radius=140] Used to determine the size of the circleslider.
@param {Boolean} [options.interval=false] Move to another block on intervals.
@param {Number} [options.intervalTime=intervalTime] Interval time in milliseconds.
@param {Number} [options.start=0] The slide to start with.
*/
$.fn[pluginName] = function(options) {
return this.each(function() {
if (!$.data(this, "plugin_" + pluginName)) {
$.data(this, "plugin_" + pluginName, new Plugin($(this), options));
}
});
};
}));
$(document).ready(function() {
var widthtoacquire = $(window).width() - 30;
var radius = (widthtoacquire - 80) / 2 > 150 ? 150 : (widthtoacquire - 80) / 2;
$("#rotatescroll").tinycircleslider({
dotsSnap: true,
radius: radius,
dotsHide: false,
slides: ["England", "Ireland", "Wales", "Guernsey", "Norway", "Netherlands", "Belgium", "Italy"],
interval: false
});
});
Also see: Tab Triggers