Skip to content

Instantly share code, notes, and snippets.

@LeoOnTheEarth
Last active May 6, 2020 08:17
Show Gist options
  • Save LeoOnTheEarth/27e5c116c4189ad3b3f7f5dff4e8f1b6 to your computer and use it in GitHub Desktop.
Save LeoOnTheEarth/27e5c116c4189ad3b3f7f5dff4e8f1b6 to your computer and use it in GitHub Desktop.
/** Basic Theme Styles **/
.easy-cover-flow {
overflow: hidden;
position: relative;
margin: 0 auto;
}
.easy-cover-flow .item {
position: absolute;
top: 0;
left: 0;
opacity: 0;
transition: all 0.3s ease-in-out;
}
.easy-cover-flow .item.item-hide {
transform: scale(0);
}
/** End of Basic Theme Styles **/
/** Demo Theme Styles **/
.easy-cover-flow.theme-default {
width: 100%;
height: 420px;
}
.easy-cover-flow.theme-default .item {
width: 48%;
}
.easy-cover-flow.theme-default .item img {
width: 100%;
height: 100%;
}
.easy-cover-flow.theme-default .item.item-hide {
transform: scale(0);
}
.easy-cover-flow.theme-default .item-1 {
transform: translate3d(0, 0, 0) scale(0.85);
transform-origin: 100% 50%;
opacity: 0.8;
z-index: 4;
}
.easy-cover-flow.theme-default .item-2 {
transform: translate3d(50%, 0, 0) scale(1);
opacity: 1;
z-index: 5;
}
.easy-cover-flow.theme-default .item-3 {
transform: translate3d(90%, 0, 0) scale(0.85);
transform-origin: 100% 50%;
opacity: 1;
z-index: 4;
}
@media screen and (min-width: 641px) {
.easy-cover-flow.theme-default {
width: 100%;
height: 471px;
}
.easy-cover-flow.theme-default .item {
width: 27%;
}
.easy-cover-flow.theme-default .item-1 {
transform: translate3d(0, 0, 0) scale(0.8);
transform-origin: 100% 50%;
opacity: 0.8;
z-index: 2;
}
.easy-cover-flow.theme-default .item-2 {
transform: translate3d(40%, 0, 0) scale(0.85);
transform-origin: 100% 50%;
opacity: 1;
z-index: 3;
}
.easy-cover-flow.theme-default .item-3 {
transform: translate3d(80%, 0, 0) scale(0.9);
transform-origin: 100% 50%;
opacity: 1;
z-index: 4;
}
.easy-cover-flow.theme-default .item-4 {
transform: translate3d(130%, 0, 0) scale(1);
opacity: 1;
z-index: 5;
}
.easy-cover-flow.theme-default .item-5 {
transform: translate3d(170%, 0, 0) scale(0.9);
transform-origin: 100% 50%;
opacity: 1;
z-index: 4;
}
.easy-cover-flow.theme-default .item-6 {
transform: translate3d(210%, 0, 0) scale(0.85);
transform-origin: 100% 50%;
opacity: 1;
z-index: 3;
}
.easy-cover-flow.theme-default .item-7 {
transform: translate3d(250%, 0, 0) scale(0.8);
transform-origin: 100% 50%;
opacity: 0.8;
z-index: 2;
}
}
@media screen and (min-width: 1201px) {
.easy-cover-flow.theme-default {
width: 1200px;
height: 471px;
}
.easy-cover-flow.theme-default .item {
width: auto;
}
}
/** End of Demo Theme Styles **/
/**
* @param {Object?} options
*
* @return {jQuery}
*/
function initialEasyCoverFlow(options) {
options = $.extend({
/**
* @var {Number|Function}
*/
itemCount: function () {
if ($(window).width() > 640) {
return 7;
}
return 3;
}
}, typeof options === 'object' ? options : {});
// 是否有觸發滑動事件
var isTouching = false;
function getItemCount($node) {
var itemCount = parseInt($node.data('item-count'));
if (!itemCount) {
if (typeof options.itemCount === 'function') {
itemCount = options.itemCount();
} else {
itemCount = options.itemCount;
}
}
return itemCount;
}
/**
* @param {jQuery} $target
*/
function getIndexes($target) {
return {
lastItemIndex: getItemCount($target),
middleItemIndex: $target.data('middle-item-index'),
leftLastItemIndex: $target.data('left-last-item-index'),
rightFirstItemIndex: $target.data('right-first-item-index'),
};
}
/**
* @param {jQuery} $target
*/
function getItems($target) {
var indexes = getIndexes($target);
return {
$first: $target.find('.item:first'),
$last: $target.find('.item:nth-child(' + indexes.lastItemIndex + ')'),
$selected: $target.find('.item:nth-child(' + indexes.middleItemIndex + ')'),
$leftLast: $target.find('.item:nth-child(' + indexes.leftLastItemIndex + ')'),
$rightFirst: $target.find('.item:nth-child(' + indexes.rightFirstItemIndex + ')'),
};
}
/**
* @param {jQuery} $target
* @param {Number} diff -1: right -> left, 1: left -> right
*/
function updateItemIndexes($target, diff) {
var $items = $target.find('.item');
var maxIndex = $items.length;
$items.each(function (i, item) {
var $item = $(item);
var index = $item.data('item-index');
var newIndex = index + diff;
newIndex = 0 >= newIndex ? $items.length : newIndex;
newIndex = maxIndex < newIndex ? 1 : newIndex;
$item.data('item-index', newIndex);
$item.removeClass('item-' + index).addClass('item-' + newIndex);
});
}
function showPrevious($target, onFinished) {
var itemCount = getItemCount($target);
var nextItemIndex = itemCount + 1 > $target.find('.item').length ? 1 : itemCount + 1;
var $next = $target.find('.item:nth-child(' + nextItemIndex + ')');
var $items = getItems($target);
updateItemIndexes($target, -1);
setTimeout(function () {
$items.$first.addClass('item-hide');
$items.$selected.removeClass('selected');
$items.$rightFirst.addClass('selected');
$next.removeClass('item-hide');
setTimeout(function () {
$target.append($items.$first);
if (typeof onFinished === 'function') {
onFinished();
}
}, 300);
}, 0);
}
function showNext($target, onFinished) {
var $next = $target.find('.item:nth-last-child(1)');
var $items = getItems($target);
updateItemIndexes($target, 1);
$target.prepend($next);
setTimeout(function () {
$next.removeClass('item-hide');
$items.$last.addClass('item-hide');
$items.$selected.removeClass('selected');
$items.$leftLast.addClass('selected');
setTimeout(function () {
if (typeof onFinished === 'function') {
onFinished();
}
}, 300);
}, 0);
}
function initialEasyCoverFlowNodes($node) {
var itemCount = getItemCount($node);
$node.find('.item').each(function (i, item) {
var $item = $(item);
var index = i + 1;
if (index > itemCount) {
$item.addClass('item-hide');
} else {
$item.removeClass('item-hide');
}
$item.addClass('item-' + index.toString());
$item.data('item-index', index);
});
var middleItemIndex = itemCount % 2 ? parseInt(itemCount / 2) + 1 : parseInt(itemCount / 2);
var leftLastItemIndex = middleItemIndex - 1;
var rightFirstItemIndex = middleItemIndex + 1;
$node.data('middle-item-index', middleItemIndex);
$node.data('left-last-item-index', leftLastItemIndex);
$node.data('right-first-item-index', rightFirstItemIndex);
$node.find('.item.selected').removeClass('selected');
$node.find('.item.left-last').removeClass('left-last');
$node.find('.item.right-first').removeClass('right-first');
$node.find('.item:nth-child(' + middleItemIndex + ')').addClass('selected');
$node.find('.item:nth-child(' + leftLastItemIndex + ')').addClass('left-last');
$node.find('.item:nth-child(' + rightFirstItemIndex + ')').addClass('right-first');
var touchStartPositionX = 0;
$node.on('touchstart', function (event) {
if (!isTouching && 0 === touchStartPositionX && 1 === event.changedTouches.length) {
touchStartPositionX = event.changedTouches[0].pageX;
}
});
$node.on('touchend', function (event) {
if (!isTouching && 1 === event.changedTouches.length) {
var touchEndPositionX = event.changedTouches[0].pageX;
isTouching = true;
if (touchEndPositionX - touchStartPositionX > 30) {
showNext($node, function () {
isTouching = false;
});
} else if (touchEndPositionX - touchStartPositionX < -30) {
showPrevious($node, function () {
isTouching = false;
});
} else {
isTouching = false;
}
touchStartPositionX = 0;
}
});
}
$('.easy-cover-flow').each(function () {
initialEasyCoverFlowNodes($(this));
});
var buttonClicked = false;
$('.easy-cover-flow-control.previous').on('click', function () {
if (buttonClicked) {
return;
}
buttonClicked = true;
showPrevious($($(this).data('easy-cover-flow')), function () {
buttonClicked = false;
});
});
$('.easy-cover-flow-control.next').on('click', function () {
if (buttonClicked) {
return;
}
buttonClicked = true;
showNext($($(this).data('easy-cover-flow')), function () {
buttonClicked = false;
});
});
$(window).on('resize', function () {
if (typeof options.itemCount === 'function') {
$('.easy-cover-flow').each(function () {
initialEasyCoverFlowNodes($(this));
});
}
});
}
initialEasyCoverFlow();
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Carousel</title>
<style type="text/css">
* {
margin: 0;
padding: 0;
}
</style>
<link rel="stylesheet" href="easy-cover-flow.css">
</head>
<body>
<div class="demo">
<!-- 必要屬性: class="easy-cover-flow theme-default" id="my-easy-cover-flow" -->
<div class="easy-cover-flow theme-default" id="my-easy-cover-flow">
<!-- 必要屬性: class="item" 裏頭的 img 圖片會自動縮放 -->
<div class="item"><img src="https://picsum.photos/327/469?random=2" /></div>
<div class="item"><img src="https://picsum.photos/327/469?random=3" /></div>
<div class="item"><img src="https://picsum.photos/327/469?random=4" /></div>
<div class="item"><img src="https://picsum.photos/327/469?random=5" /></div>
<div class="item"><img src="https://picsum.photos/327/469?random=6" /></div>
<div class="item"><img src="https://picsum.photos/327/469?random=1" /></div>
<div class="item"><img src="https://picsum.photos/327/469?random=7" /></div>
<div class="item"><img src="https://picsum.photos/327/469?random=8" /></div>
<div class="item"><img src="https://picsum.photos/327/469?random=9" /></div>
<div class="item"><img src="https://picsum.photos/327/469?random=10" /></div>
<div class="item"><img src="https://picsum.photos/327/469?random=11" /></div>
</div>
</div>
<div>
<!-- 必要屬性: class="easy-cover-flow-control previous" data-easy-cover-flow="#my-easy-cover-flow" -->
<button type="button" class="easy-cover-flow-control previous" data-easy-cover-flow="#my-easy-cover-flow">prev</button>
<!-- 必要屬性: class="easy-cover-flow-control next" data-easy-cover-flow="#my-easy-cover-flow" -->
<button type="button" class="easy-cover-flow-control next" data-easy-cover-flow="#my-easy-cover-flow">next</button>
</div>
<script src="https://code.jquery.com/jquery-3.5.1.min.js"
integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44="
crossorigin="anonymous"></script>
<script src="easy-cover-flow.js"></script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment