更新记录

8.5.0(2022-09-23)

自定义水印功能


平台兼容性

Android Android CPU类型 iOS
适用版本区间:5.0 - 12.0 armeabi-v7a:未测试,arm64-v8a:未测试,x86:未测试 适用版本区间:9 - 15

原生插件通用使用流程:

  1. 购买插件,选择该插件绑定的项目。
  2. 在HBuilderX里找到项目,在manifest的app原生插件配置中勾选模块,如需要填写参数则参考插件作者的文档添加。
  3. 根据插件作者的提供的文档开发代码,在代码中引用插件,调用插件功能。
  4. 打包自定义基座,选择插件,得到自定义基座,然后运行时选择自定义基座,进行log输出测试。
  5. 开发完毕后正式云打包

付费原生插件目前不支持离线打包。
Android 离线打包原生插件另见文档 https://nativesupport.dcloud.net.cn/NativePlugin/offline_package/android
iOS 离线打包原生插件另见文档 https://nativesupport.dcloud.net.cn/NativePlugin/offline_package/ios

注意事项:使用HBuilderX2.7.14以下版本,如果同一插件且同一appid下购买并绑定了多个包名,提交云打包界面提示包名绑定不一致时,需要在HBuilderX项目中manifest.json->“App原生插件配置”->”云端插件“列表中删除该插件重新选择


camera-view-plus

温馨提示:可下载demo示例工程(Android/IOS 包名/BundleId: net.luanqing.camerademo)

为满足开发者不同的界面UI需求,更加自由搭建页面效果,本插件仅提供预览页面(不含任何按钮文字等) + API功能(拍照、录像、切换摄像头、闪光灯、水印设置),详情可参阅示例工程。如有未满足的功能亦可联系我们进行功能升级和优化

: / 微信:

注意

支持IOS/Android两大平台,只需要将插件加入到页面,然后云打包或打包自定义基座(注意:原生插件必须要在nvue的页面,nvue和vue基本功能一直,只是存在一些差异,比如css的用法等),即可调用开放的API接口(拍照、录像、闪光灯开关、前后摄像头镜像切换、水印logo设置),插件本身为满足用户的不同UI设计,仅提供预览+开放API,让插件实现高度自由的界面自定义,用户可自行在预览界面上叠加放置其他按钮或文字(具体可参照demo项目)。

关于水印,如果用户不希望拍摄的照片上有水印,可以不传或者调用({})具体设置空值,视频的水印分为标签水印和背景防盗水印,标签水印也是通过生成,背景水印则是在stopRecord停止录像时传值控制(默认无水印)

缺陷:在android平台端小部分机型存在拍照后旋转角度的问题 !!!

API 简要说明

名称 说明 默认值 是否必须
resolutionRatio 分辨率XS/S/M/L/XL/XXL M 非
***(...) 水印内容({}),详情查看下方水印属性表 无 非
takePhoto() 执行拍照 无 非
startRecord() 开始录像 无 非
stopRecord({logoText,logoSize}) 停止录像,可选传视频背景水印文字和字号 无 非
openFront() 打开前置摄像头 无 非
openBack() 打开后置摄像头 无 非
openFlash() 打开闪光灯 无 非
closeFlash() 关闭闪光灯 无 非
defaultCamera 初始化的默认摄像头 后置摄像头 非
isSaveImage2Album 是否保存到相册(相册可见) "0"否 "1"是 0否 非
isSaveVideo2Album 是否保存到相册(相册可见) "0"否 "1"是 0否 非
@receiveRatio 可接收到android最优宽高比 无 非
@onTakePhotoSuccess 接受拍照成功的通知 无 非
@recordSuccess 接收录像成功的通知 无 非
@receiveInfo 接收反馈的一些异常报错信息 无 非
@onVideoSaveSuccess 接收录制后视频保存成功通知 无 非
@onImageSaveSuccess 接收拍照后图片保存成功通知 无 非
@restartPreview 重新预览(谨慎使用,会影响性能) 无 非
@onVideoWaterMarkProgress 视频水印处理进度 无 非

特别注意: 1、@restartPreview方法:因为有部分特定机型反复切换到摄像头页面,有概率会造成摄像头黑屏,可在onShow方法里调用此函数,但会牺牲一部分性能 2、水印添加(分为视频水印和照片水印, mode=0时为照片水印,缺省或其他任意mode值为视频水印,视频水印可以设置多个)

API *** 水印方法属性说明

名称 类型 说明 是否必须
mode Number 水印类型,0或不传是图片水印,>0是视频水印,默认0 非
tag String 视频水印标签文字 非
x Number 视频水印标签x坐标 非
y Number 视频水印标签y坐标 非
tagSize Number 视频水印标签文字尺寸 非
tagAlpha Number 视频水印标签透明度0-255 非
tagBorderAlpha Number 视频水印标签边框透明度0-255 非
tagColor String 视频水印标签文字颜色,十六进制字符串 非
tagBorderColor String 视频水印标签边框颜色,十六进制字符串 非
unShowControl Boolean 视频水印标签是否不显示拉伸和缩放小按钮,默认显示 非
address String 图片水印的地址 非
date String 图片水印的日期 非
time String 图片水印的时间 非
weekday String 图片水印的星期 非
remark String 图片水印的备注 非
weather String 图片水印的天气 非
logo String 图片水印的文字品牌logo 非
logoMarginRight Number logo的右边距 非
logoMarginBottom Number logo的底边距 非
customImgLogo Object 自定义图片Logo,详细见下表,Android端独有 非
customImgLogo 自定义图片logo属性说明
名称 类型 说明 是否必须
url String 自定义图片logo的地址,不支持网络地址,如是_doc/的路径需转换成绝对路径
sampleSize Number 压缩logo图片,如: 传2即 1/2,尺寸将是原图的50%,传4即是原图的25%,如大图可减少内存消耗 非
left Number logo图片距离屏幕左边的距离 非
top Number logo图片距离屏幕顶部的距离,left和top不填默认底部居中 非
width Number logo图片的宽度,不填默认是原图宽度 非
height Number logo图片的高度,不填默认是原图高度 非
offsetBottom Number logo图片的底部偏移量,如100则logo距离底部100 非
rotate Number logo图片的旋转角度,默认0不旋转 非
reversalX Boolean logo图片水平翻转 非
reversalY Boolean logo图片垂直翻转 非
特别注意:插件默认不会将图片、视频存入媒体库相册,如果需要在拍照录像后保存到相册请设置 isSaveImage2Album & isSaveVideo2Album ["0"不存相册 / "1"存入相册]

水印使用方法:

        <!-- 用法简述 其他方法请参考文档 -->
        <!-- 添加照片水印 此方法必须在拍照之前调用,否则水印不生效 -->
        this.$refs.cameraObj.***({
            "date":this.tempDateStr || "",  // 日期
            "logo":"· 七彩云 ·|水印相机",  // 品牌文字logo
            "address":(this.showAddress ? this.address:""),
            "time":this.tempTimeStr || "", // 时间
            "week":this.weekDay || "",  // 星期
            "remark":(this.showRemark ? this.remark:""),  // 备注
            "weather":"", // 天气描述
            "logoMarginRight": 10,  // 默认 0  logo距离屏幕右边的间距  logo默认在右下角
            "logoMarginBottom" 35,  // 默认 15  logo距离屏幕底部的间距  logo默认在右下角
            “logoSpace”: 0 // 默认0  logo图片和文字的间距
            ”customImgLogo“: {url: 'xxxx'}  // 自定义图片
        });

        // 通过下载的图片设置自定义logo图
        uni.downloadFile({
            url:'http://imgs.yisanguo.net/icons/icon_sys_mes_avatar.png',
            success(res) {
                // 需要转成绝对地址路径
                let real = plus.io.convertLocalFileSystemURL(res.tempFilePath);

                // 设置水印
                $that.$refs.cameraObj.***({
                    "logo":"·七彩云·|水印相机",
                    "customImgLogo": {url:real}
                });
                $that.$refs.cameraObj.takePhoto();
            }
        })

        <!-- 添加视频水印标签 tag标签名字必填  x/y 未填则默认初始居中 tagAlpha|标签文字透明度 tagColor|标签文字颜色  注意颜色值前面不要加#号-->
        this.$refs.cameraObj.***({
            "mode": 1,   // 视频水印的标志, 0(或不传)是图片水印,>0都是视频水印
            "unShowControl": true,  // 是否显示缩放拉伸按钮的控制视图
            "tag":"上海市·嘉定区 晴 39°",  // 水印标签文字
            "x": 100,   // 水印标签的x坐标
            "y": 200,   // 水印标签的y坐标
            "tagAlpha": 120,  // 水印标签的透明度 0 - 255
            "tagColor":"FFFFFF",  // 水印标签的颜色
        });

        <!-- 停止录像 并设置防盗背景水印 -->
        this.$refs.cameraObj.stopRecord({logoText:'上海栾青网络科技有限公司',logoSize:46});

        // 上传函数
        testUpload(filePath){
            const $that = this;
            // 改为各位大神自己的服务器上传接口地址
            const urlPath = "https://.../.../...";

            const uploadTask = uni.uploadFile({
                url: urlPath, // 仅为示例,非真实的接口地址
                filePath: filePath,
                name: 'file',
                timeout:300 * 1000,  // 五分钟超时
                header: {
                    'Content-Type': 'application/json; charset=UTF-8', // 默认值
                    'Source-Type': 'WEB',
                    'Accept': '*/*',
                },
                success: (uploadFileRes) => {
                    console.log("上传成功:",uploadFileRes.data);
                },
                fail: (e)=>{
                    console.error("上传失败",e);
                }
            });
        },

    <!-- 注意:如果需要精确的宽高,请自行计算定义宽高并更改,上述代码示例中为了方便固定了750 1200 -->
对于需要上传的开发者,可在拍照/录像完成后在回调方法里得到照片/视频的保存路径,然后调用上传接口上传即可
开发者监听回调能得到哪些数据

回调的数据格式 receiveInfo:

{
    detail:{
        code:2003,
        message:'用户未授权',
        ratio:0.75 // 仅android端返回 此参数为android设备摄像头最优的宽高比例
        videoPath:'......', // 根据平台系统不同
        imagePath:'.......' // 根据平台系统不同
        isSaveImage2Album: ? // 是否保存图片到相册 用户可以在相册中看到照片
        isSaveVideo2Album: ? // 是否保存视频到相册 用户可以在相册中看到视频
        progress: // 视频水印处理进度  回调@onVideoWaterMarkProgress时生效
    }
}
code状态码:
200成功 2001拍照失败  2002录像失败  2003缺少权限  2004图片保存失败  2005|SD卡不可用,图片保存失败   2006视频处理状态码
视频示例代码
<template>
    <!-- add by xushiyong 创建nvue页面用来承载camera原生插件 -->
    <!-- nvue (native vue) 即原生渲染方式,效率和行囊更高,但在css方面存在存在差异和不足 -->
    <!-- nvue默认flex布局,不需要再额外指明 -->
    <!-- 无法使用百分比和calc计算函数,750rpx默认是屏宽, 也可以使用flex:1来指定 -->

    <view class="window" :style="'flex:1'">

        <camera-view
            mode=2
            ref="cameraObj" 
            class="camera_view"
            :defaultCamera="currentCamera"
            resolutionRatio="M"
            isSaveImage2Album="0"
            isSaveVideo2Album="0"
            @onTakePhotoSuccess="takePhotoSuccess" 
            @onTakePhotoFail="takePhotoFail" 
            @recordSuccess="recordSuccess" 
            @recordFail="recordFail" 
            @onVideoSaveSuccess="onSaveVideoSuccess"
            @=""
            @onVideoWaterMarkProgress="onVideoWaterMarkProgress"
            :style="'width:'+750+'rpx;flex:1'"
            >
            <!-- :style="'width:'+750+'rpx;flex:1'" -->
        </camera-view>

        <view v-if="tip" class="top_tip_view">{{tip}}</view>

        <view class="root_layout">

            <view class="func_align_bottom" style="display: flex;flex-direction: row;justify-content: space-between;flex: 1;">
                <view class="flex_row flex_align_center flex1 marbot130rpx" @click="addVideoWaterText">
                    <image src="../../../static/icon/icon_video_back.png" class="tip_play_icon"></image>
                    <text class="text_white fontSize16px marginLeft10px">添加水印</text>
                </view>

                <view class="ovay_white flex_align_center marbot50rpx" v-if="!this.isRecord">
                    <view class="ovay_red flex_align_center" @click="doControlRecord">
                        <text class="text_white fontSize16px text_weight">开始</text>
                        <text class="text_white fontSize16px text_weight">录制</text>
                    </view>
                </view>

                <view class="ovay_white flex_align_center marbot50rpx" v-else>
                    <view class="ovay_gray flex_align_center" @click="doControlRecord">
                        <text class="fontSize16px text_weight">{{curSecond}}s</text>
                        <text class="fontSize16px text_weight">停止</text>
                    </view>
                </view>

                <view class="flex_row flex_align_center flex1 marbot130rpx" @click="switchCamera">
                    <image src="../../../static/icon/icon_video_switch.png" class="tip_play_icon"></image>
                    <text class="text_white fontSize16px marginLeft10px">切换镜头</text>
                </view>
            </view>
        </view>
    </view>
</template>

<script>
    export default {
        data(){
            return{
                tip:undefined,
                curSecond:25,
                maxSecond:25,
                intervalObj:undefined,
                isRecord:false,
                currentCamera:"0" // "0"后置 "1"前置
            }
        },
        methods:{
            // 处理视频水印时的进度回调
            onVideoWaterMarkProgress(e){
                console.error("视频处理中:",e);
                this.tip = '视频处理中,当前进度:'+(e?.detail?.progress);
                const $that = this;
                if(e?.detail?.progress >= 99){
                    $that.tip = "视频水印添加已完成(查看日志获取保存路径)";
                    setTimeout(()=>{
                        if($that && $that.tip){
                            $that.tip = undefined;
                        }
                    }, 3000)
                }
            },
            onSaveVideoSuccess(e){
                console.error("视频保存成功!",e);
            },
            // 开始和停止录制
            doControlRecord(){
                console.error("录制控制器");

                if(this.isRecord){
                    if(this.curSecond >= 20){
                        uni.showToast({
                            title:'拍摄视频不能短于5秒',
                            icon:'none'
                        })
                        return ;
                    }

                    if(this.intervalObj){
                        clearInterval(this.intervalObj);
                    }

                    this.isRecord = false;
                    this.$refs.cameraObj.stopRecord();
                }else{
                    this.isRecord = true;
                    this.startTimeCount();
                    this.$refs.cameraObj.startRecord();
                }
            },
            // 添加视频水印(mode > 0 时为视频水印,==0 时为照片水印)
            // unShowControl是视频水印的边框和拉伸、旋转提示按钮
            addVideoWaterText(){
                console.error("添加水印start");
                this.$refs.cameraObj.***({
                    "mode":1,
                    "unShowControl": true, 
                    "tag":"视频文字水印",
                    "x": 100, 
                    "y": 200,
                    "tagSize":"m",
                    "tagAlpha": 120,
                    "tagColor":"FFFFFF",
                });
                console.error("添加水印end");
            },
            // 启动计时器
            startTimeCount(){
                const $that = this;
                $that.curSecond = $that.maxSecond;

                if($that.intervalObj){
                    clearInterval($that.intervalObj);
                }
                $that.intervalObj = setInterval(()=>{
                    // console.error("定时器",$that.curSecond);
                    if($that.curSecond > 0){
                        $that.curSecond -= 1;
                    }
                    if($that.curSecond <= 0){
                        if($that.intervalObj){
                            $that.doControlRecord();
                            clearInterval($that.intervalObj);
                        }
                    }
                },1000);
            },
            recordSuccess(e){
                console.error("视频录制成功:",e);
            },
            recordFail(e){
                console.error("视频录制失败:",e);
            },
            // 切换前后摄像头
            switchCamera(){
                if(this.currentCamera === "0"){
                    this.currentCamera = "1";
                    this.$refs.cameraObj.openFront();
                }else{
                    this.currentCamera = "0";
                    this.$refs.cameraObj.openBack();
                }
            }
        }
    }
</script>

<style>
    .func_align_bottom{
        align-items: flex-end;
    }
    .marbot50rpx{
        margin-bottom: 100rpx;
    }
    .marbot130rpx{
        margin-bottom: 160rpx;
    }
    .flex_row{
        display: flex;
        flex-direction: row;
    }
    .flex_align_center{
        align-items: center;
        justify-content: center;
    }
    .window{
        background-color: black;
        width: 750rpx;
        position: relative;
        /* position: relative; */
    }

    .root_layout{
        position: absolute;
        width: 750rpx;
        top: 0rpx;
        bottom: 0rpx;
        left: 0rpx;
        right: 0rpx;
        z-index: 50;
        /* position: relative; */
    }

    .camera_view{
        position: absolute;
        top: 0rpx;
        bottom: 0rpx;
        left: 0rpx;
        right: 0rpx;
        z-index: 100;
    }

    .tip_layout{
        top: 100rpx;
        left: 0rpx;
        right: 0rpx;
        /* margin-top: 100rpx; */
    }

    .func_layout{
        bottom: 80rpx;
        left: 0rpx;
        right: 0rpx;
    }

    .tip_text{
        top: 180rpx;
    }

    .tip_bg{
        background-color: #E00300;
        border-radius: 50rpx;
        padding-top: 14rpx;
        padding-bottom: 14rpx;
    }

    .tip_play_icon{
        width: 40rpx;
        height: 40rpx;
    }

    .top_tip_view{
        position: fixed;
        top: 0;
        left: 0;
        right: 0;
        height: 50rpx;
        color: #ffffff;
        background-color: #E00300;
        font-size: 28rpx;
    }

    .bg_image{
        width: 750rpx;
        height: 1280rpx;
    }

    .tip1{
        color: #E00300;
    }

    .ovay_white{
        width: 165rpx;
        height: 165rpx;
        background-color: white;
        /* border: 8rpx solid white; */
        border-radius: 100rpx;
    }

    .ovay_red{
        border: 6rpx solid black;
        background-color: #E00300;
        width: 150rpx;
        height: 150rpx;
        border-radius: 100rpx;
    }

    .ovay_red:active{
        background-color: #CCC;
        border: 6rpx solid red;
    }

    .ovay_gray{
        color: #777;
        border: 6rpx solid #BBB;
        background-color: #F6F6F6;
        width: 150rpx;
        height: 150rpx;
        border-radius: 100rpx;
    }

    .ovay_gray:active{
        background-color: #E00300;
        border: 6rpx solid red;
    }
    .stop_icon{
        background-color: black;
        border-radius: 10rpx;
        width: 45rpx;
        height: 45rpx;
    }
</style>
相机示例代码
<template>
    <view class="window">

        <view class="camera_layout">

            <!-- :style="'width:'+previewWidth+'px;height:'+previewHeight+'px;margin-left:-'+marginLeft+'px'" -->

            <!-- 相机原生插件 START -->
            <camera-view
                ref="cameraObj" 
                class="camera_view"
                :class="previewSizeStyle"
                isSaveImage2Album="1"
                isSaveVideo2Album="1"
                :defaultCamera="currentCamera"
                @receiveRatio="receiveRatio"
                @takePhotoSuccess="takePhotoSuccess" 
                @recordSuccess="recordSuccess" 
                @recordFail="recordFail" 
                @receiveInfo="receiveInfo"
                @onVideoSaveSuccess="onVideoSaveSuccess"
                @onImageSaveSuccess="onImageSaveSuccess"
                >
            </camera-view>
            <!-- 相机原生插件 END -->

            <!-- 倒计时START -->
            <!-- :style="'width:'+previewWidth+'px;height:'+previewHeight+'px;'" -->
            <view class="delay_time_layout" :class="previewSizeStyle">
                <text class="delay_time_text_size" v-if="delayTakePhotoTime>0">{{delayTakePhotoTime}}</text>
            </view>
            <!-- 倒计时END -->

            <!-- 水印布局 START -->
            <!-- :style="'width:'+previewWidth+'px;height:'+previewHeight+'px;'" -->
            <view class="water_layout" :class="previewSizeStyle">
                <view class="demo_flex_row marginLeft10px" @click.stop="gotoWaterSetting">
                    <!-- <uni-dateformat format="hh:mm" :date="currentDate" class="text_white text_weight fontSize30px"></uni-dateformat> -->
                    <text class="text_white text_weight px40">{{timeStr}}</text>
                    <view class="water_text_line marginLeft15px"></view>
                    <view class="marginLeft5px">
                        <!-- <uni-dateformat format="yyyy-MM-dd" :date="currentDate" class="text_white fontSize14px"></uni-dateformat> -->
                        <text class="text_white px14">{{dateStr}}</text>
                        <text class="text_white px14">{{weekDay}}</text>
                    </view>
                </view>
                <text class="text_white px14 marginLeft10px marginBottom5px" @click.stop="gotoWaterSetting" v-if="showAddress">{{address}}</text>
                <text class="text_white px14 marginLeft10px marginBottom10px" @click.stop="gotoWaterSetting" :style="'width:'+(previewWidth/2)+'rpx'" v-if="remark && showRemark">{{remark}}</text>
                <!-- <text class="text_white px14 marginLeft10px marginBottom10px" @click.stop="gotoWaterSetting" :style="'width:'+(previewWidth/2)+'rpx'" v-if="remark && showRemark">备注:{{remark}}</text> -->
                <!-- <view style="height: 10px;"></view> -->
            </view>
            <!-- 水印布局 END -->

            <view class="water_text_location flex_align_center" @click.stop="gotoResetLocation">
                <image class="water_text_location_icon" src="../../../static/icon/icon_location.png"></image>
                <text class="text_white px14 marginTop5px">重新定位</text>
            </view>
        </view>

            <!-- <view class="camera_top_bar"></view> -->
        <!-- <view class="root_layout"> -->
            <!-- 顶部操作栏 START -->

            <view class="camera_top_bar">

                <view class="demo_flex_row">
                    <uni-icons type="back" @click="doBackPage" size="25"></uni-icons>
                    <!-- <image src="../../../static/icon/icon_back.png" class="icon_size marginLeft10px" @click="doBackPage"></image> -->
                </view>
                <view class="demo_flex_row">
<!--                    <text class="ratio_view" v-if="previewRatio === 1" @click="switchPriviewRatio">1 : 1</text>
                    <text class="ratio_view" v-if="previewRatio === 2" @click="switchPriviewRatio">4 : 3</text>
                    <text class="ratio_view" v-if="previewRatio === 3" @click="switchPriviewRatio">16 : 9</text>
 -->                    
                    <!-- 闪光灯的开关 -->
                    <image :src="flashStatus === 0 ? '../../../static/icon/icon_flash_close.png':'../../../static/icon/icon_flash_open.png'" class="icon_size marginRight20px" @click="switchFlash"></image>
                    <!-- 延时拍摄 -->
                    <image src="../../../static/icon/icon_delay_take_photo.png" class="icon_size marginRight20px" @click="delayTakePhoto(5)"></image>
                    <!-- 切换摄像头 -->
                    <image src="../../../static/icon/icon_camera_switch.png" class="icon_size2 marginRight20px" @click="switchCamera"></image>
                </view>
            </view>
            <!-- 顶部操作栏 START -->

            <!-- <view class="flex1"></view> -->

            <!-- 底部操作栏 START-->
            <view class="demo_flex_row take_photo_layout">

                <!-- <image style="width: 60rpx;height: 60rpx;"></image> -->

                <view class="ovay_red demo_flex_row">
                    <text class="ovay_red_border" @click="takePhoto"></text>
                </view>

                <!-- <view></view> -->
            </view>
            <!-- 底部操作栏 END-->
        <!-- </view> -->

    </view>
</template>

<script>
    export default {
        data() {
            return {
                // 1|1:1  2|4:3  3|16:9
                flashStatus:0, // 闪光灯,默认关闭
                delayTakePhotoTime:0, // 拍摄的剩余延时 
                delayTakePhotoInterval:undefined, // 定时器的对象
                dateTimeInterval:undefined,
                currentCamera:'0', // 当前摄像头  0|后置  1|前置
                currentDate: new Date().getTime(),
                timeStr:'',
                dateStr:'',
                weekDay:'',
                remark:'',
                // 临时存储按压快门时的时间,因为每隔2秒会递增,用来记录可能会存在时间差
                tempTimeStr:'',
                tempDateStr:'',
                showRemark:false,
                showAddress:true,
                takePhotoBtnMarginBottom:200, // 拍照按钮距离底部的边距值
                previewRatio: 2,
                previewWidth:0,
                previewHeight:851,
                screenHeight:0,
                screenWidth:0,
                marginLeft:0,
                cameraRatio:0.75,
                address:'',
                latitude:0,
                longitude:0,
                previewSizeStyle:'design_size4_3',
            }
        },
        () {
            // previewRatio
            const sys = uni.getSystemInfoSync();
            this.previewWidth = sys.screenWidth;
            this.previewHeight = sys.screenHeight;
            this.screenHeight = sys.screenHeight;
            this.screenWidth = sys.screenWidth;
            this.calcPreviewSize();

            // once注册后只接受一次,因为不需要额外多次接受,而且也可避免忘记移除
            uni.$once("receiveWaterInfo",this.receiveWaterInfo);
            uni.$once("receivePoi",this.receivePoi);

            console.error("宽度:"+this.screenWidth+"  高度:"+this.screenHeight)

            // console.error("哈哈哈")
            // // 计算出来预览页面的分辨率尺寸 START
            // const sys = uni.getSystemInfoSync();
            // this.previewWidth = sys.screenWidth;
            // this.previewHeight = sys.screenHeight;
            // this.screenHeight = sys.screenHeight;
            // this.screenWidth = sys.screenWidth;
            // console.error("哈哈哈1")

            // let tempWidth = this.previewWidth * 1.20;
            // let tempHeight = tempWidth / 0.7;

            // let heightDiff = this.previewHeight - tempHeight;
            // // 如果屏幕高度仍大于计算出来的适配高度,就需要重新计算
            // if(heightDiff > 0){
            //  tempHeight = tempHeight + heightDiff * 2;
            //  tempWidth = tempHeight * 0.7;
            // };
            // console.error("哈哈哈2")

            // this.previewWidth = tempWidth;
            // this.previewHeight = tempHeight;

            // this.marginLeft = (this.previewWidth / 2 - this.screenWidth / 2);
            // console.error("哈哈哈4")

            // 0.7 的宽高比
            // 计算出来预览页面的分辨率尺寸 END
            // this.currentDate = new Date().getTime();

            // console.error("当前时间:",new Date());
            this.currentDate = new Date().getTime();
            this.dateStr = this.getNowDate(this.currentDate);
            this.timeStr = this.getNowTime(this.currentDate);

            if(!this.address){
                this.getLocation();
            }
            this.startTimeCount();
            this.getWeekDay();
        },
        onHide() {
            if(this.dateTimeInterval)
                clearInterval(this.dateTimeInterval);
        },
        methods: {
            receiveInfo(e){
                console.error("接收到报告:",e);
            },
            recordFail(e){

            },
            recordSuccess(e){

            },
            onVideoSaveSuccess(e){
                console.error("拍摄的视频保存成功:",e);
            },
            onImageSaveSuccess(){
                console.error("拍摄的照片保存成功",e);
            },
            // 计算预览页面的一些尺寸
            calcPreviewSize(){
                this.previewWidth = this.screenWidth;
                this.previewHeight = this.screenHeight;
                let platform = uni.getSystemInfoSync().platform;

                console.error("平台:"+platform+"宽度:",this.previewWidth,"  高度:",this.previewHeight);

                if(this.previewRatio === 1){
                    this.previewSizeStyle = 'design_size1_1';
                }else if(this.previewRatio === 2){
                    this.previewSizeStyle = 'design_size4_3';
                }else if(this.previewRatio === 3){
                    this.previewSizeStyle = 'design_size16_9';
                }

                this.previewHeight = this.previewWidth * 1.333333 * 2;//  + ("android" === platform ? 40 : 0);
                this.previewWidth = this.previewWidth * 2;//  + ("android" === platform ? 40 : 0);

                this.screenHeight = this.screenHeight * 2;
                this.screenWidth = this.screenWidth * 2;

                this.takePhotoBtnMarginBottom = ((this.screenHeight - this.previewHeight) / 2 + 50);
                this.takePhotoBtnMarginBottom = this.takePhotoBtnMarginBottom < 200 ? 200 : this.takePhotoBtnMarginBottom;

                // this.previewHeight = 500;
                // let ratio;
                // if(this.previewRatio === 1){
                //  ratio = 1;
                // }else if(this.previewRatio === 2){
                //  ratio = 3.0 / 4.0;
                // }else if(this.previewRatio === 3){
                //  ratio = 9.0 / 16.0;
                // }

                // this.previewHeight = this.previewWidth * ratio;
            },
            gotoResetLocation(){
                uni.navigateTo({
                    url:'/pages/module/camera/reset-location/reset-location?latitude='+this.latitude+'&longitude='+this.longitude
                })
            },
            takePhotoSuccess(e){
                uni.showToast({
                    title:'~ 拍照成功 ~',
                    icon:'none'
                })
            },
            doBackPage(){
                uni.navigateBack({
                    delta:1
                })
            },
            // 接受用户选择的新poi点
            receivePoi(res){
                this.address = res;
                console.error("接收到:",res);
            },
            // 接收修改后的水印设置信息
            receiveWaterInfo(res){
                console.error("接收到了水印配置信息:",res);
                this.showRemark = res.showRemark;
                this.showAddress = res.showAddress;
                this.remark = res.remark;
            },
            gotoWaterSetting(){
                uni.navigateTo({
                    url:"/pages/module/camera/water-setting/water-setting?timeStr="+this.timeStr+"&dateStr="+this.dateStr+"&weekDay="+this.weekDay+"&address="+this.address
                })
            },
            getWeekDay(){
                this.weekDay =  "星期"+"日一二三四五六".charAt(new Date().getDay());
            },
            startTimeCount(){
                const $that = this;
                $that.dateTimeInterval = setInterval(()=>{
                    $that.currentDate = new Date().getTime();
                    $that.dateStr = $that.getNowDate($that.currentDate);
                    $that.timeStr = $that.getNowTime($that.currentDate);
                    // console.error("时间L:",$that.timeStr,'  ',$that.dateStr);
                },3000);
            },
            // 切换摄像头
            switchCamera(){
                if(this.currentCamera === "0"){
                    this.currentCamera = "1";
                    this.$refs.cameraObj.openFront();
                }else{
                    this.currentCamera = "0";
                    this.$refs.cameraObj.openBack();
                }
            },
            // 延迟拍摄
            delayTakePhoto(delay){
                const $that = this;
                $that.delayTakePhotoTime = delay;

                $that.delayTakePhotoInterval = setInterval(()=>{
                    $that.delayTakePhotoTime -= 1;
                    // 清除取消计时器
                    if($that.delayTakePhotoTime <= 0){
                        if($that.delayTakePhotoInterval)
                            clearInterval($that.delayTakePhotoInterval);
                        $that.takePhoto();  
                    }
                },1000);
            },
            // 切换闪光灯
            switchFlash(){
                if(this.flashStatus === 0){
                    this.flashStatus = 1;
                    this.$refs.cameraObj.openFlash();
                }else{
                    this.flashStatus = 0;
                    this.$refs.cameraObj.closeFlash();
                }
            },
            // 获取插件回传的最优宽高比
            receiveRatio(e){
                console.error("接收到了最优的宽高比例:",e);
                this.cameraRatio = e.detail.ratio;
            },
            // 切换比例模式
            switchPriviewRatio(){
                if(this.previewRatio === 3){
                    this.previewRatio = 2;
                }else if(this.previewRatio == 2){
                    this.previewRatio = 3;
                }else if(this.previewRatio == 1){
                    this.previewRatio = 2;
                }

                this.calcPreviewSize();
            },
            getLocation(){
                const $that = this;
                $that.address = '正在定位中~';

                uni.getLocation({
                    type: 'gcj02',
                        geocode: true,
                        isHighAccuracy:true,
                        success:(res) => {
                            $that.latitude = res.latitude;
                            $that.longitude = res.longitude;

                            let data = res.address;
                            $that.address = data.city + data.district + " · "+ (data.poiName ? data.poiName : (data.street ? data.street:"")+(data.streetNum ? data.streetNum:""));
                            console.log('当前位置:' , $that.address);

                            // "country": "中国",
                            // "province": "上海市",
                            // "city": "上海市",
                            // "district": "嘉定区",
                            // "street": "宝乐路",
                            // "streetNum": "58号",
                            // "poiName": "阳光葡提公馆",
                            // "cityCode": "021"

                            // $that.$refs.cameraObj.***($that.address,$that.tempDateStr,$that.tempTimeStr,$that.weekDay);
                    }
                }); 
            },
            takePhoto(){
                console.error("开始拍照1")
                if(!this.address){
                    uni.showToast({
                        title:'正在获取定位信息',
                    })
                    return;
                }
                this.tempTimeStr = this.timeStr;
                this.tempDateStr = this.dateStr;                                                                                                                                    
                // this.$refs.cameraObj.***((this.showAddress ? this.address:''),this.tempDateStr,this.tempTimeStr,this.weekDay,(this.showRemark ? this.remark:''),"· 工友会 ·|水印相机");
                // 设置水印
                this.$refs.cameraObj.***({
                    "date":this.tempDateStr || "",
                    "logo":"·工友会·|水印相机",
                    "address":(this.showAddress ? this.address:""),
                    "time":this.tempTimeStr || "",
                    "week":this.weekDay || "",
                    "remark":(this.showRemark ? this.remark:"")
                });
                this.$refs.cameraObj.takePhoto();
            },
            getNowDate(dateTime) {
                let date = new Date(dateTime);
                let year = date.getFullYear();
                let month = date.getMonth() + 1;
                let day = date.getDate();
                if (month.toString().length == 1) {
                    month = "0" + month;
                }
                if (day.toString().length == 1) {
                    day = "0" + day;
                }
                return year + "-" + month + "-" + day;
            },
            getNowTime(dateTime) {
                let date = new Date(dateTime);
                let hours = date.getHours();
                let min = date.getMinutes();
                // let sec = date.getSeconds();

                if (hours.toString().length == 1) {
                    hours = "0" + hours;
                }
                if (min.toString().length == 1) {
                    min = "0" + min;
                }
                // if (sec.toString().length == 1) {
                //  sec = "0" + sec;
                // }
                return hours + ":" + min ;
            },
        }
    }
</script>

<!-- <style src="@/pages/module/camera/camera.css"></style> -->
<!-- nvue必须要重新创建一个style标签来写新的css ,不能在上面引入外部css的style里写-->
<style>

    .demo_flex_row{
        display: flex;
        flex-direction: row;
        align-items: center;
        justify-content: center;
    }

    .marginRight20px {
        margin-right: 40rpx;
    }
    .window{
        background-color: white;
        width: 750rpx;
        position: absolute;
        height: 1624rpx;
    }
    .camera_top_bar{
        background-color: white;
        height: 176rpx;
        max-height: 176rpx;
        padding-top: 88rpx;
        padding-bottom: 16rpx;
        flex-direction: row;
        align-items: flex-end;
        justify-content: space-between;
    }
    .design_size4_3{
        width: 750rpx;
        height: 1000rpx;
    }
    .design_size16_9{
        width: 750rpx;
        height: 1333rpx;
    }
    .design_size1_1{
        width: 750rpx;
        height: 750rpx;
    }

    .icon_size{
        width: 48rpx;
        height: 48rpx;
    }
    .icon_size2{
        width: 42rpx;
        height: 42rpx;
    }

    .ratio_view{
        border: 2rpx solid #979797;
        border-radius: 6px;
        padding: 2rpx 12rpx;
        color: #333333;
        width: 60px;
        margin-right: 65rpx;
        text-align: center;
    }
    .delay_time_text_size{
        color: white;
        font-size: 150rpx;
    }
    .delay_time_layout{
        position: absolute;
        top: 0px;
        bottom: 0rpx;
        left: 0rpx;
        right: 0rpx;
        z-index: 100;
        font-weight: bold;
        flex-direction: row;
        justify-content: center;
        align-items: center;
    }
    .camera_layout{
        position: absolute;
        top: 176rpx;
        bottom: 0rpx;
        left: 0rpx;
        right: 0rpx;
        z-index: 100;
    }
    .camera_view{
        position: absolute;
        top: 0rpx;
        bottom: 0rpx;
        left: 0rpx;
        right: 0rpx;
        z-index: 100;
        /* border: 5rpx solid #CE3D3A; */
    }
    .text_white {
        color: white;
    }
    /* 新的水印布局css START */
    .water_layout{
        align-items: flex-start;
        justify-content: flex-end;
        z-index: 200;
    }
    /* 新的水印布局css END */

    .water_text_layout{
        position: relative;
        top: 0rpx;
        bottom: 0rpx;
        left: 10px;
        right: 0rpx;
        z-index: 100;
    }

    .water_text_location{
        position: absolute;
        right: 20px;
        top: 860rpx;
        z-index: 100;
    }
    .water_text_location_icon{
        width: 45rpx;
        height: 45rpx;
    }
    .water_text_line{
        height: 32px;
        width: 5px;
        background-color: #CE3D3A;
    }

    .water_text_bottom_20{
        position: absolute;
        bottom: 20rpx;
        left: 0rpx;
    }

    .water_text_bottom_40{
        position: absolute;
        bottom: 40rpx;
        left: 0rpx;
    }

    .root_layout{
        position: absolute;
        width: 750rpx;
        top: 0rpx;
        bottom: 0rpx;
        left: 0rpx;
        right: 0rpx;
        z-index: 50;
        /* position: relative; */
    }

    .take_photo_layout{
        position: absolute;
        bottom: 0rpx;
        left: 0rpx;
        right: 0rpx;
        height: 448rpx;
    }

    .ovay_red{
        width: 145rpx;
        height: 145rpx;
        background-color: #CE3D3A;
        /* border: 8rpx solid white; */
        border-radius: 100rpx;
    }

    .ovay_red_border{
        border: 2rpx solid #F0F0F0;
        background-color: #CE3D3A;
        width: 130rpx;
        height: 130rpx;
        border-radius: 100rpx;
    }

    .ovay_red_border:active{
        background-color: #CCC;
        border: 2rpx solid red;
    }

    .px14{
        font-size: 14px;
    }
    .px30{
        font-size: 30px;
    }
    .px40{
        font-size: 80rpx;
    }

    .marginLeft5px {
        margin-left: 10rpx;
    }

    .marginLeft10px {
        margin-left: 20rpx;
    }

    .marginLeft15px {
        margin-left: 30rpx;
    }
</style>

上海栾青网络科技有限公司

*** (同微信)

隐私、权限声明

1. 本插件需要申请的系统权限列表:

"android.permission.CAMERA", "android.permission.RECORD_AUDIO", "android.permission.WRITE_EXTERNAL_STORAGE"

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

插件不采集任何数据

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

无

暂无用户评论。