前端实现西瓜,抖音视频上传,视频帧选取封面功能

使用纯html,css,js实现西瓜,抖音视频上传,视频帧选取封面功能,只做了功能,部分优化可以自行修改

效果图片预览:

效果视频预览:

仿西瓜,抖音视频上传封面图功能

完整代码:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>视频帧提取封面</title>
    <style>
      * {
        margin: 0;
        padding: 0;
      }
      img {
        width: 100%;
        height: auto;
        vertical-align: bottom;
      }
      body {
        width: 100vw;
        height: 100vh;
        display: flex;
        align-items: center;
        justify-content: center;
        background-color: #fff;
      }
      .imgs {
        width: 455px;
        min-height: 256px;
        margin: 0 auto;
        display: flex;
        align-items: center;
        justify-content: center;
        overflow: hidden;
        border: 2px solid #ebebeb;
        margin-bottom: 30px;
        background-color: #fff;
      }
      .btns {
        display: flex;
        align-items: center;
        justify-content: center;
      }
      .button {
        position: relative;
        width: 100px;
        height: 36px;
        color: #fff;
        display: flex;
        align-items: center;
        justify-content: center;
        background-color: #fe3355;
        border-radius: 5px;
        margin-bottom: 50px;
      }
      .button input {
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        opacity: 0;
        cursor: pointer;
      }
      .imgs_list {
        position: relative;
        min-width: 300px;
        min-height: 100px;
        background-color: #fff;
        border: 2px solid #ebebeb;
      }
      .imgs_list_box {
        display: flex;
        align-items: center;
        justify-content: center;
      }
      .img_item {
        height: 100px;
      }
      .img_item img {
        width: auto;
        height: 100%;
      }
      /* 隐藏默认的滑块样式 */
      input[type="range"] {
        -webkit-appearance: none;
        -moz-appearance: none;
        appearance: none;
        width: 100%;
        height: 10px;
        background-color: transparent;
        border-radius: 5px;
      }
      /* 自定义滑块的样式 */
      input[type="range"]::-webkit-slider-thumb {
        -webkit-appearance: none;
        appearance: none;
        width: 20px;
        height: 100px;
        background-color: #fe3355;
        cursor: pointer;
        border: 2px solid #fff;
        box-sizing: border-box;
      }
      .schedule {
        position: absolute;
        left: 0;
        top: 0;
        width: 100%;
        height: 100%;
        display: flex;
        align-items: center;
        justify-content: center;
      }
    </style>
  </head>
  <body>
    <div class="conts">
      <div class="imgs">
        <img id="top_img" src="" alt="" />
      </div>
      <div class="btns">
        <div class="button">
          <span>选择视频</span>
          <input type="file" id="video-file" accept="video/*" />
        </div>
      </div>
      <div class="imgs_list">
        <div class="imgs_list_box"></div>
        <div class="schedule">
          <input id="media" type="range" min="0" max="100" value="0" />
        </div>
      </div>
    </div>
    <script>
      const ranges = document.querySelector("#media");
      let video_file = null;
      document
        .querySelector("#video-file")
        .addEventListener("change", async function () {
          const file = this.files[0];
          video_file = file;
          let reader = new FileReader();
          //获取视频时长
          reader.onload = function (e) {
            let video = document.createElement("video");
            video.src = e.target.result;
            video.addEventListener("loadedmetadata", function () {
              let duration = Math.floor(video.duration); //取整
              ranges.max = duration;
              ranges.value = 0;
              var count = 7; // 总共取出的数的数量
              var step = Math.floor(duration / (count - 1)); // 步长
              var result = []; // 存储结果的数组
              for (var i = 0; i < count; i++) {
                result.push(i * step);
              }

              drawCover(0); //先渲染一下封面

              // 生成7张图片并渲染上去
              document.querySelector(".imgs_list_box").innerHTML = "";
              result.forEach(async (item) => {
                const res = await captureFrame(video_file, item);
                let el = document.createElement("div");
                el.setAttribute("class", "img_item");
                el.innerHTML = ` <img src="${res.url}" />`;
                document.querySelector(".imgs_list_box").appendChild(el);
              });
            });
          };

          reader.readAsDataURL(file);
        });
      //控件移动触发
      const debouncedHandleInput = debounce(moveChang, 200);
      ranges.addEventListener("input", debouncedHandleInput);
      // 滑块选取封面
      function moveChang() {
        drawCover(this.value);
      }
      //渲染顶部封面
      async function drawCover(time) {
        const res = await captureFrame(video_file, time);
        document.querySelector("#top_img").setAttribute("src", res.url);
      }

      // 防抖函数
      function debounce(fun, time) {
        let timer;
        return function (...val) {
          clearTimeout(timer);

          timer = setTimeout(() => {
            fun.apply(this, val);
          }, time);
        };
      }

      // 获取视频帧的封面
      function captureFrame(videoFile, time = 0) {
        return new Promise((succeed) => {
          const video = document.createElement("video");
          video.currentTime = time;
          video.muted = true;
          video.autoplay = true;
          video.oncanplay = async () => {
            const res = await drawVideo(video);
            succeed(res);
          };
          video.src = URL.createObjectURL(videoFile);
        });
      }

      // 画视频
      function drawVideo(video) {
        return new Promise((res) => {
          const cvs = document.createElement("canvas");
          const ctx = cvs.getContext("2d");
          cvs.width = video.videoWidth;
          cvs.height = video.videoHeight;
          ctx.drawImage(video, 0, 0, cvs.width, cvs.height);
          // document.body.appendChild(cvs);
          cvs.toBlob((blob) => {
            res({
              blob,
              url: URL.createObjectURL(blob),
            });
          });
        });
      }
    </script>
  </body>
</html>

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值