Интересное меню с помощью спрайтов

В сегодняшнем уроке я более детально расскажу Вам про спрайты и как с их помощью сделать интересное меню.

Спрайты (Sprites) очень часто используется на больших сайтах (Yahoo!, Google, Amazon и другие), но очень редко для "нормальных" проектов. Причина для этого очень проста - многие вебмастера не хотят вникать в тонкости данной темы, им кажется, что это очень сложно. На самом же деле ничего сложного в этом нет. Главное начать :)

И начнем мы с создания очень интересного меню. В эстетическом плане оно не представляет ничего особенного, но его функциональность заинтересует любого.

Для использования данного меню нам понадобится одна картинка, немного JavaScript и калькулятор )).

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

В нашем примере мы используем 4 шага с картинкой для каждого шага.

Определяем местонахождение элемента спрайта

При работе со спрайтами мы должны знать где находится каждый элемент по отношению к нашей анимации - в % соотношении.

Для рассчета нам понадобится информация о ширине изображения и о месте старта нашей цели. Узнав эти две цифры, нам необходимо сделать небольшие рассчеты.

To calculate this as an approximation, we need to know the image’s width and where our target starts. With this two numbers, we just need to apply simple math to get what we want.

Картинка выше шириной 183 пикселя, а второй шаг находится на расстоянии 57 пикселей от левого края. У нас получится 31.15% (57/183 = 0.3115).

Маскировка

Основа спрайтов заключается в показе только того, что необходимо. Остальное необходимо спрятать или замаскировать. Для этого нам необходимо знать точный размер каждого элемента. В данном пример мы можем использовать прямоугольник 13 на 20 для показа одного кадра.

CSS и HTML

Мы можем сделать первую часть нашего меню используя CSS+HTML, и говоря "первая часть" я имею ввиду статическую версию меню. Используя HTML мы задаем структуру, которая состоит из 3 слоев (один главный контейнер, один для маскировки и один для анимированого элемента), а также один элемент "a" (гиперссылка)
<div class="item">
<div id="doctor" class="object"></div>
<div id="doctormask" class="mask"></div>
<a href="#">Parents</a>
</div>
<div class="item">
<div id="girl" class="object"></div>
<div id="girlmask" class="mask"></div>

<a href="#">Geirls</a>
</div>
<div class="item">
<div id="boy" class="object"></div>
<div id="boymask" class="mask"></div>
<a href="#">Boys</a>
</div>
<div class="item">
<div id="kid" class="object"></div>
<div id="kidmask" class="mask"></div>
<a href="#">Kids</a>
</div>   

CSS позволяет задать нам начальные позиции для каждого анимированого элемента и их масок.
body {
background:#eeeeee;
}
#parent {
      width:14px;
      height:20px;
      background:url(people.gif);
      background-position:0% 0%;
      border:none;
      position:absolute;
      z-index:10;
      }
#parentmask {
      background:#ffffff;
      width:120px;
      height:20px;
      position:absolute;
      z-index:1;

      margin-left:8px;
      }
#girl {
      width:16px;
      height:20px;
      background:url(people.gif);
      background-position:27.2% 0%;
      border:none;
      position:absolute;
      z-index:10;
      }
#girlmask {
      background:#ffffff;
      width:120px;
      height:20px;
      position:absolute;
      z-index:1;
      margin-left:8px;
      }
#boy {
      width:16px;
      height:20px;
      background:url(people.gif);
      background-position:53.8% 0%;

      border:none;
      position:absolute;
      z-index:10;
      }
#boymask {
      background:#ffffff;
      width:120px;
      height:20px;
      position:absolute;
      z-index:1;
      margin-left:8px;
      }
#kid {
      width:16px;
      height:20px;
      background:url(people.gif);
      background-position:79.9% 0%;
      border:none;
      position:absolute;
      z-index:10;
      }
#kidmask {
      background:#ffffff;
      width:120px;
      height:20px;
      position:absolute;
      z-index:1;
      margin-left:8px;
      }
.item {
      background:#cccccc;
      width:128px;
      height:20px;
      }
.item a {
      margin-left:20px;
      }

Давайте взглянем на элемент #boy, который говорит нам, что его размер 16×20 пикселей, делить свое фоновое изображение с другими элементами (people.gif), а также мы хотим начать показ с 53.8% от левой стороны и 0% от верхнего края. Для других элементов все сделано по аналогии.

В результате этого CSS+HTML у нас выйдет вот это:

jQuery

Первым делом я создал контрольные переменные, которые позволили мне пометить каждый элемент с его относительной позицией на фоне, а также контролировать процесс анимации.
var foot = [50,0,100,0];
  var step = 12;
  var sleeptime = 70;
  var mapping = Array();
  mapping["parent"] = { xr:20, xl:6.6, np:"0% 0%" };
  mapping["girl"] = { xr:47.5, xl:33, np:"27.2% 0%" };
  mapping["boy"] = { xr:74, xl:60.4, np:"53.8% 0%" };
  mapping["kid"] = { xr:100, xl:87, np:"79.9% 0%" };
px = function(val){

  return String(val)+"px";
  }
mpx = function(val){
  if(val == "auto")
  return 0;
  return Number(String(val).substring(0,String(val).length – 2));
  }

Так как все выравнено по горизонтали, мы используем “foot” как обычную переменную для того, чтобы задать вертикальную позицию каждого шага. К примеру, первый шаг на середине изображения 50%, второй шаг по верхнему краю изображения (0%) двигаясь сверху вниз.

“step” значит, что мы будем двигать наши элементы со скоростью 12 пикселей с задержкой 70 милисекунд. “px” и “mpx” только для того чтоб удалять строку “px” для данного аргумента.
$(document).ready(function(){ 
        $(".item").find(".mask").css("opacity","0.8");
        move = function(el,elmask){
                  var newleft;
                  if($(el).data("direction") == "R"){
                          if($(el).position().left >= $(el).parent().width()){
                                  $(el).css("background-position", mapping[$(el).attr("id")].np);
                                  $(el).data("isMoving",false);
                                  return;
                          }
                          newleft = $(el).position().left + step;
                          newwidth = $(elmask).width() – step;
                          newwidth = (newwidth < 0)?0:newwidth;

                  } else {
                          if($(el).position().left <= step){
                                  $(el).css("background-position", mapping[$(el).attr("id")].np);
                                  $(el).data("isMoving",false);
                                  return;
                          }

                          newleft = $(el).position().left – step;
                          newwidth = $(elmask).width() + step;
                  }
                  if($(el).data("index") == 4)
                          $(el).data("index",0);
                  var y = foot[($(el).data("index"))];
                  $(el).data("index",($(el).data("index")+1))
                  $(el).css("background-position",$(el).data("x")+"% "+y+"%").css("left",px(newleft));
                  $(elmask).css("left",px(newleft)).css("width",px(newwidth));
                  setTimeout(function(){ move(el,elmask); },sleeptime);
          }
        $(".item").each(function(){
                  $(this).find(".object").data("isMoving",false);
          });
        $(".item").mouseenter(function(e){
                  var obj = $(this).find(".object");
                  eval($(this).find("a").attr("rel"))
                  obj.data("x",mapping[obj.attr("id")].xr);
                  obj.data("index",0);
                  obj.data("direction","R");

                  if(!obj.data("isMoving")){
                          obj.data("isMoving",true);
                          move(obj.get(0),$(this).find(".mask").get(0));
                  }
          });
         $(".item").mouseleave(function(e){
                  var obj = $(this).find(".object");
                  eval($(this).find("a").attr("rel"))
                  obj.data("x",mapping[obj.attr("id")].xl);
                  obj.data("direction","L");
                  if(!obj.data("isMoving")){
                          move(obj.get(0),$(this).find(".mask").get(0));
                  }
          });
  });

С самого верха и до низа мы задаем маску с прозрачностью 80% (0.8). Далее мы определяем функцию “move” , которая берет элемент и его маску, и двигает исходя из информации, которая находится в контейнере “data”.

Весь CSS код + jQuery необходимо разместить в шапке документа, а также не забываем про подключение самого фреймворка:
<script type="text/javascript" src="jquery-1.3.2.min.js"></script>


Меню готово. Всем удачи!
Добавлено: 22 Августа 2013 11:23:18 Добавил: Андрей Ковальчук Нравится 0
Добавить
Комментарии:
Нету комментариев для вывода...