Дополнение Canvas HTML-разметкой: Часть 2. Анимация и визуализация текста

Преодоление препятствий с помощью наслоения

HTML Canvas превосходен во многих отношениях, включая высокую производительность при низких накладных расходах и возможность прямого манипулирования пикселями. Однако по нескольким статьям Canvas уступает HTML: в области отрисовки текста, поисковой оптимизации, доступности и аппаратно-независимой разметки. В первой статье этого цикла сравниваются сильные стороны традиционной HTML-модели и API Canvas. В ней также исследуются гибридные приложения HTML/Canvas. Из этой заключительной части читатель узнает, как реализовать пример приложения с визуализации текста средствами Canvas и как создать на основе Canvas игру с богатым пользовательский интерфейсом HTML, которая сочетает в себе сильные стороны обоих подходов.

Кевин Мут, инженер-программист, The Nerdery

Фото Кевина МутаКевин Мут (Kevin Moot) интересуется компьютерной графикой с момента появления на его машине Apple IIe (с ее широким спектром из шести цветов и невероятным разрешением 280x192) таких игр, как "Мальчик-с-пальчик". Работал с технологией Canvas, входящей в HTML5, при создании нескольких передовых Web-сайтов и включает в список своих специализаций HTML/CSS, JavaScript и .NET. В настоящее время ― разработчик интерактивного программного обеспечения в компании The Nerdery.



Райан Делюка, программист, The Nerdery

Фото Райана ДелюкиРайан Делюка (Ryan DeLuca) занимается программированием с 1998 года и со временем превратил свое хобби в карьеру оплачиваемого фрилансера. Затем решил формализовать свое образование и в 2011 году окончил Университет штата Висконсин со степенью бакалавра естественных наук. Вскоре поступил на работу в компанию Nerdery в качестве программиста, специализирующегося на PHP, JavaScript, CSS и HTML. В число его многих других специальностей входят реляционные базы данных/SQL и манипулирование графическими объектами.



18.02.2013

Введение

Часто используемые сокращения

  • CSS: Cascading style sheet / Каскадная таблица стилей
  • DOM: Document Object Model
  • HTML: Hypertext Markup Language
  • UI: User Interface / Интерфейс пользователя

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

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

Рисунок 1. Пример приложения, сочетающего элементы HTML и Canvas
Пример приложения, сочетающего элементы HTML и Canvas

Ссылки на исходный код примеров, приведенных в этой статье, указаны в разделе Загрузка.


Архитектура

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

Интерфейс пользователя

Хотя Canvas может обеспечить впечатляющую производительность графических операций, это не всегда лучший выбор для функционально насыщенного интерфейса пользователя. HTML-элементы лучше подходят для этой цели. Многофункциональные интернет-приложения часто состоят из разных частей, каждая из которых решает свои задачи и предъявляет свои требования. Гибридный подход, сочетающий в себе лучшие аспекты элементов Canvas и HTML, позволяет обеспечить достижение поставленных целей с наилучшим результатом.

В примере приложения используется техника послойного построения, как показано на рисунке 2. Слой Canvas преимущественно отвечает за графику и анимацию реального времени, в то время как несколько элементов HTML, плавающих над ним, составляют различные компоненты пользовательского интерфейса.

Рисунок 2. Наложение элементов HTML поверх Canvas
Наложение элементов HTML поверх Canvas

При выборе наилучшего подхода рассматриваются требования, предъявляемые отдельными частями приложения. Как правило, для слоя HTML лучше всего подходят компоненты пользовательского интерфейса, которые требуют высокого уровня интерактивности пользователя ― но не требуют обновления в режиме реального времени. Эти элементы могут содержать текст, гиперссылки и элементы форм.

Например, хотя образец приложения выполнен преимущественно в Canvas, в нем есть компонент чат-окна, в котором используется исключительно разметка HTML. Это показано на рисунке 3.

С помощью простых HTML-тегов и правил CSS легко создавать интерактивные компоненты пользовательского интерфейса, такие как текстовые поля, кнопки и полосы прокрутки. Зачем тратить много часов на попытки имитировать внешний вид и поведение компонентов пользовательского интерфейса средствами Canvas, когда браузер сделает это за вас?

Рисунок 3. Чат-окно, реализованное в HTML
Чат-окно, реализованное в HTML

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

И наоборот, Canvas ― гораздо лучшее решение в тех случаях, когда:

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

Анимация

Анимированное содержимое становится все более распространенным. Когда нужно создать простую анимацию в целях оживления Web-сайта (например, переходы при навигации) или более сложную игру на основе браузера, программист имеет в своем распоряжении несколько вариантов решений. Часто анимацию можно выполнить относительно легко с использованием модели HTML/CSS, а использование Canvas представляется избыточным.

Многие библиотеки, такие, как jQuery, содержат удобные инструменты, которые обеспечивают согласованный результат, не зависящий от браузера. Сочетание инструментов из этих библиотек с некоторым знанием CSS позволяет существенно уменьшить трудоемкость выполнения анимации — даже довольно сложной.

В нашем примере элемент космического корабля, показанный на рисунке 4, движется и вращается под управлением игрока. Это поведение можно реализовать исключительно средствами анимации HTML/CSS. В этом случае никакого знания Canvas не требуется.

Рисунок 4. Анимированный элемент космического корабля
Анимированный элемент космического корабля

Но когда речь заходит о масштабируемости, модель анимации HTML/CSS начинает проигрывать. Для одновременной анимации большого количества элементов требуется высокая загрузка браузера, а это понижает общую производительность приложения.

Каждый раз при перепозиционировании элемента DOM, которое для достижения гладкой анимации должно происходить несколько раз в секунду, механизм браузера пересчитывает и перекрашивает иерархию элементов DOM со значительным количеством накладных расходов. Умножьте это на десятки, сотни или тысячи элементов, и значительное снижение производительности будет заметно даже на самых современных компьютерах.


Текст в Canvas

Отображение текста на экране ― настолько типичная задача для любого Web-сайта, что легко забыть о колесиках, которые вращаются за кулисами. Когда нужно отобразить текст на экране, вы просто вводите его между парой тегов HTML-элемента, возможно, в сопровождении некоторых классов CSS, а остальное возлагаете на браузер. Однако в случае Canvas дело обстоит иначе.

Для отображения текста в Canvas имеется несколько основных инструментов. Они позволяют выполнить практически все те же основные функции, необходимые для создания почти всего, но не обеспечивают такой же простоты при разработке Canvas-приложений.

Основы

Объект context Canvas содержит различные свойства, которые можно устанавливать при визуализации текста. Он также предоставляет функции для фактической визуализации. В число свойств входят:

  • context.font

    context.font ― позволяет управлять семейством шрифтов, размером, весом и стилем отображаемого текста. Это одна строка с параметрами, которые отделены друг от друга пробелами.

    Формат ввода несколько многословен. Например, в этой строке нужно указывать семейство шрифтов каждый раз при изменении его значения. Листинг 1 демонстрирует параметры настройки для мелкого шрифта.

    Листинг 1. Параметры настройки мелкого шрифта
    context.font = 'italic 8px Arial';
    context.fillText('Variety is the spice of life!', 0, 50);

    Листинг 2 демонстрирует параметры настройки для крупного шрифта.

    Листинг 2. Параметры настройки крупного шрифта
    context.font = 'italic 20px Arial';
    context.fillText('Variety is the spice of life!', 0, 50);

    Нельзя однажды указать семейство шрифтов, а затем настраивать другие параметры в зависимости от того, какой текст отображается на экране. Способ решения этой проблемы обсуждается ниже;

  • context.fillStyle

    context.fillStyle используется для различных операций Canvas; в случае текста этот параметр устанавливает значение для управления цветом шрифта. Входной формат соответствует формату CSS. Ниже приведены допустимые примеры:

    • Основные цвета: 'red' (красный), 'blue' (синий), 'green' (зеленый) и т. д.
    • Шестнадцатеричные числа: '#rrggbb'
    • 'rgb(r, g, b)'
    • 'rgba(r, g, b, a)'

    Например, вот как задать параметр fillStyle: context.fillStyle = 'red';.

  • context.fillText()

    Эта функция вызывается для отображения текста в Canvas. Она принимает следующие параметры:

    • (string) text: текст, отображаемый в Canvas.
    • (float) x: координата x места, в котором будет создан текст.
    • (float) y: координата y места, в котором будет создан текст.
    • [optional] (float) maxWidth: Максимальная ширина области текста. Если это возможно, будет использоваться более плотный шрифт или даже шрифт меньшего размера.

Дополнительные инструменты

Важным дополнительным инструментом служит функция объекта контекста measureText(), которая принимает один строковый параметр. Результатом будет объект, содержащий измеренные размеры указанной строки, как показано в листинге 3.

Листинг 3. Определение ширины строки текста
context.font = '30px Arial';
var dim = context.measureText(
    'Hello, world!'
);
 
alert(
    'width: ' + dim.width + '\n' +
    'height: ' + dim.height
);

Листинг 3 отображает сообщение, как показано в листинге 4.

Листинг 4. Сообщение
    width: 164
    height: undefined

Обратите внимание на результат undefined (не определено) для высоты. Как ни странно, все браузеры всегда возвращают результат "не определено", поэтому на практике с помощью функции measureText() определить точную высоту текста невозможно. Существует несколько методов определения достаточно точного значения. Во многих шрифтах некоторые буквы близки к квадрату, такие как буква М. Можно измерить ширину одной из этих букв и использовать это значение в качестве приблизительной меры высоты шрифта.

Другой способ ― просто использовать указанный размер шрифта в качестве рабочей высоты. Если в приведенном выше примере задано значение 30px, можно добавить несколько пикселей на отступ по вертикали и использовать полученное значение как приблизительную высоту шрифта.

Конструктивные блоки

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

Листинг 5. Оформление текста в динамичном стиле с помощью Canvas
context.font = '18px Arial';
context.fillStyle = 'green';
context.fillText('Variety', 0, 50);
context.translate(60, 0);  //перемещение на 60 пикселей вправо (a)

context.font = '12px Arial';
context.fillStyle = 'blue';
context.fillText('is the', 0, 50);
context.translate(35, 0); //перемещение на 35 пикселей вправо (b)

context.font = 'italic bold 12px Arial';
context.fillStyle = 'red';
context.fillText('spice of life!', 0, 50); // (c)

На рисунке 5 показаны три шага отображения текста в Canvas согласно листингу 5.

Рисунок 5. Оформление текста в динамичном стиле с помощью Canvas
Оформление текста в динамичном стиле с помощью Canvas

Используя только API Canvas, пришлось бы написать изрядное количество кода. Упрощение кода, необходимого для достижения эффекта из приведенного выше примера, повысило бы эффективность при отрисовке текста в Canvas. Например, многочисленные строки исходного кода можно заменить кодом, представленным в листинге 6.

Листинг 6. Концепция рабочего процесса для расширения визуализации текста в Canvas
var myText = new CanvasText();
myText
    .family('Arial')
    .size('18px')
    .weight('bold')
    .color('green')
    .append('Variety')

    .size('12px')
    .weight('normal')
    .color('blue')
    .append('is the')

    .style('italic')
    .color('red')
    .append('spice of life!')

    .render();

Рисунок 6 иллюстрирует код из листинга 6. В этом примере используется сцепление ― чистый и простой синтаксис, широко применяемый в jQuery и jQuery-плагинах.

Рисунок 6. Расширение визуализации текста в Canvas
Расширение визуализации текста в Canvas

Таким образом, процесс упрощается. Хотя количество строк кода почти такое же, сложность каждой строки значительно уменьшилась. И больше не нужно вручную позиционировать каждый блок текста, в котором используются разные стили. Если позднее понадобится изменить те или иные свойства любого из блоков, вам не придется вручную перепозиционировать последующие блоки.

Напомним, что свойство Canvas.font представляет собой сочетание нескольких свойств, которые определяют, каким образом будет отображаться текст. Между блоком Variety и последующими блоками не нужно указывать семейство шрифтов. Между блоками 'is the' и 'spice of life!' также не требуется указывать размер и вес шрифта. Здесь используется простой механизм запоминания свойств, применявшийся ранее, который исключает необходимость перенастраивать уже заданные свойства текста. Действующий пример класса CanvasText приведен в разделе Ресурсы.

Для достижения этих результатов достаточно сгруппировать свойства стиля визуализируемого текста, указать соответствующие свойства, а затем вызвать функцию append() объекта CanvasText, которая закрывает группу и сохраняет ее для дальнейшего использования. При визуализации текста перебирайте эти группы и применяйте указанные в них стили. Перебирая группы, сохраняйте историю предыдущих состояний стиля и при необходимости переопределяйте их. Эти действия обеспечивают единообразие стиля и уменьшают количество необходимых спецификаций для визуализации текста в Canvas. Это только одно из преимуществ использования класса-оболочки, или набора конструктивных блоков, для автоматизации процесса отображения текста в Canvas.

Перенос слов

Перенос слов ― это функция, которую многие принимают как должное. Она просто работает, когда HTML-элемент содержит слишком длинный текст, не помещающийся в одной строке. Не нужно учитывать длину текста, ширину контейнера и т.п. В Canvas все не так просто. Элементы HTML Canvas в настоящее время не содержат встроенных функций для управления такими вещами, так что приходится создавать функции программно, используя упоминавшиеся выше инструменты и методы.

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

Листинг 7 развивает идеи листинга 6 и добавляет некоторые аргументы для передачи в конструктор класса CanvasText.

Листинг 7. Передача аргументов в конструктор класса CanvasText
var myText = new CanvasText(
    {x: 50, y: 50},
    {width: 100, height: 200}
);
myText
    .family('Arial')
    .size('18px')
    .weight('bold')
    .color('green')
    .append('Variety')

    .size('12px')
    .weight('normal')
    .color('blue')
    .append('is the')

    .style('italic')
    .color('red')
    .append('spice of life!')

    .render();

Дополнительные аргументы представляют собой координаты x и y и размеры воспроизводимого текста и контейнера соответственно. Обратите внимание, что явно указана ширина для ограничения границ содержимого.

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

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

Листинг 8. Включение функций переноса слов
// использование ширины текста 
var currentWordWidth = context.measureText(currentWord).width

// код переноса слов
if (textAdjustment.x + currentWordWidth > this._size.x || textToDraw == '\n') {
    textAdjustment.x = 0;
    textAdjustment.y += parseInt(previousFontOptions.size, 10);
}

Конечный результат показан на рисунке 7.

Рисунок 7. Результат переноса слов
Результат

Действующий пример класса CanvasText приведен в разделе Ресурсы.

С помощью довольно простого класса оболочки мы автоматизировали задачи стилевого оформления и переноса слов в Canvas. Теперь этот класс-оболочку можно использованы везде, где требуется отображение текста в Canvas.


Собираем все вместе

Мы склонны принимать удобный пользовательский интерфейс как само собой разумеющееся. Все решения от HTML до Flash и Silverlight предлагают необходимый набор компонентов пользовательского интерфейса в виде текста, меню, полос прокрутки и элементов форм.

Следующий пример составляет основу простой игры - космического шутера. Мы создадим: компонент космического корабля, который может летать по игровой площадке, чат-окно и магазин. Некоторые из компонентов требуют анимации, а другие предоставляют текстовую информацию, которая может часто обновляться.

Полный действующий пример космического шутера приведен в разделе Ресурсы.

Подход HTML

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

Теперь самое интересное: космический корабль. Для HTML-реализации создадим простой элемент DIV, добавим фоновое изображение корабля и элементы для отображения таких вещей, как имя и состояние игрока. Пока код для этих компонентов лежит исключительно в HTML/CSS-части примера.

Листинг 9 демонстрирует некоторые классы CSS, необходимые для воспроизведения корабля и текста, отображаемого под ним. Положение элемента DIV с классом игрока позднее будет изменяться в функции рендеринга DOM для достижения эффекта анимации.

Листинг 9. CSS для оформления космического корабля, имени и состояния игрока
.player {
    position: absolute;
    width: 100px;
    height: 100px;
}

.text-under-ship {
    position: absolute;
    top: 100px;
    left: 0;
    width: 100px;
}

.name {
    font-family: Georgia;
    font-size: 15px;
    font-weight: bold;
    color: red;
}

.health {
    font-family: Georgia;
    font-size: 10px;
    color: yellow;
}

На этом этапе можно начать работать с кодом для обработки логики игры, как показано в листинге 10. Код в основном сосредоточен в объекте JavaScript Game. Он отвечает за обработку данных, вводимых пользователем, и вызывает функции для обновления и отображения соответствующих компонентов.

Листинг 10. Функция gameLoop, используемая для работы приложения
gameLoop: function() {

    // расчет времени, прошедшего с момента последнего обновления
    var currentTime = new Date().getTime();
    var elapsed = currentTime - this._previousTime;

    // вызов обновления
    Ship.update(elapsed);

    // вызов отображения
    if (this._CanvasRendering) {
        CanvasManager.render();
        Ship.renderCanvas();
    } else {
        Ship.renderDOM();
    }

    // сохранение текущего времени в качестве времени предыдущего обновления
    this._previousTime = currentTime;
}

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

Большая часть того, что мы создали до сих пор, ― это многоразовые модули, не зависящие от способа визуализации. Листинг 11 дает более глубокое представление о различиях между функциями визуализации DOM и Canvas.

Листинг 11. Функция визуализации HTML
renderDOM: function() {
    var player = jQuery('#player');

    player .css({
        left: this._position.x,
        top: this._position.y
    });

    var rotationTransform = 'rotate(' + (this._rotation / 100 * 360) + 'deg)';
    var ship = player.find('#ship')
        .css('transform', rotationTransform )
        .css('-webkit-transform', rotationTransform )
        .css('-moz-transform', rotationTransform )
        .css('-ms-transform', rotationTransform )
        .css('-o-transform', rotationTransform );
}

Код, приведенный в листинге 11, минимален, так как для позиционирования космического корабля и его вращения используется jQuery. Для достижения истинной независимости от браузера необходимо указать разные версии свойства transform.

В конечном итоге HTML-подход оказывается относительно простым в реализации и требует лишь небольшого количества кода. Его недостаток ― невозможность достичь приемлемой частоты кадров из-за накладных расходов браузера при визуализации элементов DOM.

Подход Canvas

Перед началом работы с Canvas требуется ссылка на объект Canvas, с которым мы будем работать. После этого нужно инициализировать контекст. Этот контекст, который обсуждался выше, служит средством работы с элементом Canvas.

Используем простой класс Canvasmanager, как показано в листинге 12.

Листинг 12. Класс Canvasmanager
var CanvasManager = {
    Canvas: null,
    context: null,
    _size: null,

    init: function() {
        this.Canvas = document.getElementById('Canvas-game-area');
        this.context = this.Canvas.getContext('2d');

        this._size = {
            x: this.Canvas.width,
            y: this.Canvas.height,
        }
    },

    render: function() {
        this.context.clearRect(0, 0, this._size.x, this._size.y);
    }
}

В большинстве приложений каждый раз, когда нужно обновить изображение Canvas, сначала очищают предыдущее изображение, чтобы получить чистый участок холста. Это можно сделать с помощью функции clearRect(), как показано в листинге 13.

Листинг 13. Функция визуализации Canvas
renderCanvas: function() {
    var context = CanvasManager.context;

    // сохранение контекста для подготовки к  
    // предстоящему перемещению и повороту
    context.save();

    // перемещение холста в положение центра космического корабля
    context.translate(
        this._position.x + 50, 
        this._position.y + 50
    );

    // поворот холста в соответствии с направлением полета
    context.rotate(this.getRotationInRadians());

    // прорисовка корабля со смещением в половину высоты
    // и ширины относительно центра изображения
    context.drawImage(
        this._displayImage, 
        -50,
        -50
    );

    // Восстановление контекста
    context.restore();

    this._playerName.render();
}

Код, приведенный в листинге 13, демонстрирует некоторые преимущества и недостатки подхода Canvas. Главным преимуществом является повышенная производительность. Эффект увеличивается еще больше при визуализации большого количества компонентов, как показано на рисунке 8.

Рисунок 8. Увеличение числа кораблей для демонстрации разницы в производительности
Увеличение числа кораблей для демонстрации разницы в производительности

Теперь в примере воспроизводится 50 кораблей, один поверх другого (см. действующий пример в разделе Ресурсы). Очевидно, что HTML-версия несколько отстает. Переход на версию Canvas значительно улучшает производительность.

Количество кода, необходимого для этих двух подходов, заметно различается. В случае HTML для позиционирования корабля достаточно вызвать одну функцию jQuery. При подходе Canvas требуется немного больше.

В листинге 13 есть также дополнительный вызов для отображения имени игрока. В методе HTML этого не требуется, потому что позиционируемый элемент содержит не только корабль, но и сопроводительный текст. В Canvas же подобного удобства нет. Для отображения имени игрока используется класс CanvasText, который передает всю работу по визуализации корабля и сопроводительного текста из DOM в Canvas.


Заключение

В этом цикле из двух статей рассмотрены критерии выбора Canvas- или HTML-ориентированной архитектуры. В предлагаемой статье разбираются вопросы анимации и способы преодоления ограничений при отрисовке текста. Примеры показывают, как объединить обе идеи, и проливают свет на различные подходы к созданию гибридных архитектур Canvas-HTML.


Загрузка

ОписаниеИмяРазмер
Исходный код примера для статьиCanvashtmlpt2sourcecode.zip20 КБ

Ресурсы

Научиться

Получить продукты и технологии

  • jQuery: эта популярная библиотека JavaScript упрощает анализ HTML-документа, обработку событий, анимацию и Ajax-взаимодействия, ускоряя Web-разработку.
  • Kibo: другая популярная библиотека, написанная специально для ускорения кроссбраузерной обработки событий клавиатуры.

Комментарии

developerWorks: Войти

Обязательные поля отмечены звездочкой (*).


Нужен IBM ID?
Забыли Ваш IBM ID?


Забыли Ваш пароль?
Изменить пароль

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Профиль создается, когда вы первый раз заходите в developerWorks. Информация в вашем профиле (имя, страна / регион, название компании) отображается для всех пользователей и будет сопровождать любой опубликованный вами контент пока вы специально не укажите скрыть название вашей компании. Вы можете обновить ваш IBM аккаунт в любое время.

Вся введенная информация защищена.

Выберите имя, которое будет отображаться на экране



При первом входе в developerWorks для Вас будет создан профиль и Вам нужно будет выбрать Отображаемое имя. Оно будет выводиться рядом с контентом, опубликованным Вами в developerWorks.

Отображаемое имя должно иметь длину от 3 символов до 31 символа. Ваше Имя в системе должно быть уникальным. В качестве имени по соображениям приватности нельзя использовать контактный e-mail.

Обязательные поля отмечены звездочкой (*).

(Отображаемое имя должно иметь длину от 3 символов до 31 символа.)

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Вся введенная информация защищена.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=Web-архитектура, Open source
ArticleID=858372
ArticleTitle=Дополнение Canvas HTML-разметкой: Часть 2. Анимация и визуализация текста
publish-date=02182013