Hexaflip: Создаем 3d кубы для запросов сайта
В данном уроке мы рассмотрим один небольшой плагин, который позволит создать объемные кубические объекты, с различными вариантами манипуляций. Плагин достаточно гибкий это позволяет создавать различные примеры с ним, например: графический пароль, слайдер изображений, или установка времени. В демонстрации мы рассмотрим каждый из этих примеров, кроме этого, следует обратить внимание, что плагин использует некоторые трансформации css, это означает, что данная задумка будет работать не во всех современных браузерах.
Если вы не протирали штаны в школе, то наверняка знаете, что куб состоит из шести сторон, но при вращении его вокруг одной оси, мы сможем наблюдать только четыре. Данный плагин позволит не ограничиваться этими правилами, мы сможем задать сколько угодно благодаря циклу.
Много различным бесплатных шаблонов вы можете найти на сайте наших партнеров, также имеются и премиум шаблоны с круглосуточной техподдержкой и помощью в настройке:
Шаг 1. HTML
Всю необходимую разметку плагин создает самостоятельно, для отображения демонстрации нам необходим всего лишь один элемент:
1 2 3 4 |
</pre> <div class="demo" id="hexaflip-demo1"></div> <pre> |
Такие элементы как id и class здесь необходимы для добавления специальных стилей, для данной демонстрации.
Шаг 2. CSS
Плагин HexaFlip, будет автоматически присваивать класс hexaflip-cube. На основе этого мы будем определять к какому элементу будет относится стиль, давайте начнем с общих параметров.
1 2 3 4 5 6 7 8 9 10 11 |
.hexaflip-cube { font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif; text-rendering: optimizeLegibility; font-smoothing: antialiased; cursor: move; cursor: grab; display: inline-block; position: relative; transform-style: preserve-3d; transition: transform 0.4s; } |
Нам необходимо создать класс no-tween, который запретит анимацию куба с помощью JS, если вы уже зажали кнопку мыши.
1 2 3 |
.hexaflip-cube.no-tween { transition-duration: 0; } |
Каждая из сторон куба, будет вложена в блок div, поэтому для доступа ко всем сторонам, мы будем применять селектор (>) с необходимыми стилями:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
.hexaflip-cube > div { width: 100%; overflow: hidden; height: 100.5%; position: absolute; user-select: none; background-size: cover; text-align: center; background-color: #333; color: #fff; font-weight: 100; text-shadow: 0 -2px 0 rgba(0,0,0,0.3); line-height: 1.5; } |
Когда стороны куба находятся не в поле зрения мы установим для них серый цвет:
1 2 3 |
.hexaflip-left, .hexaflip-right { background-color: #555 !important; } |
Для каждой стороны куба мы установим различные цвета, они будут отображаться когда одна из сторон активна:
1 2 3 |
.hexaflip-timepicker .hexaflip-cube:last-child > div:nth-child(odd) { background-color: #ff575b; } |
Со стилями мы разобрались, перейдем к следующему шагу.
Шаг 3. JavaScript
Для начала нам необходимо определить начало и конец функции, чтобы после наполнять её всеми необходимыми элементами.
1 2 3 |
(function() { //... }).call(this); |
После того как мы определили переменные, мы должны решить поддержку необходимых CSS3 свойств, и создании необходимых префиксов под разные браузеры. Следующий фрагмент кода, будет выяснять, поддерживается ли CSS3 вашим браузером или нет.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
prefixList = ['webkit', 'Moz', 'O', 'ms']; prefixProp = function(prop) { var prefix, prefixed, _i, _len; if (document.body.style[prop.toLowerCase()] != null) { return prop.toLowerCase(); } for (_i = 0, _len = prefixList.length; _i < _len; _i++) { prefix = prefixList[_i]; prefixed = prefix + prop; if (document.body.style[prefixed] != null) { return prefixed; } } return false; |
Нам необходимо проверить два конкретных CSS3 свойства это трансформация и перспектива:
1 2 3 4 5 6 7 |
css = {}; _ref = ['Transform', 'Perspective']; for (_i = 0, _len = _ref.length; _i < _len; _i++) { prop = _ref[_i]; css[prop.toLowerCase()] = prefixProp(prop); } |
Наш конструктор будет принимать 3 значения: целевой элемент DOM, литерал объекта, содержащий наборы для отображения, и дополнительный объект настроек. Эти 3 аргумента, являются приложением к экземпляру (this):
1 2 3 4 5 |
function HexaFlip(el, sets, options) { var cube, cubeFragment, i, image, key, midPoint, option, set, setsKeys, setsLength, val, value, z, _j, _len1, _ref1, _ref2; this.el = el; this.sets = sets; this.options = options != null ? options : {}; |
Конструктор будет проверяет поддержку CSS3 свойств. Если поддержки нет, то конструктор сразу завершает работу:
1 2 3 |
if (!(css.transform && this.el)) { return; } |
Когда конструктор завершает всю работу, установив правильную высоту, ширину и перспективу для элементов контейнера и добавляет кубы.
1 2 3 4 5 6 7 |
this.cubes[setsKeys[0]].el.style.marginLeft = '0'; this.cubes[setsKeys[setsKeys.length - 1]].el.style.marginRight = '0'; this.el.classList.add(cssClass); this.el.style.height = this.size + 'px'; this.el.style.width = ((this.size + this.margin * 2) * setsLength) - this.margin * 2 + 'px'; this.el.style[css.perspective] = this.perspective + 'px'; this.el.appendChild(cubeFragment); |
Чтобы создать трехмерный куб из шести плоских поверхностей, мы должны применить цикл ко всем лицевым сторонам, при этом указывая необходимые стили для оси и необходимого угла вращения слоёв:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
for (_j = 0, _len1 = faceNames.length; _j < _len1; _j++) { side = faceNames[_j]; cube[side] = document.createElement('div'); cube[side].className = cssClass + '-' + side; rotate3d = (function() { switch (side) { case 'front': return '0, 0, 0, 0deg'; case 'back': return '1, 0, 0, 180deg'; case 'top': return '1, 0, 0, 90deg'; case 'bottom': return '1, 0, 0, -90deg'; case 'left': return '0, 1, 0, -90deg'; case 'right': return '0, 1, 0, 90deg'; } })(); cube[side].style[css.transform] = "rotate3d(" + rotate3d + ") translate3d(0, 0, " + (this.size / 2) + "px)"; cube[side].style.fontSize = this.fontSize; cube.el.appendChild(cube[side]); } |
_createCube задаcn правила манипуляций с помощью мыши и сенсорных девайсов:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
eventPairs = [['TouchStart', 'MouseDown'], ['TouchMove', 'MouseMove'], ['TouchEnd', 'MouseUp'], ['TouchLeave', 'MouseLeave']]; mouseLeaveSupport = 'onmouseleave' in window; for (_k = 0, _len2 = eventPairs.length; _k < _len2; _k++) { eventPair = eventPairs[_k]; _fn = function(fn, cube) { if (!((eString === 'TouchLeave' || eString === 'MouseLeave') && !mouseLeaveSupport)) { return cube.el.addEventListener(eString.toLowerCase(), (function(e) { return _this[fn](e, cube); }), true); } else { return cube.el.addEventListener('mouseout', (function(e) { return _this._onMouseOut(e, cube); }), true); } }; for (_l = 0, _len3 = eventPair.length; _l < _len3; _l++) { eString = eventPair[_l]; _fn('_on' + eventPair[0], cube); } } this._setSides(cube); return cube; };[php] Чтобы получить изображение на кубе мы установим функцию <em>_setContent</em>, которая будет входить сторону куба, и изображение на нём: [php]HexaFlip.prototype._setContent = function(el, content) { var key, style, val, value; if (!(el && content)) { return; } if (typeof content === 'object') { style = content.style, value = content.value; for (key in style) { val = style[key]; el.style[key] = val; } } else { value = content; } if (urlRx.test(value)) { el.innerHTML = ''; return el.style.backgroundImage = "url(" + value + ")"; } else { return el.innerHTML = value; } }; |
Функция _setSides одна из важных в HexaFlip, так как она отображает значений наборов для всех четырех активных граней куба:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
HexaFlip.prototype._setSides = function(cube) { var bottomAdj, faceOffset, offset, set, setLength, setOffset, topAdj; cube.el.style[css.transform] = this._getTransform(cube.yDelta); cube.offset = offset = Math.floor(cube.yDelta / 90); if (offset === cube.lastOffset) { return; } cube.lastOffset = faceOffset = setOffset = offset; set = this.sets[cube.set]; setLength = set.length; if (offset < 0) { faceOffset = setOffset = ++offset; if (offset < 0) { if (-offset > setLength) { setOffset = setLength - -offset % setLength; if (setOffset === setLength) { setOffset = 0; } } else { setOffset = setLength + offset; } if (-offset > 4) { faceOffset = 4 - -offset % 4; if (faceOffset === 4) { faceOffset = 0; } } else { faceOffset = 4 + offset; } } } if (setOffset >= setLength) { setOffset %= setLength; } if (faceOffset >= 4) { faceOffset %= 4; } topAdj = faceOffset - 1; bottomAdj = faceOffset + 1; if (topAdj === -1) { topAdj = 3; } if (bottomAdj === 4) { bottomAdj = 0; } this._setContent(cube[faceSequence[topAdj]], set[setOffset - 1] || set[setLength - 1]); return this._setContent(cube[faceSequence[bottomAdj]], set[setOffset + 1] || set[0]); }; |
Когда мышка находится в зажатом состоянии, то данная функция будет отображаться методом _onTouchMove:
1 2 3 4 5 6 7 8 9 |
HexaFlip.prototype._onTouchMove = function(e, cube) { if (!cube.touchStarted) { return; } e.preventDefault(); cube.diff = (e.pageY - cube.y1) * this.touchSensitivity; cube.yDelta = cube.yLast - cube.diff; return this._setSides(cube); }; |
Когда будем отпускать кнопку мыши будет срабатывать функция _onTouchEnd:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
HexaFlip.prototype._onTouchEnd = function(e, cube) { var mod; cube.touchStarted = false; mod = cube.yDelta % 90; if (mod < 45) { cube.yLast = cube.yDelta + mod; } else { if (cube.yDelta > 0) { cube.yLast = cube.yDelta + mod; } else { cube.yLast = cube.yDelta - (90 - mod); } } if (cube.yLast % 90 !== 0) { cube.yLast -= cube.yLast % 90; } cube.el.classList.remove('no-tween'); return cube.el.style[css.transform] = this._getTransform(cube.yLast); }; |
Значение getValue будет выполнять обратную задачу, он получает текущее значение стороны кубиков это делается для того, чтобы функции знали текущее положение происходящего на экране:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
HexaFlip.prototype.getValue = function() { var cube, offset, set, setLength, _ref1, _results; _ref1 = this.cubes; _results = []; for (set in _ref1) { cube = _ref1[set]; set = this.sets[set]; setLength = set.length; offset = cube.yLast / 90; if (offset < 0) { if (-offset > setLength) { offset = setLength - -offset % setLength; if (offset === setLength) { offset = 0; } } else { offset = setLength + offset; } } if (offset >= setLength) { offset %= setLength; } if (typeof set[offset] === 'object') { _results.push(set[offset].value); } else { _results.push(set[offset]); } } return _results; }; |
Мы будем работать с двумя дополнительными методами flip и flipBack. Первый переворачивает куб вперёд, а второй назад, соответственно на 90 градусов:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
HexaFlip.prototype.flip = function(back) { var cube, delta, set, _ref1, _results; delta = back ? -90 : 90; _ref1 = this.cubes; _results = []; for (set in _ref1) { cube = _ref1[set]; if (cube.touchStarted) { continue; } cube.yDelta = cube.yLast += delta; _results.push(this._setSides(cube)); } return _results; }; HexaFlip.prototype.flipBack = function() { return this.flip(true); }; |
Вот и все. Готово!
Материал взят из зарубежного источника. И представлен исключительно в ознакомительных целях.
Читайте также:
Опубликовал Cooper 28.03.2013 в 23:46, в категории Плагины. Вы можете следить за комментариями через RSS 2.0. Вы можете перейти в конец записи и оставить комментарий. Пинги запрещены. |