我想用声音制作逼真的打字效果。我使用的是Typed.js,我已经创建了一个简单的例子。
这是我的代码:
var keystrokeSound = new Audio('http://www.freesfx.co.uk/rx2/mp3s/6/18660_1464810669.mp3');
function playSound () {
keystrokeSound.pause();
keystrokeSound.currentTime = 0;
keystrokeSound.play();
}
var typed = new Typed('.element', {
strings: ["Play sound each I type character", "It's only play on start of string"],
typeSpeed: 50,
preStringTyped : function(array, self){
playSound();
}
});

.typed-cursor{
opacity: 1;
animation: typedjsBlink 0.7s infinite;
-webkit-animation: typedjsBlink 0.7s infinite;
animation: typedjsBlink 0.7s infinite;
}
@keyframes typedjsBlink{
50% { opacity: 0.0; }
}
@-webkit-keyframes typedjsBlink{
0% { opacity: 1; }
50% { opacity: 0.0; }
100% { opacity: 1; }
}
.typed-fade-out{
opacity: 0;
transition: opacity .25s;
-webkit-animation: 0;
animation: 0;
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/typed.js/2.0.6/typed.min.js"></script>
<span class="element" style="white-space:pre"></span>
&#13;
打字效果的作用是例外。但没有声音,声音只播放时只有第一个字句。我已经阅读了docs,但我找不到每个键入的字符的回调。如何在每个打字的字符上播放声音?
这里是fiddle
答案 0 :(得分:1)
尝试此代码:
var keystrokeSound = new Audio('http://www.freesfx.co.uk/rx2/mp3s/6/18660_1464810669.mp3');
var interval ;
function playSound () {
clearInterval(interval);
interval = setInterval(function(){
keystrokeSound.pause();
keystrokeSound.currentTime = 0;
keystrokeSound.play();
},220);
}
var typed = new Typed('.element', {
strings: ["Play sound each I type character", "It's only play on start of string"],
typeSpeed: 100,
preStringTyped : function(array, self){
playSound();
},
onStringTyped : function(array, self){
clearInterval(interval);
},
onComplete: function(array, self){
clearInterval(interval);
}
});
&#13;
.typed-cursor{
opacity: 1;
animation: typedjsBlink 0.7s infinite;
-webkit-animation: typedjsBlink 0.7s infinite;
animation: typedjsBlink 0.7s infinite;
}
@keyframes typedjsBlink{
50% { opacity: 0.0; }
}
@-webkit-keyframes typedjsBlink{
0% { opacity: 1; }
50% { opacity: 0.0; }
100% { opacity: 1; }
}
.typed-fade-out{
opacity: 50;
transition: opacity .25s;
-webkit-animation: 0;
animation: 0;
}
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/typed.js/2.0.6/typed.min.js"></script>
<span class="element" style="white-space:pre"></span>
&#13;
答案 1 :(得分:1)
你也可以尝试循环声音,并从typed.js调用onStringTyped方法:
import { Injectable } from '@angular/core';
import { NgModule } from '@angular/core';
import { OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import { Mobster } from './mobster.model';
import 'rxjs/add/operator/map';
@Injectable()
export class DataService {
url = 'http://localhost:3000/api/mobsters' || 'https://mobster-api.herokuapp.com/api/mobsters';
constructor(private http: HttpClient) { }
getData() {
return this.http.get(this.url);
}
}
&#13;
var keystrokeSound = new Audio('http://www.freesfx.co.uk/rx2/mp3s/6/18660_1464810669.mp3');
function playSound () {
if (typeof keystrokeSound.loop == 'boolean')
{
keystrokeSound.loop = true;
}
else
{
keystrokeSound.addEventListener('ended', function() {
this.currentTime = 0;
this.play();
}, false);
}
keystrokeSound.play();
}
function stopSound () {
keystrokeSound.pause();
}
var typed = new Typed('.element', {
strings: ["Play sound each I type character", "It's only play on start of string"],
typeSpeed: 50,
preStringTyped : function(array, self){
playSound();
},
onStringTyped : function(array, self){
stopSound();
}
});
&#13;
.typed-cursor{
opacity: 1;
animation: typedjsBlink 0.7s infinite;
-webkit-animation: typedjsBlink 0.7s infinite;
animation: typedjsBlink 0.7s infinite;
}
@keyframes typedjsBlink{
50% { opacity: 0.0; }
}
@-webkit-keyframes typedjsBlink{
0% { opacity: 1; }
50% { opacity: 0.0; }
100% { opacity: 1; }
}
.typed-fade-out{
opacity: 0;
transition: opacity .25s;
-webkit-animation: 0;
animation: 0;
}
&#13;
答案 2 :(得分:1)
回答我自己的问题,最好的方法是直接编辑源代码,并为每个键入的char创建一个回调。我只是编辑了一点源代码(未压缩版本)
找到typewrite
函数,并在函数结束前添加此脚本
// fires callback function
this.options.onCharAppended(substr.charAt(0), this);
另外,找到了defaults
对象,有回调的默认函数集合,我只是添加
onCharAppended: function onCharAppended(char, self){},
然后我可以使用额外的回调播放同步和精确时间的声音
var typed = new Typed('.element', {
strings: ["Test ^1000 with delay"],
typeSpeed: 100,
onCharAppended : function(char, self){
playSound();
}
});
答案 3 :(得分:0)
我想最好的方法是直接调整源代码,以便使这样的事件可用。
以下是我现在最好的尝试结果,使用Web Audio API以尽可能最佳的计时精度触发声音,并且...它不是那么棒......
无论出于何种原因,打字代码似乎不是很规律,我怀疑是有问题,但是不能确定,并且还不想解剖插件的来源
无论如何,这是我的尝试,如果它可以暂时帮助你。
/* A simple player using the Web Audio API */
class Player {
constructor(url) {
this.media_url = url;
}
init() {
this.ctx = new AudioContext();
return fetch(this.media_url)
.then(resp => resp.arrayBuffer())
.then(buf => this.ctx.decodeAudioData(buf))
.then(audioBuffer => this.audioBuffer = audioBuffer);
}
play() {
const node = this.ctx.createBufferSource();
node.buffer = this.audioBuffer;
node.connect(this.ctx.destination);
node.start(0);
}
}
// I have absolutely no rights on the given sound so neither do any reader
// If authors have concerns about it, simply leave me a comment, I'll remove right away
const keystrokePlayer = new Player('https://dl.dropboxusercontent.com/s/hjx4xlxyx39uzv7/18660_1464810669.mp3');
function playSound (string, delay) {
// It seems space is typed twice?
const l = string.length + string.match(/\s/g).length;
let current = 0;
function loop() {
// start our sound (1 time)
keystrokePlayer.play();
// if all have been played stop
if(current++ >= l) return;
// otherwise restart in 'delay' ms
setTimeout(loop, delay);
}
loop();
}
// load our sound
keystrokePlayer.init().then(()=> {
inp.disabled = false;
btn.onclick();
});
btn.onclick = e => {
var elem = makeNewElem();
var typed = new Typed(elem, {
strings: ["Play sound each I type character", "It's only play on start of string"],
typeSpeed: +inp.value || 50,
preStringTyped : function(index, self){
const opts = self.options;
playSound(opts.strings[index], opts.typeSpeed);
}
});
};
function makeNewElem(){
var cont = document.createElement('div');
var elem = document.createElement('span');
elem.classList.add('element');
cont.appendChild(elem);
document.body.appendChild(cont);
return elem;
}
&#13;
.typed-cursor{
opacity: 1;
animation: typedjsBlink 0.7s infinite;
-webkit-animation: typedjsBlink 0.7s infinite;
animation: typedjsBlink 0.7s infinite;
}
@keyframes typedjsBlink{
50% { opacity: 0.0; }
}
@-webkit-keyframes typedjsBlink{
0% { opacity: 1; }
50% { opacity: 0.0; }
100% { opacity: 1; }
}
.typed-fade-out{
opacity: 0;
transition: opacity .25s;
-webkit-animation: 0;
animation: 0;
}
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/typed.js/2.0.6/typed.min.js"></script>
<label>typeSpeed (ms)<input id="inp" type="number" value="50"><button id="btn">do it</button></label><br>
&#13;
答案 4 :(得分:0)
我的解决方案有点不同。我使用音频的持续时间和playbackRate属性将音频同步到打字速度:
var typeSpeed = (audio.duration * 1000) / audio.playbackRate;
然后将onComplete
和preStringTyped
道具添加到option
对象:
var options = {
typeSpeed: typeSpeed,
preStringTyped: (arrPos) => {
// Start the playing the looped audio when the typing's about to start
audio.loop = true;
audio.play();
},
onComplete: () => {
// When the typing ends we stop the looping
audio.loop = false;
audio.stop();
}
}
这会产生令人信服的重复输入声音效果。
或者,如果您想获得更多随机效果,则可以在preStringTyped
函数中启动声音,并在其中保留一个标记来代替audio.loop
(例如repeat = true
)。然后,您将为onend
事件添加一个事件侦听器,如果repeat
标志仍处于打开状态,则再次播放音频。除非这次您选择随机音频文件播放。最后,在onComplete
回调中,停止当前播放的音频并将repeat
标志设置为false
。