vue 双向绑定 音量进度条

// 父组件
<template>
<slider v-model="percent" ref="slider" />
</template>
<script>
import slider from "@/view/test1/slider";
export default {
  data() {
    // 设置百分比
    return {
      percent: 50
    }
  },
  watch: {
    // 获取拖动后的百分比
    percent(newValue, oldValue) {
      console.log(newValue);
    }
  },
  components: {
    slider
  }
};
</script>

 重点就在👇

// 子组件 音量条模块组件
<template>
  <div @mousedown.prevent='drag' style="padding: 20px 0 ;" ref="sliderWrapper">
    <div class="slider_runway">
      <div class="slider_bar" :style='barWidth'></div>
      <div class="slider_button_wrapper" :style='translate'>
       <div :class="['slider_button',{'dragging':isClick}]"></div>
      </div>
    </div>
  </div>
</template>
<script>
export default {
  model: {
    prop: 'value',
    event: 'parent-event'
  },
  props: {
    value: Number
  },
  data() {
    return {
      w: 0,
      translate: "",
      barWidth: "",
      isClick: false
    }
  },
  mounted() {
    // 获取外框的宽度作为基值
    this.w = this.$refs.sliderWrapper.offsetWidth;
    // 通过父组件传来的百分比值设置进度的位置
    this.move(this.value);
  },
  methods: {
    move(value) {
      if (value >= 0 && value < this.w) { // 设置边界防止滑动出轨
        this.$emit('parent-event', value);// 将修改后的百分比值传给父组件
        this.barWidth = `width:${value}%`;
        this.translate = `transform:translateX(${value / 100 * this.w}px)`;
      }
    },
    drag({clientX}) { // 点击后调用 move 和 up 事件
      this.isClick = true;// 点击圆点时候会鼠标会改变
      this.move(clientX / this.w * 100); // 点击轨道我们也要让他移动
      document.onmousemove = e => { // 拖动圆点进行移动
        e.preventDefault();// 取消默认事件 否则会把莫名的东西拽走
        this.move(e.clientX / this.w * 100);
      }
      document.onmouseup = e => { // 必须在抬起鼠标时候清除move 和 up事件,否则会不停的 move下去
        e.preventDefault(); // 虽然不会影响什么,但是还是把它给取消了吧
        this.isClick = false;
        document.onmousemove = null;
        document.onmouseup = null;
      }
    }
  }
};
</script>
<style scoped>
.slider_runway{
  position: relative;
  width: 100%;
  height: 4px;
  background:rgba(230, 230, 230, 0.3);
  cursor: pointer;
}
.slider_bar{
  width:0%;
  height: 4px;
  background:#000000;
}
.slider_button_wrapper{
  position: absolute;
  top: -5px;
  width: 14px;
  height: 14px;
}
.slider_button{
  position: absolute;
  width: 14px;
  height: 14px;
  top:0;
  left: -14px;
  cursor: grab;
  background: #FFFFFF;
  border-radius:50%;
  box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.23);
  transform: scale(1);
  transition:.2s;
}
.dragging{
  cursor: grabbing;
}
.slider_button:hover{
  transform: scale(1.2);
}
</style>

 

<think>嗯,用户问的是如何在uniapp中自定义video组件的进度条来调整播放音量。首先,我得理解用户的需求。他们可能想要在视频播放时,通过拖动某个自定义的进度条来控制音量,而不是使用默认的控制条。这需要结合uniapp的video组件和自定义组件来实现。 首先,我需要确认uniapp的video组件是否支持直接音量控制。查阅文档,发现video组件有volume属性,可以通过动态绑定来调整音量。所以,用户需要的是一个可以滑动调节的控件,比如一个slider,当用户拖动时改变volume的值。 接下来,考虑如何布局。用户可能需要将音量控制条放在视频的某个位置,比如右侧,可能需要绝对定位。在uniapp中,可以使用view组件配合样式来实现绝对定位,然后放置一个slider或者进度条。 然后,处理交互逻辑。当用户拖动slider时,实时调整video的volume属性。这里需要注意的是,uniapp中数据绑定是通过vue的响应式系统,所以需要将slider的值绑定到data中的volume变量,同时监听slider的变化事件,更新volume。 另外,可能需要显示当前音量的图标,比如静音图标和不同音量级别的图标。可以通过条件渲染,根据volume的值显示不同的图标。比如,volume为0时显示静音图标,否则显示普通音量图标。 还要考虑用户体验,比如触摸滑动时的实时反馈,可能需要使用@touchstart、@touchmove等事件来处理滑动操作,而不仅仅是使用slider组件。不过,如果使用原生的slider组件,可能已经处理了这些事件,但自定义样式可能需要自己实现。 测试时需要注意,不同的平台可能有不同的表现,比如iOS和Android对video组件的支持可能不同,需要做兼容性检查。此外,音量范围通常是0到1,所以slider的最小值和最大值需要设置为0和1,步长可以设置为0.1。 最后,可能需要隐藏原生的控制条,使用controls属性设置为false,然后完全自定义所有控制元素,包括播放/暂停按钮、进度条音量控制等。这样用户的自定义进度条才能更好地融入整体UI设计。 总结步骤:隐藏原生控件,添加自定义slider,绑定volume数据,监听输入事件更新音量,同时更新音量图标。可能需要处理触摸事件来实现更灵活的滑动控制,或者使用第三方组件库中的滑动组件来简化开发。</think>在 UniApp 中实现自定义视频播放器音量控制,可通过以下方案实现(使用 Vue 语法示例): ```html <template> <view class="video-container"> <!-- 视频组件 --> <video :src="videoUrl" :volume="volume" controls="{{false}}" id="myVideo" @play="onPlay" ></video> <!-- 自定义音量控制条 --> <view class="volume-control"> <view class="icon" @tap="toggleMute"> <image :src="volume === 0 ? '/static/mute.png' : '/static/volume.png'" style="width: 40rpx; height: 40rpx;" /> </view> <slider :value="volume * 100" min="0" max="100" activeColor="#4CAF50" block-size="20" @changing="handleVolumeChange" /> </view> </view> </template> <script> export default { data() { return { videoUrl: 'http://example.com/sample.mp4', volume: 0.5, // 默认音量(0-1) videoContext: null }; }, mounted() { this.videoContext = uni.createVideoContext('myVideo', this); }, methods: { // 音量滑动条事件 handleVolumeChange(e) { this.volume = e.detail.value / 100; }, // 静音切换 toggleMute() { this.volume = this.volume > 0 ? 0 : 0.5; }, // 播放状态处理 onPlay() { this.videoContext.volume = this.volume; } } }; </script> <style> .video-container { position: relative; width: 100%; } .volume-control { position: absolute; right: 20rpx; bottom: 100rpx; background: rgba(0,0,0,0.7); padding: 20rpx; border-radius: 40rpx; display: flex; align-items: center; width: 300rpx; } .volume-control .icon { margin-right: 20rpx; } </style> ``` **实现原理说明:** 1. **组件绑定** 通过 `video` 组件的 `volume` 属性绑定音量值(范围 0-1),使用 `controls="{{false}}"` 隐藏原生控件 2. **音量控制条** - 使用 `slider` 组件实现滑动条 -音量值映射为 0-100 的百分比(显示时乘以100,设置时除以100) - 通过 `@changing` 事件实时更新音量 3. **静音功能** - 点击图标切换静音状态 - 通过动态切换图标 `src` 显示不同状态 4. **视频上下文** 使用 `uni.createVideoContext` 获取视频实例,确保音量设置生效 **扩展优化建议:** 1. **手势控制增强** ```javascript // 添加触摸事件监听 handleTouchStart(e) { this.touchStartY = e.touches[0].clientY; }, handleTouchMove(e) { const deltaY = this.touchStartY - e.touches[0].clientY; const volumeDelta = deltaY / 200; // 调整灵敏度 this.volume = Math.min(1, Math.max(0, this.volume + volumeDelta)); } ``` 2. **动画效果优化** 添加 CSS 过渡效果: ```css .volume-control { transition: all 0.3s ease; opacity: 0; } .video-container:hover .volume-control { opacity: 1; } ``` 3. **多平台适配** 在 `onReady` 中添加平台检测: ```javascript onReady() { // #ifdef APP-PLUS this.volumeControlType = 'vertical'; // APP端使用垂直滑块 // #endif } ``` **注意事项:** 1. iOS 系统音量限制:部分 iOS 版本可能无法通过程序修改音量,需提示用户使用物理按键 2. 性能优化:频繁更新音量时建议添加节流函数 3. 无障碍访问:为控件添加 `aria-label` 属性 4. 单位换算:注意 rpx 与 px 的转换,确保各端显示一致 可通过 uni-app 的 `uni.getSystemInfo` 获取设备信息,实现更精准的适配方案。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值