问题描述
我正在尝试创建一个网页,用户可以通过点击“按键”或按下键盘上的相应按钮来弹奏钢琴。我按照 this blog post 中概述的方法使用 CSS 伪类对按钮进行动画处理。
博文 TL;DR:
该按钮由多个相互堆叠的 <span>
元素组成,:active
和 :hover
伪类触发 transform: translateY()
动画。
有没有办法使用 JS 切换元素的 CSS 状态?我可以强制使用 :active
和 :hover
来触发 CSS 动画吗?试图找出一种方法让我的 handleOnKeyDown
和 handleKeyUp
触发我已经编写的 CSS 动画。
显示当前位置:
const synth = new Tone.polySynth(Tone.Synth).set(
{ oscillator: { type: 'triangle8' } }
).toDestination()
const makeKeyboardControls = () => {
let notes = ['F3','G3','A3'];
let keys = ['a','s','d'];
const keyboardControls = {}
for(let i = 0; i < notes.length; i++){
keyboardControls[keys[i]] = {pressed: false,note: notes[i]}
}
return keyboardControls
}
const keyboardControls = makeKeyboardControls()
const handleKeyDown = (e) => {
const key = e.key.toLowerCase();
if(keyboardControls[key] && !keyboardControls[key].pressed){
synth.triggerAttack(keyboardControls[key].note)
keyboardControls[key].pressed = true
}
}
const handleKeyUp = (e) => {
const key = e.key.toLowerCase();
if(keyboardControls[key] && keyboardControls[key].pressed){
synth.triggerRelease(keyboardControls[key].note)
keyboardControls[key].pressed = false
}
}
document.body.addEventListener('keydown',handleKeyDown)
document.body.addEventListener('keyup',handleKeyUp)
const handleMouseDown = (note) => {
synth.triggerAttack(note)
}
const handleMouseUp = (note) => {
synth.triggerRelease(note)
}
const handleMouseEnter = (e,note) => {
if(e.buttons === 1){
synth.triggerAttack(note)
}
}
const handleMouseLeave = (note) => {
synth.triggerRelease(note)
}
let f = 'F3'
let g = 'G3'
let a = 'A3'
const aButton = document.getElementById('a')
const sButton = document.getElementById('s')
const dButton = document.getElementById('d')
aButton.addEventListener('mousedown',() => handleMouseDown('F3')
)
aButton.addEventListener('mouseup',() => handleMouseUp('F3')
)
aButton.addEventListener('mouseenter',(e) => handleMouseEnter(e,f)
)
aButton.addEventListener('mouseleave',() => handleMouseLeave(f)
)
sButton.addEventListener('mousedown',() => handleMouseDown('G3')
)
sButton.addEventListener('mouseup',() => handleMouseUp('G3')
)
sButton.addEventListener('mouseenter',g)
)
sButton.addEventListener('mouseleave',() => handleMouseLeave(g)
)
dButton.addEventListener('mousedown',() => handleMouseDown('A3')
)
dButton.addEventListener('mouseup',() => handleMouseUp('A3')
)
dButton.addEventListener('mouseenter',a)
)
dButton.addEventListener('mouseleave',() => handleMouseLeave(a)
)
html{
height: 100%;
}
.body{
height: 100%;
display: flex;
flex-flow: row wrap;
justify-content: center;
align-items: center;
align-content: center;
}
.buttons {
width: 100%;
display: flex;
justify-content: center;
align-content: center;
}
.pushable {
position: relative;
/* border: none; */
background: transparent;
padding: 0;
margin: 0.3rem 0.1rem;
cursor: pointer;
outline-offset: 4px;
transition: filter 250ms;
}
.shadow {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border-radius: 12px;
background: hsl(0deg 0% 0% / 0.25);
will-change: transform;
transform: translateY(2px);
transition:
transform
600ms
cubic-bezier(.3,.7,.4,1);
}
.edge {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border-radius: 12px;
background: linear-gradient(
to left,hsl(340deg 100% 16%) 0%,hsl(340deg 100% 32%) 8%,hsl(340deg 100% 32%) 92%,hsl(340deg 100% 16%) 100%
);
}
.front {
display: block;
position: relative;
padding: 42px 22px;
border-radius: 12px;
font-size: 1rem;
color: white;
Box-shadow: inset 0px -1px 0px rgba(255,255,0.5);
will-change: transform;
background: hsl(345deg 100% 47%);
transform: translateY(-4px);
transition:
transform
600ms
cubic-bezier(0.3,0.7,0.4,1);
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.pushable:hover {
filter: brightness(110%);
}
.pushable:hover .front {
transform: translateY(-6px);
transition:
transform
250ms
cubic-bezier(0.3,1.5);
}
.pushable:active:hover .front {
transform: translateY(-2px);
transition: transform 34ms;
}
.pushable:hover .shadow {
transform: translateY(4px);
transition:
transform
250ms
cubic-bezier(0.3,1.5);
}
.pushable:active:hover .shadow {
transform: translateY(1px);
transition: transform 34ms;
}
.pushable:focus:not(:focus-visible) {
outline: none;
}
<script src="https://unpkg.com/tone@14.7.77/build/Tone.js"></script>
<!-- <script src="https://unpkg.com/tinycolor2@1.4.2/tinycolor.js"></script> -->
<body class="body">
<div class="buttons">
<label id="a" class="pushable">
<span class="shadow"></span>
<span class="edge"></span>
<span class="front">a</span>
</label>
<label id="s" class="pushable">
<span class="shadow"></span>
<span class="edge"></span>
<span class="front">s</span>
</label>
<label id="d" class="pushable">
<span class="shadow"></span>
<span class="edge"></span>
<span class="front">d</span>
</label>
</div>
</body>
(也在 JSFiddle 上)
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)