Авторизация







Регистрация / Забыли пароль?

Регистрация нового пользователя











< Назад

Восстановление пароля





< Назад

Добро пожаловать

Выход


Ежедневное обновление статей и уроков, будь в курсе, держи руку на пульсе событий!

Главная >> jQuery

HEXAFLIP - Величественный jQuery плагин создающий 3D кубы под разные запросы вашего сайта


HexaFlip – передовой jQuery плагин, который позволит вам использовать 3D кубики, в роли элементов интерфейса. Давайте погрузимся в процесс создания превосходного плагина, чтобы узнать некоторые передовые практики в отношении гибкого пользовательского интерфейса.


    Уважаемые друзья, сегодня, я хотел бы поделиться с вами процессом создания гибкого JavaScript UI плагина, который я уже успел назвать HexaFlip.

    В последнее время, для создания своих экспериментальных плагинов пользовательского интерфейса, я использую JavaScript в сочетании с современными CSS технологиями (например, oriDomi и Maskew). 

    Как мы все знаем, куб имеет шесть сторон, но при вращении его вокруг одной оси, мы сможем наблюдать только четыре (переднюю, заднюю, верхнюю и нижнюю). Данный же плагин, имеет возможность не ограничиваться всего 4 сторонами, мы можем задать сколько угодно благодаря циклу.

    Пожалуйста, обратите ваше внимание, что данный плагин, использует некоторые CSS3 свойства, а значит для его работы, ваш браузер должен их поддерживать.

    Разметка

    HexaFlip предназначен, для использования его в качестве плагина. Всю необходимую разметку, он создаст сам исходя из введённых в него параметров. Для каждого демонстрационного примера, нам необходим только один элемент:

<div id="hexaflip-demo1" class="demo"></div>

    id и class здесь, лишь для удобства, в случае если мы хотим добавить специальные стили, для нашего экземпляра.

    CSS

    (Примечание: для краткости, следующие фрагменты стилей, не используют любые префиксы, хотя они включены в источник).

    Каждый элемент, создающийся с помощью HexaFlip, автоматически имеет класс hexaflip-cube. На основе этого, и тех опций которые задали вы, применяется стилизация к созданной плагином структуре.

.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;
}

    Для того чтобы пользователь видел, что кубом можно манипулировать, значение курсора при наведении на куб мы ставим в move. Два стиля для курсора, move и grab, мы создали в роли запасного варианта, grab будет применяться для активного куба. Свойство display мы установим в inline-block, чтобы наши кубы, находились рядом друг с другом, а position в relative, чтобы позволить JS впоследствии устанавливать z-index. transform-style особенно важен при использовании кубов, ведь каждая из шести сторон, сможет независимо изменяться в своём 3D пространстве. Если мы не установим preserve-3d, то кубы будут казаться плоскими.  И наконец, давайте зададим время для переходов всех сторон куба при вращении с помощью transition.

    Далее мы создаём класс no-tween, который запретит анимацию кубика с помощью JS, если на нём зажата кнопка мыши.

.hexaflip-cube.no-tween {
  transition-duration: 0;
}

    Этот класс, просто отключает анимацию для выбранного куба, и движение возможно непосредственно во время взаимодействия.

    Каждая сторона куба, будет вложена в блок div, поэтому для доступа ко всем сторонам, мы будем применять селектор (>) с необходимыми стилями:

.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;
}

    Вы можете заметить, что высота установлена на 100.5%. Это делается для того, чтобы лицевая сторона каждого куба, была чуть больше других его сторон, чтобы не были заметны искажения, несовпадения и трещины во время 3D CSS преобразований.  Каждой лицевой стороне, мы задали абсолютное позиционирование, чтобы прежде чем они будут преобразованы в 3D пространстве, они налагались друг на друга. Мы так же применяем свойство user-select: none, чтобы текст внутри элемента не смог быть выделен. background-size: cover действует так, что фоновое изображение которое мы хотим применить к лицевой стороне куба, не искажалось, а просто заполняло её. Остальные свойства CSS, просто задают некоторые стили, которые вы можете изменить если хотите, для стиля вашей странички.

    Следующие стили, нужны для того, чтобы стороны куба, которые в данный момент не отображаются, имели по умолчанию серый цвет:

.hexaflip-left, .hexaflip-right {
  background-color: #555 !important;
}

    Сторонам куба, мы так же можем присваивать различные цвета фона. Этот CSS будет заключительным, и здесь мы определим простой цвет для сменившейся стороны куба с помощью псевдо – класса :nth-child(odd).

.hexaflip-timepicker .hexaflip-cube:last-child > div:nth-child(odd) {
  background-color: #ff575b;
}

    JavaScript

    (Примечание: HexaFlip изначально был создан в CoffeeScript, оригинал включён в список загружаемых файлов. Давайте я расскажу вам о каждом шаге создания плагина на JavaScript).

    Мы начнём с определения начала и конца функции, чтобы после наполнить её всеми необходимыми элементами. Глобальные переменные среды, мы пока опустим. Этот способ особенно хорош, в случае если мы создаём плагин предназначенный для интеграции с другими проектами.

(function() {
    //...
}).call(this);

    После определения переменных, мы должны решить вопрос о поддержки необходимых CSS3 свойств, и создании необходимых префиксов под разные браузеры. Следующий блок кода, описывает цикл, который и будет выяснять, поддерживается ли CSS3 свойство или нет. Если соответствие не найдено, то функция возвратит нам false, для обозначения того, что браузер не поддерживает данное свойство.

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 свойства (трансформация и перспектива), хранить их мы будем в виде литерала объекта с названием css:

css = {};
 
_ref = ['Transform', 'Perspective'];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
  prop = _ref[_i];
  css[prop.toLowerCase()] = prefixProp(prop);
}

    Для работы плагина, нам необходимы некоторые параметры. Если пользователь не использует конкретные настройки, то нам необходимо создать вариант по умолчанию:

defaults = {
  size: 280,
  margin: 10,
  fontSize: 185,
  perspective: 1000,
  touchSensitivity: 1
};

   Кроме того, мы определим некоторые статические свойства, которые будут распространяться на все случаи HexaFlip:

cssClass = baseName.toLowerCase();
 
faceNames = ['front', 'bottom', 'back', 'top', 'left', 'right'];
 
faceSequence = faceNames.slice(0, 4);
 
urlRx = /^((((https?)|(file)):)?\/\/)|(data:)|(\.\.?\/)/i;

    urlRx – простое регулярное выражение, которое мы будем использовать для дальнейших работ со значениями из URL – адреса. Если строка будет начинаться с http, https, file, data:, //, ./, или ../ то HexaFlip предположит, что это URL, и загрузит как изображение к лицевой стороне куба.

    После того, как мы разобрались с путями загрузки, мы можем определить поведение HexaFlip с помощью его конструктора и прототипа. Если вы не знакомы с данной системой, мы собираемся создать функцию, которая будет создавать каждый экземпляр HexaFlip. Путём установки свойства для этой функции в виде объект-прототипа, мы определим функции для каждого экземпляра, который будет создаваться в будущем. Подчёркивание префиксом свойств, обозначает, что это свойство предназначено только для внутреннего использования HexaFlip, и пользователю, как правило, доступ к ним не нужен.

    Наш конструктор будет принимать 3 значения: целевой элемент DOM, литерал объекта, содержащий наборы для отображения, и дополнительный объект настроек, для переопределения значений по умолчанию. Эти 3 аргумента, являются приложением к экземпляру (this):

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 : {};

    Каждый ключ в наборе sets, будет создавать новый куб. Значения для него, должны быть в форме массива значений, для отображения граней куба.

    Перед тем как начать работу, конструктор проверяет поддержку CSS3 свойств, и выдаёт соответствующий результат. Если он отрицательный, конструктор сразу прекращает работу.

if (!(css.transform && this.el)) {
  return;
}

    Блок приведённый ниже, в случае неполного указания опций, заполняет недостающие, значениями по умолчанию:

for (option in defaults) {
    value = defaults[option];
    this[option] = (_ref1 = this.options[option]) != null ? _ref1 : defaults[option];
  }
  if (typeof this.fontSize === 'number') {
    this.fontSize += 'px';
  }

    Если пользователь не ввёл настройки sets, мы будем продолжать настраивать плагин для случая time-picker. Следующий блок, содержит несколько простых циклов, которые создают время в часах и минутах с интервалом 10 минут:

if (!this.sets) {
  this.el.classList.add(cssClass + '-timepicker');
  this.sets = {
    hour: (function() {
      var _j, _results;
      _results = [];
      for (i = _j = 1; _j <= 12; i = ++_j) {
        _results.push(i + '');
      }
      return _results;
    })(),
    minute: (function() {
      var _j, _results;
      _results = [];

      for (i = _j = 0; _j <= 5; i = ++_j) {
        _results.push(i + '0');
      }
      return _results;
    })(),
    meridian: ['am', 'pm']
  };
}

    Далее мы должны пройти через цикл, который установит ряд настроек. Для добавления куба, создаётся объект _createCube, и добавляется к документу. С помощью общего числа кубов, мы зададим им необходимый z-index, чтобы они правильно позиционировались на странице. Далее мы разобьём длину страницы на 2 части, и будем увеличивать z-index до середины, а после уменьшать. Благодаря 3D перспективе, мы сделаем так, что видно будет лицевые стороны кубов, и не видно боковых и верхних. Если мы не выполним эти шаги, кубы во второй половине середины, будут как бы сидеть друг на друге, и мы не получим необходимого результата.

setsKeys = Object.keys(this.sets);
setsLength = setsKeys.length;
cubeFragment = document.createDocumentFragment();
i = z = 0;
midPoint = setsLength / 2 + 1;
this.cubes = {};
_ref2 = this.sets;
for (key in _ref2) {
  set = _ref2[key];
  cube = this.cubes[key] = this._createCube(key);
  if (++i < midPoint) {
    z++;
  } else {
    z--;
  }
  cube.el.style.zIndex = z;
  this._setContent(cube.front, set[0]);
  cubeFragment.appendChild(cube.el);
  for (_j = 0, _len1 = set.length; _j < _len1; _j++) {
    val = set[_j];
    if (urlRx.test(val)) {
      image = new Image;
      image.src = val;
    }
  }
}

    В конце этого цикла, вы заметите ещё один цикл, который перебирает значения набора, и использует регулярное выражение определённое выше, для проверки URL адресов. Если есть соответствие, мы можем предположить, что пользователь хочет использовать изображение, для него мы построим объект в памяти, чтобы заставить браузер, предварительно загрузить его. Идея заключается в том, чтобы пользователь вращая куб, не увидел тех изображений, которые не предусмотрены, что могло бы снизить эффективность плагина.

    Конструктор завершает свою работу, установив правильную высоту, ширину и перспективу для элементов контейнера и добавляет кубы.

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);

    Далее, давайте рассмотрим наш первый метод, использовавшийся ранее в конструкторе:

HexaFlip.prototype._createCube = function(set) {
  var cube, eString, eventPair, eventPairs, rotate3d, side, _fn, _j, _k, _l, _len1, _len2, _len3,
    _this = this;
  cube = {
    set: set,
    offset: 0,
    y1: 0,
    yDelta: 0,
    yLast: 0,
    el: document.createElement('div')
  };
  cube.el.className = "" + cssClass + "-cube " + cssClass + "-cube-" + set;
  cube.el.style.margin = "0 " + this.margin + "px";
  cube.el.style.width = cube.el.style.height = this.size + 'px';
  cube.el.style[css.transform] = this._getTransform(0);

    Каждый куб, это просто литерал объекта, который содержит все необходимые DOM элементы. Для создания 3х мерного куба из 6 плоских слоёв, мы должны применить цикл ко всем лицевым сторонам, и указать определённые стили для оси и угла вращения названий этих слоёв:

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 задаёт правила использования наших кубов, точнее варианты манипуляций с помощью мыши и сенсорных экранов:

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;
};

    Следующий метод опирается на несколько других методов, идея его заключается в простой конкатенации строк, для создания значений CSS3:

HexaFlip.prototype._getTransform = function(deg) {
  return "translateZ(-" + (this.size / 2) + "px) rotateX(" + deg + "deg)";
};

   z-index мы установим в отрицательное значение, для того чтобы в 3D пространстве, текстура не стала расплывчатой.

    Далее мы видим функцию _setContent, которая будет иметь входным параметром лицевую сторону куба, и значение изображения на нём:

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;
  }
};

    HexaFlip, довольно гибкий плагин, ведь даже передав объект в пределах установленного массива, любое значение может иметь  специфический стиль. Если значение является объектом (не строка или число), мы проходим через цикл пар style:значение и применяем их к лицевой стороне куба.

[
    'hello',
    {
        value: 'i am green',
        style: {
            backgroundColor: '#00ff00'
        }
    }
]

    Где первый элемент (отображающий «hello»), будет иметь стиль по умолчанию, а второй, всегда отображаться на зелёном фоне.

    Наконец  _setContent проверяет значение URL и применяет фоновое изображение соответственно.

    _setSides является наиболее важным методом HexaFlip, так как занимается отображением значений наборов для всех четырех активных граней куба:

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]);
};

    В общем, этот метод вычислит сколько раз был перевернут куб относительно начального положения, и применит необходимый индекс массива значений.  Этот метод обрабатывает ряд таких случаев, когда число лицевых сторон куба меньше числа значений в массиве, а так же при вращении в обратном порядке. Ключом к иллюзии показа большего числа результатов чем сторон у куба, кроется в выводе текущего topAdj и bottomAdj сверху и снизу смежных сторон. Эти стороны являются относительными сторонами, и пользователь их не видит до тех пор, пока не переключится, поэтому мы можем незаметно изменить их, и создастся необходимый эффект. Этой хитростью будет заниматься наш метод, когда мы видим какую-либо лицевую сторону куба, каждый раз он будет назначать всё новые значения из массива и продолжать вращение, даже если значения массива закончились, т.е. начнёт показ сначала.

    Далее, нас ожидает коллекция методов, которые будут обрабатывать мышь и сенсорные экраны.  _onTouchStart вызывается во время прикосновения (или нажатия кнопки) и устанавливает начальную точку прикосновения  (touchStarted) на актуальном кубе. Стоит отметить, что кнопки мыши в данный момент, так же активны. Затем этот метод, медленно отключает  анимацию по умолчанию, предусмотренную переходами CSS, и добавляет анимацию .no-tween к классу стороны. Это сделано для того, чтобы куб вращался плавно. Движение мыши, наш следующий метод. И наконец, начальное положение мыши (или зажатой кнопки) записывается, так что позже мы сможем вычислить, как далеко он продвинулся:

HexaFlip.prototype._onTouchStart = function(e, cube) {
  e.preventDefault();
  cube.touchStarted = true;
  e.currentTarget.classList.add('no-tween');
  if (e.type === 'mousedown') {
    return cube.y1 = e.pageY;
  } else {
    return cube.y1 = e.touches[0].pageY;
  }
};

    Зажатая мышь и её смещение в это время, обрабатывается методом _onTouchMove:

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);
};

    Этот метод вызывается постоянно во время прокручивания куба пользователем, и вычисляется пройденное курсором расстояние в пикселях, в y1 мы записываем последнее смещение. yDelta – пройденное расстояние, + все предыдущие обороты в прошлом. _setSides возвращает обновление куба, его отображение с помощью цикла. _setSides так же принимает значение  yDelta, чтобы все DOM элементы куба, в результате получили правильные стили. В конечном итоге, наш куб поворачивается к нам актуальной стороной, и готов к новым пользовательским манипуляциям.

    Когда пользователь отпускает кнопку мыши, срабатывает  _onTouchEnd:

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);
};

    В большинстве случаев, пользователь будет отпускать кнопку мыши, в то время, как куб находится в движении, т.е. его угол наклона не равен 90 градусам. Вместо того чтобы его развернуть на 90 градусов, мы вычислим остаток от текущего вращения до 90, и изменим его. Перед применением этого вращения, мы должны убрать класс no-tween и результатом будет плавная анимация, к надлежащему положению куба.

    Вращение куба возможно как использованием мыши, так и с помощью сенсорных экранов. Последнее, не поддерживает событие mouseleave, поэтому мы будем использовать polyfill для этого случая:

HexaFlip.prototype._onTouchLeave = function(e, cube) {
  if (!cube.touchStarted) {
    return;
  }
  return this._onTouchEnd(e, cube);
};
 
HexaFlip.prototype._onMouseOut = function(e, cube) {
  if (!cube.touchStarted) {
    return;
  }
  if (e.toElement && !cube.el.contains(e.toElement)) {
    return this._onTouchEnd(e, cube);
  }
};

    Далее, мы должны преобразовать наши методы так, чтобы их стало возможно использовать другими разработчиками. Ведь полезность нашего плагина будет ограниченна, если мы не сможем манипулировать значениями извне. Чтобы изменить лицевую сторону куба, мы создадим метод setValue, который будет принимать литерал объекта с ключом для каждого куба, и устанавливать соответствующие значения для отображения:

HexaFlip.prototype.setValue = function(settings) {
  var cube, index, key, value, _results;
  _results = [];
  for (key in settings) {
    value = settings[key];
    if (!(this.sets[key] && !this.cubes[key].touchStarted)) {
      continue;
    }
    value = value.toString();
    cube = this.cubes[key];
    index = this.sets[key].indexOf(value);
    cube.yDelta = cube.yLast = 90 * index;
    this._setSides(cube);
    _results.push(this._setContent(cube[faceSequence[index % 4]], value));
  }
  return _results;
}; 

    Логика проста: с помощью indexOf, мы получим текущую позицию стороны куба из массива, и повернём его на 90 градусов, показав следующую сторону.

    getValue выполняет обратную задачу, он получает текущее значение стороны кубиков. Хотя это может показаться и очевидным для пользователя, но внешним функциям необходимо знать текущее положение дел на экране пользователя:

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;
};

    Выше, мы написали цикл, который делает проход по всем кубам и определяет позиции для каждого из них в массиве значений, опираясь на угол вращения 90 градусов. Результатом будет являться массив значений для каждого куба.

    Наконец, у нас так же есть два удобных метода flip и flipBack. Первый переворачивает куб вперёд, а второй назад, соответственно на 90 градусов. И хотя это возможно сделать так же с помощью setValue, но для разработчика, было бы скучно получать значение таким способом, поэтому обращаться к первоначальному значению, определять текущую позицию стороны куба, и менять направление движения, так flipBack просто накладывает дополнительную функциональность, без дополнительных настроек.

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);
};

    setValue будет игнорировать любой куб, с которым в настоящее время, работает пользователь.

    Фуф, ну наконец-то! Надеюсь вы получили некоторое представление о HexaFlip, прониклись в мыслительный процесс передовой практики плагиностроения в отношении гибкого пользовательского интерфейса.

    Демонстрации

1. Значение по умолчанию:  попробуйте манипулировать каким-либо кубом с помощью мыши;
2. Выбор времени:  перетащите кубики или используйте меню, чтобы установить время;
3. Изображения в цикле: обратите внимание, что количество изображений превышает четыре стороны куба;
4. Эксперимент с визуальным паролем: пароль “красный желтый синий зеленый”. Сможете его набрать?

    Иллюстрации к демонстрационным примерам, предоставил Jason Custer.

    Материал взят из зарубежного источника. И представлен исключительно в ознакомительных целях.


Дата публикации: 13.03.2013
Опубликовал: Сергей Кашурин
Просмотров: 715
Правила перепечатки

Правила перепечатки

Уважаемый посетитель сайта!
Ниже преведены условия использования и перепечатки материалов сайта /
Все материалы данного сайта подготовлены для Вас лично мной.

Большая часть материалов сайта - это авторские уроки, остальные, это переводы уроков с английского языка на русский.
Если Вы решили использовать материалы данного сайта где-то на своих ресурсах или в рассылке, то соблюдайте следующие требования:
1. Урок или статья должны перепечатываться «как есть» с сохранением всех ссылок на источник урока, а если это перевод, то и на сайт, авторы которого подготовили его.
2. Ссылки на сайт источника и переводчика обязательно должны быть работоспособными (при нажатии по ссылке человек должен перейти на сайт автора/переводчика). Если Вы перепечатали какой-либо документ, обязательно проверьте ссылку на работоспособность.
3. Искажение информации об авторе, источнике, переводчике при перепечатке материалов запрещено!
4. Содержание урока или статьи при перепечатке не должно подвергаться модификациям и переделке. Все уроки и статьи, размещенные на сайте, должны перепечатываться как есть. Вы не имеете права урезать, исправлять или иным образом коверкать републикуемый документ.
С уважением, Сергей Кашурин– владелец сайта /


arcticModal - простые модальные окна jQuery
В поисках простого плагина для создания модальных окон, я перепробовал кучу вариантов, наткнувшись на arcticModal я остановился. Простота работы, вес самого плагина меня очень порадовали, поэтому поделюсь с вами я именно им, так как сам его проверял.
5 прекраснейших дизайнерских решений для ваших форм входа
Уважаемые друзья, в этом уроке, собраны 5 красивейших форм регистрации/авторизации, с пошаговым объяснением, и с возможность бесплатно скачать. Вы всё ещё думаете читать или нет? А кто-то уже вовсю пользуется ими!
Colorizer: пользователь сам выберет цвет продукта на вашем сайте
Когда вы выбираете машину, или футболку в интернет магазине, хотелось бы вам самим выбрать для неё цвет? Думаю да. В этой статье, я расскажу вам про плагин Colorizer, с помощью которого, для наших дорогих пользователей, мы сможем предоставить возможность выбора цвета продукта в котором он заинтересован, что оставит о нас приятное впечатление и заявку на покупку. jQuery плагин Colorizer - изменим цвет к лучшему.

Уроки и статьи

«Найден Самый Дешевый и Эффективный Способ Рекламы в Интернете!»

Доказанo: ведение своей почтовой рассылки - это самый действенный и дешевый метод рекламы в Интернете.

Используете ли Вы его?

Если нет, то Вы давно теряете свои деньги! Если да, то пришло время вести Вашу почтовую рассылку на самом эффективном инструменте в Рунете - сервисе рассылок SmartResponder.ru

Узнать об этом подробнее >>

Быть в курсе всех событий: