通过controlslist和禁止右键使播放器不能被下载
<video src="{$data.h_video}" class="swiper-slide-img" id="qqq" controls controlslist="nodownload nofullscreen noremoteplayback" oncontextmenu = "return false">
您的浏览器不支持 video 标签。
</video>
但是在谷歌浏览器下右下角有个仨点的功能(下载和画中画),画中画去不掉,通过js的方法去掉:
var video = $('#qqq');
//console.log(video); //通过打印拿到所有的属性和方法
video[0]['disablePictureInPicture'] = true; //disablePictureInPicture的属性改为true
前言
昨天app的同事(ios跟安卓)发现webview的video全屏按钮有问题,他们想禁用掉全屏、音量控制的按钮,前端同事在根据api设置disable_full_screen=1(pc端falsh平台生效),但全屏按钮依旧存在。既然api无效,那只能曲线救国,隐藏video内部controls功能按钮进而禁用全屏按钮。(以下在ios11/12安卓小米华为测试无问题)
1、怎么查看video内部构造
chrome 下,开发者工具 setting Preferences Elements 勾选 “Show user agent shadow DOM”
2、隐藏video功能按钮
/*video默认全屏按钮*/
video::-webkit-media-controls-fullscreen-button{ display: none !important; }
/*video默认aduio音量按钮*/
video::-webkit-media-controls-mute-button { display: none !important;}
/*video默认setting按钮*/
video::-internal-media-controls-overflow-button{ display: none !important;}
/*腾讯云点播禁用firefox全屏、设置按钮*/
.trump-button[sub-component="fullscreen_btn"],.trump-button[now="fullscreen"]{ display:none!important;}
.trump-button[sub-component="setting"]{ display:none !important;}
/*禁用video的controls(要慎重!不要轻易隐藏掉,会导致点击视频不能播放)*/
video::-webkit-media-controls {
display:none !important;
}
3、删掉下载/全屏等按钮
<video controls controlsList='nofullscreen nodownload noremote footbar' ></video>
参考:https://blog.csdn.net/qq_20757489/article/details/87879820
//全屏按钮
video::-webkit-media-controls-fullscreen-button {
display: none;
}
//播放按钮
video::-webkit-media-controls-play-button {
display: none;
}
//进度条
video::-webkit-media-controls-timeline {
display: none;
}
//观看的当前时间
video::-webkit-media-controls-current-time-display{
display: none;
}
//剩余时间
video::-webkit-media-controls-time-remaining-display {
display: none;
}
//音量按钮
video::-webkit-media-controls-mute-button {
display: none;
}
video::-webkit-media-controls-toggle-closed-captions-button {
display: none;
}
//音量的控制条
video::-webkit-media-controls-volume-slider {
display: none;
}
//所有控件
video::-webkit-media-controls-enclosure{
display: none;
}
controlslist隐藏按钮
controlsList属性返回DOMTokenList,帮助用户在显示其自己的控件集时选择要在媒体元素上显示的控件,可以设置以下三个可能值中的一个或多个:nodownload,nofullscreen和noremoteplayback
nodownload关键字暗示的下载控制应使用用户代理自己的一套媒体元素控件时被隐藏。
nofullscreen关键字暗示在使用用户代理自己的媒体元素控件集时,应隐藏全屏模式控件。
noremoteplayback关键字暗示当使用用户代理自己的媒体元素控件集时,应隐藏远程播放控件。
MDN HTMLMediaElement.controlsList
// nodownload: 不要下载
// nofullscreen: 不要全屏
// noremoteplayback: 不要远程回放
// disablePictureInPicture: 不要画中画
<video controls
disablePictureInPicture="true"
controlslist="nodownload nofullscreen noremoteplayback"
</video>
隐藏播放器右下角三个点
如图 可能需要隐藏右下角的三个点,里面包含下载和画中画!需要将下载和画中画隐藏后才回完全隐藏这三个点。只需要将controlslist=“nodownload”,然后设置disablePictureInPicture="true"就可以了
或者直接使用js获取dom节点后设置对应属性
const el = document.querySelector('video');
el['disablePictureInPicture'] = true; // disablePictureInPicture的属性改为true 禁用画中画
el['controlslist'] = 'nodownload noremoteplayback'; // 隐藏下载按钮
参考:https://segmentfault.com/a/1190000038485447
<template>
<div class="healthClass">
<!-- 视频医生导航条 -->
<div class="health-nav-bar">
<div
:class="{'health-nav-bar-title':true,'active':item.id==active_index}"
@click="select(item.id)"
v-for="(item,index) in navBarList"
:key="index"
>{{item.name}}</div>
</div>
<!-- 视频医生模板 -->
<van-list
v-model="loading"
:finished="finished"
finished-text="没有更多了"
@load="load"
v-show="healthCar&&healthCar.length>0"
>
<div class="health-content">
<div
v-for="(itme,index) in healthCar"
:key="index"
class="health-car"
@click="$router.push({
name:'healthRegimen',
query:{
videoSrc:itme.videoSrc,
coverPicUrl: itme.coverPicUrl,
title:itme.title,
author:itme.author,
summary:itme.summary,
dirName:itme.dirName,
poster:itme.poster
}
})"
>
<div class="video-bg">
<!-- <img
src="/src/assets/image/fat/5.png"
alt=""
> -->
<video
class="video-content"
:src="itme.videoSrc"
:poster="itme.poster||''"
></video>
<!-- <div class="video-content"></div> -->
<div class="mask">
<img
:src="require('@/assets/image/healthRegimen/pay.png')"
alt=""
>
</div>
</div>
<div class="video-description">
<div class="description-title">{{itme.title|titlestring}}</div>
<div class="description-content">
<div class="description-content-left">
<img
:src="itme.coverPicUrl"
alt=""
>
{{itme.author}}
</div>
<div class="description-content-right">
<img
:src="require('@/assets/image/healthRegimen/number.png')"
alt=""
> 1万+
</div>
</div>
</div>
</div>
</div>
</van-list>
<van-empty
v-show="isempty"
description="暂无数据"
/>
</div>
</template>
<script>
export default {
name: "healthClass",
data() {
return {
navBarList: [
{ name: "医学科普", id: 261 },
{ name: "健康通识", id: 262 },
{ name: "营养运动", id: 263 },
{ name: "睡眠心理", id: 264 },
],
healthCar: null,
pageNum: 1,
totalpages: 1,
active_index: 261,
loading: false,
finished: false,
};
},
filters: {
titlestring(val) {
if (typeof val == "string") {
if (val.length > 8) {
return val.slice(0, 8) + "...";
} else {
return val;
}
} else {
return "医生";
}
},
},
computed: {
isempty() {
if (Array.isArray(this.healthCar)) {
return this.healthCar.length == 0 ? true : false;
} else {
return false;
}
},
},
methods: {
select(val) {
this.active_index = val;
this.pageNum = 1;
this.pageData();
},
// 获取数据
pageData() {
this.$http
.request({
url: "/ajax/web/video/page",
method: "get",
params: {
category: this.active_index,
pageNum: this.pageNum,
pageSize: 20,
},
})
.then((res) => {
console.log(res, "=======");
if (res.success && Array.isArray(res.respBody.list)) {
let healthCar = res.respBody.list.map((item, index) => {
item.content.replace(
/<video [^>]*src=['"]([^'"]+)[^>]*>/i,
function (match, capture) {
console.log(capture);
item.videoSrc = capture;
}
);
item.content.replace(
/<img [^>]*src=['"]([^'"]+)[^>]*>/i,
function (match, capture) {
console.log(capture);
item.poster = capture;
}
);
return item;
});
this.totalpages = res.respBody.pages;
if (this.pageNum == 1) {
this.healthCar = healthCar;
} else {
this.healthCar = this.healthCar.concat(healthCar);
this.loading = false;
}
}
});
},
load() {
console.log(this.loading, "====", 123456);
this.pageNum++;
if (this.totalpages > this.pageNum) {
this.pageData();
} else {
this.finished = true;
}
},
},
activated() {
this.pageNum == 1;
this.pageData();
console.log("activated");
},
deactivated() {
console.log("deactivated");
},
created() {
// this.pageData();
console.log("created");
},
mounted() {
console.log("mounted");
},
};
</script>
<style lang='scss' scoped>
@import "src/style/mixin";
.healthClass {
width: 100%;
min-height: 100vh;
padding: 0 rpx(30);
background: rgba(245, 246, 250, 1);
// 视频医生导航
.health-nav-bar {
display: flex;
align-items: center;
justify-content: space-between;
height: rpx(80);
.health-nav-bar-title {
font-size: rpx(28);
font-family: Source Han Sans CN;
font-weight: 400;
color: #666666;
&.active {
color: #ff966e;
}
}
}
// 视频医生卡片
.health-content {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
.health-car {
width: rpx(335);
height: rpx(379);
background: rgba(255, 255, 255, 1);
border-radius: rpx(24);
// background: #f00;
box-shadow: 0.1px 0.1px 1px #ccc;
margin-bottom: rem(17);
.video-bg {
width: 100%;
height: rpx(260);
background: rgba(236, 236, 236, 0.39);
opacity: 1;
border-radius: rpx(24) rpx(24) 0 0;
overflow: hidden;
position: relative;
.mask {
content: "";
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: rgba($color: #fff, $alpha: 0);
img {
position: absolute;
top: rpx(18);
right: rpx(16);
width: rpx(43);
height: rpx(43);
background: rgba(0, 0, 0, 0.39);
border-radius: 50%;
}
}
.video-content {
width: 100%;
height: 100%;
background: #000;
}
}
.video-description {
background: rgba(255, 255, 255, 1);
padding: 0 rpx(19);
.description-title {
font-size: rpx(28);
font-family: Source Han Sans CN;
font-weight: 400;
line-height: rpx(28);
color: #333333;
margin: rpx(17) 0 rpx(21);
}
.description-content {
display: flex;
align-items: center;
justify-content: space-between;
.description-content-left {
display: flex;
align-items: center;
font-size: rpx(24);
font-family: Source Han Sans CN;
font-weight: 400;
line-height: rpx(24);
color: #333333;
img {
width: rpx(36);
height: rpx(36);
background: rgba(0, 0, 0, 0.39);
border-radius: 50%;
margin-right: rpx(8);
}
}
.description-content-right {
display: flex;
align-items: center;
font-size: rpx(24);
font-family: Source Han Sans CN;
font-weight: 400;
line-height: rpx(24);
color: #333333;
img {
width: rpx(32);
height: rpx(32);
margin-right: rpx(10);
}
}
}
}
}
}
}
</style>
<template>
<div class="healthRegimen">
<video
autoplay
ref="video"
:src="$route.query.videoSrc"
class="healthRegimen-video"
controlslist="nofullscreen nodownload noremote footbar"
oncontextmenu="return false"
disablePictureInPicture=true
:poster="$route.query.poster"
></video>
<!-- 全屏蒙版 -->
<div
class="mask"
ref="mask"
>
<img
v-show="lock"
:src="require('@/assets/image/healthRegimen/pay.png')"
alt=""
>
</div>
<!-- 内容 -->
<div class="healthRegimen-description">
<div class="description-title">
<div>
<img
:src="$route.query.coverPicUrl"
alt=""
>
{{$route.query.title|titlestring}}
</div>
<div class="description-content-right">
<img
:src="require('@/assets/image/healthRegimen/number.png')"
alt=""
> 1万+
</div>
</div>
<!-- 描叙 -->
<div class="description-content">
{{$route.query.dirName}}:{{$route.query.summary|summarystring}}
</div>
<!-- 观看记录 -->
<div
id="progress"
ref="progress"
>
<div
:style="{width:percent+'%'}"
id="timeBar"
></div>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
lock: false,
// 进度条百分比
percent: 0,
};
},
filters: {
titlestring(val) {
if (typeof val == "string") {
if (val.length > 8) {
return val.slice(0, 8) + "...";
} else {
return val;
}
} else {
return "医生";
}
},
summarystring(val) {
if (typeof val == "string") {
if (val.length > 40) {
return val.slice(0, 40) + "...";
} else {
return val;
}
} else {
return "健康好尔美";
}
},
},
methods: {
// 进度条拖拽
updateprogress(x) {
console.log(x, "===888");
var percent = (x / document.getElementById("progress").clientWidth) * 100;
if (percent > 100) {
percent = 100;
} else if (percent < 0) {
percent = 0;
}
this.percent = percent;
this.$refs.video.currentTime =
(this.$refs.video.duration * percent) / 100;
},
// 进度条获取坐标调用 拖拽实现方法
enableProgressDrag() {
var that = this;
var progressDrag = false;
// this.$refs.progress.onmousedown = function (e) {
// progressDrag = true;
// that.updateprogress(e.offsetX);
// };
// document.onmouseup = function (e) {
// if (progressDrag) {
// progressDrag = false;
// that.updateprogress(e.offsetX);
// }
// };
// this.$refs.progress.onmousemove = function (e) {
// console.log("onmousemove", "==");
// if (progressDrag) {
// that.updateprogress(e.offsetX);
// }
// };
this.$refs.progress.addEventListener("touchstart", function (e) {
console.log("onmousemove", "==", e);
let distance = e.changedTouches[0].clientX;
progressDrag = true;
that.updateprogress(distance);
});
this.$refs.progress.addEventListener("touchmove", function (e) {
console.log("onmousemove", "==", e);
let distance = e.changedTouches[0].clientX;
console.log("onmousemove", distance, "==", e);
if (progressDrag) {
that.updateprogress(distance);
}
});
this.$refs.progress.addEventListener("touchend", function (e) {
let distance = e.changedTouches[0].clientX;
if (progressDrag) {
progressDrag = false;
that.updateprogress(distance);
}
});
},
// 进度条跟随
ontimeupdate() {
var that = this;
this.$refs.video.ontimeupdate = function () {
if (that.$refs.video) {
var currentTime = that.$refs.video.currentTime;
var duration = that.$refs.video.duration;
var percent = (currentTime / duration) * 100;
that.percent = percent;
}
};
},
},
mounted() {
// 监听点击 暂停 播放
this.$refs.mask.addEventListener("click", (result) => {
console.log(result, "===result");
if (this.lock) {
this.$refs.video.play();
} else {
this.$refs.video.pause();
}
this.lock = !this.lock;
});
this.$nextTick(() => {
this.enableProgressDrag();
});
this.ontimeupdate();
},
beforeDestroy() {
// this.$refs.video.offTimeUpdate();
},
};
</script>
<style lang='scss' scoped>
@import "src/style/mixin";
.healthRegimen {
width: 100%;
height: 100vh;
background: rgba(0, 0, 0, 1);
overflow: hidden;
position: relative;
.healthRegimen-video {
width: 100%;
height: 100vh;
/*video默认全屏按钮*/
&::-webkit-media-controls-fullscreen-button {
display: none !important;
}
/*video默认aduio音量按钮*/
&::-webkit-media-controls-mute-button {
display: none !important;
}
/*video默认setting按钮*/
&::-internal-media-controls-overflow-button {
display: none !important;
}
/*腾讯云点播禁用firefox全屏、设置按钮*/
.trump-button[sub-component="fullscreen_btn"],
.trump-button[now="fullscreen"] {
display: none !important;
}
.trump-button[sub-component="setting"] {
display: none !important;
}
&::-webkit-media-controls-play-button {
display: none !important;
}
&::-webkit-media-controls-current-time-display,
&::-webkit-media-controls-time-remaining-display {
display: none !important;
}
/*禁用video的controls(要慎重!不要轻易隐藏掉,会导致点击视频不能播放)*/
// video::-webkit-media-controls {
// display: none !important;
// }
// -webkit-media-controls-play-button
}
.healthRegimen-description {
position: absolute;
width: 100%;
height: rpx(316);
left: 0;
bottom: 0;
padding: 0 rpx(32);
.description-title {
display: flex;
align-items: center;
justify-content: space-between;
font-size: rpx(32);
font-family: Source Han Sans CN;
font-weight: 400;
color: #ffffff;
// opacity: 0.9;
margin-bottom: rpx(32);
img {
width: rpx(64);
height: rpx(64);
border-radius: 50%;
margin-right: rpx(16);
background: #fff;
}
.description-content-right {
display: flex;
align-items: center;
font-size: rpx(28);
font-family: Source Han Sans CN;
font-weight: 400;
color: #ffffff;
img {
width: rpx(32);
height: rpx(32);
margin-right: rpx(10);
}
}
}
.description-content {
font-size: rpx(28);
// line-height: rpx(28);
font-family: Source Han Sans CN;
font-weight: 400;
color: #ffffff;
opacity: 0.9;
margin-bottom: rpx(80);
}
#progress {
overflow: hidden;
flex-grow: 1;
height: rpx(10);
border-radius: rpx(5);
background-color: #333333;
#timeBar {
width: 0;
height: rpx(10);
background-color: tomato;
}
}
}
.mask {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
}
</style>