webew
Войти » Регистрация
 
HTML
JavaScript :: Графика

Создание градиента в тексте

14 апреля 2008, 14:24

Задача: найти способ для создания градиента в произвольном элементе, содержащем текст (или гипертекст)

Обратите внимание на заголовок. Замечаете там градиент из красного в желтый? Нет? Значит у вас отключен JavaScript и вы можете смело покинуть эту страницу :-)

Решается чисто косметическая задача. Дизайнер (или вы сами) нарисовал(и) макет в котором обнаруживается градиент символов текста. Что с ним делать?

Заверстать

Можно заверстать кусок кода с градиентом. Приходят в голову следующие мысли:

  • вырезать этот градиентый текст в виде картинки, и влепить его таким образом на страницу;
  • каждый символ пресловутого текста обернуть в span, и задать спану свой color;

Второй способ — это страшная кара для верстальщика, особенно если символов много. Однако, он подсказывает более изящное решение.

Запрограммить

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

Функцию назовем textGradient. В качестве аргументов она будет принимать имя тега с текстом, имя класса (если класса нет, то пустую строку) и массив из двух крайних цветов градиента в формате [RRGGBB,RRGGBB]. Потребуется три дополнительный функции: две для перевода и шестнадцатеричного формата в десятиричный и обратно. И одна для сбора всех узлов-потомков для заданного узла.

Собственно скрипт:

// Функция для перевода цвета из шестнадцатиричного представления формата RRGGBB
// в массив из трех десятиричных значений формата [rrr,ggg,bbb].
function hexToDec(hex) {
    var i, hash, dec = [];
    hash = {
        'A' : 10, 'B' : 11, 'C' : 12, 'D' : 13, 'E' : 14, 'F' : 15
    }
    for (i = 0; i <= 9; i++) hash[''+i] = i;
    for (i = 0; i < hex.length; i++) {
        if (i % 2 == 0) dec[parseInt(i / 2)] = hash[hex.charAt(i)] * 16;
        else dec[parseInt(i / 2)] += hash[hex.charAt(i)];
    }
    return dec;
}
// Функция обратно собирающая шестнадцатеричное представление
function decToHex(decArray) {
    var hex = ['0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'];
    var out = "#";
    for (var i = 0; i < decArray.length; i++) {
        dec = parseInt(decArray[i]);
        out += hex[parseInt(dec / 16)] + hex[dec % 16];
    }
    return out;
}
// Функция для получения всех потомков узла
function nodeList(parentNode, list, level) {
    var i, node, count;
    if (typeof list == "undefined") list = new Array();
    if (typeof level == "undefined") level = 0;
    level++;
    for (i = 0; i < parentNode.childNodes.length; i++) {
        node = parentNode.childNodes[i];
        count = list.length;
        list[count] = new Array();
        list[count][0] = node;
        list[count][1] = level;
        nodeList(node, list, level);
    }
    return list;
}
// Функция для выставления тестового градиента, принимает 3 аргумента:
// tagName - имя тега с текстом
// className - название класса элемента (можно пропустить указав пустую строку или false)
// colors - массив с 2-мя цветами формата ["RRGGBB", "RRGGBB"]
function textGradient(tagName, className, colors) {
    var i, j, k, count, rgb = [], tags, text, html = "", simb, childs, child, newchild;
    var red, green, blue;
    rgb[0] = hexToDec(colors[0]);
    rgb[1] = hexToDec(colors[1]);
    tags = document.getElementsByTagName(tagName);
    for (i = 0; i < tags.length; i++) {
        if (className) if (tags[i].className.indexOf(className) == -1) continue;
        text = tags[i].innerText ? tags[i].innerText : tags[i].textContent;
        childs = nodeList(tags[i]);
        count = 0;
        for (j = 0; j < childs.length; j++) {
            child = childs[j][0];
            // Отсортировываем только текстовые узлы
            if (child.nodeType != 3) continue;
            // Все символы текстового узла обрамляем в SPAN-ы c нужным цветом
            html = "";
            for (k = 0; k < child.nodeValue.length; k++) {
                simb = childs[j][0].nodeValue.charAt(k);
                if (simb == " ") {html += " "; continue;}
                red = parseInt(rgb[0][0] + (rgb[1][0] - rgb[0][0]) * (count / text.length));
                green = parseInt(rgb[0][1] + (rgb[1][1] - rgb[0][1]) * (count / text.length));
                blue = parseInt(rgb[0][2] + (rgb[1][2] - rgb[0][2]) * (count / text.length));
                html += "<span style=\"color:" + decToHex([red, green, blue]) + "\">" + simb + "<\/span>";
                count++;
            }
            // Заменяем текстовый узел на узел с подсвеченными span-ами
            newchild = document.createElement("span");
            newchild.innerHTML = html;
            child.parentNode.replaceChild(newchild, child);
        }
    }
}

Результат

Заголовок с градиентом FF0000 → FFFF00


DIV с изображением

Текст. Просто текст. Всего лишь текст. Текст. Просто текст. Всего лишь текст.Текст. Просто текст. Всего лишь текст.Текст. Просто текст. Всего лишь текст. Текст. Просто текст.

Код:

<h1 class="gradient">Заголовок с градиентом FF0000 &rarr; FFFF00</h1>
<script type="text/javascript">textGradient('h1', 'gradient', ['FF0000','FFFF00']);</script>

<div class="gradient">DIV со <a href="#">ссылкой</a></div><br/>
<script type="text/javascript">textGradient('div', 'gradient', ['FF0000','FFFF00']);</script>

<div class="gradientimg">DIV с <img src="http://2007.fastcoder.ru/demo/gradient.gif" width="30" height="15" alt="" /> изображением</div><br/>
<script type="text/javascript">textGradient('div', 'gradientimg', ['0000FF','00FF00']);</script>

<div class="gradienttext">Текст. Просто текст. Всего лишь текст. Текст. Просто текст. Всего лишь текст.Текст. Просто текст. Всего лишь текст.Текст. Просто текст. Всего лишь текст. Текст. Просто текст.</div>
<script type="text/javascript">textGradient('div', 'gradienttext', ['999999','F1F1F1']);</script>


// Все права на статью JavaScript::Создание градиента в тексте принадлежат сайту 2007.fastcoder.ru
Добавить комментарий
Отображение комментариев: Древовидное | Плоское
NO USERPIC

rgbeast

Оформление текста на Javascript очень помогает поисковой оптимизации. Если в документе каждая буква окружена в отдельный <span>, то поисковик может не воспринять последовательность букв как слово. Javascript решает проблему, так как поисковиком он не обрабатывается.
14.04.2008, 22:13
Ответить

bur

Вообще JavaScript-ы необходимо стараться писать так, чтобы изменения в HTML-коде были бы минимальны. В идеале изменений нет совсем, что полезно для отдачи страницы поисковикам и браузерам без JavaScript.
16.04.2008, 11:47
Ответить
NO USERPIC

Octane

Зачем такие заморочки с переводом RGB-палитры в шестнадцатиричное представление?
Цвет можно задать таким образом:
color: RGB(R,G,B);

Будет работать даже в ИЕ5 и скрипт значительно сократится, да и удобнее так...
26.06.2008, 22:20
Ответить

bur

Спасибо, полезное замечание.
27.06.2008, 12:30
Ответить
NO USERPIC

Dmitry

А ещё decToHex можно записать так:
decToHex = function (dec) {
    if (typeof dec == "number") {
        return dec.toString(16);
    }
    return null;
}

А hexToDec так:
hexToDec = function (hex) {
    if (typeof hex == "string") {
        return parseInt(hex, 16);
    }
    return null;
}
01.07.2008, 11:30
Ответить

bur

Спасибо за напоминание, никак не дойдут руки переделать старые функции...
01.07.2008, 11:58
Ответить
NO USERPIC

Gusse

Очень интересный эффект, не подскажите а можно сделать переливание 4 цветов?
07.12.2008, 03:21
Ответить

bur

Кажется мы переписывались по мылу. Надеюсь предложенное мной решение вас устраивает...
07.12.2008, 18:48
Ответить
NO USERPIC

mrnix

Предлагаю воспользоваться моим плагином для градиентных текстов, который умеет раскрашивать текст как горизонтальным, так и вертикальным градиентом. Можно ввести произвольное количество цветов и размер шага. Кроссбраузерно
mrnix.ru
08.06.2011, 01:54
Ответить
Добавить комментарий
Отображение комментариев: Древовидное | Плоское
© 2007—2016 webew.ru, связаться: x собака webew.ru
Сайт использует Flede и соответствует стандартам WAI-WCAG 1.0 на уровне A.
Rambler's Top100