PDA

Просмотр полной версии : Воспроизведение звука при наведении на клип


Maxish
23.04.2010, 05:32
Доброго времени суток!
Искал решения конкретно под свою проблему - не нашел.

А проблема заключается в следующем:
есть ряд кнопок(мувиклипы) - пунктов мею, которые при наведении onRollOver производятся в одном напрвлении, при onRollOut - обратно.
Реализвано это благодаря обработчику onEnterFrame
info_btn.onRollOver = function() { mouse_over_info = true; };
info_btn.onRollOut = function() { mouse_over_info = false; };

info_btn.onEnterFrame = function() {
if (mouse_over_info) { info_btn.nextFrame();
}else { info_btn.prevFrame(); }
};

Все работает. Но есть одно "но". Как сделать однократное воспроизведение звука при наведении? Т.е. как обойти onEnterFrame, ведь из-за него звук воспроизводится каждую секунду наведения? Спасибо.

AzagThoth
23.04.2010, 06:19
Уберите звук с таймлайна. Создавайте его программно и включайте в функции onRollOver

Maxish
23.04.2010, 13:57
Насколько я Вас понял:
var switch:Sound = new Sound();
switch.attachSound("zing.mp3");

aboutCompany_btn.onEnterFrame = function() {
if (mouse_over_about) { aboutCompany_btn.nextFrame();
zing.start();
}else { aboutCompany_btn.prevFrame();
//zing.stop(); - не принципиальный момент
}
};

Но ведь это абсолютно не меняет дело... Опять ежетактное проигрывание.

lexa2000lexa
23.04.2010, 14:00
var switch:Sound = new Sound();
switch.attachSound("zing.mp3");
info_btn.onRollOver = function() { switch.start() };
info_btn.onRollOut = function() { switch.stop() };
а вот так н еподойдет?

Maxish
23.04.2010, 14:18
Нет. потому что на onRollOver и onRollOut прописаны другие ф-ии (см. выше)

lexa2000lexa
23.04.2010, 14:34
а что мешает сделать такvar switch:Sound = new Sound();
switch.attachSound("zing.mp3");
info_btn.onRollOver = function() {
switch.start()
mouse_over_info = true;
};
info_btn.onRollOut = function() {
switch.stop()
mouse_over_info = false;
};

Maxish
23.04.2010, 15:04
Спасибо огромное! Вам - большой плюс в карму!))) Все работает.
Интересно, когда я уже исчерпаю свою плосколобость?

Тему можно закрывать.

studmar
23.04.2010, 21:47
У меня такой вопрос (очень схожий)
Я воспользовался вашим кодом
var muz:Sound = new Sound();
switch1.loadSound("some.mp3", false);

btn.onRollOver = function () {
switch1.start();
mouse_over_info = true;
};
btn.onRollOut = function () {
switch1.stop();
mouse_over_info = false;
};

Все работает правильно, т.е. при наведении на MovieClip начинает воспроизводится музыка, если отвести мышку - музыка пропадает. Но вот хотелось бы чтобы она не обрывалась, а постепенно затухала (fadeout) это как минимум, а как максимум имела бы еще и fadein
Вот тут обсуждалось нечто схожее http://www.flasher.ru/forum/showthread.php?t=136370
но совместить у меня не получается ибо мои познания в AS слабоваты.
Прошу помощи, заранее спасибо )

studmar
24.04.2010, 04:33
Покапался по иностранным сайтам и в итоге "слепил" из того, что уже было конструкцию (скорее всего неправильную, ибо я не программист, а дизайнер), но рабочую.
Источник "второго" куска кода здесь (http://www.partnersinrhyme.com/contact/tutorials.php?sub=Flash&cat=Adding%20Audio%20to%20Projects&sno=64)


var muz:Sound = new Sound();
muz.loadSound("test2.mp3", false); //подгружаем mp3 из "внешнего" источника

btn.onRollOver = function () { //для movieclip с именем btn при наведении мышки
muz.start(); //воспроизводим музон
muz.setVolume(100); //устанавливаем громкость, это по желанию
};

btn.onRollOut = fadeOutSound; // вот тут самое такое, как я понимаю при отводе мышки вызывается функция, которая сначала уменьшает громкость а потом выключает музон

function fadeOutSound():Void {
if (id) {
clearInterval(id);
}
var volume = muz.getVolume();
id = setInterval(fadeOut, 10);
function fadeOut():Void {
muz.setVolume(volume--);
if (volume<=0) {
clearInterval(id);
muz.stop();
}
}
}


Теперь все выглядит так: при наведении мышки на movieclip "btn" воспроизводится файл, при отводе плавно затихает. Если навести мышку снова - все повторится сначала, а было бы интересно сделать так, чтобы проигрывалось с того самого места, когда мышку убрали... может кто знает как этого добится?

Так же можно заморочиться и сделать еще fade in для звук

24288

mooncar
24.04.2010, 09:54
было бы интересно сделать так, чтобы проигрывалось с того самого места, когда мышку убрали...

Ставьте звук на паузу вместо stop() .
Для этого перед остановкой можно запомнить позицию (Sound.position property). И запускать уже с нужной позиции.
Только следует учесть, что position берется в миллисекундах, а офсет в start() выставляется в секундах, так что округляйте.

AzagThoth
24.04.2010, 11:02
Только вот этого
var muz:Sound = new Sound();
Лучше всегда избегать. Ибо созданный звук будет управлять всеми звуками существующими в фильме.
Предлагаю делать так
createEmptyMovieClip("clip",getNextHighestDepth());
var muz:Sound = new Sound(clip);

studmar
24.04.2010, 12:26
Ставьте звук на паузу вместо stop() .
Для этого перед остановкой можно запомнить позицию (Sound.position property). И запускать уже с нужной позиции.
Только следует учесть, что position берется в миллисекундах, а офсет в start() выставляется в секундах, так что округляйте.

А Вы можете показать как это в коде выглядело бы?

AzagThoth
24.04.2010, 12:39
snd.stop()
position=snd.position;
snd.start(Math.floor(position/1000));

studmar
24.04.2010, 12:54
snd.stop()
position=snd.position;
snd.start(Math.floor(position/1000));

К сожалению, работает некорректно, при повторном наведении музыка воспроизводится вроде с того же места, но, поскольку как бы снова срабатывает rollOver, то запускается еще раз и получаются дублирующие каналы (не знаю, правильно ли объяснил)

вот код:
createEmptyMovieClip("clip",getNextHighestDepth());
var muz:Sound = new Sound(clip);
muz.loadSound("s1.mp3", false);

btn.onRollOver = function () {
muz.start();
muz.setVolume(25);
};

btn.onRollOut = fadeOutSound;

function fadeOutSound():Void {
if (id) {
clearInterval(id);
}
var volume = muz.getVolume();
id = setInterval(fadeOut, 10);
function fadeOut():Void {
muz.setVolume(volume--);
if (volume<=0) {
clearInterval(id);
muz.stop()
position=muz.position;
muz.start(Math.floor(position/1000));
}
}
}

AzagThoth
24.04.2010, 13:00
createEmptyMovieClip("clip",getNextHighestDepth());
var muz:Sound = new Sound(clip);
var position:Number=0;
muz.loadSound("s1.mp3", false);

btn.onRollOver = function () {
muz.start(Math.floor(position/1000));
muz.setVolume(25);
};

btn.onRollOut = fadeOutSound;

function fadeOutSound():Void {
if (id) {
clearInterval(id);
}
var volume = muz.getVolume();
id = setInterval(fadeOut, 10);
function fadeOut():Void {
muz.setVolume(volume--);
if (volume<=0) {
clearInterval(id);
muz.stop()
position=muz.position;
}
}
}

studmar
24.04.2010, 13:06
я уже догадался, где "накосячил", все вроде работает правильно, но когда трек заканчивается - он не повторяется и это правильно, однако логично предположить что если отвести мышку и подвести вновь, то трек должен проиграться снова... а этого увы не происходит...

AzagThoth
24.04.2010, 13:20
Опишите обработчик функции onSoundComplete
Адекватный на сегодняшний день хелп по AS2 можете взять тут: http://nnm-club.ru/forum/viewtopic.php?t=192686

studmar
24.04.2010, 13:26
Опишите обработчик функции onSoundComplete
Вы можете показать пример?
Хелп я посмотреть могу, но правильно применить - тут проблема..
Я не совсем понимаю как это сделать ибо не программист, и поэтому делаю все методом "тыка"

AzagThoth
24.04.2010, 13:35
В вашем случае достаточно сделать так.
muz.onSoundComplete=function():Void{
position=0;
flag=true;
}
Флаг переменная со значением булево. В Вашей функции фадеОут проверяете и если она true то присваиваете false, а также не переопределяете переменную position. В противном случае переопределяете.

studmar
24.04.2010, 13:54
Покопавшись в сети, попробовал сделать, вот что получилось:
createEmptyMovieClip("clip",getNextHighestDepth());
var muz:Sound = new Sound(clip);
var position:Number=0;
muz.loadSound("s1.mp3", false);
muz.onSoundComplete=function():Void{
position=0;
flag=true;
}

btn.onRollOver = function () {
muz.start(Math.floor(position/1000));
muz.setVolume(25);
};

btn.onRollOut = fadeOutSound;

function fadeOutSound():Void {

if (id) {
clearInterval(id);
}
var volume = muz.getVolume();
id = setInterval(fadeOut, 10);
function fadeOut():Void {
muz.setVolume(volume--);
if (volume<=0) {
clearInterval(id);
muz.stop()

if (flag == true) {
flag == false;
}
else {
position=muz.position;
}
}
}
}


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

AzagThoth
24.04.2010, 18:46
Используйте оператор равенста, для присвоения значения переменной flag, а не оператор сравнения.
PS: Остаётся загадкой зачем было копаться в сети, когда я уже привёл Вам пример кода и алгоритм которым это может быть реализовано.

studmar
24.04.2010, 19:03
PS: Остаётся загадкой зачем было копаться в сети, когда я уже привёл Вам пример кода и алгоритм которым это может быть реализовано.

Потому что я не программист, и как куда чего писать толком не знаю...

Добавлено через 11 минут
Вот полные и вроде правильный код

createEmptyMovieClip("clip",getNextHighestDepth());
var muz:Sound = new Sound(clip);
var position:Number=0;
muz.loadSound("test2.mp3", false);
muz.onSoundComplete=function():Void{
position=0;
flag=true;
}


btn.onRollOver = function () {
muz.start(Math.floor(position/1000));
muz.setVolume(10);
};

btn.onRollOut = fadeOutSound;

function fadeOutSound():Void {

if (id) {
clearInterval(id);
}
var volume = muz.getVolume();
id = setInterval(fadeOut, 10);
function fadeOut():Void {

muz.setVolume(volume--);
if (volume<=0)
{
clearInterval(id);
muz.stop()

if (flag == true) {
flag = false;
}
else {
position=muz.position;
}


}
}
}

AzagThoth
24.04.2010, 19:48
Да, вроде всё гуд.
Я не написал код сразу, потому как ценен только опыт в той или иной степени полученный самостоятельно(личные наблюдения) и если у Вас есть желание разобраться, а судя по теме оно было. То всегда лучше помочь человеку дав необходимые "наводки". Для того что бы он дошёл до решения сам и лучше понял принцип всего этого.

studmar
24.04.2010, 19:56
С вами нельзя не согласиться, спасибо огромное!

Интересно было бы сделать это все для нескольких movieclip, я пытаюсь, пытаюсь, но пока ничего не получается.
Может дадите подсказку?

Понятное дело что тут нужны массивы и т.п. но в этом я точно запутаюсь...

Чуть позже покажу что получается, может вы меня поправите...

Вот, отталкиваясь от этой темы: http://www.flasher.ru/forum/showthread.php?t=136370#edit886806 и предыдущего кода

пока смог сделать (для трех movieclip):

var sounds:Array = new Array();

for (i = 1; i < 4; i++) {
sounds[i] = new Array();
var mc:MovieClip = this.createEmptyMovieClip('s' + i + '_mc', this.getNextHighestDepth());
sounds[i] = new Sound (mc);
sounds[i].loadSound('s' + i + '.mp3', false);
sounds[i].onSoundComplete = function():Void {
position=0;
flag=true;
}

var btn:MovieClip = this['s' + i + '_btn'];
btn.num = i;
btn.onRollOver = startPlay;
btn.onRollOut = fadeOutSound;

}

function startPlay() {
var n:Number = this.num;
sounds[n].start(Math.floor(position/1000));
sounds[n].setVolume(40);

}

function fadeOutSound() {
sounds[i] = new Array();
if (id) {
clearInterval(id);
}
var volume = sounds[n].getVolume();
id = setInterval(fadeOut, 10);
function fadeOut():Void {

sounds.setVolume(volume--);
if (volume<=0)
{
clearInterval(id);
sounds[n].stop()

if (flag == true) {
flag = false;
}
else {
position=sounds[n].position;
}


}
}
}



Но не срабатывает вообще функция fadeOutSound
Быть может я вообще все не так делаю...

AzagThoth
24.04.2010, 22:47
В данном случае, когда Вы хотите одним кодом работать с большим количеством объектов логично было бы описывать некоторые свойства как свойства этих объектов. То есть я имею в виду, что position и flag имеет смысл сделать свойства Ваших программно создаваемых звуков. Сделать это совсем не сложно. Просто прописав свойство через оператор точки и задав ему значение. Например так:
sounds[i].position=0;
sounds[i].flag=true;
Это если на этапе создания звука. Соответственно если на этапе выполнения функции закреплёнными за звуком, то можно сделать так:
this.position=0;
this.flag=true;
Ну и в Ваших условиях разумеется тоже проверяйте значения не position и flag, а this.position и this.flag.
Всё должно получиться.

studmar
24.04.2010, 23:00
var sounds:Array = new Array();

for (i = 1; i < 4; i++) {
sounds[i] = new Array();
var mc:MovieClip = this.createEmptyMovieClip('s' + i + '_mc', this.getNextHighestDepth());
sounds[i] = new Sound (mc);
sounds[i].loadSound('s' + i + '.mp3', false);
sounds[i].onSoundComplete = function():Void {
sounds[i].position=0;
sounds[i].flag=true;
}

var btn:MovieClip = this['s' + i + '_btn'];
btn.num = i;
btn.onRollOver = startPlay;
btn.onRollOut = fadeOutSound;

}

function startPlay() {
var n:Number = this.num;
sounds[n].start(Math.floor(position/1000));
sounds[n].setVolume(40);


}

function fadeOutSound() {
sounds[i] = new Array();
if (id) {
clearInterval(id);
}
var volume = sounds[n].getVolume();
id = setInterval(fadeOut, 10);
function fadeOut():Void {

sounds.setVolume(volume--);
if (volume<=0)
{
clearInterval(id);
sounds[n].stop()
if (this.flag == true) {
this.flag = false;
}
else {
this.position=sounds[n].position;
}


}
}
}


Пока не работает
Правильное направление?

AzagThoth
24.04.2010, 23:10
Может я чего не понимаю, но в этом вообще не вижу смысла.
var btn:MovieClip = this['s' + i + '_btn'];
btn.num = i;
btn.onRollOver = startPlay;
btn.onRollOut = fadeOutSound;

Также в функции startPlay и fadeOutSound не должно быть этого sounds[i]. Дело в том, что на момент исполнения кода значение i то на котором закончился цикл for. Следовательно работа будет происходить только с одним созданным программно звуком(последним естественно). В подобных случая надо использовать this.

studmar
24.04.2010, 23:30
К сожалению у меня ничего не получилось, а получилось вот что
var sounds:Array = new Array();

for (i = 1; i < 4; i++) {
sounds[i] = new Array();
var mc:MovieClip = this.createEmptyMovieClip('s' + i + '_mc', this.getNextHighestDepth());
sounds[i] = new Sound (mc);
sounds[i].loadSound('s' + i + '.mp3', false);
sounds[i].onSoundComplete = function():Void {
sounds[i].position=0;
sounds[i].flag=true;
}

var btn:MovieClip = this['s' + i + '_btn'];
btn.num = i;
btn.onRollOver = startPlay;
btn.onRollOut = fadeOutSound;

}

function startPlay() {
var n:Number = this.num;
sounds[n].start(Math.floor(position/1000));
sounds[n].setVolume(40);


}

function fadeOutSound() {
n = this.num;
if (id) {
clearInterval(id);
}
var volume = sounds[n].getVolume();
id = setInterval(fadeOut, 10);
function fadeOut():Void {

sounds[n].setVolume(volume--);
if (volume<=0)
{
clearInterval(id);
sounds[n].stop()
if (sounds[n].flag == true) {
sounds[n].flag = false;
}
else {
sounds[n].position=sounds[n].position;
}


}
}
}

Сейчас при наведении на 3 mc обе функции срабатывают, но каждый файл воспроизводится заново, а не с того же места...

По поводу кнопок, откуда я взял пример, написано

//работа с кнопками
var btn:MovieClip = this['s' + i + '_btn'];
btn.num = i; //сохраняем номер внутри кнопки
btn.onPress = startPlay; // в нашем случае, это btn.onRollOver = startPlay;
btn.onRelease = fadeOut; // и btn.onRollOut = fadeOutSound;

AzagThoth
24.04.2010, 23:34
Да, это я уже я чушь пишу :). Перекоротило немного. Всё у Вас нормально.
sounds[n].start(Math.floor(position/1000));
Исправьте на
sounds[n].start(Math.floor(this.position/1000));

studmar
24.04.2010, 23:44
К сожалению эта конструкция не работает, ничего не изменилось
sounds[n].start(Math.floor(this.position/1000));

но работает эта

sounds[n].start(Math.floor(sounds[n].position/1000));

однако файл после проигрывания при новом "отвод-подвод" не воспроизводится вновь

AzagThoth
25.04.2010, 00:08
Да, имел в виду как раз :) sound[n]
однако файл после проигрывания при новом "отвод-подвод" не воспроизводится вновь
Это происходит потому что свойство position которые мы с Вами придумали совпало со свойством уже имеющимся у класса Sound, с объектом которого мы работаем. То есть достаточно просто измененить имя нашего свойства position на другое.
А вот и код:
var sounds:Array = new Array();

for (i = 1; i < 4; i++) {
sounds[i] = new Array();
var mc:MovieClip = this.createEmptyMovieClip('s' + i + '_mc', this.getNextHighestDepth());
sounds[i] = new Sound (mc);
sounds[i].loadSound('s' + i + '.mp3', false);
sounds[i].onSoundComplete = function():Void {
sounds[i].positionS=0;
sounds[i].flag=true;
}

var btn:MovieClip = this['s' + i + '_btn'];
btn.num = i;
btn.onRollOver = startPlay;
btn.onRollOut = fadeOutSound;

}

function startPlay() {
var n:Number = this.num;
sounds[n].start(Math.floor(sounds[n].positionS/1000));
sounds[n].setVolume(40);


}

function fadeOutSound() {
n = this.num;
if (id) {
clearInterval(id);
}
var volume = sounds[n].getVolume();
id = setInterval(fadeOut, 10);
function fadeOut():Void {

sounds[n].setVolume(volume--);
if (volume<=0)
{
clearInterval(id);
sounds[n].stop()
if (sounds[n].flag == true) {
sounds[n].flag = false;
}
else {
sounds[n].positionS=sounds[n].position;
}


}
}
}

studmar
25.04.2010, 02:59
Странно, но не сработало...
После проигрывания полностью любого из mc и при отводе-подводе они не воспроизводятся.
посмотрите пожалуйста в чем проблема

AzagThoth
25.04.2010, 03:18
В общем это виновата моя невнимательность. Вот я поправил код.
var sounds:Array = new Array();

for (i=1; i<4; i++) {
sounds[i] = new Array();
var mc:MovieClip = this.createEmptyMovieClip('s'+i+'_mc', this.getNextHighestDepth());
sounds[i] = new Sound(mc);
sounds[i].loadSound('s'+i+'.mp3',false);
sounds[i].onSoundComplete = function():Void {
this.positionS = 0;
this.flag = true;
};
var btn:MovieClip = this['s'+i+'_btn'];
btn.num = i;
btn.onRollOver = startPlay;
btn.onRollOut = fadeOutSound;
}

function startPlay() {
var n:Number = this.num;
sounds[n].start(Math.floor(sounds[n].positionS/1000));
sounds[n].setVolume(40);
}

function fadeOutSound() {
n = this.num;
if (id) {
clearInterval(id);
}
var volume = sounds[n].getVolume();
id = setInterval(fadeOut, 10);
function fadeOut():Void {

sounds[n].setVolume(volume--);
if (volume<=0) {
clearInterval(id);
sounds[n].stop();
if (sounds[n].flag == true) {
sounds[n].flag = false;
} else {
sounds[n].positionS = sounds[n].position;
}
}
}
}

Добавлено через 4 минуты
Причём тут - http://www.flasher.ru/forum/showpost.php?p=903229&postcount=25
Я написал, что нужно в функции обработчике объекта Sound описывать параметры объекта через ключевое слово this. А потом видимо "расслабился" и сам упустил это из виду :) Эх.

studmar
25.04.2010, 03:24
Вот теперь все круто!
Огромное Вам спасибо, надеюсь тема будет полезна!