当前位置: 首页 > news >正文

网站和做空间沈阳网站建设制作公司

网站和做空间,沈阳网站建设制作公司,门户网站的建设方式有哪些,线上营销存在的问题一、需求前提 特殊场景中,需要拍照的同时打开闪光灯,(例如黑暗场景下的设备维护巡检功能)。 起初我是用的uviewui中的u-upload组件自带的拍照功能,但是这个不支持拍照时打开闪光灯,也不支持从通知栏中打开…

一、需求前提

特殊场景中,需要拍照的同时打开闪光灯,(例如黑暗场景下的设备维护巡检功能)。

起初我是用的uviewui中的u-upload组件自带的拍照功能,但是这个不支持拍照时打开闪光灯,也不支持从通知栏中打开闪光灯。

二、解决方案

采用组合形式解决:

  1. 使用uniapp官方内置组件中的 媒体组件:camera 实现闪光灯拍照,uni.createCameraContext()获取返回图片结果
  2. 结合uniapp官方内置组件中的 视图容器:cover-view 做定制化布局

1. 媒体组件:camera

camera 是页面内嵌的区域相机组件。注意这不是点击后全屏打开的相机。
其中flash属性可以动态实现拍照闪光灯的功能,值为auto, on, off, torch

拍照动作可以使用uni.createCameraContext()获取拍照的图片结果,再做后续操作。

注意

  • camera 组件是由客户端创建的原生组件,它的层级是最高的,不能通过 z-index 控制层级。可使用 cover-view 、cover-image 覆盖在上面。
  • 同一页面只能插入一个 camera 组件。(多次打开自定义的拍照界面可以使用v-if做销毁)

2. 视图容器:cover-view

cover-view是覆盖在原生组件上的文本视图。
app-vue和小程序框架,渲染引擎是webview的。但为了优化体验,部分组件如map、video、textarea、canvas通过原生控件实现,原生组件层级高于前端组件(类似flash层级高于div)。为了能正常覆盖原生组件,设计了cover-view。

注意

  • 容器内的每一个元素最好都用cover-view标签包裹(包括文字内容),否则会出现渲染异常问题。

三、 示例

在这里插入图片描述

<!--* @Description: 自定义文件上传组件,支持拍照、闪光灯、本地图片选择* @Doc: 双向绑定使用 <customUpload :modelValue.sync="test"></customUpload>* @Author: y* @Date: 2024-03-07 09:51:25
-->
<template><view class="custom-upload"><!-- 预览图片 --><template v-if="previewImage"><view class="file-item" v-for="(item,index) in fileList" :key="index" :style="[{width,height}]"><view v-if="item.status ==='uploading'" class="file-uploading"><u-loading-icon color="#19be6b"></u-loading-icon></view><u--image v-else :showLoading="true" :src="item.thumb || item.url" :width="width" :height="height"@tap="onPreviewImage(item)"><template v-slot:loading><!-- 此处后期需要优化为本地文件地址,避免走两次加载 --><u-loading-icon text="加载中" textSize="18"></u-loading-icon></template></u--image><!-- 删除按钮角标 --><view class="upload-deletable" @tap.stop="deleteItem(index)"><view class="upload-deletable-icon"><u-icon name="close" color="#ffffff" size="10"></u-icon></view></view><!-- 文件状态角标 --><view class="upload-success" v-if="item.status === 'success'"><view class="upload-success-icon"><u-icon name="checkmark" color="#ffffff" size="12"></u-icon></view></view></view></template><!-- 如果图片数量在设定范围内 --><template v-if="isInCount"><view class="upload-button" @tap="chooseOperationType" :style="[{width,height}]"><u-icon name="plus" size="26" color="#2979ff"></u-icon><text v-if="uploadText" class="upload-button-text">{{ uploadText }}</text><text v-else class="upload-button-text">上传</text></view></template><!-- 选项弹出层 --><u-popup :show="showOptionsPopup" :round="10" mode="bottom" :closeable="true" @close="this.showOptionsPopup=false"><view class="option-list"><view v-if="showTakePhoto" class="option-btn" @tap="onTakePhoto">拍照</view><view v-if="showChoosePhoto" class="option-btn" @tap="onChoosePhoto">从相册选择</view><view class="option-btn-close" @tap="this.showOptionsPopup=false">取消</view></view></u-popup><!-- 相机弹出层 --><u-overlay v-if="showCameraPopup" :show="showCameraPopup" mask-click-able="false"><!-- 添加v-if避免缓存相机,每次打开都需要重新创建 --><view class="camera-container"><camera device-position="back" :flash="flashStatus" style="width: 100%; height: calc(100% - 200rpx);"><cover-view class="user-location"><!-- 此处只可以使用cover-image插入图片(待开发) --><cover-view v-if="!userLocationRefreshing" class="icon-location"></cover-view><cover-view v-else class="icon-location-refreshing"></cover-view><cover-view v-if="userLocationRefreshing" style="color: #ff9900;">加载中...</cover-view><cover-view>{{userLocation||'---'}}</cover-view></cover-view></camera><view class="camera-option-list"><view class="option-btn" @tap.stop="$u.throttle(refreshLocation, 1000)">刷新定位</view><view class="option-btn" @tap.stop="takePhoto">拍照</view><view class="option-btn" @tap.stop="openFlash">{{flashStatus==='auto'?'闪光灯长亮':'闪光灯自动'}}</view></view></view></u-overlay></view>
</template><script>import { mapState, mapActions } from 'vuex';import { apiUrl } from '@/utils/env.js'; // 全局项目地址export default {name: "customUpload",props: {// 对外:上传的文件列表 {status:success|uploading|fail, url:''}modelValue: {type: Array,default: () => []},showTakePhoto: {type: Boolean,default: true},showChoosePhoto: {type: Boolean,default: true},// 上传组件的宽度width: {type: String,default: '180rpx'},// 上传组件的高度height: {type: String,default: '180rpx'},// 上传图标的文字uploadText: {type: String,default: ''},// 上传文件的存储位置fileStorageLocation: {type: String,default: 'yhtest'},},data() {return {fileList: [], // 对内:上传的文件列表 {status:success|uploading|fail, url:''}isFileError: false, // 文件列表出现故障(待开发)previewImage: false, // 预览图片isInCount: true, // 是在限制的文件数量范围内showOptionsPopup: false, // 选项弹出层showCameraPopup: false, // 相机弹出层flashStatus: 'auto', // 闪光灯,值为auto, on, off, torchuserLocationRefreshing: false, // 用户位置刷新中userLocation: '', // 用户位置};},watch: {// 监听文件列表数据长度变化,存在数据则显示预览fileList(newData, oldData) {this.$emit('update:modelValue', newData);this.previewImage = newData.length ? true : false;},modelValue: {handler: function(newData, oldData) {this.fileList = newData;},immediate: true,deep: true}},computed: {...mapState(['userInfo']),},async created() {this.flashStatus = 'auto';},methods: {// 引入vuex中方法...mapActions(['getUserLocation']),// 选择操作类型chooseOperationType() {this.showOptionsPopup = true;this.refreshLocation(); // 获取定位},// 拍照onTakePhoto() {this.flashStatus = 'auto';this.showOptionsPopup = false;this.showCameraPopup = true;},//从文件夹选择onChoosePhoto() {this.showOptionsPopup = false;uni.chooseMedia({count: 9,mediaType: ['image', 'video'], // 文件类型sourceType: ['album'], // 指定从相册获取maxDuration: 30,success: async (res) => {// 按顺序执行异步操作,异步迭代for (let item of res.tempFiles) {const tempUrl = item.tempFilePath;console.log('拍照的临时图片地址:', tempUrl);this.fileList.push({status: 'uploading', // 状态为上传中url: tempUrl, // 文件的临时地址thumb: tempUrl, // 文件的临时地址});const realUrl = await this.uploadFilePromise(item.tempFilePath); // 上传图片console.log('上传返回的真实图片地址:', realUrl);this.fileList.pop();this.fileList.push({status: 'success', // 状态为上传中url: realUrl, // 文件的真实地址thumb: tempUrl, // 文件的临时地址});}},fail: (err) => {console.log('文件夹选择报错:', err);},})},// 手动拍照async takePhoto() {console.log('拍照按钮点击---------', new Date());// 创建并返回 camera 组件的上下文 cameraContext 对象const ctx = uni.createCameraContext();setTimeout(() => {this.showCameraPopup = false; // 关闭弹出层}, 200);await ctx.takePhoto({quality: 'high',success: async (res) => {uni.$u.toast('拍摄成功');// 返回照片文件的临时路径const tempUrl = res.tempImagePath;console.log('拍照的临时图片地址:', tempUrl);this.fileList.push({status: 'uploading', // 状态为上传中url: tempUrl, // 文件的临时地址thumb: tempUrl, // 文件的临时地址});const realUrl = await this.uploadFilePromise(res.tempImagePath); // 上传图片console.log('上传返回的真实图片地址:', realUrl);this.fileList.pop();this.fileList.push({status: 'success', // 状态为上传中url: realUrl, // 文件的真实地址thumb: tempUrl, // 文件的临时地址});},fail: (err) => {console.log('手动拍照报错:', err);},});},// 打开闪光灯openFlash() {if (this.flashStatus === 'auto') {this.flashStatus = 'torch'; // 闪光灯长亮} else {this.flashStatus = 'auto'; // 闪光灯长亮}},// 刷新定位async refreshLocation() {this.userLocationRefreshing = true;this.userLocation = await this.getUserLocation(); // 获取用户位置信息setTimeout(() => {this.userLocationRefreshing = false;}, 1000)},// 上传图片async uploadFilePromise(filePath) {return new Promise((resolve, reject) => {let token = "Bearer ";token += uni.getStorageSync('token');let a = uni.uploadFile({url: `${apiUrl}/wx/wxfile/upload`, // 接口地址filePath: filePath,name: 'multipartFile', // 此处默认值是file,实际需要根据后端接口做更改header: {'Content-Type': 'multipart/form-data','Authorization': token},// HTTP 请求中其他额外的 form dataformData: {"cameraMan": this.userInfo.nickName || '---', // 拍摄人"cameraSite": this.userLocation || '---', // 拍摄位置"customPath": this.fileStorageLocation, // 自定义文件存放路径},success: (res) => {let parseData = JSON.parse(res.data);console.log("上传成功的地址", parseData);resolve(parseData.data);}});})},// 按下标删除图片deleteItem(index) {this.fileList.splice(index, 1);},// 预览图片onPreviewImage(item) {if (item.status !== 'success') return;uni.previewImage({// 先filter找出为图片的item,再返回filter结果中的图片urlurls: this.fileList.filter((item) => item.status === 'success' && item.url).map((item) => item.url || item.thumb),current: item.url || item.thumb,fail() {uni.$u.toast('预览图片失败')},});},}}
</script><style lang="scss">.custom-upload {// border: 1px dashed red;display: flex;flex-direction: row;flex-wrap: wrap;.file-item {position: relative;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 2px;margin: 0 8px 8px 0;box-sizing: border-box;.upload-deletable {position: absolute;top: 0;right: 0;background-color: #373737;height: 14px;width: 14px;display: flex;flex-direction: row;border-bottom-left-radius: 100px;align-items: center;justify-content: center;z-index: 3;.upload-deletable-icon {position: absolute;-webkit-transform: scale(0.7);transform: scale(0.7);top: 0px;right: 0px;}}.upload-success {position: absolute;bottom: 0;right: 0;display: flex;flex-direction: row;border-style: solid;border-top-color: transparent;border-left-color: transparent;border-bottom-color: #5ac725;border-right-color: #5ac725;border-width: 9px;align-items: center;justify-content: center;.upload-success-icon {position: absolute;-webkit-transform: scale(0.7);transform: scale(0.7);bottom: -10px;right: -10px;}}}.upload-button {padding: 10rpx;display: flex;flex-direction: column;justify-content: center;align-items: center;background-color: #f4f5f7;border-radius: 2px;margin: 0 8px 8px 0;box-sizing: border-box;.upload-button-text {margin-top: 8rpx;color: #ccc;text-align: center;}}.option-list {display: flex;flex-direction: column;justify-content: center;align-items: center;padding: 40rpx 40rpx 20rpx 40rpx;.option-btn {border-bottom: 1px solid #ccc6;padding: 30rpx;width: 100%;text-align: center;font-size: 16px;}.option-btn-close {padding: 30rpx;width: 100%;text-align: center;font-size: 16px;}}.camera-container {position: relative;width: 100%;height: 100%;.user-location {position: absolute;bottom: 20rpx;left: 20rpx;padding: 20rpx;background-color: #cccccc9c;color: #fff;border-radius: 10rpx;display: flex;flex-direction: row;justify-content: center;align-items: center;.icon-location {width: 30rpx;height: 30rpx;border-radius: 50%;background-color: #19be6b;margin: 6rpx;border: 2px solid #ecddd5;}.icon-location-refreshing {width: 30rpx;height: 30rpx;border-radius: 50%;background-color: #ff9900;margin: 6rpx;border: 2px solid #ecddd5;}}.camera-option-list {width: 100%;height: 200rpx;background-color: #f4f5f7;display: flex;flex-direction: row;.option-btn {display: flex;flex-direction: column;justify-content: center;border: 2px solid #2979ff;box-sizing: border-box;height: 100%;width: 33.33%;text-align: center;font-size: 18px;}}}}
</style>

文章转载自:
http://erysipelothrix.rtzd.cn
http://semiliterate.rtzd.cn
http://hypocrite.rtzd.cn
http://bungarotoxin.rtzd.cn
http://tamar.rtzd.cn
http://ism.rtzd.cn
http://autoerotism.rtzd.cn
http://vegetable.rtzd.cn
http://crackajack.rtzd.cn
http://opporunity.rtzd.cn
http://stair.rtzd.cn
http://ectomere.rtzd.cn
http://yill.rtzd.cn
http://mun.rtzd.cn
http://arbutus.rtzd.cn
http://micrococcus.rtzd.cn
http://ultraconservatism.rtzd.cn
http://chafer.rtzd.cn
http://codein.rtzd.cn
http://orthognathous.rtzd.cn
http://stigmatism.rtzd.cn
http://scholastic.rtzd.cn
http://putrefy.rtzd.cn
http://hareem.rtzd.cn
http://defectivation.rtzd.cn
http://outfield.rtzd.cn
http://protochordate.rtzd.cn
http://pneumograph.rtzd.cn
http://autoalarm.rtzd.cn
http://frigidarium.rtzd.cn
http://evildoer.rtzd.cn
http://tuscany.rtzd.cn
http://urological.rtzd.cn
http://claxon.rtzd.cn
http://dwelling.rtzd.cn
http://patras.rtzd.cn
http://hemochromogen.rtzd.cn
http://kwangchowan.rtzd.cn
http://sandrock.rtzd.cn
http://deovolente.rtzd.cn
http://portulaca.rtzd.cn
http://achiote.rtzd.cn
http://landswoman.rtzd.cn
http://serialisation.rtzd.cn
http://curvulate.rtzd.cn
http://plasterer.rtzd.cn
http://organosilicon.rtzd.cn
http://utility.rtzd.cn
http://intuc.rtzd.cn
http://unsatisfactory.rtzd.cn
http://dript.rtzd.cn
http://commiserative.rtzd.cn
http://facto.rtzd.cn
http://ruthenia.rtzd.cn
http://rationally.rtzd.cn
http://vulgus.rtzd.cn
http://oily.rtzd.cn
http://phonily.rtzd.cn
http://telecom.rtzd.cn
http://dished.rtzd.cn
http://codfish.rtzd.cn
http://vitiator.rtzd.cn
http://matrilateral.rtzd.cn
http://obdurate.rtzd.cn
http://hokum.rtzd.cn
http://zg.rtzd.cn
http://immunocompetence.rtzd.cn
http://essentiality.rtzd.cn
http://veal.rtzd.cn
http://sarum.rtzd.cn
http://opiumism.rtzd.cn
http://whereupon.rtzd.cn
http://illyria.rtzd.cn
http://ptyalectasis.rtzd.cn
http://octet.rtzd.cn
http://baobab.rtzd.cn
http://schoolteaching.rtzd.cn
http://motorise.rtzd.cn
http://discovrery.rtzd.cn
http://isotype.rtzd.cn
http://screamingly.rtzd.cn
http://undeniable.rtzd.cn
http://decoder.rtzd.cn
http://dispope.rtzd.cn
http://khalifa.rtzd.cn
http://cytometry.rtzd.cn
http://arithmancy.rtzd.cn
http://unselfconscious.rtzd.cn
http://katabatic.rtzd.cn
http://illume.rtzd.cn
http://offside.rtzd.cn
http://limehouse.rtzd.cn
http://interjaculate.rtzd.cn
http://vesperal.rtzd.cn
http://trigonon.rtzd.cn
http://decagramme.rtzd.cn
http://macroptic.rtzd.cn
http://fatso.rtzd.cn
http://lucknow.rtzd.cn
http://sabbath.rtzd.cn
http://www.hrbkazy.com/news/69006.html

相关文章:

  • 微信网站平台怎么建立哪里有学电脑培训班
  • 开淘宝店和自己做购物网站哪个好台湾新闻最新消息今天
  • 网站用户注册怎么做公司网站的推广方案
  • seo信息优化西安网站seo外包
  • 如何替别人建网站挣钱深圳网站建设找哪家公司好
  • 旅游做的视频网站怎样做网站的优化、排名
  • 做网站一般用什么 语言专业拓客公司联系方式
  • 网站上传文件代码软文营销方法有哪些
  • 有没有做翻译赚钱的网站一个产品的网络营销方案
  • 网站开发要什么软件最近的热点新闻
  • 用jquery做网站好吗威海seo优化公司
  • 优秀网站设计欣赏合肥网站建设
  • 网站开发进度确认单网站页面怎么优化
  • 做图表的网站推荐财经新闻每日财经报道
  • 建筑设计网上接单平台网站收录优化
  • 做网站编辑累吗百度公司介绍
  • 企业网站怎么做html培训心得体会1500字
  • ASP 动态网站建设襄阳seo优化排名
  • 鲜花网站建设项目策 划书免费发seo外链平台
  • 推广计划有哪些杭州百度首页优化
  • 福建省建设安全监督站的网站找人帮忙注册app推广
  • 西安高新区网站建设谷歌商店下载不了软件
  • 做照片的网站百度域名收录
  • 做网站在哪里找素材北京网站制作公司
  • 网站做装修效果图免费b站推广网站
  • jsp网站建设期末作业seo网站优化
  • 证券投资网站做哪些内容成都seo推广员
  • 奥迪汽车建设网站小红书如何引流推广
  • 百度搜索搜不到网站成都百度搜索排名优化
  • h5网站建设功能计划表杭州网站设计