четверг, 7 апреля 2011 г.

ЧАСЫ lua+cairo

На примере создания скрипта вывода часов, с помощью lua+cairo, хочу показать как это можно сделать.



Написание скрипта выводящего наипростейшие часы, такого вида


начнем с указания программе, что будет использоваться язык cairo

require 'cairo'

создаем функцию для запуска вывода изображения часов

function conky_clock ()

необходимые данные для вывода часов

    clock_settings = {

    {
    x = 150,
               -- координаты центра часов по горизонтали
    y = 150,               -- координаты центра часов по вертикали
    radius = 100,       -- радиус часов
    color = 0xffffff,    -- цвет
    alpha = 1,             -- насыщенность цвета
    }
    }


проверяем, существует окно конки или нет, если нет, выходим из программы

    if conky_window == nil then return end

создаем образ окна conky

    local cs = cairo_xlib_surface_create(conky_window.display, conky_window.drawable, conky_window.visual, conky_window.width, conky_window.height)

считываем заданные данные

    for i, v in pairs(clock_settings) do

забираем образ окна conky

        cr = cairo_create (cs)

запускаем вывод изображения

        display_clock (v)

закрываем вывод изображения

        cairo_destroy (cr)
    end


выходим из программы

end

Для работы с цветом добавляем функцию перекодировки цвета из шестнадцатиричного формата в формат RGB

function rgb_to_r_g_b(colour,alpha)
    return ((colour / 0x10000) % 0x100) / 255., ((colour / 0x100) % 0x100) / 255., (colour % 0x100) / 255., alpha
end


функция рисования часов

function display_clock (t)

производим проверку вводимых данных и задаем значения по умолчанию

    if t.x            == nil then t.x = conky_window.width/2 end
    if t.y            == nil then t.y = conky_window.height/2 end
    if t.radius        == nil then t.radius = 75 end
    if t.color        == nil then t.color = 0xffffff end
    if t.alpha        == nil then t.alpha = 1 end


начнем с вывода циферблата
сначала зададим цвет

    cairo_set_source_rgba(cr, rgb_to_r_g_b(t.color, t.alpha))

и толщину линии

    cairo_set_line_width(cr, 2)

рисуем окружность

    cairo_arc (cr, t.x, t.y, t.radius, 0, 2*math.pi)

выводим изображение

    cairo_stroke (cr)

для вывода стрелок необходимо забрать данные о времени из ОС

    local hours = os.date("%I")
    local mins = os.date("%M")
    local secs = os.date("%S")


немного о следующих строках. От ОС получаем значения в виде
01-12 для часов
00-59 для минут и секунд
для перевода этих значений в угол поворота стрелки находим количество радиан на одно деление
2 * math.pi в радианах равна 360 градусам
для минут и секунд делим это значение на 60 (2*math.pi/60) получаем значения одного деления
умножив значение одного деления на количество минут или секунд получим угол поворота стрелки

    secs_arc = (2 * math.pi / 60) * secs
    mins_arc = (2 * math.pi / 60) * mins


немного иначе дело обстоит с часовой стрелкой
если все сделать так, как для минут и секунд, то стрелка, во время перехода от одного часа к другому, будет "прыгать" на 30 градусов, что не очень приятно наблюдать, да и непривычно
поэтому к значению часа прибавляется значение минут деленных на 12, получаем плавное движение стрелки

    hours_arc = (2 * math.pi / 12) * hours + mins_arc / 12

рисование часовой стрелки начнем с определения координат конца стрелки
принимаем длину стрелки равной 70% от длины радиуса
для координаты x умножаем длину стрелки на синус угла стрелки и прибавляем к координатам центра часов

    xh = t.x + 0.7 * t.radius * math.sin(hours_arc)

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

    yh = t.y - 0.7 * t.radius * math.cos(hours_arc)

помещаем начало стрелки в центр часов

    cairo_move_to (cr, t.x, t.y)

и проводим линию до конца стрелки

    cairo_line_to (cr, xh, yh)
    cairo_stroke (cr)


рисуем минутную стрелку

    xm = t.x + 0.9 * t.radius * math.sin(mins_arc)
    ym = t.y - 0.9 * t.radius * math.cos(mins_arc)
    cairo_move_to (cr, t.x, t.y)
    cairo_line_to (cr, xm, ym)
    cairo_stroke (cr)


рисуем секундную стрелку

    xs = t.x + 0.9 * t.radius * math.sin(secs_arc)
    ys = t.y - 0.9 * t.radius * math.cos(secs_arc)
    cairo_move_to (cr, t.x, t.y)
    cairo_line_to (cr, xs, ys)
    cairo_stroke (cr)
end


В следующий раз расскажу как можно улучшить вид часов.

Комментариев нет:

Отправить комментарий