HTML5技术实现的小钢琴

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>

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

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

idea如何在一个service窗口中显示多个服务教程

idea在service窗口中显示多个服务 展示效果如下: 找到.idea > workspace.xml 中找到 RunDashboard 替换成如下 <component name"RunDashboard"><option name"configurationTypes"><set><option value"SpringBootApplicatio…

DataDreamer:让创建自定义数据集轻松无比!还自带标注!

编辑&#xff1a;OAK中国 首发&#xff1a;oakchina.cn 喜欢的话&#xff0c;请多多&#x1f44d;⭐️✍ 内容可能会不定期更新&#xff0c;官网内容都是最新的&#xff0c;请查看首发地址链接。 ▌前言 Hello&#xff0c;大家好&#xff0c;这里是OAK中国&#xff0c;我是Ash…

易宝OA DownloadFile 任意文件读取漏洞复现

0x01 产品简介 易宝OA系统是一种专门为企业和机构的日常办公工作提供服务的综合性软件平台,具有信息管理、 流程管理 、知识管理(档案和业务管理)、协同办公等多种功能。 0x02 漏洞概述 易宝OA系统DownloadFile接口处存在任意文件读取漏洞,未授权的攻击者可以利用此漏洞…

【力扣 - 搜索插入位置】

题目描述 给定一个排序数组和一个目标值&#xff0c;在数组中找到目标值&#xff0c;并返回其索引。如果目标值不存在于数组中&#xff0c;返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 题解1 int searchInsert(int* nums, int numsSize, in…

69.x的平方根

目录 一、题目 二、暴力求解 三、二分查找&#xff08;改进&#xff09; 一、题目 https://leetcode.cn/problems/sqrtx/description/ 二、暴力求解 1.溢出问题 2.x为1 class Solution { public:int mySqrt(int x) {if(x 1)return 1;long long i0;for(i;i<x/2;i){if(…

C#中的关键字params的用法

C#中有一个关键字params&#xff0c;它相对于一些主要关键字来说&#xff0c;还算是较为低频的&#xff0c;但也会用到。我们可以了解和学习下。 一、定义及约束 params关键字的作用在于可以让方法参数的数目可变。 params的参数类型必须是一维数组。 一旦在方法加入了para…

qt-动画圆圈等待-LED数字

qt-动画圆圈等待-LED数字 一、演示效果二、关键程序三、下载链接 一、演示效果 二、关键程序 #include "LedNumber.h" #include <QLabel>LEDNumber::LEDNumber(QWidget *parent) : QWidget(parent) {//设置默认宽高比setScale((float)0.6);//设置默认背景色se…

发布6-JRT摄像头调用

截止这之前&#xff0c;JRT已经拥有Web、打印、导出Excel、监听程序、Linux命令、连设备这些功能&#xff0c;还缺摄像头调用功能。本次补全摄像头调用支持&#xff0c;同时支持把摄像头内嵌到浏览器来供业务做功能。 演示视频 内嵌效果 弹出效果 demo代码 <!DOCTYPE…

镜像的使用条件

Q&#xff1a;老师&#xff0c;我怎么才能把做了一半的脸直接复制呢&#xff1f; A&#xff1a;镜像&#xff0c;但是镜像是有条件的 Q&#xff1a;镜像的使用条件有哪些呢&#xff1f; A&#xff1a; 1.对称面不能存在&#xff0c;必须是镂空的&#xff08;以哪个面做对称…

如何解决服务器之间大量数据文件传输交换慢的问题?

在信息化时代&#xff0c;企业运营的核心之一便是服务器间的数据交换效率。数据流通的速度直接关系到业务的响应速度和企业的整体表现。然而&#xff0c;数据传输速度缓慢的问题时常成为企业发展的绊脚石&#xff0c;可能导致严重的业务损失。本文将深入探讨造成服务器数据传输…

漫漫数学之旅031

文章目录 经典格言数学习题古今评注名人小传 - 经典格言 如果没有数学知识&#xff0c;这个世界的事物是无法搞清楚的。——罗杰培根&#xff08;Roger Bacon&#xff09; 好的&#xff0c;各位看官&#xff0c;让我们来听听罗杰培根这位中世纪的“科学老顽童”是怎么说的&…

招聘不能停!达坦科技2024实习岗位等你来~

01、我们是谁 达坦科技始终致力于打造高性能Al Cloud 基础设施平台DatenLord&#xff0c;积极推动AI应用的落地。DatenLord通过软硬件深度融合的方式&#xff0c;提供高性能存储和高性能网络。为AI 应用提供弹性、便利、经济的基础设施服务&#xff0c;以此满足不同行业客户对…

2024开年,手机厂商革了自己的命

文&#xff5c;刘俊宏 编&#xff5c;王一粟 2024开年&#xff0c;AI终端的号角已经由手机行业吹响。 OPPO春节期间就没闲着&#xff0c;首席产品官刘作虎在大年三十就迫不及待地宣布&#xff0c;OPPO正式进入AI手机时代。随后在开年后就紧急召开了AI战略发布会&#xff0c;…

手写myscrapy(五)

项目地址&#xff1a;https://gitee.com/wyu_001/myscrapy 我们继续完成返回的处理类 MyResponse的实现 先上类图&#xff1a; 主要功能&#xff1a; json() 方法解析返回的json格式内容&#xff0c;转换为 python 的json对象 xpath(&#xff09;方法解析返回的html格式的内…

C++标准库与Boost库:功能丰富的开发工具集

C标准库与Boost库&#xff1a;功能丰富的开发工具集 C是一种强大的编程语言&#xff0c;而C标准库和Boost库则为C开发者提供了广泛的工具和功能。本文将深入探讨C标准库和Boost库&#xff0c;介绍它们的特点、提供的功能以及如何在项目中使用它们来加速开发过程和提高代码质量。…

腾讯云宝塔Linux安装Mysql5.7

一、下载官方mysql包 wget http://dev.mysql.com/get/mysql-community-release-el7-5.noarch.rpm二、安装mysql包 rpm -ivh mysql-community-release-el7-5.noarch.rpm三、安装mysql yum install mysql-community-server -y四、启动数据库 systemctl start mysqld.service…

JAVA工程师面试专题-Mysql篇

一、基础 1、mysql可以使用多少列创建索引&#xff1f; 16 2、mysql常用的存储引擎有哪些 存储引擎Storage engine&#xff1a;MySQL中的数据、索引以及其他对象是如何存储的&#xff0c;是一套文件系统的实现。常用的存储引擎有以下&#xff1a; Innodb引擎&#xff1a;In…

spark 少量key倾斜的join优化

背景 在使用spark join时&#xff0c;我们经常遇到少量key拥有大量的数据而导致的数据倾斜的问题&#xff0c;这导致了task任务数据处理非常不均匀而影响最终时效 少量key数据倾斜的join优化 这里有一个前提&#xff0c;join的另一边的表没有数据倾斜问题&#xff0c;也就是…

C语言----字符数组指针

1.char arr[] {a,b,c,d,e,f}; sizeof分析类型就可以计算所占的内存空间的大小&#xff1b; &#xff08;1&#xff09;printf("%d\n", sizeof(arr)); 数组名单独放进里面&#xff0c;计算整个数组大小&#xff0c;所以是6字节&#xff1b; &#xff08;2&#xff…

R语言【base】——abs(),sqrt():杂项数学函数

Package base version 4.2.0 Description abs(x) 计算 x 的绝对值&#xff0c;sqrt(x) 计算 x 的正平方根。 Usage abs(x) sqrt(x) Arguments 参数【x】&#xff1a;一个数值或复数向量或数组。 Details 这些都是内部泛型原语函数:可以为它们单独定义方法&#xff0c;也可以…