HTML5技术实现的小钢琴

news2025/2/24 16:28:50

HTML5技术实现的小钢琴

用HTML5实现的小钢琴,按下钢琴键上的相应字母用或用鼠标点击钢琴键发声,源码如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>用HTML5实现的小钢琴</title>
  <style>
    .key {
      width: 50px;
      height: 150px;
      border: 1px solid black;
      display: inline-block;
      margin: 5px;
      text-align: center;
      line-height: 150px;
      cursor: pointer;
      position: relative; /* 为了绝对定位伪元素而需要 */
      transition: transform 0.1s; /* 按键按下时平滑过渡效果 */
    }
    /* 当按键被按下时的样式 */
    .key.active {
      transform: translateY(4px); /* 将按键向下移动 */
    }
  </style>
</head>
<body>
  <div id="A" class="key">A</div>
  <div id="S" class="key">S</div>
  <div id="D" class="key">D</div>
  <div id="F" class="key">F</div>
  <div id="G" class="key">G</div>
  <div id="H" class="key">H</div>
  <div id="J" class="key">J</div>
  <div id="K" class="key">K</div>


  <script>
    // 创建一个新的AudioContext实例,用于处理音频
    const audioContext = new (window.AudioContext || window.webkitAudioContext)();

    // 播放特定频率的声音
    function playSound(frequency) {
      const oscillator = audioContext.createOscillator();
      oscillator.type = 'sine'; // 选择波形类型,这里是正弦波
      oscillator.frequency.setValueAtTime(frequency, audioContext.currentTime); // 设置频率
      oscillator.connect(audioContext.destination); // 连接到音频输出
      oscillator.start(); // 开始播放
      oscillator.stop(audioContext.currentTime + 0.3); // 0.3秒后停止播放
    }

    // 获取所有的琴键元素
    const keys = document.querySelectorAll('.key');
    keys.forEach(key => {
      // 为每个琴键添加鼠标点击事件
      key.addEventListener('click', () => {
        playNote(key.textContent); // 播放琴键对应的音符
        animatePress(key); // 触发按键动画效果
      });
    });

    // 监听键盘按下事件
    document.addEventListener('keydown', (event) => {
      const keyName = event.key.toUpperCase(); // 获取按键名并转为大写
      const keyElement = document.getElementById(keyName); // 获取对应的琴键元素
      if (keyElement) {
        playNote(keyName); // 播放琴键对应的音符
        animatePress(keyElement); // 触发按键动画效果
      }
    });

    // 触发琴键按下的动画效果
    function animatePress(keyElement) {
      keyElement.classList.add('active'); // 添加按下状态的样式类
      setTimeout(() => {
        keyElement.classList.remove('active'); // 在100毫秒后移除按下状态的样式类
      }, 100); // 这个时间应该与CSS中的过渡时间一致
    }

    // 根据音符播放声音
    function playNote(note) {
      let frequency;
      switch (note) {
        case 'A':
          frequency = 261.63;
          break;
        case 'S':
          frequency = 293.66;
          break;
        case 'D':
          frequency = 329.63;
          break;
        case 'F':
          frequency = 349.23;
          break;
        case 'G':
          frequency = 392.00;
          break;
        case 'H':
          frequency = 440.00;
          break;
        case 'J':
          frequency = 493.88;
          break;
        case 'K':
          frequency = 523.25;
          break;
        default:
          return; // 如果不是琴键对应的字母,则不执行任何操作
      }
      playSound(frequency); // 调用函数播放声音
    }
  </script>
</body>
</html>

代码中使用了JavaScript中的箭头函数(Arrow Function)语法。箭头函数是ES6中的一种函数声明方式,它的语法比较简洁。箭头函数的基本格式是:(参数) => {函数体}。

keys.forEach(key => { })

箭头函数的参数是key,表示forEach遍历的每个元素。

key.addEventListener('click', () => { })

它是给每个琴键添加鼠标点击事件的代码。addEventListener 方法用于给元素添加事件监听器。这里添加了一个点击事件的监听器,当用户点击琴键时,箭头函数会被执行。

我对乐理了解很少,相关音高(pitch)请参考这里https://www.autopiano.cn/toolbox/pitch

用浏览器运行效果如下:

你可以用英文状态下按下琴键上的字符,或用鼠标单击琴键试试了。

钢琴演奏中,滑音是通过在音符之间平滑地滑动手指,使音符之间产生连贯的过渡效果。

上面的代码滑动按键能产生了滑音效果,但滑动鼠标不能,现在修改上面程序,使用鼠标都能产生了滑音效果。

修改后源码如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>用HTML5实现的小钢琴2</title>
  <style>
    .key {
      width: 50px;
      height: 150px;
      border: 1px solid black;
      display: inline-block;
      margin: 5px;
      text-align: center;
      line-height: 150px;
      cursor: pointer;
      position: relative;
      transition: transform 0.1s;
    }
    .key.active {
      transform: translateY(4px);
    }
  </style>
</head>
<body>
  <div id="A" class="key">A</div>
  <div id="S" class="key">S</div>
  <div id="D" class="key">D</div>
  <div id="F" class="key">F</div>
  <div id="G" class="key">G</div>
  <div id="H" class="key">H</div>
  <div id="J" class="key">J</div>
  <div id="K" class="key">K</div>

  <script>
    const audioContext = new (window.AudioContext || window.webkitAudioContext)();
    let isMouseDown = false; // 记录鼠标是否被按下

    function playSound(frequency) {
      const oscillator = audioContext.createOscillator();
      oscillator.type = 'sine';
      oscillator.frequency.setValueAtTime(frequency, audioContext.currentTime);
      oscillator.connect(audioContext.destination);
      oscillator.start();
      oscillator.stop(audioContext.currentTime + 0.3);
    }

    const keys = document.querySelectorAll('.key');

    keys.forEach(key => {
      key.addEventListener('mousedown', (event) => {
        isMouseDown = true; // 设置鼠标按下状态为true
        playNoteFromElement(event.target);
      });

      key.addEventListener('mouseenter', (event) => {
        if (isMouseDown) { // 如果鼠标处于按下状态,则播放音符
          playNoteFromElement(event.target);
        }
      });

      // 鼠标按下并移动到其他琴键时,无需额外mouseup事件监听
    });

    // 监听文档的mouseup事件,以处理鼠标在琴键外松开的情况
    document.addEventListener('mouseup', () => {
      isMouseDown = false;
    });

    // 监听键盘按下事件
    document.addEventListener('keydown', (event) => {
      const keyName = event.key.toUpperCase(); // 获取按键名并转为大写
      const keyElement = document.getElementById(keyName); // 获取对应的琴键元素
      if (keyElement && !keyElement.classList.contains('active')) {
        playNoteFromElement(keyElement);
      }
    });

    function playNoteFromElement(element) {
      const note = element.textContent;
      playNote(note);
      animatePress(element);
    }

    function animatePress(keyElement) {
      keyElement.classList.add('active');
      setTimeout(() => {
        keyElement.classList.remove('active');
      }, 100);
    }

    function playNote(note) {
      let frequency;
      switch (note) {
        case 'A':
          frequency = 261.63;
          break;
        case 'S':
          frequency = 293.66;
          break;
        case 'D':
          frequency = 329.63;
          break;
        case 'F':
          frequency = 349.23;
          break;
        case 'G':
          frequency = 392.00;
          break;
        case 'H':
          frequency = 440.00;
          break;
        case 'J':
          frequency = 493.88;
          break;
        case 'K':
          frequency = 523.25;
          break;
        default:
          return;
      }
      playSound(frequency);
    }
  </script>
</body>
</html>

请注意,这段代码包含了对鼠标按下、移动和松开,以及键盘按下的事件监听。

你可以在此基础上继续改进优化。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1465716.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[SSD 测试 1.4] 硬件测试之主控测试 (CP | FT) | 主控是如何保证品质的?

专栏 《深入理解SSD》 <<<< 返回总目录 <<<< 主控制器方面&#xff0c;消费级市场的主要厂商包括三星、英特尔、西部数据、海力士和东芝&#xff0c;他们的产品涵盖了SATA和Nvme Pcie3.0/4.0接口。而在企业级市场&#xff0c;国内厂商华为海思H181x系…

VBA_MF系列技术资料1-385

MF系列VBA技术资料1-385 为了让广大学员在VBA编程中有切实可行的思路及有效的提高自己的编程技巧&#xff0c;我参考大量的资料&#xff0c;并结合自己的经验总结了这份MF系列VBA技术综合资料&#xff0c;而且开放源码&#xff08;MF04除外&#xff09;&#xff0c;其中MF01-0…

深陷债务风波,折价变卖股权,皓宸医疗能否自救于水火?

近日&#xff0c;皓宸医疗科技股份有限公司&#xff08;下称“皓宸医疗”&#xff09;发布公告称&#xff0c;上海金融法院于1月24日至27日对其持有的抚顺银行股份有限公司出资额为2.27亿元的非上市股份有限公司股权进行了第一次公开拍卖&#xff0c;拍卖结果为流拍。 皓宸医疗…

Jenkins2.426邮件通知配置

之前安装的jenkins出现问题了&#xff0c;重新装了jenkins&#xff0c;需要重新配置&#xff1a;Maven&#xff0c;JDK&#xff0c;Allure报告&#xff0c;邮件通知&#xff0c;Extended E-mail Notification等 配置Maven&#xff0c;JDK参考&#xff1a;CICD集合(四):Jenkins…

vue实现拖拽(vuedraggable)

实现效果: 左侧往右侧拖动&#xff0c;右侧列表可以进行拖拽排序。 安装引用&#xff1a; npm install vuedraggable import draggable from vuedraggable 使用&#xff1a; data数据&#xff1a; componentList: [{groupName: 考试题型,children: [{componentType: danxua…

JVM内存随着服务器内存的升高而升高问题排查

一、故障描述 公司测试环境和线上环境&#xff0c;都会有&#xff1a;JVM内存随着服务器内存的升高而升高 这种问题 二、排查 1、linux服务器上使用htop查看java项目内存占比&#xff0c;给最大最小推内存300m&#xff0c;但是实际上超出一倍 2、排查方案 a、通过后面的学习…

Emlog博客网站快速搭建并结合内网穿透实现远程访问本地站点

文章目录 前言1. 网站搭建1.1 Emolog网页下载和安装1.2 网页测试1.3 cpolar的安装和注册 2. 本地网页发布2.1 Cpolar临时数据隧道2.2.Cpolar稳定隧道&#xff08;云端设置&#xff09;2.3.Cpolar稳定隧道&#xff08;本地设置&#xff09; 3. 公网访问测试总结 前言 博客作为使…

人工智能 — 图像滤波器

目录 一、图像噪声1、高斯噪声2、椒盐噪声3、泊松噪声4、乘性噪声5、瑞利噪声6、伽马噪声 二、图像滤波三、各种滤波器1、均值滤波2、中值滤波3、最大最小值滤波4、引导滤波 四、图像增强1、点处理1、线性变换2、分段线性变换3、对数变换4、幂律变换/伽马变换 2、领域处理3、图…

浏览器自动填充

input同时有多个 当input框的类型为typepassword&#xff0c;其上一个框为typetext&#xff0c;浏览器会自动填充保存过的账户密码、解决自动填充有以下几种处理方法&#xff1a; 1、在浏览器端设置 2、给出一组假页面存储&#xff0c;必须在同一个Form表单中&#xff0c;让填充…

解决SpringAMQP工作队列模型程序报错:WARN 48068:Failed to declare queue: simple.queue

这里写目录标题 1.运行环境2.报错信息3.解决方案4.查看解决之后的效果 1.运行环境 使用docker运行了RabbitMQ的服务器&#xff1a; 在idea中导入springAMQP的jar包&#xff0c;分别编写了子模块生产者publisher&#xff0c;消费者consumer&#xff1a; 1.在publisher中运行测试…

[AI]部署安装有道QanyThing

前提条件&#xff1a; 1、win10系统更新到最新的版本&#xff0c;系统版本最好为专业版本 winver 查看系统版本&#xff0c;内部版本要大于19045 2、CPU开启虚拟化 3、开启虚拟化功能&#xff0c;1、2、3每步完成后均需要重启电脑&#xff1b; 注&#xff1a;windows 虚拟…

农业四情在线监测站的应用

TH-Q3农业四情在线监测站可广泛应用于农田管理、作物种植、病虫害防治、气象灾害预警等领域。通过实时监测和数据分析&#xff0c;该系统可以帮助农民实现精准施肥、科学灌溉、合理调控作物生长等目标&#xff0c;提高农业生产效率和质量。同时&#xff0c;该系统还可以为政府决…

Pytorch学习(杂知识)

Mini-batch Mii-batch是一种在机器学习中常用的训练算法。它是将大的数据集分成一些小的数据集&#xff0c;每次只用一个小的数据集来训练模型。通常情况下&#xff0c;训练数据集中的数据越多&#xff0c;训练出的模型越准确&#xff0c;但是如果数据集太大&#xff0c;就会导…

【OpenFeign常用配置】

OpenFeign常用配置 快速入门&#xff1a;1、引入依赖2、启用OpenFeign 实践1、引入依赖2、开启连接池功能3、模块划分4、日志5、重试 快速入门&#xff1a; OpenFeign是一个声明式的http客户端&#xff0c;是spring cloud在eureka公司开源的feign基础上改造而来。其作用及时基于…

红日靶场3

靶场链接&#xff1a;漏洞详情 在虚拟机的网络编辑器中添加两个仅主机网卡 信息搜集 端口扫描 外网机处于网端192.168.1.0/24中&#xff0c;扫描外网IP端口&#xff0c;开放了80 22 3306端口 80端口http服务&#xff0c;可以尝试登录网页 3306端口mysql服务&#xff0c;可…

Megalinter 初体验

简介 MegaLinter 是一个多语言、多工具的集成代码检查工具&#xff0c;它能够通过一个统一的工作流来运行多个静态代码分析工具&#xff0c;从而提供全面的代码质量检查。 官网&#xff1a;https://megalinter.io/latest/ MegaLinter 的特点&#xff1a; 多语言支持&#x…

精品基于Spring Boot智能无人仓库管理-进销存储

《[含文档PPT源码等]精品基于Spring Boot智能无人仓库管理[包运行成功]》该项目含有源码、文档、PPT、配套开发软件、软件安装教程、项目发布教程、包运行成功&#xff01; 软件开发环境及开发工具&#xff1a; Java——涉及技术&#xff1a; 前端使用技术&#xff1a;HTML5…

统计图玫瑰图绘制方法

统计图玫瑰图绘制方法 常用的统计图有条形图、柱形图、折线图、曲线图、饼图、环形图、扇形图。 前几类图比较容易绘制&#xff0c;饼图环形图绘制较难。 还有一种玫瑰图的绘制也较难&#xff0c;今提供玫瑰图的绘制方法供参考。 本方法采用C语言的最基本功能&#xff1a; &am…

ESP8266智能家居(1)——开发环境的搭建

1.前期介绍 本次打算使用esp8266的开发板——NodeMCU&#xff0c;进行物联网相关项目的学习。开发环境使用Arduino软件。 NodeMCU实物图为&#xff1a; 开发环境截图为&#xff1a; 2.软件下载 我使用的arduino版本为1.8.5&#xff0c;其安装包如下&#xff1a; 【免费】ar…

【鸿蒙 HarmonyOS 4.0】路由router

一、介绍 页面路由指在应用程序中实现不同页面之间的跳转和数据传递。HarmonyOS提供了Router模块&#xff0c;通过不同的url地址&#xff0c;可以方便地进行页面路由&#xff0c;轻松地访问不同的页面。 二、页面跳转 2.1、两种跳转模式&#xff1a; router.pushUrl()&…