一个交互式的动画SVG(鼓)工具包

所属分类:媒体-音频和视频

 1127  22  查看评论 (6)
一个交互式的动画SVG(鼓)工具包 ie兼容10

今天,我们将创建一个可以通过点击,点击或使用键盘来演奏的SVG动画鼓套件,也可以编程为单独播放!我们将使用GreenSock的 TweenMax动画库,jQuery和<audio>元素。

创建SVG

打开你选择的矢量编辑软件(我使用的是Adobe Illustrator,但有许多选择,如Affinity Designer, Sketch或Inkscape),并得到绘图!我发现有几张照片想要画在我的画板上,以供参考。保持风格平坦,相当简单,无论是在绘画还是动画方面,都会让生活变得更加轻松,而功能较弱的设备会感谢您减少渲染的内容。在这种风格中,鼓套件实际上是一组相当简单的(大部分)矩形对象。在绘制任何想要动画的SVG的同时,还有几件事值得记住:

<g> 是关键

“g元素是一个用于分组其他SVG元素的容器。应用于g元素的转换将在其所有子元素上执行,并且其任何属性都由其子元素继承。

对于我们来说,这个关键部分是“在所有子元素上执行应用于g元素的转换”,这在将SVG动画化时非常方便, 我们可以简单地将我们想要的动画元素进行分组,并将单个动画应用到该组,从而不用将动画应用到小鼓的每个单独组件。 命名良好的组织将在以后更轻松地操纵SVG!

如果您的绘图应用程序有这样的选项,请启用XML标识名称(在Illustrator首选项>单位>标识对象:> XML ID),这允许您编辑/查看id我们将使用的元素和组的实际属性瞄准他们。

我们需要将两个主要元素集合在一起:

1.点击/点击目标

我们希望能够触发我们的动画和声音基于他们各自的鼓被点击/点击,所以我们需要将点击/点击“目标”元素分组在一起。 例如,将整个小鼓,包括支架组合在一起,所以用户触摸的任何部分都会触发动画/声音。

2.动画目标

将我们想要动画的元素组合在一起。例如,将小军鼓组合起来; 当小军鼓动画被触发时,我们只想要鼓动画,而不是立场。

画出来,然后揭示

“我发现绘制所有东西都很有用,然后在需要时显示部分。”

我们希望能够用键盘演奏鼓,所以某些指示哪些键触发鼓将是有用的。选择你想要“演奏”每个鼓的键,并添加一些指示到您的SVG。将它们组合在一起,以便我们稍后可以隐藏/显示。

导出SVG

将所有组保存为一个.svg文件,然后在文本编辑器中打开它。

我们可以把它直接放到我们的HTML文档中。不过,我建议首先优化Web的SVG。有足够的工具可以做到这一点,SVGOMG可能是最简单的使用之一。

看见鼓, 听见鼓

我们提供音频元素ID,以便我们可以在需要播放时对其进行定位。

<audio id="Snare-Audio">
  <source src="mp3/Snare.mp3" type="audio/mp3">
</audio>

(前)加载这些节拍

通过添加属性,preload="auto"我们可以告诉浏览器“用户需要这个,确保它被下载”。这就是它在某些浏览器中的工作原理。其他浏览器(特别是移动设备上的浏览器)实际上忽略了这一点,这可能会导致一些奇怪的行为,但我们稍后会回到这一点。

<audio id="Snare-Audio" preload="auto">
  <source src="mp3/Snare.mp3" type="audio/mp3">
</audio>

时间JavaScript!

在我们打鼓之前,我们还有很多事情要做,但每个鼓部分可以分成三个步骤:

音频、动画、触发这些用户交互。

首先将我们需要的DOM元素作为变量进行存储。例如,对于小鼓,我们想要小鼓音频和小鼓,两个位我们想要动画和部分将触发动画和音频。

曲调

播放我们的音频实际上非常简单:我们只是.play()在我们想播放的音频元素上使用该方法。

var snareAudio = $('#Snare-Audio');
snareAudio.get(0).play();

就是这样!嗯, 几乎..。这很有用, 但是如果我们在音频已经播放时再次调用该方法, 则不会发生任何事情。我们希望在每次触发鼓时从音频文件的开头触发声音。因此, 我们需要设置的音频开始位置是每次触发。

var snareAudio = $('#Snare-Audio');
var snareAudioEl = snareAudio.get(0);
snareAudioEl.currentTime = 0;
snareAudioEl.play();

Tweens

对于那些不熟悉的人来说,TweenMax是一个JavaScript库,可以随时间处理任何对象(或对象数组)的一个或多个属性的“补间”。我不打算深入每一个动画的解剖,但每个可以分解成几个简单的步骤:

创建一个新的时间轴Tween属性补 (或大量属性)

我们只是试图模拟一些接近于我们“期望”鼓被击中时移动的东西。有时为了达到预期的效果,夸大运动量是值得的。这在一定程度上是反复试验的,但幸运的是,GreenSock在行动中有很多很好的例子,你可以检查灵感。同样,像Chris Gannon这样的人是看GreenSock能做什么的好方法。

最后,easing是GreenSock提供给你的动画最有用的工具之一。GreenSock有一个很容易的可视化,它可以帮助你决定什么是适合你的动画。

snareDrum = $('#Snare-Drum');

// Create a new timeline, that's paused by default
var snaretl = new TimelineMax({
  paused: true
});

// The animation tweens
snaretl.to(snareDrum, 0.1, {scaleX: 1.04, transformOrigin: "50% 50%", ease: Expo.easeOut})
       .to(snareDrum, 0.1, {scaleY: 0.9, transformOrigin: "50% 100%", ease: Expo.easeOut}, '0')
       // The last tween, returns the element to it's original properties
       .to(snareDrum, 0.4, {scale: 1, transformOrigin: "50% 100%", ease: Elastic.easeOut});

Stop. Trigger Time

我们有我们的音频和我们的动画准备。现在我们只需要把它放在一起并在用户交互中触发它。我们将音频和动画方法封装在一个函数中:

function snare(){
  snaretl.restart();
  snaretl.play();
  var snareAudioEl = snareAudio.get(0);
  snareAudioEl.currentTime = 0;
  snareAudioEl.play();
}

然后,在点击/触摸事件上调用该函数:

var clickTouchSnareDone = false;
snareDrumAll.on("touchstart click", function() {
	if(!clickTouchSnareDone) {
		clickTouchSnareDone = true;
		setTimeout(function() {
			clickTouchSnareDone = false;
		}, 100);
		snare();
		return false;
	}
});

当用户点击或触摸鼓时,会触发动画和音频。下一步是连接键盘。

document.onkeydown = function(e) {
  switch (e.keyCode) {
    case 72:
      snare();
      break;
  }
};

使用键盘时,我们甚至可以为键盘指定动画:

function animateKey(key) {
  keytl = new TimelineMax({
    paused: true
  });
  keytl.to(key, 0.1, {scale: 1.1, transformOrigin: "50% 50%", ease: Expo.easeOut})
  .to(key, 0.4, {scale: 1, transformOrigin: "50% 50%", ease: Elastic.easeOut});
  keytl.restart();
  keytl.play();
}

document.onkeydown = function(e) {
  // This string will have to match the id of your key guides
  thisKeyID = 'Key-' + e.keyCode;
  thisKey = $('#' + thisKeyID);
  switch (e.keyCode) {
    case 72:
    snare();
    animateKey(thisKey);
    break;
  }
};

冲洗并重复这个过程中的每个鼓在我们的套件。

现在我们已经有了一个功能齐全的鼓组套件,我们可以用鼠标,键盘或触摸来玩。但是,我们不要停留在这里。

编程可编程(节拍)

我们有可玩的鼓,但可以使我们的鼓可编程。我们要构建一个可以编程来播放循环的音序器。这可能相当复杂,但同样可以分解成简单的步骤:

  • 创建一个表示鼓和时间 (或节拍) 的 "矩阵"

  • 循环通过列或节拍

  • 如果鼓是活跃的在当前敲打, 演奏鼓

构建矩阵

幸运的是,我可以确切地告诉你我们的矩阵是什么!这是一个简单的网格,其中:

行将代表我们的鼓列将代表节拍

我们需要能够选择在我们的音序器的每个节拍中是否播放鼓。<input>具有该type="checkbox"属性的< 元素是完全适合这个,但是,这不是那么容易的风格,但有一个黑客。

我们将为每个鼓创建一个行,并为每个节拍创建一个列。在这个演示中,我们将使用8节拍。我们将添加一个data-target-drum属性(这可以被称为任何东西)与我们之前创建的鼓功能的名称。我们可以使用该属性来帮助我们确定要调用哪个相应的函数。

<!-- A "row" of our sequencer, we'll need one of these for each drum -->
<div class="row" data-target-drum="snare">
  <!-- This image indicates which drum the row controls -->
  <img src="img/snare.png">
  <label><input type="checkbox"><div></div></label>
  <label><input type="checkbox"><div></div></label>
  <label><input type="checkbox"><div></div></label>
  <label><input type="checkbox"><div></div></label>
  <label><input type="checkbox"><div></div></label>
  <label><input type="checkbox"><div></div></label>
  <label><input type="checkbox"><div></div></label>
  <label><input type="checkbox"><div></div></label>
</div>

而且一次循环“行”和“拍”的功能如下所示:

rows = $('.row');
rowLength = rows.first().children().length;
labels = $('label');
// Beat starts at 1 because 0 is the img for each row
beat = 1;

// Sequencer
function sequencer () {
  labels.removeClass('active');
  // Do this function for each .row
  $(rows).each(function() {
    // Select the child element at the "beat" index
    current = $(this).children().eq(beat);
    current.addClass('active');
    // If the current input is checked do some stuff!
    if (current.find('input').is(":checked")) {
      targetDrum = (current.parent().attr('data-target-drum'));
      // If there a function that shares the same name as the data attribute, do it!
      fn = window[targetDrum];
      if (typeof fn === "function") {
        fn();
      }
    }
  });
  // If we get to the last child, start over
  if ( beat < (rowLength - 1) ) {
    ++beat;
  } else {
    beat = 1;
  }
}

时机就是一切

我们有一个功能来演奏当前节拍的鼓声。但我们需要循环这些节拍。我们可以用这个.setInterval()方法来做到这一点。它基本上定义了函数应该执行的频率(以毫秒为单位)。所以我们可以用它来启动音序器并设置其速度。在音乐方面,节拍(或节奏)的频率通常被称为bpm或每分钟节拍。所以bpm可以简单地定义为一分钟内的毫秒数除以bpm。我们将bpm设置为合理的默认值150.然后我们设置点击播放按钮的时间间隔。

sequencerOn = false;

// Start Sequencer
$('#sequencer-active-btn').click(function () {
  intervalId = window.setInterval(sequencer, interval);
  sequencerOn = true;
});

这很好,但是当我们需要停止音序器时呢?我们可以通过将.setInterval()方法返回的ID传递给方法来停止顺序器.clearInterval():

sequencerOn = false;

// Start/Stop Sequencer
$('#sequencer-active-btn').click(function () {
  if (sequencerOn === false) {
    intervalId = window.setInterval(sequencer, interval);
    sequencerOn = true;
  } else {
    window.clearInterval(intervalId);
    sequencerOn = false;
  }
});

快走,慢点

如果我们可以改变我们的拍子的bpm以获得更快或更慢的循环,那将会更加酷:

bpm = 150;
interval = 60000 / bpm;

// Set tempo
function setTempo() {
  window.clearInterval(intervalId);
  intervalId = window.setInterval(sequencer, interval);
}

// Increase tempo
$('#bpm-increase-btn').click(function() {
  if ( bpm < 300 ) {
    bpm = parseInt($('#bpm-indicator').val());
    bpm += 10;
    interval = 60000 / bpm;
    $('#bpm-indicator').val(bpm);
    if(sequencerOn === true) {
      setTempo();
    }
  }
});

//Decrease tempo
$('#bpm-decrease-btn').click(function() {
  if ( bpm > 100 ) {
    bpm = parseInt($('#bpm-indicator').val());
    bpm -= 10;
    interval = 60000 / bpm;
    $('#bpm-indicator').val(bpm);
    if(sequencerOn === true) {
      setTempo();
    }
  }
});

Phoning it in

许多移动浏览器不仅忽略,preload="auto"而且实际上只会在用户触摸事件中加载音频。这基本上意味着我们的音序器不会触发任何音频,直到它已经被用户触发。所以我们需要在第一次用户交互中加载音频。这是一个黑客,但它意味着音序器将在移动设备上工作。

// Load audio on iOS devices on the first user interaction
$('#sequencer-visible-btn').one('click', function() {
  $("audio").each(function(i) {
    this.play();
    this.pause();
  });
});

就是这样!我们制作了一个我们可以玩的鼓乐器,我们可以编程自己玩。我希望这个教程能够激发你创建自己的交互式动画SVG。使用相同的技巧,你可以建立其他乐器,或任何东西!如果你这样做,请让我知道,我很想看看你创造了什么!

相关插件-音频和视频

音频播放歌词同步插件APlayer.js

歌词同步MP3播放器代码
  音频和视频
 13031  59

HTML5,CSS3,jQuery自制video播放器

HTML5,CSS3,jQuery自制video播放器
  音频和视频
 104121  84

时间播放器

类似视频播放器下面的时间播放控制
  音频和视频
 13738  23

jwplayer响应式多终端适配视频播放器

jwplaye,自定义视频图片封面,全浏览器兼容、响应式多终端适配视频播放器
  音频和视频
 106038  319

讨论这个项目(6)回答他人问题或分享插件使用方法奖励jQ币

    SiriBen 0
    2017/12/7 9:56:44

    这个唯有膝盖才能表达厉害,哈哈

    回复
    演?。 0
    2017/12/7 9:29:34

    你赔我时间  我玩了一早上。

    回复
    半??抱 0
    2017/12/6 17:02:30
    ?水 0
    2017/12/6 15:50:30
    大木 0
    2017/12/6 14:22:11
    a'╃ ?? 0
    2017/12/6 10:05:49
取消回复