RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1436197
Accepted
Опан
Опан
Asked:2022-08-04 22:24:29 +0000 UTC2022-08-04 22:24:29 +0000 UTC 2022-08-04 22:24:29 +0000 UTC

如何使用纯 CSS 制作留声机针和喇叭?

  • 772

我很早就有了为网​​站开发留声机形式的音频播放器的想法。我已经创建了一个旋转记录,我没有预见到案例背后有什么特别的复杂性,但是我还想在 CSS 上制作一个带喇叭的针,这样你就可以用鼠标抓住、抬起和重新排列针从一个地方记录到另一个地方。我想根据一个示例模型,如这些图片中所示: 在此处输入图像描述 在此处输入图像描述

有人对此有任何想法吗?如果是,我将不胜感激。我附上了旋转板的草图代码:

let garmony = [1, 2, 5, 7, 9, 17];
for(i = 0; i < 2 * Math.PI; i += 0.015){
    let translateZ = 0;
    for(j = 0; j < garmony.length; j ++){
        translateZ += 0.7 * Math.sin(i * garmony[j]);
    }
    let d = document.createElement('span'),
    x = 100 + Math.floor(100 * Math.sin(i)),
    y = 100 + Math.floor(100 * Math.cos(i));
    d.style.transform = 'translateX(' + x + 'px) translateY(' + y + 'px) translateZ(' + translateZ + 'px)';
    s.append(d);
}
*{
    transition: 2s;
}
#c{
    transform: translateX(0px) rotateX(70deg) rotateZ(0deg);
    transform-style: preserve-3d;
}
#s{
    width: 200px;
    height: 200px;
    transform-style: preserve-3d;
    animation: progress 10s linear infinite;
}
span{
    position: absolute;
    width: 2px;
    height: 2px;
    border-style: solid;
    border-width: 0px;
    background: black;
}
@keyframes progress{
    from{transform: rotateZ(0deg);}
    to{transform: rotateZ(360deg);}
}
<div id=c><div id=s></div></div>

html css
  • 3 3 个回答
  • 259 Views

3 个回答

  • Voted
  1. Best Answer
    Laukhin Andrey
    2022-08-09T07:03:50Z2022-08-09T07:03:50Z

    有一种旋转记录的愿望。

    您的方法效率极低,因为它创建了 400 多个元素。事实上,你可以只用 CSS 和渐变来绘制盘子。为了让盘子在旋转过程中感觉像是在旋转,你可以使用一些技巧:

    1. 添加噪点,以便在视觉上旋转更多纹理细节。
    2. 稍微倾斜盘子,使其略微悬垂。
    3. 为记录创建标签。

    当然,您需要设计一个可以放置 3D 对象的场景。我最终得到了这个(最好将其扩展到整个页面):

    .viewport,
    .viewport * {
      display: flex;
      justify-content: center;
      align-items: center;
      box-sizing: border-box;
    }
    
    .viewport {
      width: 100%;
      height: 350px;
      perspective: 1200px;
      position: relative;
      overflow: hidden;
    }
    
    .scene {
      user-select: none;
      transform: rotateX(50deg);
    }
    
    .scene,
    .scene * {
      position: absolute;
      transform-style: preserve-3d;
      backface-visibility: hidden;
    }
    
    .table {
      width: 900px;
      height: 400px;
      background-color: #d9a35c;
      transform: translate3d(0, 0, -10px);
    }
    
    .record {
      width: 400px;
      height: 400px;
      font-family: Times;
    }
    
    .first { transform: translate3d(-51%, 0, 0); }
    .second { transform: translate3d(51%, 0, 0); }
    
    .vinyl-wrap {
      width: 100%;
      height: 100%;
    }
    
    .vinyl {
      width: 100%;
      height: 100%;
      border-radius: 50%;
      background-color: black;
      background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAMAAAAp4XiDAAAAUVBMVEWFhYWDg4N3d3dtbW17e3t1dXWBgYGHh4d5eXlzc3OLi4ubm5uVlZWPj4+NjY19fX2JiYl/f39ra2uRkZGZmZlpaWmXl5dvb29xcXGTk5NnZ2c8TV1mAAAAG3RSTlNAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAvEOwtAAAFVklEQVR4XpWWB67c2BUFb3g557T/hRo9/WUMZHlgr4Bg8Z4qQgQJlHI4A8SzFVrapvmTF9O7dmYRFZ60YiBhJRCgh1FYhiLAmdvX0CzTOpNE77ME0Zty/nWWzchDtiqrmQDeuv3powQ5ta2eN0FY0InkqDD73lT9c9lEzwUNqgFHs9VQce3TVClFCQrSTfOiYkVJQBmpbq2L6iZavPnAPcoU0dSw0SUTqz/GtrGuXfbyyBniKykOWQWGqwwMA7QiYAxi+IlPdqo+hYHnUt5ZPfnsHJyNiDtnpJyayNBkF6cWoYGAMY92U2hXHF/C1M8uP/ZtYdiuj26UdAdQQSXQErwSOMzt/XWRWAz5GuSBIkwG1H3FabJ2OsUOUhGC6tK4EMtJO0ttC6IBD3kM0ve0tJwMdSfjZo+EEISaeTr9P3wYrGjXqyC1krcKdhMpxEnt5JetoulscpyzhXN5FRpuPHvbeQaKxFAEB6EN+cYN6xD7RYGpXpNndMmZgM5Dcs3YSNFDHUo2LGfZuukSWyUYirJAdYbF3MfqEKmjM+I2EfhA94iG3L7uKrR+GdWD73ydlIB+6hgref1QTlmgmbM3/LeX5GI1Ux1RWpgxpLuZ2+I+IjzZ8wqE4nilvQdkUdfhzI5QDWy+kw5Wgg2pGpeEVeCCA7b85BO3F9DzxB3cdqvBzWcmzbyMiqhzuYqtHRVG2y4x+KOlnyqla8AoWWpuBoYRxzXrfKuILl6SfiWCbjxoZJUaCBj1CjH7GIaDbc9kqBY3W/Rgjda1iqQcOJu2WW+76pZC9QG7M00dffe9hNnseupFL53r8F7YHSwJWUKP2q+k7RdsxyOB11n0xtOvnW4irMMFNV4H0uqwS5ExsmP9AxbDTc9JwgneAT5vTiUSm1E7BSflSt3bfa1tv8Di3R8n3Af7MNWzs49hmauE2wP+ttrq+AsWpFG2awvsuOqbipWHgtuvuaAE+A1Z/7gC9hesnr+7wqCwG8c5yAg3AL1fm8T9AZtp/bbJGwl1pNrE7RuOX7PeMRUERVaPpEs+yqeoSmuOlokqw49pgomjLeh7icHNlG19yjs6XXOMedYm5xH2YxpV2tc0Ro2jJfxC50ApuxGob7lMsxfTbeUv07TyYxpeLucEH1gNd4IKH2LAg5TdVhlCafZvpskfncCfx8pOhJzd76bJWeYFnFciwcYfubRc12Ip/ppIhA1/mSZ/RxjFDrJC5xifFjJpY2Xl5zXdguFqYyTR1zSp1Y9p+tktDYYSNflcxI0iyO4TPBdlRcpeqjK/piF5bklq77VSEaA+z8qmJTFzIWiitbnzR794USKBUaT0NTEsVjZqLaFVqJoPN9ODG70IPbfBHKK+/q/AWR0tJzYHRULOa4MP+W/HfGadZUbfw177G7j/OGbIs8TahLyynl4X4RinF793Oz+BU0saXtUHrVBFT/DnA3ctNPoGbs4hRIjTok8i+algT1lTHi4SxFvONKNrgQFAq2/gFnWMXgwffgYMJpiKYkmW3tTg3ZQ9Jq+f8XN+A5eeUKHWvJWJ2sgJ1Sop+wwhqFVijqWaJhwtD8MNlSBeWNNWTa5Z5kPZw5+LbVT99wqTdx29lMUH4OIG/D86ruKEauBjvH5xy6um/Sfj7ei6UUVk4AIl3MyD4MSSTOFgSwsH/QJWaQ5as7ZcmgBZkzjjU1UrQ74ci1gWBCSGHtuV1H2mhSnO3Wp/3fEV5a+4wz//6qy8JxjZsmxxy5+4w9CDNJY09T072iKG0EnOS0arEYgXqYnXcYHwjTtUNAcMelOd4xpkoqiTYICWFq0JSiPfPDQdnt+4/wuqcXY47QILbgAAAABJRU5ErkJggg==),
        repeating-radial-gradient(#2a292866, #2a292866 1px, #444 2px, #2a292866 3px);
      background-size: 20% 20%, 100% 100%;
      transform: rotateX(0.25deg);
    }
    
    .light {
      border-radius: 50%;
      width: 100%;
      height: 100%;
      background: conic-gradient(from 10deg, transparent 0deg, #ffffff44 30deg, transparent 60deg, transparent 180deg, #ffffff66 210deg, transparent 240deg);
      -webkit-mask-image: radial-gradient(transparent 25%, black 25.8%);
      mask-image: radial-gradient(transparent 25%, black 25.8%);
      transform: translate3d(0, 0, 1px);
    }
    
    .label {
      border: solid 2px #d9a388;
      width: 33%;
      height: 33%;
      border-radius: 50%;
      box-shadow: 0 0 0 4px #da5b33;
      background: #da5b33;
      color: white;
      text-align: center;
    }
    
    .label:after {
      transform-style: preserve-3d;
      position: absolute;
      border-radius: 50%;
      background: black;
      width: 14%;
      height: 14%;
      content: '';
    }
    
    .label h1 { top: -6%; }
    .label p {
      top: 53%;
      font-size: 83%;
    }
    
    .label.rock {
      background: #007ac5;
      box-shadow: 0 0 0 8px #ffffff66;
      border: none;
    }
    
    .record:hover .vinyl-wrap {
      transition: 5s;
      transform: rotateZ(5turn);
    }
    <div class="viewport">
      <div class="scene">
        
        <div class="table"></div>
        
        <div class="record first">
          <div class="vinyl-wrap">
            <div class="vinyl">
              <div class="label jazz">
                <h1>Jazz</h1>
                <p>Greatest Hits<br>vol 1</p>
              </div>
            </div>
          </div>
          <div class="light"></div>
        </div>
    
        <div class="record second">
          <div class="vinyl-wrap">
            <div class="vinyl">
              <div class="label rock">
                <h1>Rock</h1>
                <p>Greatest Hits<br>vol 2</p>
              </div>
            </div>
          </div>      
          <div class="light"></div>
        </div>
      
      </div>
    </div>


    UPD
    厌倦了观看唱片旋转。我想控制针...

    夹持针的支架设计有两个自由度。它就像一只机械手。拥有 3D 场景,很容易实现这一点。最主要的是要对物体旋转的点有一个很好的了解。要表达“方阵”,您只需将一个嵌套到另一个中,然后子元素将考虑到父元素的转换。
    在此处输入图像描述

    第一个角度设置针在唱片上的位置,第二个角度允许您将针抬起至上方。剩下的就是实现一个简单的拖放,将第一个角的值与标签的播放位置同步<audio>,不要忘记播放和暂停事件。

    我用普通的女主角非常原始地画了它。所有元素都可以在棱镜的基础上构建,使用 CSS 相对容易创建。

    我把标准播放器放在角落里,这样你就可以检查同步了。可以用鼠标移动针。享受:

    let needleRange = [-29.5, -57.5];
    let needleDrag = false;
    let prevX = 0;
    let dragSens = 0.2;
    
    const rangeLimit = (v, a, b) => v < a ? a : (v > b ? b : v);
    const rangePercentByValue = (v, a, b) => (v - a) / (b - a);
    const rangeValueByPercent = (p, a, b) => (b - a) * p + a;
    
    const elRecord = document.querySelector('.record');
    const elSupport = document.querySelector('.support');
    const elSeg2 = document.querySelector('.seg2');
    
    const setNeedlePos = (pos) => elSupport.style.setProperty('--angle', pos + "deg");
    const getNeedlePos = () => parseFloat(getComputedStyle(elSupport).getPropertyValue('--angle'));
    
    const needleUp = () => {
      elSeg2.classList.remove('jumping');
      void elSeg2.offsetHeight;
      elSeg2.classList.add('up');
    }
    
    const needleDown = () => {
      elSeg2.classList.remove('up');
      setTimeout(() => {
        if (!audio.paused) elSeg2.classList.add('jumping')
      }, 300);
    }
    
    holder.onmousedown = (e) => {
      audio.pause();
      needleDrag = true;
      prevX = e.pageX;
    }
    
    window.onmousemove = (e) => {
      if (needleDrag) {
        let da = (e.pageX - prevX) * dragSens;
        let r = needleRange;
        let a = getNeedlePos();
        let aNew = rangeLimit(a - da, r[1], r[0]);
        setNeedlePos(aNew);
        audio.currentTime = (1 - rangePercentByValue(aNew, r[1], r[0])) * audio.duration;
        prevX = e.pageX;
      }
    }
    
    window.onmouseup = (e) => {
      needleDrag = false;
      audio.play();
    }
    
    audio.ontimeupdate = function(e) {
      if (!needleDrag) {
        let percent = 1 - audio.currentTime / audio.duration;
        let aNew = rangeValueByPercent(percent, needleRange[1], needleRange[0]);
        setNeedlePos(aNew);
      }
    };
    
    audio.addEventListener("pause", needleUp);
    audio.addEventListener("ended", needleUp);
    audio.addEventListener("play", needleDown);
    #audio {
      position: absolute;
      right: 20px;
      top: 20px;
    }
    
    .viewport,
    .viewport * {
      display: flex;
      justify-content: center;
      align-items: center;
      box-sizing: border-box;
    }
    
    .viewport {
      width: 100%;
      height: 350px;
      perspective: 1200px;
      position: relative;
      overflow: hidden;
    }
    
    .scene {
      user-select: none;
      transform: rotateX(50deg);
    }
    
    .scene,
    .scene * {
      position: absolute;
      transform-style: preserve-3d;
      backface-visibility: hidden;
    }
    
    .table {
      width: 500px;
      height: 400px;
      background-color: #d9a35c;
      transform: translate3d(0, 0, -10px);
    }
    
    .table .back-rack {
      border-radius: 25% 25% 0 0;
      bottom: 100%;
      width: 170px;
      height: 100px;
      background-color: #a9a35c;
    }
    
    .table .back-rack .base {
      width: 30px;
      height: 80px;
      background-color: black;
      transform: translateZ(40px) rotateX(-90deg);
    }
    
    .support {
      --angle: -29.5deg;
      right: 0%;
      width: 250px;
      height: 20px;
      transform-origin: 100% 50%;
      transform: translate3d(0, -250px, 30px) rotateZ(var(--angle)) rotateX(-90deg);
      background: green;
    }
    
    .seg2 {
      right: 100%;
      width: 70px;
      height: 20px;
      transform-origin: 100% 50%;
      transform: rotateY(90deg) rotateZ(0deg);
      background: blue;
      backface-visibility: visible;
      transition: 0.2s;
    }
    
    .seg2.up {
      transition: 0.5s;
      animation: none;
      transform: rotateY(90deg) rotateZ(45deg);
    }
    
    .seg2.jumping {
      animation: 0.2s jumping infinite alternate;
    }
    
    .seg3 {
      border-radius: 50%;
      right: calc(100% - 19px);
      width: 40px;
      height: 40px;
      transform-origin: 50% 50%;
      transform: rotateY(90deg) rotateZ(0deg);
      background: darkred;
      backface-visibility: visible;
    }
    
    .seg3:hover {
      outline: 3px solid yellow;
    }
    
    .needle {
      top: 100%;
      height: 10px;
      width: 3px;
      background: yellow;
      backface-visibility: visible;
    }
    
    .record {
      width: 400px;
      height: 400px;
      font-family: Times;
    }
    
    .record.rotating .vinyl-wrap {
      animation: 1s rotation infinite linear;
    }
    
    .vinyl-wrap {
      width: 100%;
      height: 100%;
    }
    
    .vinyl {
      width: 100%;
      height: 100%;
      border-radius: 50%;
      background-color: black;
      background-image: url(data:image/png;base64,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), repeating-radial-gradient(#2a292866, #2a292866 1px, #444 2px, #2a292866 3px);
      background-size: 20% 20%, 100% 100%;
      transform: rotateX(0.25deg);
    }
    
    .light {
      border-radius: 50%;
      width: 100%;
      height: 100%;
      background: conic-gradient(from 10deg, transparent 0deg, #ffffff44 30deg, transparent 60deg, transparent 180deg, #ffffff66 210deg, transparent 240deg);
      -webkit-mask-image: radial-gradient(transparent 25%, black 25.8%);
      mask-image: radial-gradient(transparent 25%, black 25.8%);
      transform: translate3d(0, 0, 1px)
    }
    
    .label {
      border: solid 2px #d9a388;
      width: 33%;
      height: 33%;
      border-radius: 50%;
      box-shadow: 0 0 0 4px #da5b33;
      background: #da5b33;
      color: white;
      text-align: center;
    }
    
    .label:after {
      transform-style: preserve-3d;
      position: absolute;
      border-radius: 50%;
      background: black;
      width: 14%;
      height: 14%;
      content: '';
    }
    
    .label h1 {
      top: -6%;
    }
    
    .label p {
      top: 53%;
      font-size: 83%;
    }
    
    @keyframes rotation {
      100% {
        transform: rotateZ(1turn);
      }
    }
    
    @keyframes jumping {
      100% {
        transform: rotateY(90deg) rotateZ(0.7deg);
      }
    }
    <div class="viewport">
      <div class="scene">
    
        <div class="table" id="table">
          <div class="back-rack">
            <div class="base"></div>
          </div>
        </div>
    
        <div class="record rotating">
          <div class="vinyl-wrap">
            <div class="vinyl">
              <div class="label jazz">
                <h1>Jazz</h1>
                <p>Greatest Hits<br>vol 1</p>
              </div>
            </div>
          </div>
          <div class="light"></div>
        </div>
    
        <div class="support">
          <div class="seg2 up">
            <div class="seg3" id="holder">
              <div class="needle"></div>
            </div>
          </div>
        </div>
      </div>
    </div>
    
    <audio id="audio" controls src="https://www.therosenbergtrio.info/wp-content/uploads/2016/04/02-Ive-Got-Rhythm-Featuring-Mozes-Johnny-Rosenberg.mp3?_=1">

    毫无疑问,WebGL 和 Three.js 在这个项目的实施中提供了更大的视角。

    • 6
  2. puffleeck
    2022-08-05T03:40:50Z2022-08-05T03:40:50Z

    在动针的部分,甚至头部应该适合

    <label><input type='range' min=1 max=9/></label>
    

    其中 max=9 是可包含的曲目的限制。在这种情况下,拖动指针将在轨道之间切换。抬起头来,当然是一个标签包裹的复选框。或者如果通过拖动进行狩猎,则再次进行范围但范围为 1-2。就头部的视觉布局而言,就算是xs……也懒得细看,但明明没有什么复杂的,喉舌会比较吃力。

    喇叭的扩展部分 - 单个容器中的 3+ 个块,在 2D 中旋转 40 45 度。+ 玩一点透视 https://webref.ru/css/value/perspective 您 也可以尝试一个表格,表格的每一列都会应用不同的透视图。

    喇叭输出,从左图 - 贴在透视表的末端,例如,带有圆形按钮。在右边......又是一堆具有不同旋转角度和透视角度的块。或者只是一个带有背景图像的圆形块。

    我是这样介绍的。

    顺便说一句,如果你想用针“缠绕”轨道,你可以尝试将它绑定到标签的进度条

    <audio>
    

    尝试

    <label **for=''**>
    
    • 1
  3. Опан
    2022-08-11T08:53:24Z2022-08-11T08:53:24Z

    这是将简单播放列表连接到获胜者变体的实现:

    let sounds = 'track1, track2, track3, track4, track5'.split(', ');
    let url = 'https://mysynthesizer.github.io/index.hetemeel/';
    let index = 0;
    audio.src = url + sounds[index] + '.mp3';
    function playTrack(){
        audio.src = url + sounds[index] + '.mp3';
        audio.play();
        for (j = 0; j < sounds.length; j ++) document.getElementById('td' + j).style.background = 'white';
        document.getElementById('td' + index).style.background = 'gold';
    }
    function changeTrack(direction){
        index += direction;
        if (index >= sounds.length) index = 0;
        if (index < 0) index = sounds.length - 1;
        playTrack();
    }
    document.onkeydown = e => {
        if(e.keyCode == 38) changeTrack(-1);
        if(e.keyCode == 40) changeTrack(1);
        return false;
    }
    for(i = 0; i < sounds.length; i ++){
        let tr = document.createElement('tr');
        let td = document.createElement('td');
        td.id = 'td' + i;
        td.textContent = sounds[i];
        td.onclick = function(){
            index = parseInt(this.id.substring(2));
            playTrack();
        }
        tr.append(td);
        tr.append(td);
        table1.append(tr);
    }
    let needleRange = [-29.5, -57.5];
    let needleDrag = false;
    let prevX = 0;
    let dragSens = 0.2;
    
    const rangeLimit = (v, a, b) => v < a ? a : (v > b ? b : v);
    const rangePercentByValue = (v, a, b) => (v - a) / (b - a);
    const rangeValueByPercent = (p, a, b) => (b - a) * p + a;
    
    const elRecord = document.querySelector('.record');
    const elSupport = document.querySelector('.support');
    const elSeg2 = document.querySelector('.seg2');
    
    const setNeedlePos = (pos) => elSupport.style.setProperty('--angle', pos + "deg");
    const getNeedlePos = () => parseFloat(getComputedStyle(elSupport).getPropertyValue('--angle'));
    
    const needleUp = () => {
      elSeg2.classList.remove('jumping');
      void elSeg2.offsetHeight;
      elSeg2.classList.add('up');
    }
    
    const needleDown = () => {
      elSeg2.classList.remove('up');
      setTimeout(() => {
        if (!audio.paused) elSeg2.classList.add('jumping')
      }, 300);
    }
    
    holder.onmousedown = (e) => {
      audio.pause();
      needleDrag = true;
      prevX = e.pageX;
    }
    
    window.onmousemove = (e) => {
      if (needleDrag) {
        let da = (e.pageX - prevX) * dragSens;
        let r = needleRange;
        let a = getNeedlePos();
        let aNew = rangeLimit(a - da, r[1], r[0]);
        setNeedlePos(aNew);
        audio.currentTime = (1 - rangePercentByValue(aNew, r[1], r[0])) * audio.duration;
        prevX = e.pageX;
      }
    }
    
    window.onmouseup = (e) => {
      needleDrag = false;
      audio.play();
    }
    
    audio.ontimeupdate = function(e) {
      if (!needleDrag) {
        let percent = 1 - audio.currentTime / audio.duration;
        let aNew = rangeValueByPercent(percent, needleRange[1], needleRange[0]);
        setNeedlePos(aNew);
      }
    };
    
    audio.addEventListener("pause", needleUp);
    audio.addEventListener("ended", needleUp);
    audio.addEventListener("play", needleDown);
    .viewport,
    .viewport * {
      display: flex;
      justify-content: center;
      align-items: center;
      box-sizing: border-box;
    }
    
    .viewport {
      width: 100%;
      height: 350px;
      perspective: 1200px;
      position: relative;
      overflow: hidden;
    }
    
    .scene {
      user-select: none;
      transform: rotateX(50deg);
    }
    
    .scene,
    .scene * {
      position: absolute;
      transform-style: preserve-3d;
      backface-visibility: hidden;
    }
    
    .table {
      width: 500px;
      height: 400px;
      background-color: #d9a35c;
      transform: translate3d(0, 0, -10px);
    }
    
    .table .back-rack {
      border-radius: 25% 25% 0 0;
      bottom: 100%;
      width: 170px;
      height: 100px;
      background-color: #a9a35c;
    }
    
    .table .back-rack .base {
      width: 30px;
      height: 80px;
      background-color: black;
      transform: translateZ(40px) rotateX(-90deg);
    }
    
    .support {
      --angle: -29.5deg;
      right: 0%;
      width: 250px;
      height: 20px;
      transform-origin: 100% 50%;
      transform: translate3d(0, -250px, 30px) rotateZ(var(--angle)) rotateX(-90deg);
      background: green;
    }
    
    .seg2 {
      right: 100%;
      width: 70px;
      height: 20px;
      transform-origin: 100% 50%;
      transform: rotateY(90deg) rotateZ(0deg);
      background: blue;
      backface-visibility: visible;
      transition: 0.2s;
    }
    
    .seg2.up {
      transition: 0.5s;
      animation: none;
      transform: rotateY(90deg) rotateZ(45deg);
    }
    
    .seg2.jumping {
      animation: 0.2s jumping infinite alternate;
    }
    
    .seg3 {
      border-radius: 50%;
      right: calc(100% - 19px);
      width: 40px;
      height: 40px;
      transform-origin: 50% 50%;
      transform: rotateY(90deg) rotateZ(0deg);
      background: darkred;
      backface-visibility: visible;
    }
    
    .seg3:hover {
      outline: 3px solid yellow;
    }
    
    .needle {
      top: 100%;
      height: 10px;
      width: 3px;
      background: yellow;
      backface-visibility: visible;
    }
    
    .record {
      width: 400px;
      height: 400px;
      font-family: Times;
    }
    
    .record.rotating .vinyl-wrap {
      animation: 2s rotation infinite linear;
    }
    
    .vinyl-wrap {
      width: 100%;
      height: 100%;
    }
    
    .vinyl {
      width: 100%;
      height: 100%;
      border-radius: 50%;
      background-color: black;
      background-image: url(data:image/png;base64,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), repeating-radial-gradient(#2a292866, #2a292866 1px, #444 2px, #2a292866 3px);
      background-size: 20% 20%, 100% 100%;
      transform: rotateX(0.25deg);
    }
    
    .light {
      border-radius: 50%;
      width: 100%;
      height: 100%;
      background: conic-gradient(from 10deg, transparent 0deg, #ffffff44 30deg, transparent 60deg, transparent 180deg, #ffffff66 210deg, transparent 240deg);
      -webkit-mask-image: radial-gradient(transparent 25%, black 25.8%);
      mask-image: radial-gradient(transparent 25%, black 25.8%);
      transform: translate3d(0, 0, 1px)
    }
    
    .label {
      border: solid 2px #d9a388;
      width: 33%;
      height: 33%;
      border-radius: 50%;
      box-shadow: 0 0 0 4px #da5b33;
      background: #da5b33;
      color: white;
      text-align: center;
    }
    
    .label:after {
      transform-style: preserve-3d;
      position: absolute;
      border-radius: 50%;
      background: black;
      width: 14%;
      height: 14%;
      content: '';
    }
    
    .label h1 {
      top: -6%;
    }
    
    .label p {
      top: 53%;
      font-size: 83%;
    }
    
    @keyframes rotation {
      100% {
        transform: rotateZ(1turn);
      }
    }
    
    @keyframes jumping {
      100% {
        transform: rotateY(90deg) rotateZ(0.7deg);
      }
    }
    #table1{
        width: 100px;
        text-align: center;
        font-family: arial;
    }
    td{
        cursor: pointer;
        border-radius: 5px;
        transition: 0.5s;
    }
    td:hover{
        background: pink;
        transition: 0.5s;
    }
    <div class="viewport">
      <div class="scene">
    
        <div class="table" id="table">
          <div class="back-rack">
            <div class="base"></div>
          </div>
        </div>
    
        <div class="record rotating">
          <div class="vinyl-wrap">
            <div class="vinyl">
              <div class="label jazz">
                <h1>Мелодия</h1>
                <p>Фабрика граммпластинок<br>vol 1</p>
              </div>
            </div>
          </div>
          <div class="light"></div>
        </div>
    
        <div class="support">
          <div class="seg2 up">
            <div class="seg3" id="holder">
              <div class="needle"></div>
            </div>
          </div>
        </div>
      </div>
    </div>
    <center>
    <button onclick='changeTrack(-1)' title='предыдущий трек'> << </button>
    <button onclick='changeTrack(1)' title='следующий трек'> >> </button><br /><br />
    <table id=table1 border=0 cellspacing=5 cellpadding=0></table>
    </center>
    <audio id="audio" onended='changeTrack(1)'></audio>

    您可以通过单击曲目名称、使用向上和向下箭头键以及使用<<和按钮来切换曲目>>。

    • 0

相关问题

  • 具有非均匀背景的块内的渐变边框

  • 离开页脚

  • 如何将三个字段的数据收集到一封电子邮件中?

  • Html 元素刚从父元素中出来

  • 如何在css中制作这个背景?

  • 如何制作带有斜条纹的背景?

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    我看不懂措辞

    • 1 个回答
  • Marko Smith

    请求的模块“del”不提供名为“default”的导出

    • 3 个回答
  • Marko Smith

    "!+tab" 在 HTML 的 vs 代码中不起作用

    • 5 个回答
  • Marko Smith

    我正在尝试解决“猜词”的问题。Python

    • 2 个回答
  • Marko Smith

    可以使用哪些命令将当前指针移动到指定的提交而不更改工作目录中的文件?

    • 1 个回答
  • Marko Smith

    Python解析野莓

    • 1 个回答
  • Marko Smith

    问题:“警告:检查最新版本的 pip 时出错。”

    • 2 个回答
  • Marko Smith

    帮助编写一个用值填充变量的循环。解决这个问题

    • 2 个回答
  • Marko Smith

    尽管依赖数组为空,但在渲染上调用了 2 次 useEffect

    • 2 个回答
  • Marko Smith

    数据不通过 Telegram.WebApp.sendData 发送

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5