【译】Josh 大神亲自带你一起感受前端音乐的魅力

3,762 阅读8分钟

原文地址:www.joshwcomeau.com/react/annou…

作者:Josh Comeau、 译者:林鸿鹄

未经授权禁止转载。

读前须知

本篇译文涉及到的部分 音频demo 需要前往到 原文 进行尝试。

强力推荐去试试看哦~ (需翻墙)

image.png

介绍

可能因为我是一个音频工程师,本人很期待能在浏览器里听到更多的音效。

我知道这时候会有一大堆的人反驳我,很大部分原因是曾经音频在浏览器里被乱用,从而导致一部分人觉得在浏览器听到声音是一件很讨厌的事情。

早期遇到音频往往是在以下情况:

  • 老的浏览器里使用 MIDI 文件作为背景音乐 🎺
  • 黑客病毒类曾用音效来达到一些邪恶的目的,来获取用户的注意力,让诈骗更可信 😈
  • 还有自动播放视频等等 😬

但是我认为这个想法还是可以拯救一下的。我相信音效可以强调用户的行为,增强给用户的反馈、给枯燥的用户行为增添一些快乐。当声音被高雅地使用后,产品会更加地真实、更加地栩栩如生。

给项目添加音效并不是一个新主意:例如网页游戏,或手机app上一直有在使用音效来提升用户交互的体验。实际上,web 才是个奇葩,我能想到的所有数字媒体都有用到音效吧?你们说是不是?

当我搭建这个博客的时候,我就想要开始这个试验。在我这个博客里,当你和很多 UI 组件互动的时候都会发出声音哦~

去试试看吧!

你可以尝试点击博客的右上角 (需翻墙)

或尝试一下原文的在线代码编辑区,真的非常有意思!

image.png

因为音效在浏览器上真的是太少太少了,所以体验的时候你会感觉特别的吸引人的"耳球"。所以只要把声音用在正确的项目里,这会是一个绝对的秘密武器,给 everybody 带来大大滴惊喜!

为了让你们比较方便的开始,我把这个博客的 hook,use-sound, 发布到 NPM 上了。本篇博客会尽快得让你们知道它可以做什么,我还会分享一些如何在 web 中正确使用音效的技巧。

直接看文档?

如果你想直接用这个 hook,你可以 直接跳到这个 GITHUB 链接 哦~

概述

use-sound 是一个 react hook 让你可以播放音效。这里是一个比较简单的例子:

import useSound from 'use-sound';
import boopSfx from '../../sounds/boop.mp3'; // 导入你自己的音频
const BoopButton = () => {
  const [play] = useSound(boopSfx);
  return <button onClick={play}>Boop!</button>;
};

useSound 会异步加载10kb的第三方依赖包 Howler,但对你的包只加大约1kb。

它提供了一大堆很赞的东西,包括:

  • 提早停止声音,或者暂停/重播声音。
  • 加载一个雪碧音频,然后分裂成很多独立的声音。
  • 让声音加速或减速。
  • 拥有一大堆事件!
  • 还有好多好多 Howler 所实现的高级东西。

假如你想看更多复杂的使用方式或 API详情,你可以 点击此处查看文档

让我们开始吧!

安装

第一步我们要做的是通过 NPM 或者 Yarn 来进行安装包:

# 用 YARN
yarn add use-sound
# 或,用 NPM
npm install use-sound

导入

这个包只导出一个默认的 hook,useSound

import useSound from 'use-sound';

在使用这个 hook 之前,你还需要导入你的音频文件。

如果你是使用 create-react-app/Gatsby 这样的脚手架,你应该可以像导入图片或其他media一样的方式来导入 MP3 文件:

import boopSfx from '../../sounds/boop.mp3';

如果你在捣鼓自己的 Webpack 配置,你可以用到 file-loader 使 .mp3 格式的文件成为随意的文件类型。

前端好声音!

知道如何安装依赖和写代码只是成功的一半;我们还需要准备好优美动听的音乐才行!

我最喜欢的资源是 freesound.org。几乎博客的所有音频都来自于这个网站。你需要先注册一个账号来下载他们的资源,所有东西都是免费的喔。

请做好寻找音乐的准备。网站里很多里面的声音都录的不是很清晰,

可能就是大海捞针的感觉 嘻嘻 毕竟是免费的

准备音频

很多来自 freesound.org 的音频我们都需要先处理一下:

  • 比如说一些和弦,音频播放时是断断续续的。你需要把他们裁剪一下,达到触发声音后就立马能听到的效果。
  • 假如一些音频音量一会儿高一会儿低的,你还得调整音频的音量调成一致哦。
  • 下载下来的音频格式可能不同,你还需要转成 MP3 的格式~

完成以上几点,你播放的音频才会完美哟~

image.png

你可以使用一个免费,开源,跨平台的音频编辑器来编辑你下载的音频

我推荐你们使用 Audacity(该地址需要翻墙下载)

译者在百度找到了这个下载地址:audacity.onl/

当然学习怎么使用 Audacity 不是这个博客的重点,但是外面还是有很多免费的资源来学习如何使用它。

为什么一定要使用 MP3?

在好久以前,还没有一个哪里都支持的音频格式;大家常用 MP3,AIFF,或是 WAV,在不同的环境下加载不同的文件。

开心的是, MP3 当今被所有主流的 浏览器支持,包括 Internet Explorer 9。和其他格式相比,MP3 可以很好的被压缩成更小的文件大小。

所以我强推 MP3!

音频 🔊 & 辅助功能 ♿️ & 可用性

即使音频被网页所支持,我注意到有一部分用户不会在乎它的存在,他们可能更喜欢静静地呆着。

对于那些视力损伤的人群一般都会使用屏幕朗读软件来访问网页。如果我们给网页放置过多的音效,可能会导致这类用户在聆听朗读的内容时,被这些音效所打扰到。

以上原因所致,在你的页面上放置一个静音按钮 🔕 是非常重要的。而且把静音"状态保持"住也是至关重要的,这样用户就不再需要反复地设置是否需要静音啦!

相反的,对于听力有障碍的用户而言,他们察觉不到声音是否被触发了。因此,我们绝不能仅通过音频来传递重要的信息。如果你在使用音效来作为反馈用户的途径,请也确保拥有视觉上的反馈。这样、网页才能100%在没声音的情况下保持可用性。

状态保持 Sticky 是作者的另外一篇文章,

假如同学们感兴趣可以在评论区点赞留言,小编抽空再翻译一下~

小试牛刀

请前往作者的博客尝试不同在线的 demo 吧~

请不要忘记打开本地设备的声音哦~

1. Checkbox

当我点击这个 checkbox 的时候,我已经颅内升天了(゜-゜)つ!!如果有鼠标的或触控板的话,请尝试一次飞快的点击,然后再尝试一次缓慢的点击,听听他们的音效。

image.png

代码:


function Demo() {
  const [isChecked, setIsChecked] = React.useState(
    false
  );

  const [playActive] = useSound(
    '/sounds/pop-down.mp3',
    { volume: 0.25 }
  );
  const [playOn] = useSound(
    '/sounds/pop-up-on.mp3',
    { volume: 0.25 }
  );
  const [playOff] = useSound(
    '/sounds/pop-up-off.mp3',
    { volume: 0.25 }
  );

  return (
    <Checkbox
      name="demo-checkbox"
      checked={isChecked}
      size={24}
      label="I agree to self-isolate"
      onChange={() => setIsChecked(!isChecked)}
      onMouseDown={playActive}
      onMouseUp={() => {
        isChecked ? playOff() : playOn();
      }}
    />
  );
}

2. 互动音频

有时候你只希望声音在互动的时候被播放。 注意到下面这个 demo 声音只在 hover 的时候被播放:

image.png

代码:

function Demo() {
  const soundUrl = '/sounds/rising-pops.mp3';
  // 你可以通过更换资源 'rising-pops' 成下面的音频资源听听看哟~
  // - fanfare
  // - dun-dun-dun
  // - guitar-loop
  const [play, { stop }] = useSound(
    soundUrl,
    { volume: 0.5 }
  );

  const [isHovering, setIsHovering] = React.useState(
    false
  );

  return (
    <Button
      onMouseEnter={() => {
        setIsHovering(true);
        play();
      }}
      onMouseLeave={() => {
        setIsHovering(false);
        stop();
      }}
    >
      <ButtonContents isHovering={isHovering}>
        Hover over me!
      </ButtonContents>
    </Button>
  );
}

3. 逐步升高的音阶

我在点赞的按钮上加了一个很有意思的技巧:每次点击的音频音阶,都会比上一次的点击的要更高一点。我是这么实现的:

image.png

代码:

function Demo() {
  const soundUrl = '/sounds/glug-a.mp3';

  const [playbackRate, setPlaybackRate] = React.useState(0.75);

  const [play] = useSound(soundUrl, {
    playbackRate,
    volume: 0.5,
  });

  const handleClick = () => {
    setPlaybackRate(playbackRate + 0.1);
    play();
  };

  return (
    <Button onClick={handleClick}>
      <span role="img" aria-label="Heart">
        💖
      </span>
    </Button>
  );
}

4. 播放/暂停 按钮

你可以用这个播放按钮搞一个新的网易音音乐了哈哈哈。

image.png

代码:

function Demo() {
  const soundUrl = '/sounds/guitar-loop.mp3';

  const [play, { stop, isPlaying }] = useSound(soundUrl);

  return (
    <PlayButton
      active={isPlaying}
      size={60}
      iconColor="var(--color-background)"
      idleBackgroundColor="var(--color-text)"
      activeBackgroundColor="var(--color-primary)"
      play={play}
      stop={stop}
    />
  );
}

5. 雪碧音频

如果你的组件打算用很多音效,我建议你使用雪碧音频哦~ 雪碧音频是一个音频文件集合了很多不同的音效。把音频都结合成一个单独文件后,我们可以写出更优美的代码,此外防止很多并行的 HTTP 请求。

这里我们用了一个雪碧音频搭建了一个打碟机!尝试点击这些按钮,或者点击你键盘上的1234听听看吧!

image.png

代码:

function Demo() {
  const soundUrl = '/sounds/909-drums.mp3';

  const [play] = useSound(soundUrl, {
    sprite: {
      kick: [0, 350],
      hihat: [374, 160],
      snare: [666, 290],
      cowbell: [968, 200],
    }
  });

  // Custom hook that listens for 'keydown',
  // and calls the appropriate handler function.
  useKeyboardBindings({
    1: () => play({ id: 'kick' }),
    2: () => play({ id: 'hihat' }),
    3: () => play({ id: 'snare' }),
    4: () => play({ id: 'cowbell' }),
  })

  return (
    <>
      <Button
        aria-label="kick"
        onMouseDown={() => play({ id: 'kick' })}
      >
        1
      </Button>
      <Button
        aria-label="hihat"
        onMouseDown={() => play({ id: 'hihat' })}
      >
        2
      </Button>
      <Button
        aria-label="snare"
        onMouseDown={() => play({ id: 'snare' })}
      >
        3
      </Button>
      <Button
        aria-label="cowbell"
        onMouseDown={() => play({ id: 'cowbell' })}
      >
        4
      </Button>
    </>
  );
}

更多关于雪碧音频的详情 查看 API 文档

百万种可行性

在网页中探索声音的过程深深触动着我,因为实在是有太多尚未开发的领域了!!我在网页上尝试音频有一段时间了,但我感觉我仅仅只是触碰到了表面而已。

现在你有了开始试验的工具,我希望能鼓励到你去尝试一下,看看你能走多远 😁

你可以通过 GitHub 了解更多关于 use-sound 这个 hook 噢~ 快去行动起来吧~