原生js转成vue3

这段代码里的原生js怎么转成vue3啊
写了半天全是错
这段代码是想通过鼠标滑轮来控制视频的进度


```html
<!DOCTYPE html>
<html lang="en">
<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="./style.css">
</head>
<body>
    <div class="container">
        <video src="./video.webm"></video>

        <div class="txt-item">
            撒旦飒飒大<span>苏打实打</span> 实大苏打实打实的反对德里克十分激烈对抗放进了口袋精神分裂的
        </div>
        <div class="txt-item">
            <div class="line"></div>
            <div class="txt">
                的时间反抗<span>类毒素解</span>放路口的就是浪费空间独立思考解放立刻搭街坊立刻决定离开房间地方大师傅大幅度随风倒十分
            </div>
        </div>
        <div class="txt-item">
            <div class="line"></div>
            的房间里<span>电视机分</span>厘卡的就是浪费空间领导的洛杉矶发了大家分厘卡九点十六分雕刻技法角度来说
        </div>
        <div class="txt-item">
            肯定就浪费了<span>扩大解释法</span>律框架的绿色开放的链接发来看的房间里的就是浪费的房间里的开发建设
        </div>
    </div>
    <script>
        // 原理,一个视频,根据滚动距离与整个body高度的比值 设置 对应视频的当前播放位置
        const videoEl = document.querySelector('video')

        const txtItems = document.querySelectorAll('.txt-item')

        let duration = 0 // 视频总时长


        videoEl.load() // 刚开始就让视频重新加载一下,有些时候会因为没加载导致下面的事件没触发

        videoEl.addEventListener('durationchange', function(e){
            duration = videoEl.duration
        })


        function showTxt(percent){

            txtItems.forEach(dom => {
                dom.className = 'txt-item'
            })

            // 当时常到百分之几时,对应的文字出现,这个随便调
            if(percent > 5 && percent <= 33){
                txtItems[0].className = 'txt-item active'
            }else if(percent > 45 && percent <= 58){
              }else if(percent > 45 && percent <= 58){
                txtItems[1].className = 'txt-item active'
            }else if(percent > 69 && percent <= 85){
                txtItems[2].className = 'txt-item active'
            }else if(percent > 90){
                txtItems[3].className = 'txt-item active'
            }

        }


        function updateCurrentTime(){

            // 滚动的距离占总高度的多少,那当前时间就是总时长的多少 比如滚动的距离占body的50%那么,当前的时间就应该是总时长的50%
            const percent = Math.ceil(window.scrollY) / (document.body.offsetHeight - window.innerHeight)

            videoEl.currentTime = duration * percent


            showTxt(percent*100)
        }

        document.addEventListener('scroll', updateCurrentTime)

    </script>

</body>
</html>

这是部分是css

```css

<style>
    body {
  width: 100%;
  height: 600vh;
  margin: 0;
  background-color: #000;
}

.container {
  width: 1000px;
  height: 100vh;
  margin: 0 auto;
  position: sticky;
  top: 0;
  color: #fff;
  display: flex;
  flex-direction: column;
}

video {
  width: 400px;
  display: block;
  margin: auto;
}
.txt-item {
  position: absolute;
  width: 280px;
  font-weight: bold;
  color: gray;
  transition: all .8s linear;
  letter-spacing: 1px;
  text-align: center;
  font-size: 13px;
  opacity: 0;
}

.txt-item span {
  color: yellowgreen;
}

.txt-item.active {
  opacity: 1;
}

.txt-item:nth-child(2) {
  top: 80%;
  left: 50%;
  transform: translateX(-50%);
}
.txt-item:nth-child(3) {
  width: 230px;
  padding-top: 15px;
  top: 60%;
  left: 60%;
}

.txt-item:nth-child(3) .txt {
  transition: all .3s linear;
  transform: translateY(50px);
}

.txt-item:nth-child(3) .line {
  border-top: 1px solid gray;
  position: absolute;
  top: 0;
  right: 0;
  width: 0;
  transition: all .5s linear;
}

.txt-item:nth-child(3).active .txt {
  transform: translateY(0);
}
.txt-item:nth-child(3).active .line {
  width: 300px;
}

.txt-item:nth-child(4) {
  top: 75%;
  left: 58%;
}

.txt-item:nth-child(4) .line {
  position: absolute;
  left: -20px;
  border-left: 1px solid gray;
  height: 0;
  bottom: 0;
  transition: all .5s;
}

.txt-item:nth-child(4).active .line {
  height: 130px;
}
.txt-item:nth-child(5) {
  top: 80%;
  left: 50%;
  transform: translateX(-50%);
}
</style>
不知道你这个问题是否已经解决, 如果还没有解决的话:
  • 这有个类似的问题, 你可以参考下: https://ask.csdn.net/questions/7770478
  • 这篇博客也不错, 你可以看下记一次在vue中引入原生js文件
  • 除此之外, 这篇博客: Vue实现弹幕滚动中的 这里主要涉及Vue中通过原生JS来实现弹幕滚动(只是前端) 部分也许能够解决你的问题, 你可以仔细阅读以下内容或者直接跳转源博客中阅读:

    由于自己看直播突发奇想想做个弹幕的效果,在这里采用js来实现相关前端的功能,框架也不是特别重要。话不多说直接开始。
    我的思路是设置一个screen类来存放可能需要引用的视频,而我的弹幕是用相关的div小盒子来进行存放输入的数据的。
    在这里插入图片描述

    <template>
      <div class="barrage" :style="{ height: wrapperHeight + 'px' }">
        <div class="screen" v-show="showBarrage">
          <template v-for="(item, index) in barrArr">
            <div class="barrItem" :key="index" v-show="true">
              {{ item }}
            </div>
          </template>
        </div>
        <div class="btn_screen" @click="showbarr"><div class="btn"></div></div>
        <div class="input_fixed">
          <input type="text" v-model="input_value" />
          <button @click="addBarrArr(input_value)">😊</button>
        </div>
      </div>
    </template>
    

    模板这里很简单就是一个输入框,一个按钮,以及做了一个滑动开关来打开关闭弹幕。关于弹幕数据我是将其放入一个数组中,通过遍历动态的读取相关的数据。
    其实我们弹幕的思路就是

    1. 输入数据,将数据存储到数组中
    2. 动态的遍历数据
    3. 设置存放数据的div位置(这里随机给他一个高度的位置)
    4. 让其从最右边滚动到最左边
     addBarrArr(value) {
          let _this = this;
          _this.$set(_this.barrArr, _this.barrArr.length, value);
          setTimeout(() => {
            let barr = document.getElementsByClassName("barrItem");
            let barritem = barr[barr.length - 1];
            Object.assign(barritem.style, {
              visibility: "hidden",
              right: -barritem.offsetWidth + "px",
              top: this.randomTop() + "px",
              color: this.getRandomColor()
            });
            barritem.style.visibility = "visible";
            this.leftAnimate(barritem);
          }, 10);
          this.input_value = "";
        },
    

    这里我t通过Vm.set将数据加到数组中,并将最新添加的数据盒子加入相关样式。通过absolute定位使其脱流,因为一开始我们需要隐藏其样式,不然可能会出现在页面中闪一下这样的Bug。这里通过randomTop()和getRandomColor()来给随机的top值和字体颜色。由于是从右往左的弹幕滚动,所以我设置right的值,我们一开始需要将其隐藏然后慢慢的进入可视区,因为我们没有单独设置每个数据盒子的宽度,因为这样效果很差,所以采用自适应用内容来撑开盒子,那么就有个问题我们无法通过style来得到盒子的width值,因为他是一直为空,在由于我们需要将其显示在屏幕右侧的外面,那么就需要设给right给一个盒子宽度的负值,这样我们盒子的左侧边距就可以和我们屏幕又侧边线重合。我们可以通过offesetWidth来获取这个盒子的宽度来替代style.width。
    盒子的位置设置好后我们就需要来给他加入动画效果了。在这里setInterval()就可以完成我们想要的效果,可是这需要设置时长,如果时间过长或者过短都会出现不流畅的效果,那么我们就可以在这里采用H5的一个新的API:requireAnimationFrame()。这个API不需要传入时间,会由系统自动分配时间,从而达到相对流畅的效果。

     leftAnimate(value) {
          let rightNum = Number(this.$utils.getNumber(value.style.right, "px"));
          rightNum++;
          if (rightNum < document.documentElement.clientWidth) {
            requestAnimationFrame(() => {
              value.style.right = rightNum + "px";
              this.leftAnimate(value);
            });
          } else {
            // console.log(value.parentNode);
            value.parentNode.removeChild(value);
          }
        },
    

    我们获取当前初始的right值,通过递增来使其值不断变大,显示在屏幕中,然后当其刚好出屏幕时,就结束动画,因为只是前端的展现效果,所以我在结束后会将弹幕删除来简化内容。
    这样我们的主要内容就完成了,其实功能相对还是不难的,希望对大家有帮助,这只是我想到的一个实现,肯定还会有更好的!
    在这里附上产生随机颜色

    getRandomColor() {
          let r = Math.random() * 256;
          let g = Math.random() * 256;
          let b = Math.random() * 256;
          let color = `rgb(${r},${g},${b})`;
          return color;
        },
    

    这里我是用rgb()的颜色格式当然还有很多其他的样式,就不一一介绍了。

  • 您还可以看一下 张颜源老师的2019全新vue2.5项目实战全家桶单页面仿京东电商实战前端js教程课程中的 精讲个人中心实现及注销登录功能小节, 巩固相关知识点
  • 以下回答来自chatgpt:

    由于问题描述不明确,无法给出具体的代码段和出错信息,需要更多细节才能给出准确的建议。关于Vue3的理解程度和原生JS的熟悉程度也需要更多信息才能回答。


如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^

你把body里的放到 template里 style 也拿出来放 style里。 js可以放到 script里 应该也能运行,vue里 用原生js 也可以,只不过不提倡,可能会出现问题。 顶多就是,docunment 的方法换成 ref 获取dom元素。然后 变量可以也用ref 声明响应式数据(有必要的话)

<template>
  <div>
    <video ref="video"></video>
    <div v-for="(item, index) in txtItems" :key="index" :class="{ 'txt-item': true, 'active': activeItem === index }">{{ item }}</div>
  </div>
</template>
<script>
import { ref, onMounted } from 'vue'
export default {
  setup() {
    const videoEl = ref(null)
    const txtItems = ref(['text1', 'text2', 'text3', 'text4'])
    const activeItem = ref(-1)
    let duration = 0
    function showTxt(percent) {
      activeItem.value = -1
      if (percent > 5 && percent <= 33) {
        activeItem.value = 0
      } else if (percent > 45 && percent <= 58) {
        activeItem.value = 1
      } else if (percent > 69 && percent <= 85) {
        activeItem.value = 2
      } else if (percent > 90) {
        activeItem.value = 3
      }
    }
    function updateCurrentTime() {
      const percent = Math.ceil(window.scrollY) / (document.body.offsetHeight - window.innerHeight)
      videoEl.value.currentTime = duration * percent
      showTxt(percent * 100)
    }
    onMounted(() => {
      videoEl.value.load()
      videoEl.value.addEventListener('durationchange', (e) => {
        duration = videoEl.value.duration
      })
      document.addEventListener('scroll', updateCurrentTime)
    })
    return {
      videoEl,
      txtItems,
      activeItem
    }
  }
}
</script>


回答采用文心一言:

<script>  
import { ref, onMounted, onUnmounted } from 'vue';  
  
export default {  
  setup() {  
    const videoEl = ref(null);  
    const txtItems = ref([]);  
    const duration = ref(0);  
  
    const loadVideo = () => {  
      videoEl.value.load();  
      videoEl.value.addEventListener('durationchange', () => {  
        duration.value = videoEl.value.duration;  
      });  
    };  
  
    const showTxt = (percent) => {  
      txtItems.value.forEach((dom) => {  
        dom.className = 'txt-item';  
      });  
  
      // 当时常到百分之几时,对应的文字出现,这个随便调  
      if (percent > 5 && percent <= 33) {  
        txtItems.value[0].className = 'txt-item active';  
      } else if (percent > 45 && percent <= 58) {  
      } else if (percent > 45 && percent <= 58) {  
        txtItems.value[1].className = 'txt-item active';  
      } else if (percent > 69 && percent <= 85) {  
        txtItems.value[2].className = 'txt-item active';  
      } else if (percent > 90) {  
        txtItems.value[3].className = 'txt-item active';  
      }  
    };  
  
    const updateCurrentTime = () => {  
      // 滚动的距离占总高度的多少,那当前时间就是总时长的多少 比如滚动的距离占body的50%那么,当前的时间就应该是总时长的50%  
      const percent = Math.ceil(window.scrollY) / (document.body.offsetHeight - window.innerHeight);  
  
      videoEl.value.currentTime = duration.value * percent;  
  
      showTxt(percent * 100);  
    };  
  
    onMounted(() => {  
      document.addEventListener('scroll', updateCurrentTime);  
      loadVideo();  
    });  
  
    onUnmounted(() => {  
      document.removeEventListener('scroll', updateCurrentTime);  
      videoEl.value.removeEventListener('durationchange', loadVideo);  
    });  
  
    return { videoEl, txtItems, duration };  
  },  
};  
</script>