通过 JS 函数更改 CSS 伪类状态

问题描述

我正在尝试创建一个网页,用户可以通过点击“按键”或按下键盘上的相应按钮来弹奏钢琴。我按照 this blog post 中概述的方法使用 CSS 伪类对按钮进行动画处理。

博文 TL;DR: 该按钮由多个相互堆叠的 <span> 元素组成,:active:hover 伪类触发 transform: translateY() 动画。

有没有办法使用 JS 切换元素的 CSS 状态?我可以强制使用 :active:hover 来触发 CSS 动画吗?试图找出一种方法让我的 handleOnKeyDownhandleKeyUp 触发我已经编写的 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 (将#修改为@)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...