Spec-Zone.ru › Angular.js 1.7

Улучшить эту документацию ngAnimate

Установка

Сначала получите файл:

  • Google CDN например
    "//ajax.googleapis.com/ajax/libs/angularjs/X.Y.Z/angular-animate.js"
  • NPM например
    npm install --save angular-animate@X.Y.Z
    или
    yarn add angular-animate@X.Y.Z
  • Bower например
    bower install angular-animate#X.Y.Z
  • code.angularjs.org (не рекомендуется для использования в производстве) например
    "//code.angularjs.org/X.Y.Z/angular-animate.js"

где X.Y.Z — версия AngularJS, которую вы используете.

Затем включите angular-animate.js в свой HTML:

<script src="path/to/angular.js"></script>
<script src="path/to/angular-animate.js"></script>

Наконец, загрузите модуль в своё приложение, добавив его в качестве зависимого модуля:

angular.module('app', ['ngAnimate']);

Теперь вы готовы приступить к работе!

Модуль ngAnimate предоставляет поддержку анимаций на основе CSS (ключевые кадры и переходы), а также анимаций на основе JavaScript через обратные вызовы. Анимации по умолчанию не включены. Однако, включив ngAnimate, анимационные обратные вызовы будут включены для приложения AngularJS.

Использование

Проще говоря, есть два способа использовать анимации с помощью ngAnimate: с помощью CSS и JavaScript. Первый способ работает исключительно на основе CSS (используя соответствующие CSS селекторы/стили), а второй запускает анимации, зарегистрированные через module.animation(). Для анимаций CSS и JS единственное требование состоит в наличии соответствующего CSS class, которое существует как в зарегистрированной анимации, так и в HTML-элементе, на котором будет вызвана анимация.

Поддержка директивы

Следующие директивы «осознают» анимации:

Директива Поддерживаемые анимации
form / ngForm добавление и удаление (различные классы)
ngAnimateSwap ввод и вывод
ngClass / {{class}​} добавление и удаление
ngClassEven добавление и удаление
ngClassOdd добавление и удаление
ngHide добавление и удаление (класс ng-hide)
ngIf ввод и вывод
ngInclude ввод и вывод
ngMessage / ngMessageExp ввод и вывод
ngMessages добавление и удаление (классы ng-active/ng-inactive)
ngModel добавление и удаление (различные классы)
ngRepeat ввод, вывод и перемещение
ngShow добавление и удаление (класс ng-hide)
ngSwitch ввод и вывод
ngView ввод и вывод

(Дополнительную информацию можно найти, посетив документацию, связанную с каждой директивой.)

Для полного разбора шагов, вовлечённых в каждом анимационном событии, обратитесь к $animate документации API.

Анимации на основе CSS

CSS-анимации с ngAnimate уникальны тем, что не требуют никакого JavaScript-кода. Используя CSS-класс, на который мы ссылаемся между нашим HTML и CSS-кодом, мы можем создать анимацию, которая будет распознана AngularJS, когда базовая директива выполнит операцию.

Пример ниже показывает, как можно реализовать анимацию enter для элемента с использованием ng-if:

<div ng-if="bool" class="fade">
   Fade me in out
</div>
<button ng-click="bool=true">Fade In!</button>
<button ng-click="bool=false">Fade Out!</button>

Заметили CSS-класс fade? Теперь мы можем создать CSS-код перехода, который ссылается на этот класс:

/* The starting CSS styles for the enter animation */
.fade.ng-enter {
  transition:0.5s linear all;
  opacity:0;
}

/* The finishing CSS styles for the enter animation */
.fade.ng-enter.ng-enter-active {
  opacity:1;
}

Важно помнить, что в зависимости от события анимации (которое запускают вышеперечисленные директивы в зависимости от происходящих событий) к элементу будут применены два сгенерированных CSS-класса; в приведённом примере у нас есть .ng-enter и .ng-enter-active. Для CSS-переходов код перехода должен быть определён внутри начального CSS-класса (в данном случае .ng-enter). Класс назначения — это то, к чему будет анимироваться переход.

Если, например, мы хотели создать анимации для leave и move (ngRepeat запускает перемещение), то мы можем сделать это, используя ту же согласованность именования CSS:

/* now the element will fade out before it is removed from the DOM */
.fade.ng-leave {
  transition:0.5s linear all;
  opacity:1;
}
.fade.ng-leave.ng-leave-active {
  opacity:0;
}

Мы также можем использовать CSS-ключевые кадры, сославшись на анимацию ключевых кадров в исходном CSS-классе:

/* there is no need to define anything inside of the destination
CSS class since the keyframe will take charge of the animation */
.fade.ng-leave {
  animation: my_fade_animation 0.5s linear;
  -webkit-animation: my_fade_animation 0.5s linear;
}

@keyframes my_fade_animation {
  from { opacity:1; }
  to { opacity:0; }
}

@-webkit-keyframes my_fade_animation {
  from { opacity:1; }
  to { opacity:0; }
}

Вы можете смешивать переходы и ключевые кадры, а также любые другие CSS-классы в одном элементе.

Анимации на основе CSS-классов

Анимации на основе классов (анимации, которые запускаются через ngClass, ngShow, ngHide и некоторые другие директивы) имеют немного другую согласованность именования. Анимации на основе классов достаточно просты, чтобы стандартный переход или ключевой кадр можно было использовать в классе, добавляемом и удаляемом.

Например, если мы хотели сделать CSS-анимацию для ngHide, мы поместим анимацию в CSS-класс .ng-hide:

<div ng-show="bool" class="fade">
  Show and hide me
</div>
<button ng-click="bool=!bool">Toggle</button>

<style>
.fade.ng-hide {
  transition:0.5s linear all;
  opacity:0;
}
</style>

Всё, что происходит здесь с ngShow/ngHide за кулисами, — это добавление/удаление класса .ng-hide (когда состояние скрытия имеет место). Поскольку ngShow и ngHide «осознают» анимации, мы можем сопоставить переход, а ngAnimate позаботится о остальном.

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

<div ng-class="{on:onOff}" class="highlight">
  Highlight this box
</div>
<button ng-click="onOff=!onOff">Toggle</button>

<style>
.highlight {
  transition:0.5s linear all;
}
.highlight.on-add {
  background:white;
}
.highlight.on {
  background:yellow;
}
.highlight.on-remove {
  background:black;
}
</style>

Мы также можем использовать CSS-ключевые кадры, поместив их в CSS-классы.

Анимации с эффектом «ступенчатого» повторения

Анимация с эффектом «ступенчатого» повторения — это набор анимаций, выпущенных с небольшой задержкой между каждым последующим действием, что создаёт эффект шторки. Модуль ngAnimate (версии ≥1.2) поддерживает анимации с эффектом «ступенчатого» повторения, и этот эффект можно получить, создав CSS-класс ng-EVENT-stagger и добавив этот класс к основному CSS-классу, используемому для анимации. Свойство стиля, ожидаемое в классе stagger, может быть свойством transition-delay или animation-delay (или обоими, если ваша анимация содержит как переходы, так и анимации ключевых кадров).

.my-animation.ng-enter {
  /* standard transition code */
  transition: 1s linear all;
  opacity:0;
}
.my-animation.ng-enter-stagger {
  /* this will have a 100ms delay between each successive leave animation */
  transition-delay: 0.1s;

  /* As of 1.4.4, this must always be set: it signals ngAnimate
    to not accidentally inherit a delay property from another CSS class */
  transition-duration: 0s;

  /* if you are using animations instead of transitions you should configure as follows:
    animation-delay: 0.1s;
    animation-duration: 0s; */
}
.my-animation.ng-enter.ng-enter-active {
  /* standard transition styles */
  opacity:1;
}

Анимации с эффектом «ступенчатого» повторения по умолчанию работают в ngRepeat (при условии, что CSS-класс определён). За пределами ngRepeat для использования анимаций с эффектом «ступенчатого» повторения самостоятельно их можно запускать, вызывая несколько вызовов того же события в $animate. Однако ограничения заключаются в том, что каждый элемент должен иметь одинаковое значение CSS className и тот же родительский элемент. Операция stagger также будет сброшена, если с момента многократных вызовов $animate прошло одно или несколько анимационных кадров.

Следующий код вызовет событие ng-leave-stagger для указанного элемента:

var kids = parent.children();

$animate.leave(kids[0]); //stagger index=0
$animate.leave(kids[1]); //stagger index=1
$animate.leave(kids[2]); //stagger index=2
$animate.leave(kids[3]); //stagger index=3
$animate.leave(kids[4]); //stagger index=4

window.requestAnimationFrame(function() {
  //stagger has reset itself
  $animate.leave(kids[5]); //stagger index=0
  $animate.leave(kids[6]); //stagger index=1

  $scope.$digest();
});

Анимации с эффектом «ступенчатого» повторения в настоящее время поддерживаются только в CSS-определённых анимациях.

Класс CSS ng-animate

При анимации элемента с помощью ngAnimate к элементу будет применён CSS-класс ng-animate на время анимации. Это временный CSS-класс, и он будет удалён после завершения анимации (как для анимаций на основе JavaScript, так и на основе CSS).

Следовательно, анимации могут быть применены к элементу с помощью этого временного класса непосредственно через CSS.

.zipper.ng-animate {
  transition:0.5s linear all;
}
.zipper.ng-enter {
  opacity:0;
}
.zipper.ng-enter.ng-enter-active {
  opacity:1;
}
.zipper.ng-leave {
  opacity:1;
}
.zipper.ng-leave.ng-leave-active {
  opacity:0;
}

(Обратите внимание, что CSS-класс ng-animate зарезервирован и его нельзя применять к элементу напрямую, поскольку ngAnimate всегда удалит CSS-класс после завершения анимации.)

Класс ng-[event]-prepare

Это специальный класс, который можно использовать для предотвращения нежелательной мерцания/мигания содержимого перед началом фактической анимации. Класс добавляется сразу после инициализации анимации, но удаляется перед фактическим началом анимации (после ожидания $digest). Он также добавляется только для структурных анимаций (enter, move, и leave).

На практике мерцание может возникнуть при вложенности элементов со структурными анимациями, такими как ngIf, в элементы, имеющие анимации на основе классов, такие как ngClass.

<div ng-class="{red: myProp}">
  <div ng-class="{blue: myProp}">
    <div class="message" ng-if="myProp"></div>
  </div>
</div>

Возможно, что во время анимации enter div .message будет на мгновение виден, прежде чем он начнёт анимироваться. В таком случае вы можете добавить стили в CSS, которые обеспечат скрытие элемента перед началом анимации:

.message.ng-enter-prepare {
  opacity: 0;
}

Анимация при изменении значений

Иногда вам нужно анимировать между различными состояниями выражения, значения которых необязательно должны быть известны или указаны в CSS-стилях. Если это возможно с помощью другой «директивы, осознающей анимации», этот конкретный случай всегда можно решить с помощью ngAnimateSwap, как показано в этом примере.

Обратите внимание, что ngAnimateSwap — это структурная директива, что означает, что она создаёт новый экземпляр элемента (включая все другие/дочерние директивы, которые он может иметь) и связывает его с новой областью видимости каждый раз, когда происходит swap. В некоторых случаях это может быть нежелательно (например, по причинам производительности или когда вы хотите сохранить внутреннее состояние в исходном экземпляре элемента).

Анимации на основе JavaScript

ngAnimate также позволяет использовать анимации, потребляемые JavaScript-кодом. Подход аналогичен CSS-анимациям (где есть общий CSS-класс, на который ссылается наш HTML-код), но дополнительно нам нужно зарегистрировать JavaScript-анимацию в модуле. С помощью функции модуля module.animation() мы можем зарегистрировать анимацию.

Давайте посмотрим пример анимации входа/выхода, использующий ngRepeat:

<div ng-repeat="item in items" class="slide">
  {{ item }}
</div>

Видите CSS-класс slide? Давайте воспользуемся этим классом для определения анимации, которую мы структурируем в коде модуля, используя module.animation:

myModule.animation('.slide', [function() {
  return {
    // make note that other events (like addClass/removeClass)
    // have different function input parameters
    enter: function(element, doneFn) {
      jQuery(element).fadeIn(1000, doneFn);

      // remember to call doneFn so that AngularJS
      // knows that the animation has concluded
    },

    move: function(element, doneFn) {
      jQuery(element).fadeIn(1000, doneFn);
    },

    leave: function(element, doneFn) {
      jQuery(element).fadeOut(1000, doneFn);
    }
  }
}]);

Преимущество JS-анимаций заключается в возможности подключения других сервисов и использования расширенных библиотек анимации, таких как greensock.js и velocity.js.

Если наш код анимации основан на классах (то есть, что-то вроде ngClass, ngHide и ngShow его запускает), то мы все равно можем определять анимации внутри зарегистрированной анимации, однако входные аргументы функций немного отличаются:

<div ng-class="color" class="colorful">
  this box is moody
</div>
<button ng-click="color='red'">Change to red</button>
<button ng-click="color='blue'">Change to blue</button>
<button ng-click="color='green'">Change to green</button>
myModule.animation('.colorful', [function() {
  return {
    addClass: function(element, className, doneFn) {
      // do some cool animation and call the doneFn
    },
    removeClass: function(element, className, doneFn) {
      // do some cool animation and call the doneFn
    },
    setClass: function(element, addedClass, removedClass, doneFn) {
      // do some cool animation and call the doneFn
    }
  }
}]);

CSS + JS анимации вместе

AngularJS 1.4 и выше предпринял шаги, чтобы сделать объединение CSS и JS анимаций более гибким. Однако, в отличие от более ранних версий AngularJS, определение CSS и JS анимаций для работы с одним и тем же классом CSS больше не работает. Поэтому пример ниже будет только JS анимации будут управлять анимацией:

<div ng-if="bool" class="slide">
  Slide in and out
</div>
myModule.animation('.slide', [function() {
  return {
    enter: function(element, doneFn) {
      jQuery(element).slideIn(1000, doneFn);
    }
  }
}]);
.slide.ng-enter {
  transition:0.5s linear all;
  transform:translateY(-100px);
}
.slide.ng-enter.ng-enter-active {
  transform:translateY(0);
}

Значит ли это, что CSS и JS анимации не могут использоваться вместе? У JS-анимаций всегда более высокий приоритет? Мы можем компенсировать отсутствие CSS-анимаций, используя сервис $animateCss, чтобы запускать собственные настроенные CSS-анимации непосредственно из нашего собственного JS-кода анимации:

myModule.animation('.slide', ['$animateCss', function($animateCss) {
  return {
    enter: function(element) {
       // this will trigger `.slide.ng-enter` and `.slide.ng-enter-active`.
      return $animateCss(element, {
        event: 'enter',
        structural: true
      });
    }
  }
}]);

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

Сервис $animateCss очень мощный, поскольку мы можем передавать любые дополнительные свойства, которые будут оценены и переданы в CSS-переход или анимацию ключевых кадров. Например, если мы хотим анимировать высоту элемента, добавляя и удаляя классы, то мы можем сделать это, передав эти данные в $animateCss напрямую:

myModule.animation('.slide', ['$animateCss', function($animateCss) {
  return {
    enter: function(element) {
      return $animateCss(element, {
        event: 'enter',
        structural: true,
        addClass: 'maroon-setting',
        from: { height:0 },
        to: { height: 200 }
      });
    }
  }
}]);

Теперь мы можем заполнить остальное с помощью нашего CSS-кода перехода:

/* the transition tells ngAnimate to make the animation happen */
.slide.ng-enter { transition:0.5s linear all; }

/* this extra CSS class will be absorbed into the transition
since the $animateCss code is adding the class */
.maroon-setting { background:red; }

И $animateCss рассчитает остальное. Просто убедитесь, что обратный вызов done() запускает функцию doneFn, чтобы сигнализировать о завершении анимации.

Чтобы узнать больше о возможностях, посетите $animateCss сервис.

Привязка анимации (через ng-animate-ref)

ngAnimate в AngularJS 1.4 поставляется со способностью анимировать элементы между структурными областями приложения (например, представлениями), связывая элементы с помощью атрибута, называемого ng-animate-ref.

Предположим, например, что у нас есть два представления, управляемые ng-view, и мы хотим показать, что существует взаимосвязь между двумя компонентами, расположенными в этих представлениях. Используя атрибут ng-animate-ref, мы можем определить, что два компонента связаны вместе, и затем мы можем прикрепить анимацию, которая запускается при изменении представления.

Предположим, например, что у нас есть следующий шаблон кода:

<!-- index.html -->
<div ng-view class="view-animation">
</div>

<!-- home.html -->
<a href="#/banner-page">
  <img src="./banner.jpg" class="banner" ng-animate-ref="banner">
</a>

<!-- banner-page.html -->
<img src="./banner.jpg" class="banner" ng-animate-ref="banner">

Теперь, когда представление меняется (после нажатия ссылки), ngAnimate проверит содержимое HTML, чтобы увидеть, есть ли соответствие ссылки между компонентами в покидающем представлении и входящем представлении. Он просканирует как удаляемое (leave), так и вставляемое (enter) представление, чтобы увидеть, есть ли какие-либо спаренные DOM-элементы, содержащие соответствующее значение ref.

Два изображения совпадают, так как они имеют одинаковое значение ref. Теперь ngAnimate создаст элемент транспортировки (который является копией первого элемента изображения) и попытается анимировать его к позиции второго элемента изображения в следующем представлении. Для работы анимации специальный CSS-класс, называемый ng-anchor, будет добавлен к элементу транспортировки.

Теперь мы можем прикрепить переход к CSS-классу .banner.ng-anchor, и тогда ngAnimate обработает весь переход за нас, а также добавление и удаление любых изменений CSS-классов между элементами:

.banner.ng-anchor {
  /* this animation will last for 1 second since there are
         two phases to the animation (an `in` and an `out` phase) */
  transition:0.5s linear all;
}

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

.view-animation.ng-enter, .view-animation.ng-leave {
  transition:0.5s linear all;
  position:fixed;
  left:0;
  top:0;
  width:100%;
}
.view-animation.ng-enter {
  transform:translateX(100%);
}
.view-animation.ng-leave,
.view-animation.ng-enter.ng-enter-active {
  transform:translateX(0%);
}
.view-animation.ng-leave.ng-leave-active {
  transform:translateX(-100%);
}

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

В приведенном выше примере настраивается переход для обоих фаз (вход и выход), но мы также можем напрямую нацеливаться на фазы выхода или входа с помощью ng-anchor-out и ng-anchor-in.

.banner.ng-anchor-out {
  transition: 0.5s linear all;

  /* the scale will be applied during the out animation,
         but will be animated away when the in animation runs */
  transform: scale(1.2);
}

.banner.ng-anchor-in {
  transition: 1s linear all;
}

Демонстрация привязки

Как осуществляется транспортировка элемента?

При выполнении анимации привязки ngAnimate клонирует исходный элемент и помещает его точно в то место, где находится исходный элемент на экране, используя абсолютное позиционирование. Клонированный элемент будет размещен внутри корневого элемента приложения (где был определен ng-app), и все CSS-классы исходного элемента будут применены. Затем элемент будет анимирован в анимации out и in, и, в конечном итоге, достигнет координат и будет соответствовать размерам целевого элемента. В течение всей анимации к исходному и целевому элементам будет применен CSS-класс .ng-animate-shim для их скрытия (CSS-стили для класса: visibility:hidden). После достижения якорем пункта назначения он будет удален, и целевой элемент станет видимым, так как класс маски будет удален.

Как обрабатывается морфинг?

CSS-привязка опирается на переходы и ключевые кадры, и внутренний код достаточно интеллектуален, чтобы определить, какие CSS-классы отличаются между исходным и целевым элементами. Эти отличающиеся CSS-классы будут добавлены/удалены в элементе якоря, и будет применен переход (переход, предоставленный в классе якоря). Короче говоря, ngAnimate определит, какие классы добавить и удалить, что сделает переход элемента максимально плавным и автоматизированным. Используйте простые CSS-классы, которые не полагаются на структуру вложенности DOM, чтобы элемент якоря выглядел так же, как и исходный элемент (так как клонированный элемент размещается внутри корневого элемента, который, скорее всего, близок к тегу body).

Обратите внимание, что если корневой элемент находится в элементе <html>, то клонированный узел будет помещен внутрь тега body.

Использование $animate в вашем директиве кода

До сих пор мы изучали, как передавать анимации в приложение AngularJS, но как мы запускаем анимации внутри собственных директив в нашем приложении? Введя сервис $animate в наш код директивы, мы можем запустить структурные и основанные на классах крючки, которые затем могут быть использованы анимациями. Представьте себе поле приветствия, которое отображается и скрывается при изменении данных

<greeting-box active="onOrOff">Hi there</greeting-box>
ngModule.directive('greetingBox', ['$animate', function($animate) {
  return function(scope, element, attrs) {
    attrs.$observe('active', function(value) {
      value ? $animate.addClass(element, 'on') : $animate.removeClass(element, 'on');
    });
  });
}]);

Теперь CSS-класс on добавляется и удаляется из компонента поля приветствия. Теперь, если мы добавим CSS-класс поверх элемента поля приветствия в наш HTML-код, мы можем запустить CSS или JS анимацию.

/* normally we would create a CSS class to reference on the element */
greeting-box.on { transition:0.5s linear all; background:green; color:white; }

Сервис $animate содержит множество других методов, таких как enter, leave, animate и setClass. Чтобы узнать больше о возможностях, посетите $animate сервис API страницы.

Обратные вызовы и обещания

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

// somewhere within the depths of the directive
$animate.enter(element, parent).then(function() {
  //the animation has completed
});

(Обратите внимание, что в более ранних версиях AngularJS до v1.4 код обещания требовал обернуть его с помощью $scope.$apply(...). Это больше не так.)

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

ngModule.controller('HomePageController', ['$animate', function($animate) {
  $animate.on('enter', ngViewElement, function(element) {
    // the animation for this route has completed
  }]);
}])

(Обратите внимание, что вам необходимо запустить переваривание внутри обратного вызова, чтобы AngularJS заметил любые изменения, связанные с областью видимости.)

Компоненты модуля

Директива

Название Описание
ngAnimateChildren

ngAnimateChildren позволяет указать, что дочерние элементы этого элемента должны анимироваться, даже если у одного из родителей детей активна анимация. По умолчанию, когда у элемента есть активная enter, leave, или move (структурная) анимация, дочерние элементы, которые также имеют активную структурную анимацию, не анимируются.

ngAnimateSwap

ngAnimateSwap — это директива, ориентированная на анимацию, которая позволяет контейнеру удаляться и вставляться всякий раз, когда связанное выражение меняется. Распространенное использование этой директивы — это компонент вращающегося баннера или слайдера, который содержит одно изображение, присутствующее в данный момент. Когда активное изображение меняется, старое изображение выполнит анимацию leave, а новый элемент будет вставлен с помощью анимации enter.

Сервис

Название Описание
$animateCss

Сервис $animateCss — полезная утилита для запуска настраиваемых CSS-переходов/анимаций ключевых кадров из JS-анимации или непосредственно из директивы. Цель $animateCss — НЕ обойти механизм работы $animate и ngAnimate, а цель — позволить существующим анимациям или директивам создавать более сложные анимации, которые могут управляться исключительно с помощью CSS-кода.

$animate

Документация сервиса ngAnimate $animate идентична документации основного сервиса $animate.

© 2010–2018 Google, Inc.
Licensed under the Creative Commons Attribution License 4.0.
https://code.angularjs.org/1.7.8/docs/api/ngAnimate

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API