Эта функция - ЭКСПЕРИМЕНТАЛЬНАЯ. Поведение, имя и всё остальное, что задокументировано для данной функции может быть изменено в будущих релизах РНР без предупреждения. Вы можете использовать эту функцию только на свой страх и риск.
swfaction() создаёт новую Action и компилирует данный скрипт в SWFAction-объект.
Синтаксис скрипта основан на языке C, но большими изъятиями - машина SWF-байтокода очень сильно упрощена.
К примеру, мы не может реализовать вызовы функции без большого объёма
дополнительной работы, поскольку jump-байтокод имеет жёстко кодированное
значение смещения. Без push вашего вызывающего адреса в стэк и возвращения -
каждой функции необходимо будет знать точно, куда возвращать.
Что же осталось? Компилятор распознаёт следующие лексемы:
break
for
continue
if
else
do
while
Типизированные данные отсутствуют; все значения в SWF action-машине хранятся как строки.
Следующие функции можно использовать в выражениях:
time()
Возвращает количество миллисекунд (?), прошедших после старта клипа.
random(seed)
Возвращает псевдо-случайное число в диапазоне 0-посеянное.
length(expr)
Возвращает длину данного выражения.
int(number)
Возвращает данное число, округлённое в сторону уменьшения до ближайшего integer.
concat(expr, expr)
Возвращает конкатенацию данных выражений.
ord(expr)
Возвращает ASCII-код данного символа
chr(num)
Возвращает символ с данным ASCII-кодом
substr(string, location, length)
Возвращает подстроку длиной length в точке location данной строки string
Кроме того, можно использовать следующие команды:
duplicateClip(clip, name, depth)
Дублирует именованный movie-клип (как sprite/спрайт). Новый movie-клип
имеет имя name и глубину depth.
removeClip(expr)
Удаляет именованный movie-клип.
trace(expr)
Записывает данное выражение в trace log. Сомнительно, что
plugin браузера сделает с ним что-нибудь.
Начинает перетаскивание целевого movie-клипа. Аргумент lock указывает, блокируется ли мышь (?) - 0 (FALSE)
или 1 (TRUE). Необязательные параметры определяют границы области для перетаскивания.
stopDrag()
Остановить перетаскивание movie-клипа.
callFrame(expr)
Вызвать именованный кадр как
getURL(url, target, [method])
Загрузить данный URL в именованный target. Аргумент target
соответствует целям HTML-документа (таким как "_top" или "_blank").
Необязательный аргумент method может быть POST или GET, если вы хотите отправить переменные обратно на сервер.
loadMovie(url, target)
Загружает данный URL в именованный target. Аргументом target может
быть имя кадра (я думаю) или одно из магических значений: "_level0" (заместить
текущий клип) или "_level1" (загрузить новый movie поверх текущего movie).
nextFrame()
Перейти в следующему кадру.
prevFrame()
Перейти к последнему (или всё же - к предыдущему?) кадру.
play()
Начать проигрывание movie.
stop()
Остановить проигрывание movie.
toggleQuality()
Переключает между высоким и низким качеством.
stopSounds()
Остановить проигрывание всех звуков.
gotoFrame(num)
Перейти к кадру номер num. Номера кадров начинаются с 0.
gotoFrame(name)
Перейти к именованному кадру name. Что даёт много хорошего, если я ещё
не добавил ярлыки кадров.
setTarget(expr)
Устанавливает контекст акции. Или, как говорится - я не знаю, что
она действительно делает.
Есть и ещё нечто сверхъестественное. Выражение frameLoaded(num) может
использоваться в операторах if и циклах while для проверки того, может ли
данный кадр с номером быть загружен.
Это предполагается, ноя не тестировал её и сильно сомневаюсь, что она
действительно работает. Вместо этого вы можете использовать просто /:framesLoaded.
Movie-клипы (с этого момента всё это - спрайты) имеют свойства. Вы можете
читать все их и устанавливать некоторые из них:
x
y
xScale
yScale
currentFrame - (read-only)
totalFrames - (read-only)
alpha - уровень прозрачности
visible - 1=on, 0=off (?)
width - (read-only)
height - (read-only)
rotation
target - (read-only) (???)
framesLoaded - (read-only)
name
dropTarget - (read-only) (???)
url - (read-only) (???)
highQuality - 1=high, 0=low (?)
focusRect - (???)
soundBufTime - (???)
Так, можно установить позицию x спрайта как /box.x = 100;.
Но почему слэш перед box? Таким способом flash отслеживает спрайты в клипе,
точно как в файловой системе unix - здесь показано, что box находится на
верхнем уровне. Если именованный бокс спрайта имел внутри себя другой
именованный спрайт, вы можете установить его x-позицию: /box/biff.x = 100;.
Как минимум, я так думаю; исправьте меня, если это не так (здесь и далее в
этом файле это комментарии автора - прим. перев.).
Этот простой пример перемещает красный квадрат через окно.
Следующий простой пример отслеживает вашу мышь на экране.
Пример 2. swfaction()
<?php
$m = new SWFMovie();
$m->setRate(36.0);
$m->setDimension(1200, 800);
$m->setBackground(0, 0, 0);
/* спрайт трэкинга мыши - пустой, но следует за мышью, так что мы можем
получить её x и y координаты */
$i = $m->add(new SWFSprite());
$i->setName(’mouse’);
$m->add(new SWFAction("
startDrag(’/mouse’, 1); /* ’1’ означает блокировать спрайт на мыши */
"));
/* можно также отключить antialiasing, поскольку это просто квадраты */
$m->add(new SWFAction("
this.quality = 0;
"));
/* morphing box */
$r = new SWFMorph();
$s = $r->getShape1();
/* Заметьте, это backwards нормальных фигур. Не знаю, зачем. */
$s->setLeftFill($s->addFill(0xff, 0xff, 0xff));
$s->movePenTo(-40, -40);
$s->drawLine(80, 0);
$s->drawLine(0, 80);
$s->drawLine(-80, 0);
$s->drawLine(0, -80);
$s = $r->getShape2();
$s->setLeftFill($s->addFill(0x00, 0x00, 0x00));
$s->movePenTo(-1, -1);
$s->drawLine(2, 0);
$s->drawLine(0, 2);
$s->drawLine(-2, 0);
$s->drawLine(0, -2);
/* контейнер спрайта для morphing box -
это просто timeline w/ box morphing */
$box = new SWFSprite();
$box->add(new SWFAction("
stop();
"));
$i = $box->add($r);
for($n=0; $n<=20; ++$n)
{
$i->setRatio($n/20);
$box->nextFrame();
}
/* этот спрайт-контейнер даёт нам возможность использовать
один код акции многократно */
$cell = new SWFSprite();
$i = $cell->add($box);
$i->setName(’box’);
$cell->add(new SWFAction("
setTarget(’box’);
/* ...x обозначает x-координату parent, т.е. (..).x */
dx = (/mouse.x + random(6)-3 - ...x)/5;
dy = (/mouse.y + random(6)-3 - ...y)/5;
gotoFrame(int(dx*dx + dy*dy));
"));
$cell->nextFrame();
$cell->add(new SWFAction("
gotoFrame(0);
play();
"));
$cell->nextFrame();
/* наконец, добавим пачку ячеек в movie */
for($x=0; $x<12; ++$x)
{
for($y=0; $y<8; ++$y)
{
$i = $m->add($cell);
$i->moveTo(100*$x+50, 100*$y+50);
}
}
$m->nextFrame();
$m->add(new SWFAction("
gotoFrame(1);
play();
"));
header(’Content-type: application/x-shockwave-flash’);
$m->output();
?>
Вот то же, что и выше, но более красиво раскрашенные шарики ...
Пример 3. swfaction()
<?php
$m = new SWFMovie();
$m->setDimension(11000, 8000);
$m->setBackground(0x00, 0x00, 0x00);
$m->add(new SWFAction("
this.quality = 0;
/frames.visible = 0;
startDrag(’/mouse’, 1);
"));
// спрайт трэкинга мыши
$t = new SWFSprite();
$i = $m->add($t);
$i->setName(’mouse’);
$g = new SWFGradient();
$g->addEntry(0, 0xff, 0xff, 0xff, 0xff);
$g->addEntry(0.1, 0xff, 0xff, 0xff, 0xff);
$g->addEntry(0.5, 0xff, 0xff, 0xff, 0x5f);
$g->addEntry(1.0, 0xff, 0xff, 0xff, 0);
// градиент фигуры
$s = new SWFShape();
$f = $s->addFill($g, SWFFILL_RADIAL_GRADIENT);
$f->scaleTo(0.03);
$s->setRightFill($f);
$s->movePenTo(-600, -600);
$s->drawLine(1200, 0);
$s->drawLine(0, 1200);
$s->drawLine(-1200, 0);
$s->drawLine(0, -1200);
// нужно сделать это спрайтом, чтобы мы могли multColor его
$p = new SWFSprite();
$p->add($s);
$p->nextFrame();
// поместить фигуры здесь, каждый кадр своим цветом
$q = new SWFSprite();
$q->add(new SWFAction("gotoFrame(random(7)+1); stop();"));
$i = $q->add($p);
$i->multColor(1.0, 1.0, 1.0);
$q->nextFrame();
$i->multColor(1.0, 0.5, 0.5);
$q->nextFrame();
$i->multColor(1.0, 0.75, 0.5);
$q->nextFrame();
$i->multColor(1.0, 1.0, 0.5);
$q->nextFrame();
$i->multColor(0.5, 1.0, 0.5);
$q->nextFrame();
$i->multColor(0.5, 0.5, 1.0);
$q->nextFrame();
$i->multColor(1.0, 0.5, 1.0);
$q->nextFrame();
// наконец, код акции
$p = new SWFSprite();
$i = $p->add($q);
$i->setName(’frames’);
$p->add(new SWFAction("
dx = (/:mousex-/:lastx)/3 + random(10)-5;
dy = (/:mousey-/:lasty)/3;
x = /:mousex;
y = /:mousey;
alpha = 100;
"));
$p->nextFrame();
$p->add(new SWFAction("
this.x = x;
this.y = y;
this.alpha = alpha;
x += dx;
y += dy;
dy += 3;
alpha -= 8;
"));
$p->nextFrame();
$p->add(new SWFAction("prevFrame(); play();"));
$p->nextFrame();
$i = $m->add($p);
$i->setName(’frames’);
$m->nextFrame();
$m->add(new SWFAction("
lastx = mousex;
lasty = mousey;
mousex = /mouse.x;
mousey = /mouse.y;
++num;
if(num == 11)
num = 1;
removeClip(’char’ & num);
duplicateClip(/frames, ’char’ & num, num);
"));
$m->nextFrame();
$m->add(new SWFAction("prevFrame(); play();"));
header(’Content-type: application/x-shockwave-flash’);
$m->output();
?>
Следующий простой пример обрабатывает акции клавиатуры.
(Вам, возможно нужно щёлкнуть на окне для передачи ему фокуса.
И, возможно, вы должны будете также оставить мышь в кадре.
Если вы знаете, как передавать фокус кнопкам программно, это не обязательно.)
Пример 4. swfaction()
<?php
/* спрайт имеет одну букву на кадр */
$p = new SWFSprite();
$p->add(new SWFAction("stop();"));
$chars = "abcdefghijklmnopqrstuvwxyz".
"ABCDEFGHIJKLMNOPQRSTUVWXYZ".
"1234567890!@#$%^&/*()_+-=/[]{}|;:,.<>?`~";
$f = new SWFFont("_sans");
for($n=0; $nremove($i);
$t = new SWFTextField();
$t->setFont($f);
$t->setHeight(240);
$t->setBounds(600,240);
$t->align(SWFTEXTFIELD_ALIGN_CENTER);
$t->addString($c);
$i = $p->add($t);
$p->labelFrame($c);
$p->nextFrame();
}
/* захватить область для кнопки - весь кадр */
$s = new SWFShape();
$s->setFillStyle0($s->addSolidFill(0, 0, 0, 0));
$s->drawLine(600, 0);
$s->drawLine(0, 400);
$s->drawLine(-600, 0);
$s->drawLine(0, -400);
/* проверка нажатия клавиши кнопки, отправка спрайта в кадр */
$b = new SWFButton();
$b->addShape($s, SWFBUTTON_HIT);
for($n=0; $naddAction(new SWFAction("
setTarget(’/char’);
gotoFrame(’$c’);
"), SWFBUTTON_KEYPRESS($c));
}
$m = new SWFMovie();
$m->setDimension(600,400);
$i = $m->add($p);
$i->setName(’char’);
$i->moveTo(0,80);
$m->add($b);
header(’Content-type: application/x-shockwave-flash’);
$m->output();
?>