H5、Vue3、UniApp实现抖音短视频功能

H5、Vue3、UniApp实现抖音短视频功能

ml-swiper

https://ext.dcloud.net.cn/plugin?id=18973

可 0 配置,高性能、低代码、全端兼容

APP端效果图

在这里插入图片描述

微信小程序端效果图

在这里插入图片描述

Vue网页端效果图

ml-swiper

可 0 配置,高性能、低代码、全端兼容

APP端效果图

APP开发时,请仔细阅读本文档的 APP开发说明

在这里插入图片描述

微信小程序端效果图

微信小程序开发时 直接在 vue页面中 引入该插件,不需要配置 复制下方 示例代码 即可运行

在这里插入图片描述

Vue网页端效果图

网页端开发时 直接在 vue页面中 引入该插件,不需要配置 复制下方 示例代码 即可运行

在这里插入图片描述

ml-swiper介绍

  1. 仿抖音短视频(超高性能)H5、APP、小程序全端支持。
  2. 可简单 0 配置,仿抖音短视频,丝滑切换视频效果 ,无限数据加载不卡顿。
  3. 插件下载即用,下方 示例 代码可直接复制运行。
  4. 使用组件需要关闭下拉刷新事件,page.json -> “enablePullDownRefresh”: false

使用说明

  1. APP端需要配置manifest.json -> App模块配置 -> 勾选VideoPlay(视频播放)。
  2. 运行到微信小程序videoSrc要为http/https开头。

安装方式

本组件符合easycom规范,HBuilderX 2.5.5起,只需将本组件导入项目,在页面template中即可直接使用,无需在页面中import和注册components

APP端特别说明

APP 端特别说明

APP 端特别说明

APP 端特别说明

在这里插入图片描述

代码演示

以下代码 可自行参考改动,APP、H5、小程序 均可直接复制 粘贴运行,APP端请使用 ·nvue· 以下代码无需特殊改动便可运行

**注意:该组件 依赖于 ml-player播放器组件,请自行下载 ** ml-player 播放器

<template>
  <ml-swiper 
    :videoList="realList" 
    :width="width"
    :height="height"
    @loadMore="loadMore" 
    @change="onchange" 
    @play="play" 
    @pause="pause" 
    @ended="ended"
    @error="error" 
    @waiting="waiting" 
    @videoClick="videoClick" 
    @doubleClick="doubleClick" 
    @maskClick="maskClick">
    <!-- 使用 right 插槽,定义右侧 用户头像、喜欢、收藏、设置等 -->
    <template v-slot:right="{ video, index }">
      <view class="uniui-right">
        <!-- 用户头像 -->
        <image v-if="video" class="userAvatar" :src="video?.poster"></image>
        
        <!-- 喜欢数量 -->
        <uni-icons type="heart-filled" :color="index % 2 == 0 ? '#ff0000' : '#fff'" size="25">
        </uni-icons>
        <text class="iconTitle">{{ Math.ceil(Math.random() * 9999) }}</text>
        
        <!-- 收藏数量 -->
        <uni-icons type="star-filled" :color="index % 2 != 0 ?'#ffaa00':'#fff'" size="25">
        </uni-icons>
        <text class="iconTitle">{{ Math.ceil(Math.random() * 9999) }}</text>

        <!-- 视频设置 -->
        <uni-icons type="gear-filled" size="25" color="#fff"></uni-icons>
        <text class="iconTitle">设置</text>
      </view>
    </template>
    <!-- 使用 bottom 插槽,定义底部 视频标题等 -->
    <template v-slot:bottom="{ video, index }">
      <!-- 视频标题 -->
      <text class="videoTitle" v-if="video">
        {{ video?.title }}
      </text>
    </template>
  </ml-swiper>
</template>

<script setup >
  import { ref } from 'vue';
  import { onLoad } from '@dcloudio/uni-app';

  const win = uni.getSystemInfoSync();
  const width = win.windowWidth; // 视频组件宽度,可传可不传
  const height = win.windowHeight;  // 视频组件高度,可传可不传
  const realList = ref([]); // 【必须传入,{url:"必填",title:"非必填,建议传入",poster:"预览图,非必填,建议传入",...:"可传入其他自定义参数,插槽中可以拿到"}】
  const current = ref(0); // 当前播放的视频的索引
  let context = null; // 视频上下文对象,用于操作视频组件(暂停、播放、倍速、静音、弹幕等)
  const counter = ref(0);

  // 视频滑动事件,根据需要,可写可不写,非必须
  const onchange = (index) => {
    console.log("onchange-当前索引:", index);
    current.value = index;
  };
  
  // 是否加载更多,根据需要,可写可不写,非必须
  const loadMore = (index, size) => {
    console.log("加载更所视频:", index + " / " + size);
    // 请求 5 次 后不在请求 
    if (counter.value > 5) return;
    // 模拟从后台请求数据,并将请求到的数据追加到列表中
    getList().forEach((item) => {
      item.title = realList.value.length + "," + item.title + item.title + item.title;
      realList.value.push(item);
    });
    counter.value = counter.value + 1;
  };
  
  // 视频开始播放,根据需要,可写可不写,非必须
  const play = (context) => {
    context = context;
    console.log("视频开始播放");
    uni.showToast({ title: "视频开始播放", icon: "none", mask: false });
  };

  // 视频暂停播放,根据需要,可写可不写,非必须
  const pause = (context) => {
    context = context;
    console.log("视频暂停播放");
    uni.showToast({ title: "视频暂停播放", icon: "none", mask: false });
  };
    
  // 视频播放结束,根据需要,可写可不写,非必须
  const ended = (context) => {
    context = context;
    console.log("视频播放结束");
    uni.showToast({ title: "视频播放结束", icon: "none", mask: false });
  };
  
  // 视频播放出错,根据需要,可写可不写,非必须
  const error = (context, event) => {
    context = context;
    console.error("视频播放出错:", event);
    uni.showToast({ title: "视频播放出错", icon: "none", mask: false });
  };
  
  // 视频出现缓冲,根据需要,可写可不写,非必须
  const waiting = (context) => {
    context = context;
    console.error("视频出现缓冲");
    uni.showToast({ title: "视频出现缓冲", icon: "none", mask: false });
  };
  
  // 视频点击事件,根据需要,可写可不写,非必须
  const videoClick = (context, video) => {
    context = context;
    console.log("点击了视频:", video);
    uni.showToast({ title: "点击了视频", icon: "none", mask: false });
  };
  
  // 视频双击事件,根据需要,可写可不写,非必须
  const doubleClick = (context, video) => {
    context = context;
    console.log("双击了视频:", video);
    uni.showToast({ title: "双击了视频", icon: "none", mask: false });
  };
  
  // 蒙层点击事件,根据需要,可写可不写,非必须
  const maskClick = (index, video) => {
    context = context;
    console.log("点击了蒙层:", index, video);
    uni.showToast({ title: "点击了蒙层", icon: "none", mask: false });
  };

  /**
   * 短视频列表
   */
  const getList = () => {
    return [{
      videoId: realList.value.length + 1,
      title: "抖音美女主播,JK超短裙学生妆美女跳舞展示,爱了爱了。",
      poster: "https://i02piccdn.sogoucdn.com/2acf176d90718d73",
      url: "https://txmov2.a.yximgs.com/upic/2020/11/08/19/BMjAyMDExMDgxOTQxNTlfNTIzNDczMzQ0XzM4OTQ1MDk5MTI4XzFfMw==_b_Bc770a92f0cf153407d60a2eddffeae2a.mp4",
      uploadTime: "2023-11-08 19:41",
      ipLocation: "上海",
      author: {
        authorId: 101,
        avatar: "https://i02piccdn.sogoucdn.com/2acf176d90718d73",
        nickName: "陌路",
        genderName: "男"
      }
    },
    {
      videoId: realList.value.length + 2,
      title: "御姐美女抖音作品,来个自拍视频把,好美啊。",
      poster: "https://i02piccdn.sogoucdn.com/2acf176d90718d73",
      url: "https://txmov2.a.yximgs.com/upic/2020/10/02/09/BMjAyMDEwMDIwOTAwMDlfMTIyMjc0NTk0Ml8zNjk3Mjg0NjcxOF8xXzM=_b_B28a4518e86e2cf6155a6c1fc9cf79c6d.mp4",
      uploadTime: "2023-10-02 09:41",
      ipLocation: "贵州",
      author: {
        authorId: 102,
        avatar: "https://i02piccdn.sogoucdn.com/2acf176d90718d73",
        nickName: "御姐呀",
        genderName: "女"
      }
    },
    {
      videoId: realList.value.length + 3,
      title: "抖音主播可爱妹子新学的舞蹈,超可爱的美女主播。",
      poster: "https://i02piccdn.sogoucdn.com/2acf176d90718d73",
      url: "https://txmov6.a.yximgs.com/upic/2020/08/23/00/BMjAyMDA4MjMwMDMyNDRfMTYzMzY5MDA0XzM0ODI4MDcyMzQ5XzFfMw==_b_B9a1c9d4e3a090bb2815994d7f33a906a.mp4",
      uploadTime: "2023-08-23 00:41",
      ipLocation: "广州",
      author: {
        authorId: 103,
        avatar: "https://i02piccdn.sogoucdn.com/2acf176d90718d73",
        nickName: "野花猫",
        genderName: "女"
      }
    },
    {
      videoId: realList.value.length + 4,
      title: "多个美女带着遮阳帽出去散步自拍视频,好好看。",
      poster: "https://i02piccdn.sogoucdn.com/2acf176d90718d73",
      url: "https://alimov2.a.yximgs.com/upic/2020/07/02/14/BMjAyMDA3MDIxNDUyMDlfOTExMjIyMjRfMzE1OTEwNjAxNTRfMV8z_b_Bf3005d42ce9c01c0687147428c28d7e6.mp4",
      uploadTime: "2023-07-02 14:41",
      ipLocation: "山西",
      author: {
        authorId: 104,
        avatar: "https://i02piccdn.sogoucdn.com/2acf176d90718d73",
        nickName: "蓝姬",
        genderName: "女"
      }
    }
    ];
  }

  onLoad(() => {
    // 组件加载时,模拟请求后台获取到数据,并向列表中追加数据
    getList().forEach((item) => {
      item.title = realList.value.length + "," + item.title + item.title + item.title;
      realList.value.push(item);
    });
  });
</script>

<style scoped lang="scss">
  .uniui-right {
    /* #ifndef APP-NVUE */
    display: grid;
    text-align: center;
    margin: 0 auto;
    /* #endif */
    justify-content: center;
  }

  .videoTitle {
    padding: 5px;
    color: #fff;
    font-size: 13px;
    lines: 3;
    white-space: normal;
  }

  .userAvatar {
    width: 35px;
    height: 35px;
    border-radius: 100px;
    margin-bottom: 10px;
    border: 1rpx solid #fff;
    background-color: #fafafa;
  }

  .iconTitle {
    font-size: 12px;
    color: #fff;
    text-align: center;
    padding-bottom: 5px;
  }
</style>

props

属性名类型默认值可选值说明必填
widthNumber--播放器宽度,默认设备同宽
heightNumber--播放器高度,默认设备同高
rightStyleObject, String--自定义右侧样式(用户头像、点赞、收藏…)
bottomStyleObject, String--自定义底部样式(视频标题、用户昵称…)
videoListArray--视频资源列表,option 详情见下文
countNumber2-临界值,当视频剩余 多少时 触发加载更多函数(loadMore
showPlayBooleantruefalse应用从后台显示时 是否播放视频,同 uniapp onShow
hidePauseBooleantruefalse应用从前台隐藏时 是否暂停视频,同 uniapp onHide

videoList详情配置

属性名类型默认值可选值说明必填
urlString--视频资源的url链接地址
titleString--视频资源的标题
posterString--视频资源的预览图
------
– 其他可根据需要自行定义 –-----
likes喜欢数、star收藏数…Any--可自行添加其他属性,插槽中可使用-
userinfoObject{}-自定义userinfo属性,插槽中可使用-
commentArray[]-自定义comment评论列表数据,插槽中可使用-

事件 Events

事件名返回参数说明
@changeindex:当前索引视频滑动事件,返回当前视频的索引
@playcontext:视频上下文对象,可以操作 video 组件视频开始播放,返回 context 视频上下文对象
@pausecontext:视频上下文对象,可以操作 video 组件视频暂停播放,返回 context 视频上下文对象
@endedcontext:视频上下文对象,可以操作 video 组件视频播放结束,返回 context 视频上下文对象
@errorcontext:视频上下文对象,event:错误信息视频播放出错,返回 context ,event:错误信息
@waitingcontext:视频上下文对象,可以操作 video 组件视频出现缓冲,返回 context 视频上下文对象
@videoClickcontext:视频上下文对象,video:视频数据视频点击事件,返回 context,video:视频数据
@doubleClickcontext:视频上下文对象,video:视频数据视频双击事件,返回 context,video:视频数据
@maskClickindex:当前视频的索引,video:视频数据蒙层点击事件,返回 index,video:视频数据
@loadMoreindex,当前视频的索引,size:视频列表的长度加载更多数据,返回 index,size:视频列表的长度

注意事项

  • APP需要按照文档进行配置。
  • APP端,需要使用.nvue文件。
  • APP端需要配置manifest.json -> App模块配置 -> 勾选VideoPlay(视频播放)。
  • 使用组件需要关闭下拉刷新事件,page.json -> "enablePullDownRefresh": false

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

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

相关文章

mybatis-plus 实体中空字段更新不上

FieldStrategy 是一个枚举类型&#xff0c;它定义了字段的几种策略&#xff1a; IGNORED&#xff1a;忽略判断&#xff0c;所有字段都进行更新操作 NOT_NULL&#xff1a;非 NULL 判断&#xff08;默认策略&#xff09;&#xff0c;字段非 NULL 才进行更新 NOT_EMPTY&#xff…

【ai】tx2 nx: trition client安装nvidia-pyindex 一直失败

系统版本的pip和python虚拟环境的pipyolov4-triton-tensorrt的master分支 官方client jetson:pip3 install --user nvidia-pyindex 不成功啊 这个是让nvidia-pyindex 拉取nvidia@tx2-nx:~$ pip3 install --user nvidia-pyindex Collecting nvidia-pyindexDownloading https://…

聚星文社ai工具下载

您可以在聚星文社官方网站上下载他们的AI工具。请访问他们的官方网站&#xff0c; 然后找到下载页面&#xff0c;从中选择并下载所需的AI工具。下载 如果您对下载过程有任何问题&#xff0c;建议您直接联系聚星文社的客服人员寻求帮助。

小程序的基本使用

【 0 】前言 【 0 】 这个就是js代码的存放地方 app.json // pages/banner/banner.js Page({/*** 页面的初始数据*/data: {},/*** 生命周期函数--监听页面加载*/onLoad(options) {},/*** 生命周期函数--监听页面初次渲染完成*/onReady() {},/*** 生命周期函数--监听页面显示…

等差数列和等比数列的介绍及在Java编程中的实现

等差数列 (Arithmetic Sequence) 定义&#xff1a;等差数列是指相邻两项的差相等的数列&#xff0c;这个差值叫做“公差” d。 公式&#xff1a; 第 n 项的公式&#xff1a; 前 n 项和的公式&#xff1a; 示例&#xff1a; 假设第一项 ( a1 ) 为 2&#xff0c;公差 ( d …

浮点数原理与`BigDecimal`实践应用

浮点数原理与BigDecimal实践应用 问题引入&#xff1a; 浮点数 浮点数如何表示数字&#xff1f; 浮点数采用科学计数法表示一个数字&#xff0c;具体格式为&#xff1a; V ( − 1 ) S ∗ M ∗ R E V (-1)^S * M * R^E V(−1)S∗M∗RE S&#xff1a;符号位&#xff0c;取…

第一百二十六节 Java面向对象设计 - Java枚举类

Java面向对象设计 - Java枚举类 枚举类型的超类 编译枚举类型时&#xff0c;编译器会创建一个类。 枚举类型可以具有构造函数&#xff0c;字段和方法。枚举类型仅在编译器生成的代码中实例化。 每个枚举类型都隐式地扩展java.lang.Enum类。 Enum类中定义的所有方法都可以与…

网络爬虫中Xpath的使用方法

正则表达式虽然可以处理包含了诸如 HTML 或 XML 内容的字符串&#xff0c;但只能根据文本的 特征匹配字符串&#xff0c;而忽略字符串所包含的内容的真实格式。为了解决这个问题&#xff0c;Python 引入 XPath 以及支持 XPath 的第三方库 lxml&#xff0c;专门对 XML 或 HTML 格…

基于python的随机森林多分类模型

1.随机森林多分类模型 1.1 基本原理 随机森林&#xff08;Random Forest&#xff09;是一种基于决策树的集成学习方法&#xff0c;它通过将多个决策树进行组合&#xff0c;以投票或平均的方式得到最终的预测结果。在多分类问题中&#xff0c;随机森林通过构建多个决策树&#…

Gartner发布开发敏捷网络安全计划指南:安全计划是一个在快速变化的环境中运作的复杂生态系统

随着企业数字化程度的提高&#xff0c;它们面临的网络安全风险和威胁只会增加。这项研究有助于高管领导了解敏捷网络安全计划的重要性&#xff0c;以及如何与安全和风险利益相关者合作&#xff0c;为下一次重大破坏做好准备。 主要发现 新冠肺炎疫情、地区冲突、全球政治紧张局…

cropperjs 裁剪/框选图片

1.效果 2.使用组件 <!-- 父级 --><Cropper ref"cropperRef" :imgUrl"url" searchImg"searchImg"></Cropper>3.封装组件 <template><el-dialog :title"title" :visible.sync"dialogVisible" wi…

游戏服务器研究二:大世界的 scale 问题

这是一个非常陈旧的话题了&#xff0c;没什么新鲜的&#xff0c;但本人对 scale 比较感兴趣&#xff0c;所以研究得比较多。 本文不会探讨 MMO 类的网游提升单服承载人数有没有意义&#xff0c;只单纯讨论技术上如何实现。 像 moba、fps、棋牌、体育竞技等 “开房间类型的游戏…

前端:HTML、CSS、JavaScript 代码注释 / 注释与代码规范

一、HTML 行内注释 HTML注释是在HTML代码中添加说明和解释的一种方法&#xff0c;这些注释不会被浏览器渲染或显示在页面上&#xff0c;而是被浏览器忽略。HTML注释对于代码的可读性、可维护性和团队协作非常重要。 1.1、HTML注释的语法 HTML注释的语法是以<!--开始&…

中小学劳技课程开展创意木工 传承非遗木工魅力

学生劳技课程&#xff0c;全称劳动技术课程&#xff0c;是一门旨在通过实践活动培养学生的劳动技能、创新思维、实践能力和社会责任感的基础教育课程。这门课程强调学生的参与和体验&#xff0c;让学生在动手实践中学习并掌握知识&#xff0c;提高解决问题的能力。 学生劳技课程…

大模型应用研发基础环境配置(Miniconda、Python、Jupyter Lab、Ollama等)

老牛同学之前使用的MacBook Pro电脑配置有点旧&#xff08;2015 年生产&#xff09;&#xff0c;跑大模型感觉有点吃力&#xff0c;操作起来有点卡顿&#xff0c;因此不得已捡起了尘封了快两年的MateBook Pro电脑&#xff08;老牛同学其实不太喜欢用 Windows 电脑做研发工作&am…

解码数智升级良方:中国一拖、中原传媒、神火股份等企业数字化实践分析

大模型、AI等技术的成熟以及政策法规的细化&#xff0c;数据资源的权属论证、合规确权、资产论证等环节逐渐走向实用性、价值化。 而伴随着“业财税数融”综合性数字化成为企业数字化转型的主流选择&#xff0c;财务部门的纽带属性被放大&#xff0c;财务数据的融合能力成为企业…

ABC234G Divide a Sequence 题解

题目来源 ABC234G 洛谷 Description 给定长度为 n n n 的序列 { a n } \{a_n\} {an​}。定义一种将 { a n } \{a_n\} {an​} 划分为若干段的方案的价值为每段的最大值减去最小值的差的乘积。求所有划分方案的价值的总和并对 998244353 998244353 998244353 取模。 1 ≤…

Vue3 使用 Vue Router 时,params 传参失效

前言&#xff1a; 在写项目的时候&#xff0c;使用了 vue-router 的 params 进行传参&#xff0c;但是在详情页面中一直获取不到参数。原因&#xff1a;Vue Router 在2022-8-22的那次更新后&#xff0c;使用这种方式在新页面上无法获取&#xff01; 正文&#xff1a; 在列表页进…

从零开始做题:老照片中的密码

老照片中的密码 1.题目 1.1 给出图片如下 1.2 给出如下提示 这张老照片中的人使用的是莫尔斯电报机&#xff0c;莫尔斯电报机分为莫尔斯人工电报机和莫尔斯自动电报机&#xff08;简称莫尔斯快机&#xff09;。莫尔斯人工电报机是一种最简单的电报机&#xff0c;由三个部分组…

【笔记】从零开始做一个精灵龙女-拆uv阶段

目录 先回顾一下拆uv的基础流程吧 肩部盔甲分UV示例 手环UV部分 腰带UV部分 其它也差不多&#xff0c;需要删掉一半的就先提前删掉一半&#xff0c;然后把不需要的被遮挡的面也删掉 龙角UV 胸甲UV 侧边碎发UV 马尾UV 脸部/耳朵UV 特殊情况&#xff1a;如果要删一半再…