{"id":13337832,"url":"https://github.com/akFace/uniapp-tiktok","last_synced_at":"2025-03-11T07:31:19.819Z","repository":{"id":176602668,"uuid":"658227839","full_name":"akFace/uniapp-tiktok","owner":"akFace","description":"仿抖音小程序短视频组件-基于uniapp+vue3+typescript","archived":false,"fork":false,"pushed_at":"2024-03-27T07:37:33.000Z","size":45,"stargazers_count":16,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-03-27T08:25:49.151Z","etag":null,"topics":["tiktok","uniapp","vue3"],"latest_commit_sha":null,"homepage":"","language":"Vue","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/akFace.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2023-06-25T06:45:05.000Z","updated_at":"2024-03-09T01:30:01.000Z","dependencies_parsed_at":null,"dependency_job_id":"44b4a6b8-da16-4bd1-9191-c3bd6e3ec0f8","html_url":"https://github.com/akFace/uniapp-tiktok","commit_stats":null,"previous_names":["akface/uniapp-tiktok"],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akFace%2Funiapp-tiktok","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akFace%2Funiapp-tiktok/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akFace%2Funiapp-tiktok/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akFace%2Funiapp-tiktok/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/akFace","download_url":"https://codeload.github.com/akFace/uniapp-tiktok/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":213069719,"owners_count":15532844,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["tiktok","uniapp","vue3"],"created_at":"2024-07-29T19:15:02.994Z","updated_at":"2024-10-23T16:31:34.125Z","avatar_url":"https://github.com/akFace.png","language":"Vue","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 基于 uniapp 开发的仿抖音小程序组件（超高性能）\n\n### GIF 截图效果\n\n\u003cfigure class=\"center\"\u003e\n    \u003cimg src=\"https://github.com/akFace/tool/blob/master/video.gif?raw=true\"\u003e\n\u003c/figure\u003e\n\n- GIF 帧率不够，实际真机效果非常丝滑\n\n### 注：组件使用 vue3+typescript 开发\n\n- 全局仅渲染 3 个 swiper-item\n- 实测，不管加载多少数据也能丝滑滚动\n- 适用于 vue3，vue2 请自行修\n- 自动预加载视频\n- 首次渲染优化\n\n## 快速开始，下载插件后请按照此方法运行调试\n\n1. 安装 nodejs: https://nodejs.org/en/\n2. 安装依赖: `npm i`\n3. 运行项目: `npm run dev:mp-weixin`\n4. 构建项目资源: `npm run build:mp-weixin`\n5. 打开小程序开发工具导入`dist/dev/mp-weixin` 即可\n6. 真机预览，请点小程序开发工具上的预览，扫码真机预览即可\n\n## 参考 API\n\n| 属性                | 类型        | 默认值 | 说明                                                                                                    |\n| ------------------- | ----------- | ------ | ------------------------------------------------------------------------------------------------------- |\n| videoList           | Array       | -      | 视频列表，数组对象 `{src: string, poster?: string, objectFit?: string}`                                 |\n| autoObjectFit       | Boolean     | true   | 是否开启视频自动自适应平铺模式，竖屏全屏覆盖，横屏自适应居中, 此参数优先级低于 videoList 中的 objectFit |\n| loop                | Boolean     | true   | 是否循环播放视频                                                                                        |\n| controls            | Boolean     | false  | 显示原生控制栏                                                                                          |\n| autoplay            | Boolean     | true   | 是否自动播放                                                                                            |\n| autoChange          | Boolean     | false  | 是否自动滚动播放                                                                                        |\n| loadMoreOffsetCount | Number      | 2      | 滚动加载阈值（即播放到剩余多少个之后触发加载更多                                                        |\n| @play               | EventHandle | -      | 当开始/继续播放时触发 play 事件                                                                         |\n| @error              | EventHandle | -      | 视频播放出错时触发                                                                                      |\n| @ended              | EventHandle | -      | 当播放到末尾时触发 ended 事件                                                                           |\n| @loadMore           | EventHandle | -      | 当滚动到最后第 N 条数据后，需要加载更多时触发                                                           |\n| @change             | EventHandle | -      | 切换视频时触发                                                                                          |\n| @click              | EventHandle | -      | 点击整个视频区域触发                                                                                    |\n| @controlstoggle     | EventHandle | -      | 控制栏状态变化触发                                                                                      |\n\n### Slots 插槽\n\n| 属性    | 默认值 | 说明                                                                                    |\n| ------- | ------ | --------------------------------------------------------------------------------------- |\n| default | -      | 自定义内容，覆盖到视频上方的所有自定义内容 v-slot=\"data\" 为当前渲染数据，请参照使用示例 |\n\n### 方法\n\n```javascript\n// 播放第几个视频\nmTikTokRef.value?.initSwiperData(index);\n\n// 播放与暂停\nmTikTokRef.value?.togglePlay();\n\n// 播放跳转到指定位置，单位 s\nmTikTokRef.value?.playSeeked(8);\n```\n\n## 使用示例\n\n```javascript\n\n\u003ctemplate\u003e\n  \u003cdiv class=\"video-container\"\u003e\n    \u003cmTikTok\n      ref=\"mTikTokRef\"\n      :video-list=\"state.videoList\"\n      @loadMore=\"loadMore\"\n      @change=\"change\"\n    \u003e\n      \u003c!-- 此处为用户完全自定义 data 中的数据为当前渲染的数据 --\u003e\n      \u003ctemplate v-slot=\"data\"\u003e\n        \u003c!-- active修复视频悬浮层消失和点击的问题 --\u003e\n        \u003cview\n          class=\"video-side-right\"\n          :class=\"{ active: state.cutVideo.id === data.item.id }\"\n        \u003e\n          \u003cview class=\"action-item action-item-user\"\u003e\n            \u003cimage\n              class=\"shop-logo\"\n              src=\"https://examples-1251000004.cos.ap-shanghai.myqcloud.com/sample.jpeg?imageMogr2/crop/180x180/gravity/center\"\n            /\u003e\n            \u003cview class=\"action-btn\"\u003e\n              \u003ctext class=\"iconfont\"\u003e+\u003c/text\u003e\n            \u003c/view\u003e\n            \u003ctext class=\"action-item-text\"\u003e\u003c/text\u003e\n          \u003c/view\u003e\n          \u003cview class=\"action-item\"\u003e\n            \u003ctext class=\"iconfont icon-star11beifen\"\u003e❤\u003c/text\u003e\n            \u003ctext class=\"action-item-text\"\u003e{{ data.item.id }}\u003c/text\u003e\n          \u003c/view\u003e\n          \u003cview class=\"action-item\"\u003e\n            \u003ctext class=\"iconfont icon-share\"\u003e☝\u003c/text\u003e\n            \u003ctext class=\"action-item-text\"\u003e分享\u003c/text\u003e\n          \u003c/view\u003e\n        \u003c/view\u003e\n        \u003c!-- active修复视频悬浮层消失和点击的问题 --\u003e\n        \u003cview\n          class=\"video-bottom-area\"\n          :class=\"{ active: state.cutVideo.id === data.item.id }\"\n        \u003e\n          \u003cview class=\"shop-name\"\u003e @{{ data.item.name }} \u003c/view\u003e\n          \u003cview class=\"shop-card\"\u003e{{ data.item.desc }}\u003c/view\u003e\n        \u003c/view\u003e\n      \u003c/template\u003e\n    \u003c/mTikTok\u003e\n  \u003c/div\u003e\n\u003c/template\u003e\n\u003cscript lang=\"ts\" setup\u003e\nimport { onMounted, reactive, ref } from \"vue\";\n// 导入组件\nimport mTikTok from \"@/components/mTikTok.vue\";\n\nconst mTikTokRef = ref\u003cInstanceType\u003ctypeof mTikTok\u003e\u003e();\n\nconst state = reactive({\n  cutVideo: {} as AnyObject,\n  videoList: [\n    {\n      src: \"https://xjc.demo.hongcd.com/uploads/20230214/84e165388f5bfdb1550522f50f5a57bb.mp4\",\n      id: \"1\",\n      name: \"开玩笑的鸡毛\",\n      desc: \"这里是简介内容\",\n    },\n    {\n      src: \"https://xjc.demo.hongcd.com/uploads/20230214/3f26d950ac286eecedba49f5295f0819.mp4\",\n      id: \"2\",\n      name: \"开玩笑的鸡毛\",\n      desc: \"这里是简介内容\",\n    },\n    {\n      src: \"https://xjc.demo.hongcd.com/uploads/20230215/8b5ac0420fe61e2f9660d7b8af998f7b.mp4\",\n      id: \"3\",\n      name: \"开玩笑的鸡毛\",\n      desc: \"这里是简介内容\",\n    },\n    {\n      src: \"https://xjc.demo.hongcd.com/uploads/20210128/d932b2d78cebb0a8cb8f9a6216790dfb.mp4\",\n      id: \"4\",\n      name: \"开玩笑的鸡毛\",\n      desc: \"这里是简介内容\",\n    },\n    {\n      src: \"https://xjc.demo.hongcd.com/uploads/20210128/0c64cbeea28b10c06eee8728c762449e.mp4\",\n      id: \"5\",\n      name: \"开玩笑的鸡毛\",\n      desc: \"这里是简介内容\",\n    },\n    {\n      src: \"https://xjc.demo.hongcd.com/uploads/20210327/1b72e1b6153cd29df07f5449991e8083.mp4\",\n      id: \"6\",\n      name: \"开玩笑的鸡毛\",\n      desc: \"这里是简介内容\",\n    },\n    {\n      src: \"https://xjc.demo.hongcd.com/uploads/20230214/7e1a0baaebc4e656bbbfbc44d7a55a60.mp4\",\n      id: \"7\",\n      name: \"开玩笑的鸡毛\",\n      desc: \"这里是简介内容\",\n    },\n  ],\n});\n\nconst loadMore = () =\u003e {\n  // 触发加载更多\n  console.log(\"加载更多\");\n};\n\nconst change = (e: any) =\u003e {\n  state.cutVideo = e.detail;\n  console.log(\"🚀 ~ file: index.vue:53 ~ change ~ data:\", e);\n};\n\n// 播放第几个\nconst playIndex = (index: number) =\u003e {\n  mTikTokRef.value?.initSwiperData(index);\n};\n\nonMounted(() =\u003e {\n  // 直接播放第3个\n  // playIndex(3);\n});\n\u003c/script\u003e\n\u003cstyle lang=\"scss\"\u003e\n$zIndex: 99;\n\n.video-layer {\n  position: absolute;\n  right: 12px;\n  bottom: 120px;\n  color: #fff;\n}\n\n.video-bottom-area {\n  position: absolute;\n  left: 20px;\n  bottom: 40px;\n  opacity: 0;\n  transition: all 250ms;\n  z-index: 0;\n\n  \u0026.active {\n    opacity: 1;\n    z-index: $zIndex;\n    transition-delay: 200ms;\n  }\n\n  .shop-name {\n    color: #fff;\n    margin-bottom: 6px;\n  }\n\n  .shop-card {\n    width: 160px;\n    height: 80px;\n    background-color: rgba(255, 255, 255, 0.5);\n    border-radius: 4px;\n  }\n}\n\n.video-side-right {\n  position: absolute;\n  right: 12px;\n  bottom: 120px;\n  color: #fff;\n  opacity: 0;\n  transition: all 250ms;\n  z-index: 0;\n\n  \u0026.active {\n    opacity: 1;\n    z-index: $zIndex;\n    transition-delay: 200ms;\n  }\n\n  .action-item {\n    position: relative;\n    margin-bottom: 20px;\n    text-align: center;\n\n    .shop-logo {\n      width: 40px;\n      height: 40px;\n      border-radius: 50%;\n      overflow: hidden;\n    }\n\n    .iconfont {\n      display: block;\n      font-size: 28px;\n    }\n\n    .action-item-text {\n      display: block;\n      font-size: 12px;\n    }\n\n    .action-btn {\n      position: absolute;\n      left: 50%;\n      transform: translateX(-50%);\n      bottom: -8px;\n      width: 20px;\n      height: 20px;\n      border-radius: 50%;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      background-color: #f60;\n\n      .iconfont {\n        font-size: 16px;\n      }\n    }\n  }\n\n  .action-item-user {\n    margin-bottom: 40px;\n  }\n}\n\u003c/style\u003e\n\n\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FakFace%2Funiapp-tiktok","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FakFace%2Funiapp-tiktok","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FakFace%2Funiapp-tiktok/lists"}