我正在构建“音乐机器”,但是我遇到了无法解决的问题。音乐机的所有其他部分都能正常工作。只有我想要,如果您单击(或按相应的键)新的音乐垫,最后一个“取消激活”其样式。等等,只有当前正在播放的声音具有活动板。
我已经尝试过这个和其他几个例子。
document.addEventListener("pause", function(){
var audioDiv = document.getElementsByClassName("clip");
for (var i = 0, len = audioDiv.length; i < len; i++) {
audioDiv[i].style.backgroundColor = "Grey";
audioDiv[i].style.margin = "50px"
}
}, true)
这是代码的SoundPad部分
class SoundPad extends React.Component {
constructor(props) {
super(props);
this.state = {
padStyle: inactiveStyle,
toPlay: true,
};
this.playSound = this.playSound.bind(this);
this.handleKeyPress = this.handleKeyPress.bind(this);
this.padControl = this.padControl.bind(this);
this.stopOther = this.stopOther.bind(this)
}
componentDidMount() {
document.addEventListener("keydown", this.handleKeyPress);
document.addEventListener("play", this.stopOther, true);
document.addEventListener("pause", function(){
var audioDiv = document.getElementsByClassName("clip");
for (var i = 0, len = audioDiv.length; i < len; i++) {
audioDiv[i].style.backgroundColor = "Grey";
audioDiv[i].style.margin = "50px"
}
}, true)
}
componentWillUnmount() {
document.removeEventListener("keydown", this.handleKeyPress);
document.removeEventListener("play", this.stopOther, true);
document.removeEventListener("pause", function(){
var audioDiv = document.getElementsByClassName("clip");
for (var i = 0, len = audioDiv.length; i < len; i++) {
audioDiv[i].style.backgroundColor = "Grey";
audioDiv[i].style.margin = "50px"
}
}, true)
}
handleKeyPress(e) {
if (e.keyCode === this.props.keyCode) {
this.playSound();
}
}
playSound(e) {
if (this.state.toPlay) {
const sound = document.getElementById(this.props.keyTrigger);
sound.currentTime = 0;
sound.play();
this.padControl();
this.props.changeDisplay(this.props.clipName);
} else {
const sound = document.getElementById(this.props.keyTrigger);
sound.currentTime = 0;
sound.pause();
this.padControl();
this.props.changeDisplay(String.fromCharCode(160));
}
}
padControl() {
this.state.toPlay
? this.setState({
padStyle: activeStyle,
toPlay: !this.state.toPlay
})
: this.setState({
padStyle: inactiveStyle,
toPlay: !this.state.toPlay
});
}
stopOther(e) {
var audios = document.getElementsByClassName("clip");
for (var i = 0, len = audios.length; i < len; i++) {
if (audios[i] != e.target) {
audios[i].pause();
}
}
}
render() {
return (
<div
className="drum-pad"
id={this.props.clipId}
onClick={this.playSound}
style={this.state.padStyle}
>
<audio
className="clip"
id={this.props.keyTrigger}
src={this.props.clip}
/>
{this.props.keyTrigger}
</div>
);
}
}
const inactiveStyle = {
backgroundColor: "Grey",
margin: "50px"
};
const activeStyle = {
backgroundColor: "Blue",
margin: "40px"
};
完整代码:https://codepen.io/mathiascoding/pen/GaZxgr?editors=1010
如果解决方案使用JS而不是JQuery,将不胜感激
答案 0 :(得分:1)
我用您要查找的逻辑编写了一个简单的代码段:
for (var el of document.getElementsByClassName('box')) {
el.addEventListener('click', (e) => {
var activeEl = document.getElementsByClassName('active')[0]
if (activeEl) activeEl.classList.remove('active')
e.target.classList.add('active')
})
}
.box {
background-color: grey;
border: 1px solid black;
height: 20px;
width: 20px;
}
.active {
background-color: blue
}
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
在每次单击按钮时,您要查找具有active
类的所有元素并将其删除,然后将active
类应用于刚刚单击的元素。从技术上讲,您可以使用样式来实现此目的,但是类的使用要容易得多。
编辑:浏览完代码笔后,此代码应该可以正常工作:
const inactiveStyle = {
backgroundColor: "Grey",
margin: "50px"
};
const activeStyle = {
backgroundColor: "Blue",
margin: "40px"
};
document.addEventListener('click', (e) => {
// If the element clicked has the class drum-pad
if (e.target.classList.contains('drum-pad')) {
// then get all the elements with the class drum-pad
var drumPads = document.getElementsByClassName('drum-pad')
// For each drum-pad
for (var drumPad of drumPads) {
// Loop over the keys in inactiveStyle
Object.keys(inactiveStyle).map(key => {
// and apply it to the element
drumPad.style[key] = inactiveStyle[key]
})
}
// Then loop over the keys in active style
Object.keys(activeStyle).map(key => {
// and apply it to the click element
e.target.style[key] = activeStyle[key]
})
}
})
<div id="Music-Bank">
<!-- react-text: 11 -->
<!-- /react-text -->
<div class="drum-pad" id="Pair-Of-Dice" style="background-color: blue; margin: 40px;"><audio class="clip" id="Q" src="https://dl.dropbox.com/s/u32apb7wl4z0abr/Ti%C3%ABsto%20%20Allure%20-%20Pair%20Of%20Dice%20%28Radio%20Edit%29.mp3?dl=0" style="background-color: grey; margin: 50px;"></audio>
<!-- react-text: 14 -->Q
<!-- /react-text -->
</div>
<div class="drum-pad" id="Speechless" style="background-color: blue; margin: 40px;"><audio class="clip" id="W" src="https://dl.dropbox.com/s/rirdacgv842n19z/Robin%20Schulz%20feat.%20Erika%20Sirola%20-%20Speechless%20%28Lyrics%29.mp3?dl=0" style="background-color: grey; margin: 50px;"></audio>
<!-- react-text: 17 -->W
<!-- /react-text -->
</div>
<div class="drum-pad" id="Sunset-Love" style="background-color: blue; margin: 40px;"><audio class="clip" id="E" src="https://dl.dropbox.com/s/ncv727qclyg0e5l/PETIT%20BISCUIT%20-%20Sunset%20Lover.mp3?dl=0" style="background-color: grey; margin: 50px;"></audio>
<!-- react-text: 20 -->E
<!-- /react-text -->
</div>
<div class="drum-pad" id="Lets-Go-Home" style="background-color: blue; margin: 40px;"><audio class="clip" id="A" src="https://dl.dropbox.com/s/nixax61siercuzm/Eklo%20-%20Lets%20Go%20Home%20%28Sinco%20Remix%29.mp3?dl=0" style="background-color: grey; margin: 50px;"></audio>
<!-- react-text: 23 -->A
<!-- /react-text -->
</div>
<div class="drum-pad" id="Are-You-With-Me" style="background-color: blue; margin: 40px;"><audio class="clip" id="S" src="https://dl.dropbox.com/s/9hruu7ag6nk5e49/Lost%20Frequencies%20-%20Are%20You%20With%20Me%20%28Kungs%20Remix%29.mp3?dl=0" style="background-color: grey; margin: 50px;"></audio>
<!-- react-text: 26 -->S
<!-- /react-text -->
</div>
<div class="drum-pad" id="Fallen" style="background-color: blue; margin: 40px;"><audio class="clip" id="D" src="https://dl.dropbox.com/s/8np1rhnfutwyimw/KLYMVX%20feat.%20COZY%20-%20Fallen%20%28Kygo%20Rework%29.mp3?dl=0" style="background-color: grey; margin: 50px;"></audio>
<!-- react-text: 29 -->D
<!-- /react-text -->
</div>
<div class="drum-pad" id="Swing" style="background-color: blue; margin: 40px;"><audio class="clip" id="Z" src="https://dl.dropbox.com/s/4c2ypp31ofdjbjl/Danny%20Ocean%20-%20Swing%20%28Letra%20%20Lyrics%29.mp3?dl=0" style="background-color: grey; margin: 50px;"></audio>
<!-- react-text: 32 -->Z
<!-- /react-text -->
</div>
<div class="drum-pad" id="Otro Trago" style="background-color: blue; margin: 40px;"><audio class="clip" id="X" src="https://dl.dropbox.com/s/vu8u5qntv9qhfzf/Sech%20%20Darell%20-%20%20Otro%20Trago%28LETRA%29.mp3?dl=0" style="background-color: grey; margin: 50px;"></audio>
<!-- react-text: 35 -->X
<!-- /react-text -->
</div>
<div class="drum-pad" id="Mi Error" style="background-color: blue; margin: 40px;"><audio class="clip" id="C" src="https://dl.dropbox.com/s/xeoceqaj9vyizxm/Eladio%20Carrion%20Ft%20Zion%20-%20Mi%20Error%20%28Letra%29.mp3?dl=0" style="background-color: grey; margin: 50px;"></audio>
<!-- react-text: 38 -->C
<!-- /react-text -->
</div>
<!-- react-text: 39 -->
<!-- /react-text -->
</div>
答案 1 :(得分:1)
科比的答案是正确的,但是React具有您自己的操作DOM的方式,不建议使用document
,而可以使用React.createRef()
或{{1}用钩子。您可以找到文档here。
引用提供了一种方法,可以访问在render方法中创建的DOM节点或React元素。
在典型的React数据流中,道具是父组件与其子组件交互的唯一方式。要修改孩子,您可以使用新道具重新渲染它。但是,在某些情况下,您需要在典型数据流之外强制修改子级。要修改的子级可以是React组件的实例,也可以是DOM元素。对于这两种情况,React都提供了一个逃生舱口。
答案 2 :(得分:-1)
可以通过从您的SoundPadSide
父组件向您的孩子SoundPad
组件提供其他道具来实现欲望行为。
我的想法是从其父组件SoundPad
控制SoundPadSide
的活动状态。
基本上,您需要在state
组件中定义SoundPadSide
,以控制当前处于活动状态的内容。
然后,您需要定义一个回调函数,该函数将更改活动的Pad:
class SoundPadSide extends React.Component {
constructor(props) {
super(props);
this.state = {
activeSoundPadId: "Speechless"
};
this.handleActiveChanged = this.handleActiveChanged.bind(this);
}
handleActiveChanged(id) {
this.setState({ activeSoundPadId: id });
}
}
在构造函数中,您可以定义activeSoundPadId
的初始状态。例如,我从您的音乐列表中拿了第二个。
接下来,您需要通过SoundPad
方法将这些属性传递给render()
组件:
MusicBank = this.props.musicData.map((Obj, i, MusicArr) => {
return (
<SoundPad
clipId={MusicArr[i].id}
clip={MusicArr[i].url}
keyCode={MusicArr[i].keyCode}
keyTrigger={MusicArr[i].keyTrigger}
clipName={MusicArr[i].clipName}
changeDisplay={this.props.changeDisplay}
power={this.props.power}
isActive={this.state.activeSoundPadId === MusicArr[i].id}
activate={this.handleActiveChanged}
/>
);
}
SoundPad
组件中有几处更改。由于现在收到的其他道具比我们应该应用的要多。
如果当前的activate
y没有激活,我会在您的palySound
方法中调用SoundPad
回调:
playSound(e) {
this.props.activate(this.props.clipId);
if (this.state.toPlay) {
const sound = document.getElementById(this.props.keyTrigger);
sound.currentTime = 0;
sound.play();
this.padControl();
this.props.changeDisplay(this.props.clipName);
} else {
const sound = document.getElementById(this.props.keyTrigger);
sound.currentTime = 0;
sound.pause();
this.padControl();
this.props.changeDisplay(String.fromCharCode(160));
}
SoundPad
render()
方法中的另一项更改:
return (
<div
class="Inactive"
className="drum-pad"
id={this.props.clipId}
onClick={this.playSound}
style={this.props.isActive ? activeStyle : inactiveStyle}
>
...
我已经稍微更新了您的代码。 Here您可以找到演示