功能:在小程序中调取手机相机录制视频,录制过程中提词器中字体跟着滚动,提词器颜色改变。
效果展示
提词器不显示:
修改提词器样式:
内容编写:
提词器下拉增加高,提词器可上下拖动:
开始录制(再次点击接受录制返回视频路径):
退出录制:
以下粘贴为部分代码,获取全部代码可联系作者:
<template>
<view class="box">
<view class="fixedTop">
<view
class="tui-status-bar"
:style="{ height: statusBarHeight + 'px' }"
></view>
<view class="btn" :style="{height:height+'px'}">
<image src="https://doctor.sdxxtop.com/img/tools/teleprompterClone.png" @click="showBackPopUp = !showBackPopUp"></image>
<image v-if="showTextPopUp" src="https://doctor.sdxxtop.com/img/tools/teleprompterShow.png" @click="showTextPopUp = false"></image>
<image v-else src="https://doctor.sdxxtop.com/img/tools/teleprompterUnShow.png" @click="showTextPopUp = true"></image>
</view>
<view class="textPopUp" v-if="showTextPopUp" :style="'margin-top:'+dragPopUpHeight+'px'" @touchmove="handleTouchMovePopUp" @touchstart="touchstartPopUp($event)">
<view class="text" :style="{ height: dragHeight + 'px',color:textColor }">
<scroll-view scroll-y :style="{ height: dragHeight + 'px' }" lower-threshold="0" :scroll-top="scrollTop" @scrolltolower="scrollBottom">
{{text?text:'你好,欢迎来到医生医影提词器,已为你开启智能跟随模式,台词跟着语速走,念到哪走到哪,节奏由你掌控;点击左下角设置按钮,可以修改台词样式配快来尝试录制示下吧~'}}
</scroll-view>
</view>
<view class="textBtn">
<image @click="teleprompterSet" src="https://doctor.sdxxtop.com/img/tools/teleprompterSet.png"></image>
<image @click="teleprompterLog" src="https://doctor.sdxxtop.com/img/tools/teleprompterLog.png"></image>
<image @touchmove.stop="handleTouchMove" @touchstart="touchstart($event)" src="https://doctor.sdxxtop.com/img/tools/teleprompterZoom.png"></image>
</view>
</view>
<view class="backPopUp" v-if="showBackPopUp">
<text></text>
<view @click="quit">
<image src="https://doctor.sdxxtop.com/img/tools/teleprompterBack.png"></image>
<text>退出拍摄页</text>
</view>
<view @click="againTake">
<image src="https://doctor.sdxxtop.com/img/tools/teleprompterAgain.png"></image>
<text>重新拍摄</text>
</view>
</view>
</view>
<view class="content">
<camera :device-position="devicePosition ? 'back' : 'front'" flash="off" @error="loadCameraError" :style="{width: '100%', height: winHeight+'px'}"></camera>
</view>
<!-- 开始录制 -->
<view class="start">
<image src="https://doctor.sdxxtop.com/img/tools/teleprompterStart.png" v-if="!isStartRecord" @click="startVideotape"></image>
<image src="https://doctor.sdxxtop.com/img/tools/teleprompterStop.png" v-else @click="stopVideoTape"></image>
<view class="turn" @click="turnCamera" v-if="!isStartRecord">
<image src="https://doctor.sdxxtop.com/img/tools/teleprompterTurn.png"></image>
<view>翻转</view>
</view>
<view class="time" v-if="isStartRecord">{{formatSeconds(recordTime)}}</view>
</view>
<!-- 蒙层 -->
<view class="mongolian" v-if="mongolian">
<view class="colorBox">
<view v-for="(item,index) in 9" :class="chooseColorIndex == index ? 'chooseColor' : '' " @click="chooseColor(index)"></view>
</view>
</view>
<!-- 修改编写 -->
<view class="editText" v-if="editTextPopUp" :style="{ marginTop : ( statusBarHeight + 44 ) +'px' }">
<view class="editTextTitle">
<text @click="cancelText">取消</text>
<text>修改编写</text>
<text @click="confirmText">确认</text>
</view>
<view class="editTextContent">
<textarea maxlength="-1" v-model="text" :style="'height:'+(winHeight-200)+'px;'" placeholder="请输入或粘贴"></textarea>
</view>
</view>
</view>
</template>
<script>
import { Debounce } from "@/utils/debounce.js";
export default {
data(){
return {
// 手机高度
winHeight: 0,
//状态栏高度
statusBarHeight: 0,
//header高度
height: 44,
// 显示提词器弹窗
showTextPopUp:true,
// 触摸开始的Y坐标
startY: 0,
// 拖动区域的高度
dragHeight: 150,
// 最大高度限制
maxHeight: 450 ,
// 整个弹窗触摸开始y的坐标
startPopUpY:0,
// 拖动区域的高度
dragPopUpHeight: 0,
// 选中颜色下标
chooseColorIndex:0,
// 动态字体颜色
textColor:"#FFFFFF",
// 是否显示蒙层
mongolian:false,
// 内容
text:"",
// 编辑文字弹窗
editTextPopUp:false,
// 相机内置
ctx:null,
// 录制生成的视频
createVideoUrl:'https://xxx/jinan_demo/video/20240328/d8a426d9a9ef37b2a28040fbcd470f28.mp4',
// 是否开始录制
isStartRecord:false,
// 前后置摄像头 true:前置 false:后置
devicePosition:true,
// 录制时长
recordTime:0,
// 录制时长定时器
recordTimeFun:null,
// 显示返回弹窗
showBackPopUp:false,
// 提词器移动定时事件
scrollTopTimeFun:null,
// 滚动条位置
scrollTop:0
}
},
created() {
uni.getSystemInfo({
success: (res) => {
this.statusBarHeight = res.statusBarHeight
}
})
},
onLoad(option) {
var that = this;
if(option.text){
this.text = option.text
}
uni.getSystemInfo({
success: function(res) {
that.winHeight = res.windowHeight
},
});
},
onReady() {
this.ctx = uni.createCameraContext();
},
methods:{
}
}
</script>
<style lang="scss" scoped>
.box{
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
.fixedTop{
background-color: black;
position: fixed;
width: 100%;
top: 0;
left: 0;
z-index: 123;
.tui-status-bar {
width: 100%;
}
.btn{
padding-right: 250rpx;
display: flex;
align-items: center;
justify-content: space-between;
padding-left: 30rpx;
image{
width: 50rpx;
height: 50rpx;
}
}
.textPopUp{
position: absolute;
top:100%;
left: 50%;
z-index: 123;
width: 90%;
box-sizing: border-box;
background-color: #00000050;
padding: 30rpx;
border-radius: 20rpx;
transform: translateX(-50%);
.text{
font-size: 35rpx;
color: #FFFFFF;
line-height: 63rpx;
overflow: hidden;
}
.textBtn{
margin-top: 60rpx;
display: flex;
align-items: center;
justify-content: space-between;
image{
width: 43rpx;
height: 43rpx;
}
image:nth-of-type(1){
height: 36rpx
}
image:nth-of-type(2){
width: 35rpx;
height: 35rpx;
}
}
}
.backPopUp{
position: absolute;
top: 115%;
left: 20rpx;
z-index: 1111;
background-color: white;
border-radius: 20rpx;
font-size: 28rpx;
&>text{
border-color: #ff450000 #ff450000 white #ff450000;
display: inline-block;
width: 0;
height: 0;
border-width: 20rpx;
border-style: solid;
position: absolute;
top: 0%;
transform: translateY(-90%);
left: 15rpx;
}
&>view{
padding: 30rpx;
display: flex;
align-items: center;
&>image{
width: 32rpx;
height: 32rpx;
margin-right: 20rpx;
}
}
&>view:nth-of-type(1){
border-bottom: 2rpx solid #EFEFEF;
color: #621AA4;
&>image{
width: 40rpx;
height: 32rpx;
}
}
}
}
.start{
position: fixed;
bottom: 180rpx;
left: 50%;
transform: translateX(-50%);
display: flex;
align-items: center;
&>image{
width: 120rpx;
height: 120rpx;
}
.turn{
margin-left: 80rpx;
text-align: center;
image{
height: 35rpx;
width: 42rpx;
}
font-size: 28rpx;
color: #FFFFFF;
}
.time{
font-size: 38rpx;
color: #FFFFFF;
position: absolute;
top: -80%;
left: 50%;
transform: translateX(-50%);
}
}
.mongolian{
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #000000;
.colorBox{
position: absolute;
bottom: 200rpx;
left: 50%;
transform: translateX(-50%);
display: flex;
align-items: center;
justify-items: center;
.chooseColor{
border: 2rpx solid white;
}
view{
width: 63rpx;
height: 63rpx;
}
view:nth-of-type(1){
background-color: white;
}
view:nth-of-type(2){
background-color: #424242;
}
view:nth-of-type(3){
background-color: #000000;
}
view:nth-of-type(4){
background-color: #FA797D;
}
view:nth-of-type(5){
background-color: #FB6F24;
}
view:nth-of-type(6){
background-color: #F9D63C;
}
view:nth-of-type(7){
background-color: #77E46F;
}
view:nth-of-type(8){
background-color: #5A95EF;
}
view:nth-of-type(9){
background-color: #998BFC;
}
}
}
.editText{
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: white;
z-index: 123;
border-radius: 20rpx 20rpx 0 0;
.editTextTitle{
display: flex;
align-items: center;
justify-content: space-between;
padding: 30rpx 20rpx;
border-bottom: 2rpx solid #D8D8D8;
text:nth-of-type(1){
font-size: 28rpx;
color: #666666;
}
text:nth-of-type(2){
font-size: 32rpx;
}
text:nth-of-type(3){
font-size: 28rpx;
color: #621AA4;
}
}
.editTextContent{
padding: 20rpx;
textarea{
width: 100%;
}
}
}
}
</style>