内容比较简单,不做过多赘述,只做分享,测试demo,功能有些缺陷,希望路过的大佬多多指正
/(*/\*)
import { showToast, showSuccessToast, showFailToast, showLoadingToast } from 'vant';
import { onBeforeMount, onMounted, reactive, ref } from 'vue'
const videoArr = ref([])
const odelSel = ref('')//当前使用的摄像头
const myInterval = ref(null)
const mediaStreamTrack = ref('') // 退出时关闭摄像头
const video_stream = ref('') // 视频stream
const recordedBlobs = ref([]) // 视频音频 blobs
const isRecord = ref(false) // 视频是否正在录制
const content = ref('按住拍摄,点击拍照')
let test = 'c'
const startStauts = ref(true)// 开始录制按钮样式
// video参数
const videoRef = ref(null);
// 画布参数(照片回显)
const cs = ref(null)
const css = ref(null)
const csss = ref(null)
const cssss = ref(null)
const csssss = ref(null)
// 回显画布宽高
const canWidth = ref('')
const canHeight = ref('')
const echo_Status = ref(false)
const canvas_echo = ref(null)
// 关闭摄像头
const closeStatus = ref(true)
// 切换按钮状态
const cutStatus = ref(false)
// 照片数量限制
const photoNum = ref([])
// 照片回显数组
const videoList = ref([])
const videoNum = ref(0)
const timeOutEvent = ref(null服务器托管)
const returns = ref(false)
// 录制参数
const isRecording = ref(false)
const videoBlob = ref(null)
// 前置后置摄像头切换
const cameraStatu = ref(0)
// 预览内容
let contents = ref({});
const showCenter = ref(false)
onMounted(() => {
let cedioele = document.getElementsByClassName('camera_video')[0]
canWidth.value = cedioele.offsetWidth
canHeight.value = cedioele.offsetHeight
let canvasList = document.getElementsByClassName('canns')
})
// 前置后置切换
const changeDevice = () => {
if(cameraStatu.value == 2){
cameraStatu.value = 1
}else{
cameraStatu.value = 2
}
console.log(666);
// 旧版本浏览器可能根本不支持mediaDevices,我们首先设置一个空对象
if (navigator.mediaDevices === undefined) {
navigator.mediaDevices = {};
}
console.log(navigator.mediaDevices);
navigator.mediaDevices.getUserMedia({
video: cameraStatu.value == 1 ? { facingMode: 'user' } : { facingMode: { exact: "environment" } },
})
.then((stream) => {
// 摄像头开启成功
console.log(stream);
startStauts.value = false
mediaStreamTrack.value = typeof stream.stop === 'function' ? stream : stream.getTracks()[0];
video_stream.value = stream;
console.log(videoRef);
videoRef.value.srcObject = stream;
videoRef.value.play();
closeStatus.value = false
})
.catch(err => {
console.log(err);
});
console.log(cameraStatu.value);
}
// ------------------------------摄像头开关按钮-------------------------------
// 开启摄像头事件
const getCamera = () => {
cameraStatu.value = 1
console.log(cameraStatu.value);
navigator.mediaDevices
.getUserMedia({
audio: true,
video: { facingMode: { exact: "environment" } },
})
.then((stream) => {
// 摄像头开启成功
startStauts.value = false
mediaStreamTrack.value = typeof stream.stop === 'function' ? stream : stream.getTracks()[0];
video_stream.value = stream;
console.log(videoRef);
videoRef.value.srcObject = stream;
videoRef.value.play();
})
.catch((err) => {
console.log(err);
});
console.log(cameraStatu.value);
}
// 关闭摄像头
const closeCamera = () => {
if (!videoRef.value.srcObject) return;
let stream = videoRef.value.srcObject;
let tracks = stream.getTracks();
tracks.forEach(track => {
track.stop();
});
videoRef.value.srcObject = null;
startStauts.value = true
closeStatus.value = true;
}
// ==========================点击拍照============================
const shoot = () => {
if (startStauts.value == true) {
showFailToast('请打开摄像头');
} else {
if (videoList.value.length {
console.log('拍单张');
console.log(videoList.value.length);
console.log(cs.value);
let sc = cs.value[videoList.value.length - 1].getContext('2d');
sc.drawImage(videoList.value[videoList.value.length - 1].val, 0, 0, 50, 50);
}, 700)
} else {
showFailToast('照片已达上限');
}
}
}
// 检测点击按钮事件定时器
let times = null;
function echo_btn(index) {
console.log(index);
console.log(videoList.value);
if (videoList.value[index].type == 1) {
echo_Status.value = true
closeStatus.value = true
cutStatus.value = true
startStauts.value = false
const image = cs.value[index].toDataURL("image/png");
contents = {
index: videoNum.value++,
type: 1,
url: image
}
showCenter.value = true
console.log(image);
} else {
echo_Status.value = true
closeStatus.value = true
cutStatus.value = true
startStauts.value = false
contents = {
index: videoNum.value++,
type: 2,
url: videoList.value[index].val
}
showCenter.value = true
}
}
// 用户是否长按 false 点击、ture 长按
let userStatus = ref(false);
const currentNum = ref(0)
// 手指点击触发
const photosStart = () => {
console.log(videoList.value.length);
if (startStauts.value == true) {
showFailToast('请打开摄像头');
} else {
// 判断是否超过5个
if (videoList.value.length > 5) {
showFailToast("最多录制5个文件!");
return;
}
times = setTimeout(() => {
userStatus.value = true;
pressEvenet();
}, 500);
}
};
// 长按录像
let mediaRecorder = null;
let inte = null;
let eouts = null;
let stops = false;
const pressEvenet = () => {
console.log(videoList.value);
if (videoList.value.length {
if (event.data && event.data.size > 0) {
chunks.push(event.data);
}
};
mediaRecorder.onstop = () => {
const blob = new Blob(chunks, { type: "video/webm" });
const url = URL.createObjectURL(blob);
console.log(url);
videoList.value.push({服务器托管
val: url,
id: videoNum.value++,
type: 2
})
chunks = [];
};
mediaRecorder.start();
inte = setInterval(() => {
currentNum.value++;
if (currentNum.value >= 100) {
showDeleteButton()
}
}, 100);
eouts = setTimeout(() => {
clearInterval(inte);
showSuccessToast("录制完成");
mediaRecorder.stop();
stops = false;
}, 10000);
} else {
showFailToast("最多录制5个文件!");
}
};
const showDeleteButton = () => {
currentNum.value = 0
// 判断是否超过5个
if (videoList.value.length > 5) {
showFailToast("最多录制5个文件!");
return;
}
clearTimeout(times);
pressStop();
}
// 停止录制事件
const pressStop = () => {
if (stops) {
mediaRecorder.stop();
showSuccessToast("录制完成");
stops = false;
clearInterval(inte);
clearTimeout(eouts);
}
};
function close(index) {
console.log(666);
videoList.value.splice(index, 1)
}
开启摄像头
关闭摄像头
完成
.close_btn {
position: absolute;
top: 0;
right: 0;
z-index: 10;
width: 0;
height: 0;
border-top: 16px solid #EEEEEE;
border-left: 16px solid transparent;
display: flex;
justify-content: center;
align-items: center;
}
.close_btn>img {
width: 8px;
height: 8px;
position: absolute;
top: -13px;
right: 1px;
}
.clack {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
}
.clack>img {
width: 100%;
height: 100%;
}
.canvas_echo {
position: absolute;
top: 0;
left: 0;
}
.camera_box {
width: calc(100vw);
height: 100vh;
padding: 10px;
}
.success_btn {
padding: 10px;
}
.start_live {
padding: 10px;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 5;
}
.end_live {
padding: 10px;
position: absolute;
bottom: 0;
right: 0;
transform: translate(-50%, -50%);
z-index: 5;
}
.cut_live {
padding: 10px;
position: absolute;
bottom: 0;
left: 0;
z-index: 5;
}
.image_box {
width: 100%;
height: 60vh;
position: relative;
border-radius: 0 0 10px 10px;
border: 1px solid #EEEEEE;
}
.live_window {
width: 100%;
}
.back_btn {
width: 20px;
height: 20px;
border: 50%;
opacity: 0.5;
}
.btn_box {
width: 100%;
display: flex;
padding: 10px;
justify-content: space-between;
position: absolute;
top: 0;
font-size: 1rem;
}
.image_list {
width: 100%;
height: 50px;
margin-top: 10px;
display: flex;
justify-content: center;
align-items: center;
}
.btn_boxs {
width: 100%;
height: 100px;
margin-top: 20px;
display: flex;
align-items: center;
justify-content: center;
position: relative;
}
.image_go {
width: 20%;
}
.camera_go {
width: 20%;
display: flex;
justify-content: right;
}
.pach_box {
border-radius: 50%;
}
.pach_boxs {
width: 100%;
height: 100%;
position: absolute;
border-radius: 50%;
z-index: -1;
display: flex;
justify-content: center;
align-items: center;
}
.pach_icon {
width: 80%;
height: 80%;
}
.pach_btn {
width: 70px;
height: 70px;
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
}
.pach_img {
width: 34px;
height: 34px;
}
.add_btn {
width: 20px;
height: 20px;
background-color: #FA9A24;
display: flex;
justify-content: center;
align-items: center;
border-radius: 5px;
margin-left: 10px;
}
.add_btn>img {
width: 12px;
height: 12px;
}
.list {
display: flex;
align-items: center;
}
.list_item {
width: 50px;
height: 50px;
background-color: #EEEEEE;
margin-left: 10px;
border-radius: 8px;
overflow: hidden;
position: relative;
}
#file {
display: none;
}
.message {
margin-top: 30px;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
}
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
CSS-DAY1 一共有七天,加油,一天大概三十节 1.CSS简介 1.1HTML的局限性 HTML只关注内容的语义,并且很丑 1.2CSS-网页的美容师 CSS 是层叠样式表 ( Cascading Style Sheets ) 的简称. 有时我们也会称之为…