javaScript蓝桥杯---视频弹幕


一、介绍

弹幕指直接显现在视频上的评论,可以以滚动、停留甚⾄更多动作特效⽅式出现在视频上,是观看视频的⼈发送的简短评论。通过发送弹幕可以给观众⼀种“实时互动”的错觉,弹幕的出现让观看过程充满乐趣。本题需要在已提供的基础项⽬中,完成视频弹幕的功能。

二、准备

开始答题前,需要先打开本题的项⽬代码⽂件夹,⽬录结构如下:

├── effect.gif
├── css
│ └── style.css
├── video
│ └── video1.webm
├── index.html
└── js
└── index.js

其中:

  • index.html 是主⻚⾯。
  • js/index.js 是需要补充代码的 js ⽂件。
  • css/style.css 是样式⽂件。
  • effect.gif 是完成的效果图。
  • video 是存放视频的⽂件夹。

在浏览器中预览 index.html ⻚⾯,显示如下所示:
在这里插入图片描述

三、⽬标

请在 js/index.js ⽂件中补全代码。具体需求如下:

  1. 补全 renderBullet 函数中的代码,控制弹幕的显示颜⾊和移动。功能说明如下:
    • 每个弹幕内容包裹在 span 标签中,作为⼦节点插⼊到 #video 元素节点内。
    • ⽣成的 span 元素节点相对于 #video 元素绝对定位 ,初始位置的 left 是 #video 元素的宽, top 是 #video 元素的⾼内的随机数。

    注意:需求中所需样式可直接通过已提供的 getEleStyle ⽅法获取。

    • 弹幕每隔 bulletConfig.time (弹幕配置对象) 时间,向左移动距离为bulletConfig.speed (弹幕配置对象)。
    • 当弹幕最右端完全移出 #video 元素时,移除 span 元素。
  2. 补全 #sendBulletBtn 元素的绑定事件,点击发送按钮,输⼊框中的⽂字出现在弹幕中,样式不同于普通弹幕(样式红⾊字体红⾊框已设置,类名为 create-bullet )。通过调⽤renderBullet ⽅法和正确的传参实现功能。

最终效果可参考⽂件夹下⾯的 gif 图,图⽚名称为 effect.gif(提示:可以通过 VS Code 或者浏览器预览gif 图⽚)。
在这里插入图片描述

四、代码

index.html

<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>视频弹幕</title>
    <link rel="stylesheet" href="./css/style.css" />
  </head>

  <body>
    <div class="container">
      <div class="video-header">
        <h1 class="title">workerman基础</h1>
        <div class="video-info">
          <span>13.2亿播放</span>
          <span>656.5万弹幕</span>
          <span>2022-12-11 15:29:24</span>
        </div>
      </div>
      <div id="video">
        <video src="./video/video1.webm" poster="" id="vd" controls>
          您的浏览器不支持 video 标签。
        </video>
      </div>
      <div class="player-sending-area">
        <p class="player-video-info">231 人正在看,4396 条弹幕</p>
        <div class="switch-box">
          <input
            type="checkbox"
            name=""
            id="switchButton"
            class="switch"
            checked
          />
          <label for="switchButton"></label>
        </div>
        <input
          type="text"
          name=""
          id="bulletContent"
          placeholder="请输入您的弹幕"
        />
        <button id="sendBulletBtn">发送</button>
      </div>
    </div>
    <script src="./js/index.js"></script>
  </body>
</html>

css/style.css

* {
  margin: 0;
  padding: 0;
}

.container {
  width: 850px;
  margin: 0px auto;
}

.container .video-header {
  box-sizing: border-box;
  padding: 24px 0;
}

.container .video-header .title {
  font-size: 20px;
  font-family: PingFang SC, HarmonyOS_Regular, Helvetica Neue, Microsoft YaHei,
    sans-serif;
  font-weight: 500;
  margin-bottom: 6px;
  color: #18191c;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.container .video-header .video-info {
  display: flex;
  align-items: center;
}

.container .video-header .video-info span {
  margin-right: 12px;
  font-size: 13px;
  color: #9499a0;
}

#video {
  width: 850px;
  height: 560px;
  background-color: #000;
  position: relative;
  overflow: hidden;
}

#video > video {
  width: 100%;
  height: 100%;
}

#video > span {
  position: absolute;
  white-space: nowrap;
  color: #fff;
  font-size: 16px;
}

#video > .create-bullet {
  border: 1px solid red;
  box-shadow: 0 0 5px 5px rgb(255, 84, 84);
  padding: 5px 10px;
  border-radius: 10px;
  color: red !important;
  background-color: rgba(255, 255, 255, 0.5);
}

.container .player-sending-area {
  display: flex;
  align-items: center;
  width: 830px;
  height: 50px;
  background-color: #fff;
  box-shadow: 0 1px 5px rgb(207, 207, 207);
  padding: 0 10px;
}

.container .player-sending-area .player-video-info {
  font-size: 14px;
  color: rgb(95, 95, 95);
  margin: 0 15px;
}

.container .player-sending-area .switch-box {
  width: 48px;
}

.container .player-sending-area .switch-box .switch {
  display: none;
}

.container .player-sending-area .switch-box label {
  position: relative;
  display: block;
  margin: 1px;
  height: 28px;
  cursor: pointer;
}

.container .player-sending-area .switch-box label::before {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  margin-top: -13px;
  margin-left: -14px;
  width: 26px;
  height: 26px;
  border-radius: 100%;
  background-color: #fff;
  box-shadow: 1px 1px 1px 1px rgba(0, 0, 0, 0.06);
  transform: translateX(-9px);
  transition: all 0.3s ease;
}

.container .player-sending-area .switch-box .switch:checked ~ label::before {
  transform: translateX(10px);
}

.container .player-sending-area .switch-box label::after {
  content: "";
  display: block;
  border-radius: 30px;
  height: 28px;
  background-color: #dcdfe6;
  transition: all 0.3s ease;
}

.container .player-sending-area .switch-box .switch:checked ~ label::after {
  background-color: #00a1d6;
}

.container .player-sending-area > input {
  width: 250px;
  height: 30px;
  margin-left: 20px;
  border: 1px solid #e7e7e7;
  outline: none;
  text-indent: 10px;
  background-color: rgb(245, 244, 244);
  font-size: 12px;
  color: rgb(36, 35, 35);
}

.container .player-sending-area > input::placeholder {
  font-size: 12px;
}

.container .player-sending-area > button {
  width: 60px;
  height: 32px;
  color: #fff;
  background-color: #00a1d6;
  border: none;
}

js/index.js

const bullets = [
  "前方高能",
  "原来如此",
  "这么简单",
  "学到了",
  "学费了",
  "666666",
  "111111",
  "workerman",
  "学习了",
  "别走,奋斗到天明",
];

/**
 * @description 根据 bulletConfig 配置在 videoEle 元素最右边生成弹幕,并移动到最左边,弹幕最后消失
 * @param {Object} bulletConfig 弹幕配置
 * @param {Element} videoEle 视频元素
 * @param {boolean} isCreate 是否为新增发送的弹幕,为 true 表示为新增的弹幕
 *
 */
function renderBullet(bulletConfig, videoEle, isCreate = false) {
  const spanEle = document.createElement("SPAN");
  spanEle.classList.add(`bullet${index}`);
  if (isCreate) {
    spanEle.classList.add("create-bullet");
  }
  // TODO:控制弹幕的显示颜色和移动,每隔 bulletConfig.time 时间,弹幕移动的距离  bulletConfig.speed
}

document.querySelector("#sendBulletBtn").addEventListener("click", () => {
  // TODO:点击发送按钮,输入框中的文字出现在弹幕中
});

function getEleStyle(ele) {
  // 获得元素的width,height,left,right,top,bottom
  return ele.getBoundingClientRect();
}

function getRandomNum(end, start = 0) {
  // 获得随机数,范围是 从start到 end
  return Math.floor(start + Math.random() * (end - start + 1));
}

// 设置 index 是为了弹幕数组循环滚动
let index = 0;
const videoEle = document.querySelector("#video");
// 弹幕配置
const bulletConfig = {
  isHide: false, // 是否隐藏
  speed: 5, // 弹幕的移动距离
  time: 50, // 弹幕每隔多少ms移动一次
  value: "", // 弹幕的内容
};
let isPlay = false;
let timer; // 保存定时器
document.querySelector("#vd").addEventListener("play", () => {
  // 监听视频播放事件,当视频播放时,每隔 1000s 加载一条弹幕
  isPlay = true;
  bulletConfig.value = bullets[index++];
  renderBullet(bulletConfig, videoEle);
  timer = setInterval(() => {
    bulletConfig.value = bullets[index++];
    renderBullet(bulletConfig, videoEle);
    if (index >= bullets.length) {
      index = 0;
    }
  }, 1000);
});

document.querySelector("#vd").addEventListener("pause", () => {
  isPlay = false;
  clearInterval(timer);
});

document.querySelector("#switchButton").addEventListener("change", (e) => {
  if (e.target.checked) {
    bulletConfig.isHide = false;
  } else {
    bulletConfig.isHide = true;
  }
});

五、完成


/**
 * @description 根据 bulletConfig 配置在 videoEle 元素最右边生成弹幕,并移动到最左边,弹幕最后消失
 * @param {Object} bulletConfig 弹幕配置
 * @param {Element} videoEle 视频元素
 * @param {boolean} isCreate 是否为新增发送的弹幕,为 true 表示为新增的弹幕
 *
 */
function renderBullet(bulletConfig, videoEle, isCreate = false) {
  const spanEle = document.createElement('SPAN')
  spanEle.classList.add(`bullet${index}`)
  if (isCreate) {
    spanEle.classList.add('create-bullet')
  }
  // TODO:控制弹幕的显示颜色和移动,每隔 bulletConfig.time 时间,弹幕移动的距离  bulletConfig.speed
  if (bulletConfig.isHide) {
    return
  }
  //设置弹幕随机颜色
  spanEle.style.color = `rgb(${getRandomNum(255)},${getRandomNum(255)},${getRandomNum(255)})`
  //设置弹幕内容
  spanEle.innerHTML = bulletConfig.value
  //   ⽣成的 span 元素节点相对于 #video 元素绝对定位 ,
  spanEle.style.position = 'absolute'
  //初始位置的 left 是 #video 元素的宽,
  let leftSpan = getEleStyle(videoEle).width
  spanEle.style.left = leftSpan + 'px'
  // top 是 #video 元素的⾼内的随机数。
  spanEle.style.top = getRandomNum(getEleStyle(videoEle).height) + 'px'
  let _timer = setInterval(() => {
    //弹幕每隔 bulletConfig.time (弹幕配置对象) 时间,向左移动距离为
    leftSpan -= bulletConfig.speed
    spanEle.style.left = leftSpan + 'px'
    //每个弹幕内容包裹在 span 标签中,作为⼦节点插⼊到 #video 元素节点内
    videoEle.appendChild(spanEle)
    if (leftSpan < 0) {
      clearInterval(_timer)
      videoEle.removeChild(spanEle)
    }
  }, bulletConfig.time)
}

document.querySelector('#sendBulletBtn').addEventListener('click', () => {
  // TODO:点击发送按钮,输入框中的文字出现在弹幕中
  bulletConfig.value = document.querySelector('#bulletContent').value
  renderBullet(bulletConfig, videoEle, true)
})
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

懒羊羊h

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值