пятница, 11 июня 2010 г.

Календарь

Здрасте всем, вот на днях пришлось делать такой календарик, может кому пригодится :)

[SWF]http://coolisee.com/wordpress/wp-content/uploads/2010/06/11/calendar.swf, 230, 280[/SWF]






Шаг 1. Готовим графику



Создаем в Flash документ actionscript 3.0 размером 230х280.
Для календаря нам понадобятся следующие мувики:

Мувики для нашего календаря
Рисунок 1. – Мувики для нашего календаря



ячейка даты (BgDate);
ячейка дня недели (BgDay);
кнопки «вперед» и «назад» для изменения месяца (NextMonthButton и PrevMonthButton соответственно);
кнопки «вперед» и «назад» для изменения года (NextYearButton и PrevYearButton соответственно);
текстовое поле с присоединенным шрифтом, упакованное в мувик (TextEmbed).

Для каждого из них при создании указываем Export for ActionScript и в поле Class пишем соответствующее название.
В мувике BgDate создаем три слоя.

BgDate
Рисунок 2. – BgDate



В слое «actions» прописываем stop(), в слое «label» прописываем метки для кадров – default, currentday, rollover для первого, второго, третьего кадров соответственно и в слое «graphics» отрисовываем вид ячейки для трех состояний – в кадре default вид по умолчанию; в кадре currentday вид, если ячейка отображает текущее число; в кадре rollover вид, если пользователь навел на ячейку указатель мыши.

Думаю, не будет лишним встроить в наш календарь шрифт, который мы будем использовать для текстов, для этого в мувике TextEmbed создаем динамическое текстовое поле, в свойствах которого:

1 - выбираем шрифт, который хотим использовать для текстов и нажимаем кнопку Character Embedding…
2 - Затем, чтобы не увеличивать размер файла нашего календаря, в появившемся окошке выбираем только набор символов Cyrillic (если язык календаря русский) и
3 - дополнительно прописываем символы цифр.

Встраиваем шрифт
Рисунок 3. – Встраиваем шрифт



Графика готова, переходим к коду.


Шаг 2. Пишем код



Класс нашего fla – Calendar, подробные пояснения я постарался дать в комментариях:

package {

import flash.display.MovieClip;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.text.TextFormatAlign;
import com.greensock.*;
import com.greensock.easing.*;

public class Calendar extends MovieClip {

public static const CHANGEDATE:String = 'changedate';//константа для имени события
public static const XGRID:Number = 12;//координаты сетки из ячеек с датами и панельки с днями недели
public static const YGRID:Number = 95;
public static const YDAYS:Number = 60;
public static const BETWEENCELLS:Number = 5;//расстояние между ячейками

private var _dateObject:Date;//экземпляр нужен для получения значений текущей даты, дня недели, года

private var _currentDate:Number;//текущая дата
private var _currentDay:Number;//текущий день недели
private var _currentMonth:Number;//текущий месяц
private var _currentYear:Number;//текущий год
private var _days:Array;//массив для хранения названий дней недели
private var _dates:Array;//массив для хранения дат
private var _months:Array;//массив для хранения названий месяцев
private var _daysinMonth:Array;//массив для хранения количества дней в месяце

private var _nextMonthButton:NextMonthButton;//кнопки
private var _prevMonthButton:PrevMonthButton;
private var _nextYearButton:NextYearButton;
private var _prevYearButton:PrevYearButton;
private var _textCurrentMonth:TextField;//текстовое поле для названия месяца
private var _textCurrentYear:TextField;//текстовое поле для значения года
private var _formateTextMonthAndYear:TextFormat;//форматы для текстовых полей
private var _formateTextDate:TextFormat;
private var _formateTextDays:TextFormat;

private var _startCell:Number;//ячейка с сегодняшней датой

public function Calendar() {
init();
}

private function init():void {

_dateObject = new Date();
_currentDate = _dateObject.getDate();
_currentDay = _dateObject.getDay();
_currentYear = _dateObject.getFullYear();
_currentMonth = _dateObject.getMonth();
_days = ['пн', 'вт', 'ср', 'чт', 'пт', 'сб', 'вс']
_months = ["январь", "февраль", "март", "апрель", "май", "июнь", "июль", "август", "сентябрь", "октябрь", "ноябрь", "декабрь"];
_daysinMonth = [31,28,31,30,31,30,31,31,30,31,30,31];

buildHeader();//создаем текстовые поля для названия месяца, года; создаем панельку с днями недели
buildGrid();//создаем сетку из ячеек с датами
showCurrentDate();//изменяем сетку в соответствии с видом текущего месяца

//когда пользователь кликает по кнопкам для изменения даты или года (см метод onClick()),
//мы отправляем событие Calendar.CHANGEDATE, которое обрабатывает метод onChangeDate()
addEventListener(MouseEvent.CLICK, onClick);
addEventListener(Calendar.CHANGEDATE, onChangeDate);
addEventListener(MouseEvent.ROLL_OVER, onROver, true);//а это, чтоб покрасивее :)
addEventListener(MouseEvent.ROLL_OUT, onROut, true);
}

private function buildHeader():void {

//создаем экземпляр текстового поля с присоединенным шрифтом, чтобы
//этот шрифт можно было использовать в нашем ролике
var textEmbed:TextEmbed = new TextEmbed();

//создаем формат текстовых полей для названия месяца и значения года
_formateTextMonthAndYear = new TextFormat();
_formateTextMonthAndYear.color = 0x333333;
_formateTextMonthAndYear.font = 'Tahoma';
_formateTextMonthAndYear.size = '16';
_formateTextMonthAndYear.bold = true;
_formateTextMonthAndYear.align = TextFormatAlign.CENTER;

//создаем формат текстового поля для значений даты
_formateTextDate = new TextFormat();
_formateTextDate.color = 0xffffff;
_formateTextDate.font = 'Tahoma';
_formateTextDate.size = '13';
_formateTextDate.bold = true;
_formateTextDate.align = TextFormatAlign.CENTER;

//создаем формат текстового поля для значений дней недели
_formateTextDays = new TextFormat();
_formateTextDays.color = 0xffffff;
_formateTextDays.font = 'Tahoma';
_formateTextDays.size = '14';
_formateTextDays.bold = true;
_formateTextDays.align = TextFormatAlign.CENTER;

//создаем текстовое поле для названия месяца
_textCurrentMonth = new TextField();
_textCurrentMonth.selectable = false;
_textCurrentMonth.defaultTextFormat = _formateTextMonthAndYear;
_textCurrentMonth.embedFonts = true;
_textCurrentMonth.x = 23;
_textCurrentMonth.y = 25;
_textCurrentMonth.width = 90;
_textCurrentMonth.height = 40;
_textCurrentMonth.text = _months[_currentMonth];
addChild(_textCurrentMonth);

//создаем текстовое поле для значения года
_textCurrentYear = new TextField();
_textCurrentYear.embedFonts = true;
_textCurrentYear.selectable = false;
_textCurrentYear.defaultTextFormat = _formateTextMonthAndYear;
_textCurrentYear.x = 137;
_textCurrentYear.y = 25;
_textCurrentYear.width = 80;
_textCurrentYear.height = 40;
_textCurrentYear.text = _currentYear.toString();
addChild(_textCurrentYear);

//создаем ячейки с названиями дней недели
for (var i:int = 0; i < _days.length; i++) {
var bgDay:BgDay = new BgDay();
addChild(bgDay);
bgDay.x = i * (bgDay.width + BETWEENCELLS) + XGRID;
bgDay.y = YDAYS;

var textDay:TextField = new TextField();
textDay.mouseEnabled = false;
textDay.selectable = false;
textDay.text = _days[i];
textDay.width = 30;
textDay.height = 30;
textDay.embedFonts = true;
textDay.setTextFormat(_formateTextDays);
bgDay.addChild(textDay);
textDay.x = -3;//эти значения получаем опытным путем :)
textDay.y = 1;

}


//создаем кнопки для изменения месяцев и лет
_nextMonthButton = new NextMonthButton();
_nextMonthButton.stop();
_nextMonthButton.x = 115;
_nextMonthButton.y = 33;
_nextMonthButton.buttonMode = true;
_nextMonthButton.useHandCursor = true;
addChild(_nextMonthButton);

_prevMonthButton = new PrevMonthButton();
_prevMonthButton.stop();
_prevMonthButton.x = 15;
_prevMonthButton.y = 33;
_prevMonthButton.buttonMode = true;
_prevMonthButton.useHandCursor = true;
addChild(_prevMonthButton);

_nextYearButton = new NextYearButton();
_nextYearButton.stop();
_nextYearButton.x = 209;
_nextYearButton.y = 33;
_nextYearButton.buttonMode = true;
_nextYearButton.useHandCursor = true;
addChild(_nextYearButton);

_prevYearButton = new PrevYearButton();
_prevYearButton.stop();
_prevYearButton.x = 137;
_prevYearButton.y = 33;
_prevYearButton.buttonMode = true;
_prevYearButton.useHandCursor = true;
addChild(_prevYearButton);
}

private function onChangeDate(e:Event):void {
clearGrid()//убираем старую сетку
buildGrid();//делаем новую
showCurrentDate();
}

private function clearGrid():void {

//удаляем все ячейки
_dates = null;
while (getChildAt(numChildren-1) is BgDate) {
removeChild(getChildAt(numChildren-1));
};

//создаем новый объект Date, со значениями года и месяца, которые выбрал пользователь
_dateObject = new Date(_currentYear,_currentMonth, _currentDate);
_currentDate = _dateObject.getDate();
_currentDay = _dateObject.getDay();
_currentYear = _dateObject.getFullYear();
_currentMonth = _dateObject.getMonth();
}

private function showCurrentDate():void {

//небольшая проверка на високосный год, если год не високосный, то в феврале 28 дней
_daysinMonth[1] = 28;

//если високосный - 29
if ((_currentYear / 4 - Math.floor(_currentYear / 4) == 0)) {
_daysinMonth[1] = 29;
}

if (_currentYear / 100 - Math.floor(_currentYear / 100) == 0 &&
_currentYear / 400 - Math.floor(_currentYear / 400) != 0) {
_daysinMonth[1] = 28;
}

//ищем в сетке ближайшую ячейку, день недели которой совпадает со значением _currentDay
for (var i:Number = _currentDate - 1; i < _dates.length - 1; i++) {
if (_dates[i][1] == _currentDay) {
_startCell = i;
_dates[i][2].gotoAndStop(2);
break;
}
}

var tempNumber:Number;
tempNumber = _startCell;

//функция добавляет текстовое поле в ячейку
function attachTextField(it:Number):void {
var textDate:TextField = new TextField();
textDate.mouseEnabled = false;
textDate.selectable = false;
textDate.text = it.toString();
textDate.width = 30;
textDate.height = 30;
textDate.embedFonts = true;
textDate.setTextFormat(_formateTextDate);
_dates[tempNumber][2].addChild(textDate);
textDate.x = -3;//эти значения получаем опытным путем :)
textDate.y = 1;
}

//добавляем текстовые поля к ячейкам от текущей даты до первого числа месяца
for (var j:Number = _currentDate; j > 0; j--) {
attachTextField(j);
tempNumber--;
}

//восстанавливаем значение tempNumber
tempNumber = _startCell;

//добавляем текстовые поля к ячейкам от текущей даты до последнего числа месяца
for (var k:Number = _currentDate; k <= _daysinMonth[_currentMonth]; k++) {
attachTextField(k);
tempNumber++;
}

//удаляем ячейки без текстовых полей из списка отображения, хотя можно этого и не делать,
//а просто изменять их внешний вид
for (var l:Number = 0; l < _dates.length ; l++) {
if (_dates[l][2].numChildren==1) {
removeChild(_dates[l][2]);
}
}

//применяем твин к ячейкам
function tween():void {
for (var i:Number = 0; i < _dates.length ; i++) {
if (_dates[i][2].stage) {
var randomX:Number = Math.floor(Math.random() * 100);
var randomY:Number = Math.floor(Math.random() * 100);
_dates[i][2].x = _dates[i][2].x + randomX;
_dates[i][2].y = _dates[i][2].y + randomY;
var tw:TweenLite = new TweenLite(_dates[i][2], 1, { x:_dates[i][2].x - randomX, y:_dates[i][2].y - randomY, ease:Bounce.easeOut } );
}
}
}

tween();
}

//создаем сетку из ячеек дат
private function buildGrid():void {

_dates = new Array();

var it:Number = 0;

for (var i:Number = 0; i < 6; i++) {

for (var j:Number = 0; j <= 7; j++) {

if (j == 7) {
break;
}
it++;
var dateOfMonth:Number;
dateOfMonth = it;

var dayOfWeek:Number;
dayOfWeek = j + 1;
if (dayOfWeek == 7) {
dayOfWeek = 0;
}

var bgDate:BgDate = new BgDate();
addChild(bgDate);
bgDate.x = j * (bgDate.width + BETWEENCELLS) + XGRID;
bgDate.y = i * (bgDate.height + BETWEENCELLS) + YGRID;

_dates.push([dateOfMonth, dayOfWeek, bgDate]);
}
}
}

//обработчик события MouseEvenе.ROLL_OVER - при наведении мыши окрашиваем ячейку в другой цвет
//и немного поднимаем относительно других
private function onROver(e:MouseEvent):void {

if (e.target is BgDate) {
if (e.target.currentFrameLabel == 'currentday') {//если это ячейка с сегодняшним днем ничего не делаем
} else {
e.target.gotoAndStop('rollover');
e.target.y = e.target.y - 2;
}
}
}

//обработчик события MouseEvenе.ROLL_OUT - окрашиваем ячейку в начальный цвет
//и возвращаем начальное значение координате y
private function onROut(e:MouseEvent):void {

if (e.target is BgDate) {
if (e.target.currentFrameLabel == 'currentday') {
} else {
e.target.gotoAndStop('default');
e.target.y = e.target.y + 2;
}
}
}

//обработчик события MouseEvent.CLICK - здесь меняем месяцы и даты
//и отправляем событие Calendar.CHANGEDATE
private function onClick(e:MouseEvent):void {

if (e.target is NextMonthButton || e.target is PrevMonthButton
||e.target is NextYearButton || e.target is PrevYearButton) {

if (e.target is NextMonthButton) {
_currentMonth++;
if (_currentMonth == 12) {
_currentMonth = 0;
_currentYear++;
_textCurrentYear.text = _currentYear.toString();
}
_textCurrentMonth.text = _months[_currentMonth];
} else if (e.target is PrevMonthButton) {
_currentMonth--;
if (_currentMonth == -1) {
_currentMonth = 11;
_currentYear--;
_textCurrentYear.text = _currentYear.toString();
}
_textCurrentMonth.text = _months[_currentMonth];
}

if (e.target is NextYearButton) {
_currentYear++;
_textCurrentYear.text = _currentYear.toString();
} else if (e.target is PrevYearButton) {
_currentYear--;
_textCurrentYear.text = _currentYear.toString();
}

dispatchEvent(new Event(CHANGEDATE));
}
}
}
}


На этом у меня все.

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

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