Вжух, вжух! Добавляем звук меча на любой странице

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

Что­бы магия сра­бо­та­ла, дви­гать мыш­кой нуж­но рез­ко, пото­му что мед­лен­ный меч не изда­ёт зву­ка.

Логика программы

  1. Загру­жа­ем нуж­ный звук на стра­ни­цу.
  2. Начи­на­ем отсле­жи­вать все дви­же­ния мыши.
  3. Если рез­ко — про­иг­ры­ва­ем звук меча.

Теперь сде­ла­ем всё по шагам.

Загружаем звук на страницу

Что­бы вос­про­из­ве­сти звук на стра­ни­це, исполь­зу­ют объ­ект audio. С ним мож­но рабо­тать через JavaScript. Глав­ное, что нуж­но сде­лать, — это ука­зать путь к тре­бу­е­мо­му фай­лу.

Для уско­ре­ния рабо­ты мы сра­зу под­гру­зим его на стра­ни­цу. Он будет висеть в памя­ти и в нуж­ный момент вос­про­из­ве­дёт­ся без задерж­ки.

    
language: JavaScript
// Создаём новый аудиообъект на странице

var audio = new Audio();

// Подготавливаем звук, чтобы он сразу был готов к воспроизведению

audio.preload = 'auto';

// Указываем путь к аудиофайлу

audio.src = 'https://thecode.media/wp-content/uploads/2020/02/ninja-sword.mp3';


Ско­пи­ро­вать код
Код ско­пи­ро­ван

Мы загру­зи­ли наш звук меча на сайт и ука­за­ли к нему пол­ный путь. Вы може­те исполь­зо­вать любой дру­гой звук, но тогда поме­няй­те путь на свой.

Следим за мышью

Наша зада­ча — полу­чить теку­щие коор­ди­на­ты мыши. Кро­ме это­го, нам нуж­но сле­дить за вре­ме­нем, кото­рое про­шло с момен­та послед­не­го дви­же­ния. Суть в том, что зная вре­мя и рас­сто­я­ние, кото­рое про­шёл кур­сор, мож­но понять, с какой ско­ро­стью он дви­гал­ся. Это нам пона­до­бит­ся на сле­ду­ю­щем эта­пе, поэто­му сосре­до­то­чим­ся пока на коор­ди­на­тах и вре­ме­ни. Сра­зу заве­дём нуж­ные пере­мен­ные:

// Переменные для отслеживания времени и координат мыши
var timestamp = null;
var lastMouseX = null;
var lastMouseY = null;

Что­бы все­гда быть в кур­се, что мышь нача­ла дви­гать­ся, доба­вим обра­бот­чик это­го собы­тия. Всё осталь­ное будем про­пи­сы­вать внут­ри него:

document.body.addEventListener("mousemove", function(e) {}

С это­го момен­та скрипт сам будет сле­дить за тем, дви­га­ет­ся мышь или нет. Если дви­га­ет­ся — скрипт выпол­нит то, что напи­са­но внут­ри обра­бот­чи­ка.

Когда обра­бот­чик запу­стит­ся пер­вый раз, он не смо­жет посчи­тать рас­сто­я­ние, кото­рое про­шёл кур­сор, пото­му что он не запом­нил началь­ную пози­цию и не засёк вре­мя. Испра­вим это:

    
language: JavaScript
// Если мы ещё не начали следить за временем…

    if (timestamp === null) {

        // …то запоминаем текущее время 

        timestamp = Date.now();

        // и запоминаем координаты мыши

        lastMouseX = e.screenX;

        lastMouseY = e.screenY;

        // На первый раз сделали всё, что нужно, возвращаем управление назад 

        return;

    }


Ско­пи­ро­вать код
Код ско­пи­ро­ван

Теперь у нас есть все дан­ные, что­бы узнать прой­ден­ное рас­сто­я­ние и вре­мя. Логи­ка про­стая: мы полу­ча­ем све­жие коор­ди­на­ты и теку­щее вре­мя, нахо­дим раз­ни­цу с преды­ду­щи­ми и полу­ча­ем то, что нам нуж­но:

    
language: JavaScript
// Тут мы будем хранить текущее время

    var now = Date.now();

    // Тут — сколько времени прошло с момента последнего шевеления мышки

    var dt =  now - timestamp;

    // А в этих двух переменных — расстояние по Х и У, которые прошёл курсор

    var dx = e.screenX - lastMouseX;

    var dy = e.screenY - lastMouseY;


Ско­пи­ро­вать код
Код ско­пи­ро­ван

Смотрим, быстрое движение или нет

Меч сви­стит в воз­ду­хе толь­ко при быст­рых дви­же­ни­ях, поэто­му мы тоже долж­ны посчи­тать ско­рость дви­же­ния кур­со­ра по экра­ну. Для это­го исполь­зу­ем фор­му­лу из физи­ки: скорость = расстояние / время.

К это­му момен­ту мы зна­ем оба пара­мет­ра, поэто­му спо­кой­но можем най­ти ско­рость кур­со­ра по каж­дой оси:

    
language: JavaScript
    // Скорость — это расстояние, делённое на время. Сделаем отдельные переменные для скорости по Х и У

    var speedX = Math.round(dx / dt * 100);

    var speedY = Math.round(dy / dt * 100);

    // Берём текущее время

    timestamp = now;

    // Запоминаем текущие координаты мыши

    lastMouseX = e.screenX;

    lastMouseY = e.screenY;


Ско­пи­ро­вать код
Код ско­пи­ро­ван

Послед­нее, что нам оста­лось сде­лать, — решить, какую ско­рость счи­тать быст­рой. Нам нра­вит­ся чис­ло 400, но вы може­те уве­ли­чить его, если вам нужен мак­си­маль­но быст­рый меч.

Обра­ти­те вни­ма­ние, что мы исполь­зу­ем функ­цию моду­ля Math.abs(), когда рабо­та­ем со ско­ро­стью. Дело в том, что при дви­же­ни­ях сни­зу вверх и спра­ва нале­во ско­рость будет отри­ца­тель­ной, пото­му что ноль нахо­дит­ся в левом верх­нем углу. Что­бы у нас ско­рость была все­гда поло­жи­тель­ной, исполь­зу­ем модуль чис­ла — это такое же чис­ло, но без зна­ка минус.

// Если скорость была больше 400 по любой оси — включаем звук меча
    if ((Math.abs(speedX) > 400) || ( Math.abs(speedY) > 400)) { audio.play(); };

Готовый код

    
language: JavaScript
// Создаём новый аудиообъект на странице

var audio = new Audio();

// Подготавливаем звук, чтобы он сразу был готов к воспроизведению

audio.preload = 'auto';

// Указываем путь к аудиофайлу

audio.src = 'https://thecode.media/wp-content/uploads/2020/02/ninja-sword.mp3';

 

// Переменные для отслеживания времени и координат мыши

var timestamp = null;

var lastMouseX = null;

var lastMouseY = null;

 

// Добавляем новый обработчик события, который следит за каждым движением мыши

document.body.addEventListener("mousemove", function(e) {

    // Если мы ещё не начали следить за временем…

    if (timestamp === null) {

        // …то запоминаем текущее время и дату

        timestamp = Date.now();

        // и запоминаем координаты мыши

        lastMouseX = e.screenX;

        lastMouseY = e.screenY;

        // На первый раз сделали всё, что нужно, возвращаем управление назад 

        return;

    }

 

    // Тут мы будем хранить текущее время

    var now = Date.now();

    // Тут — сколько времени прошло с момента последнего шевеления мышки

    var dt =  now - timestamp;

    // А в этих двух переменных — расстояние по Х и У, которые прошёл курсор

    var dx = e.screenX - lastMouseX;

    var dy = e.screenY - lastMouseY;

 

    // Скорость — это расстояние, делённое на время. Сделаем отдельные переменные для скорости по Х и У

    var speedX = Math.round(dx / dt * 100);

    var speedY = Math.round(dy / dt * 100);

    // Берём текущее время

    timestamp = now;

    // Запоминаем текущие координаты мыши

    lastMouseX = e.screenX;

    lastMouseY = e.screenY;

    

    // Если скорость была больше 400 по любой оси — включаем звук меча

    if ((Math.abs(speedX) > 400) || ( Math.abs(speedY) > 400)) { audio.play(); };

});


Ско­пи­ро­вать код
Код ско­пи­ро­ван

Как запускать

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

var js = document.createElement('script'); js.src = "https://thecode.media/wp-content/uploads/2020/02/ninja_snd.js"; document.body.appendChild(js);

Если нуж­но встро­ить этот код через исход­ный код стра­ни­цы, исполь­зуй­те обыч­ный импорт скрип­та:

<script src="https://thecode.media/wp-content/uploads/2020/02/ninja_snd.js"></script>