今天我们来学习一些知识点,拓宽视野,从而将来高屋建瓴
五个知识点
阅读完本文,读者可以学习到以下知识点:
- Vue3中xgplayer视频播放
- driver.js做操作导航
- html2canvas做截图
- 仿写vue的{{}}语法
- 仿写vue中:style的用法
Vue3中xgplayer视频播放
什么是xgplayer?
- xgplayer是字节的西瓜团队出品的一款比较好用的音视频解决方案
- 背靠大厂,前途无限,放心靠谱
- 字节具体应用的地方有:西瓜视频和抖音视频(不会烂尾)
- 而且github上xgplayer的star快8K了(毕竟还很年轻)
- 要知道,老牌的video.js这么多年也才37.4K的star
- 大家审查DOM可以看到对应结构层级
配置封装xgplayer
这里是在Vue3中,去举这个例子,主要是学习xgplayer的配置项语法规则
首先来一个DOM元素,作为xgplayer的占位的地方
<template>
<div id="xgPlayerWrap"></div>
</template>
然后把xgplayer下载一下,在引入到对应.vue文件中使用,指定配置项,就能够出来对应效果了
下载npm i xgplayer --save
这里是单独封装一个MyVideo
组件,便于复用
<template>
<div id="xgPlayerWrap"></div>
</template>
<script setup>
import { ref, onMounted, reactive, computed } from 'vue';
import Player, { Events } from 'xgplayer'; // 引入西瓜视频模块
import 'xgplayer/dist/index.min.css'; // 引入西瓜视频样式
import { conf } from "./conf"; // 配置文件单独拎出来一个js文件
defineOptions({ name: 'MyVideo' })
onMounted(() => { init() })
let player = null // 实例
console.log('Events', Events);
const init = () => {
player = new Player({
...conf
});
player.on(Events.PLAY, (ev) => {
console.log('-播放开始-', ev);
})
player.on(Events.PAUSE, (ev) => {
console.log('-播放结束-', ev);
})
player.on('loadedmetadata', (ev) => {
console.log('-媒体数据加载好了-', ev);
})
player.on(Events.SEEKED, (ev) => {
console.log('-跳着播放-', ev);
})
// 等各种监听事件
}
</script>
<style scoped>
#xgPlayerWrap { flex: auto; }
#xgPlayerWrap video { width: 100%; }
</style>
注意,这里的配置项挺多的,笔者取出来一部分常用的,大家可以复制粘贴直接用,或者再改一下。
以下是单独拎出来的配置项的js文件
./conf.js文件
export const conf = {
/**
* 基础功能配置
* */
id: 'xgPlayerWrap', // 占位dom元素
width: 600, height: 400, // 视频宽高尺寸
url: 'https://sf1-cdn-tos.huoshanstatic.com/obj/media-fe/xgplayer_doc_video/mp4/xgplayer-demo-360p.mp4', // 视频源
poster: "http://ashuai.work/static/img/avantar.png", // 视频封面
autoplay: false, // 是否自动播放,不自动播放,浏览器有限制规则
autoplayMuted: false, // 是否自动播放(静音播放)
videoInit: true, // 是否默认初始化video,默认初始化,默认true
playsinline: true, // 是否启用内联播放模式,仅移动端生效
defaultPlaybackRate: 1, // 默认播放速度(可选:0.5/0.75/1/1.5/2等)
volume: 0.72, // 播放音量(可选:0 ~ 1)
loop: false, // 是否循环播放,默认不循环播放
startTime: 0, // 点播模式下,初始起播时间
videoAttributes: {}, // video扩展属性,暂且不配置
lang: 'zh-cn', // 播放器初始显示语言,设置为中文
fluid: true, // 是否流式布局(宽高优先于流失布局,默认16:9)注掉上方宽高看效果
fitVideoSize: 'fixed', // 保持容器宽/高,不做适配,按照容器来
videoFillMode: 'auto', // 宽高不够自动底色填充(fill拉伸填充等...)
seekedStatus: 'play', // 跳转后继续播放
// 播放器进度条故事点信息数组
progressDot: [
{
id: 0, // 唯一标识,用于删除的时候索引
time: 30, // 展示的时间点,例子为在播放到10s钟的时候展示
text: '进度条信息提示...', // hover的时候展示文案,可以为空
duration: 5, // 展示时间跨度,单位为s
style: { // 指定样式
backgroundColor: 'pink'
}
},
],
thumbnail: null, // 进度条预览图配置,普通业务用不到
marginControls: false, // 是否开启画面和控制栏分离模式,不开启空间多一些
domEventType: 'default', // 响应的事件类型,不用指定,用默认的即可
/**
* 交互功能配置(一般使用默认即可)
* */
/**
* 插件配置,根据需求自选
* */
icons: {}, // 使用默认的icon图标
i18n: [], // 使用默认的中文
// 自定义一些颜色
commonStyle: {
progressColor: 'green', // 整个进度条颜色
playedColor: 'chocolate', // 已播放的进度条颜色
volumeColor: 'pink', // 音量大小竖向滑块颜色
},
controls: true, // 是否使用底部控制栏,默认使用
miniprogress: true, // 是否使用mini进度条(当底部控制栏隐藏时生效)
screenShot: false, // 关闭截图功能
rotate: true, // 是否使用视频旋转插件,默认不使用
download: true, // 是否使用下载按钮,一般不用,一般自定义控制
pip: true, // 使用使用画中画模式,默认不用
mini: true, // 是否使用小屏幕控件
cssFullscreen: true, // 是否使用网页样式全屏按钮开关
playbackRate: [0.5, 1, 1.5, 2, 3], //传入倍速可选数组
playbackRate: true, //false,禁用倍速播放(即控制栏不显示)
keyShortcut: false, // 是否开启快捷键模式
}
因为MyVideo已经简单封装好了,那么直接使用即可。
使用封装的xgplayer
<template>
<div class="out">
<MyVideo />
</div>
</template>
<script setup>
import MyVideo from "../../components/MyVideo/MyVideo.vue";
</script>
<style>
.out { width: 600px; }
</style>
效果图
完整代码
完整代码,请移步笔者的github:https://github.com/shuirongshuifu/vue3-echarts5-example
西瓜播放器官网:https://v2.h5player.bytedance.com/
xgplayer中的xg就是xigua西瓜的首字母拼音缩写...
driver.js做操作导航
什么是driver.js?
- 任何技术的诞生,都有对应的应用场景
- 比如一个新手刚注册某个平台
- 那么,我们除了给到用户帮助文档让他自己看之外
- 还可以,来点交互操作动画让用户快速更好的理解系统平台的功能
大家看一下效果图即明了:
效果图
demo代码
- 前人在开发中,想到会有这个需求,因此,driver.js应运而生
- driver.js官网:https://driver.employleague.cn/guide/
先引入CDN
<script src="https://cdn.jsdelivr.net/npm/driver.js@1.0.1/dist/driver.js.iife.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/driver.js@1.0.1/dist/driver.css" />
引入CDN后,模块会被挂在windows上
直接就能使用window.driver.js.driver
实例了
然后再加上配置项:
// 引入的cdn的driver.js挂在windows上,可直接用
const driver = window.driver.js.driver;
// 实例化对象,传相应参数
const driverObj = driver({
showProgress: true,
steps: [
{ element: '.one', popover: { title: '第一步', description: '阅读001' } },
{ element: '.two', popover: { title: '第二步', description: '阅读002' } },
{ element: '.three', popover: { title: '第三步', description: '阅读003' } },
{ element: '.four', popover: { title: '第四步', description: '阅读004' } },
]
});
最后,在合适的时机驱动,比如点击按钮驱动driver.js开始做导航功能
document.getElementById('startTour').addEventListener('click', function () {
driverObj.drive();
});
完整代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Driver.js Demo</title>
<!-- CDN -->
<script src="https://cdn.jsdelivr.net/npm/driver.js@1.0.1/dist/driver.js.iife.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/driver.js@1.0.1/dist/driver.css" />
<style>
li {
margin-bottom: 16px;
}
</style>
</head>
<body>
<ul>
<li class="one">白日依山尽</li>
<li class="two">黄河入海流</li>
<li class="three">欲穷千里目</li>
<li class="four">更上一层楼</li>
</ul>
<button id="startTour">点击开始指引</button>
<script>
// 引入的cdn的driver.js挂在windows上,可直接用
const driver = window.driver.js.driver;
// 实例化对象,传相应参数
const driverObj = driver({
showProgress: true,
steps: [
{ element: '.one', popover: { title: '第一步', description: '阅读001' } },
{ element: '.two', popover: { title: '第二步', description: '阅读002' } },
{ element: '.three', popover: { title: '第三步', description: '阅读003' } },
{ element: '.four', popover: { title: '第四步', description: '阅读004' } },
]
});
document.getElementById('startTour').addEventListener('click', function () {
driverObj.drive();
});
// 官网:https://driverjs.com/
</script>
</body>
</html>
html2canvas做截图
什么是html2canvas?
简而言之,html2canvas就做了三件事
- 读取DOM:html2canvas会遍历指定的DOM节点(或者默认的可视区域),收集其中的元素结构和样式信息。
- 渲染到canvas:利用收集到的信息,它会在一个隐藏的canvas元素上重新绘制这些元素和样式,尽力模拟原始HTML的外观。
- 输出图像:一旦渲染完成,你可以选择将canvas的内容导出为Base64编码的字符串,或者创建一个图片链接,甚至下载为文件。
读取DOM、渲染到canvas、输出图像
基于此,我们可以用来做截图功能
效果图
第一步,引入html2canvas库
<!-- 引入html2canvas库 -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.3.3/html2canvas.min.js"></script>
第二步,使用html2canvas的toDataURL把指定dom的内容,转成base64图片输入即可
function takeScreenshot(elementId, fileName) {
// 选中指定的dom元素
var element = document.getElementById(elementId);
// 执行html2canvas的方法
html2canvas(element).then(function (canvas) {
// 将canvas转换为data URL
var dataURL = canvas.toDataURL("image/png");
// 创建一个img元素来显示截图
var img = document.createElement('img');
// 指定图片地址
img.src = dataURL;
// 将截图结果显示在页面上
document.body.appendChild(img);
}).catch(function (error) {
console.error('Error while taking screenshot:', error);
});
}
完整代码
CV演示
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>截图</title>
<!-- 引入html2canvas库 -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.3.3/html2canvas.min.js"></script>
<style>
ul {
background-color: pink;
width: 120px;
}
</style>
</head>
<body>
<ul id="target">
<li>白日依山尽</li>
<li>黄河入海流</li>
<li>欲穷千里目</li>
<li>更上一层楼</li>
</ul>
<button>一键截图并下载</button>
<hr>
<script>
function takeScreenshot(elementId, fileName) {
var element = document.getElementById(elementId);
html2canvas(element).then(function (canvas) {
// 将canvas转换为data URL
var dataURL = canvas.toDataURL("image/png");
// 创建一个img元素来显示截图
var img = document.createElement('img');
// 指定图片地址
img.src = dataURL;
// 将截图结果显示在页面上
document.body.appendChild(img);
// 并且下载
downloadImage(dataURL, fileName);
}).catch(function (error) {
console.error('Error while taking screenshot:', error);
});
}
function downloadImage(dataURL, fileName = 'screenshot.png') {
// 创建隐藏的可下载链接
var downloadLink = document.createElement("a");
downloadLink.href = dataURL;
downloadLink.download = fileName; // 设置默认文件名
// 隐藏链接
downloadLink.style.display = 'none';
document.body.appendChild(downloadLink);
// 触发点击
downloadLink.click();
// 稍后移除链接
setTimeout(function () {
document.body.removeChild(downloadLink);
}, 0);
}
document.querySelector('button').onclick = () => {
takeScreenshot('target', '下载');
}
</script>
</body>
</html>
仿写vue的{{}}语法
思路分析
- vue的双花括号表达式实际上就是一个“标识”
- 但凡是一个dom标签里面,有这个{{变量}},vue都会去查找双花括号中的对应变量对应的值
- 然后把这个值,替换到这个dom标签里面
- 实际上,我们自己也可以仿写的。
- 比如vue用{{变量}},我们也可以用{变量}
- 那么
- 我们第一步,可以document文档中所有的标签(要排除script标签)
- 第二步,看看这个标签里面的内容是否包含{}这个标识,若是包含,再第三步
- 第三步,就提取这个{}中的变量,比如这个是
<h2>{vvv}</h2>
(即提取出来这个vvv
) - 第四步,再去查找定义的变量中,有没有这个vvv对应的值,然后替换一下
代码层面
CV演示
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1>{aaa}</h1>
<h2>{bbb}</h2>
<h3>{ccc}</h3>
<h4>唐僧</h4>
<script>
// 判断是否有花括号
function isHaveKuoHao(str) {
if (str[0] == '{' && str.at(-1) == '}') {
return true
} else {
return false
}
}
// 提取花括号中的内容,也就是key
function getKuoHaoKey(str) {
let key = str.split('{')[1].split('}')[0]
return key
}
// data数据函数
window.data = function () {
return {
aaa: '孙悟空',
bbb: '猪八戒',
ccc: '沙和尚'
}
}
// 获取所有body的元素标签
const bodyChildren = document.body.children;
// 遍历操作
for (const dom of bodyChildren) {
// 排除掉script标签
if (dom.tagName != 'SCRIPT') {
// 包含双花括号的
if (isHaveKuoHao(dom.innerHTML)) {
// 提取花括号中的内容,就是字段key
let key = getKuoHaoKey(dom.innerHTML)
// data函数定义的字典
let Dict = data()
// 重新赋值,即改变了数据视图
dom.innerHTML = Dict[key]
}
}
}
</script>
</body>
</html>
这里笔者只演示了一层对象,还有多层对象,就是要用递归的操作了。不过思路最重要,有思路了,问题就好办了
仿写vue中:style的用法
我们知道,vue中:style有一种写成函数返回对象的写法,如下:
<div :style="{ color: dynamicColor, fontSize: fontSize + 'px' }"></div>
即:
<div :style="styleFn"></div>
const styleFn = () = {
return { color: 'pink', fontSize: '24px' }
}
实际上,我们也可以自己实现对应功能,仿写,思路如下:
仿写思路
- 比如我们有这样的
<h3 :style="fn">新的一天,打工仔加油</h3>
- 我们只是需要,去拿到这个dom身上的:style属性的值
- 这个值是一个函数,然后去methods对象中找到这个函数
- 再把这个函数的返回值,给应用到这个dom上即可
- 代码如下:
CV大家再看一下,结合注释,就明白啦
代码层面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h3 :style="fn">新的一天,打工仔加油</h3>
<script>
/**
* window全局,注册一个中转函数,用来把传进来的函数执行一下
* */
window.mounted = function (cb) { cb() }
/**
* 定义对象,里面有很多函数,每一个函数的返回值,都是可以使用的样式
* */
const methods = {
fn() {
let conf = {
background: 'pink',
color: 'green'
}
return conf
},
fn1() {
let conf = {
background: 'chocolate',
color: 'deepskyblue'
}
return conf
},
fn2() {
let conf = {
background: 'gray',
color: 'yellowgreen'
}
return conf
},
}
/**
* 钩子函数
* */
mounted(() => {
// 选中dom
let h3Dom = document.querySelector('h3')
// 获取:style绑定的值,对应就是methods对象中的key
let val = h3Dom.getAttribute(':style') // fn
// 遍历对比查找
for (const fnName in methods) {
if (val == fnName) { // 找到了
let targetFn = methods[fnName]
let styleObj = targetFn()
// 动态给标签元素,添加样式
for (const key in styleObj) {
// 原生js语法
h3Dom.style[key] = styleObj[key]
}
}
}
})
</script>
</body>
</html>
这里,笔者并没有做一些边界值的控制
因为更多的是提供代码操作思路
而Vue框架则是把特别多的情况考虑到,
然后做边界控制,兜错处理
这就是框架的复杂之处(当然还有别的方面...)
好记性不如烂笔头,记录一下吧...
A good memory is better than a bad pen. Write it down...
以上快速学习的案例代码,全部都在笔者的github仓库中。
仓库地址: https://github.com/shuirongshuifu/vue3-echarts5-example
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。