邃芒智像大屏项目
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 

499 行
11 KiB

  1. <template>
  2. <div class="page">
  3. <div class="top">
  4. <div class="example">
  5. <div>文案与模板提示区域</div>
  6. </div>
  7. <div class="model">
  8. <img :src="modelUrl" alt="" />
  9. </div>
  10. </div>
  11. <div class="bottom">
  12. <video
  13. v-if="!isSuccess"
  14. id="video"
  15. muted
  16. autoplay="autoplay"
  17. :controls="false"
  18. ></video>
  19. <div v-if="!isSuccess">
  20. <div class="selectImg" @click="uploadImg">
  21. <img src="../../assets/img/selectImg.png" />
  22. <div class="uploadText">上传照片</div>
  23. </div>
  24. <div id="action" @click="takePicture">
  25. <div class="circleInside"></div>
  26. </div>
  27. </div>
  28. <div v-if="isSuccess">
  29. <div class="selectImg" @click="uploadImg">
  30. <img src="../../assets/img/selectImg.png" />
  31. <div class="uploadText">上传照片</div>
  32. </div>
  33. <div class="confirm" @click="confirmPhoto">
  34. <img src="../../assets/img/success.png" />
  35. <div class="uploadText">就这张了</div>
  36. </div>
  37. <div class="reTry" @click="reTry">
  38. <img src="../../assets/img/reTry.png" />
  39. <div class="uploadText">重新拍摄</div>
  40. </div>
  41. </div>
  42. <canvas
  43. v-if="isShowCanvas"
  44. id="canvas"
  45. style="width: 1530; height: 950"
  46. ></canvas>
  47. <div v-if="isSuccess" class="preview">
  48. <img v-if="!isUpload" class="fromCamera" :src="CimgSrc" />
  49. <img v-if="isUpload" class="fromUpload" :src="UimgSrc" />
  50. </div>
  51. </div>
  52. <!-- Top section -->
  53. <u-overlay class="overlay" :show="showQrCode" opacity="0.9">
  54. <view class="content">
  55. <view class="imageBox">
  56. <image :src="QRCodeUrl" mode="scaleToFill" />
  57. </view>
  58. <text>打开微信扫码上传照片</text>
  59. <view class="orangeBtn" style="margin-top: 100rpx" @click="cancelUplaod"
  60. >取&nbsp;消</view
  61. >
  62. </view>
  63. </u-overlay>
  64. </div>
  65. </template>
  66. <script setup>
  67. import { ref, onMounted } from "vue";
  68. import { onLoad, onShow, onUnload } from "@dcloudio/uni-app";
  69. import { getImageQrcode, findImage } from "../../api/camera.js";
  70. let CimgSrc = ref(""); // 相机拍照的图片路径,上传前需校验
  71. let UimgSrc = ref(""); // 用户上传的图片路径,上传无需校验
  72. let isSuccess = ref(false);
  73. let isShowCanvas = ref(true);
  74. let isUpload = ref(false);
  75. let modelUrl = ref("");
  76. let QRCodeUrl = ref("");
  77. let showQrCode = ref(false);
  78. let timer = ref(null);
  79. const startCamera = () => {
  80. function getUserMedia(constraints, success, error) {
  81. if (navigator.mediaDevices.getUserMedia) {
  82. //最新的标准API
  83. navigator.mediaDevices
  84. .getUserMedia({
  85. audio: {
  86. echoCancellation: true,
  87. },
  88. video: {
  89. facingMode: "user",
  90. },
  91. })
  92. .then(success)
  93. .catch(error);
  94. } else if (navigator.webkitGetUserMedia) {
  95. //webkit核心浏览器
  96. navigator.webkitGetUserMedia(constraints, success, error);
  97. } else if (navigator.mozGetUserMedia) {
  98. //firfox浏览器
  99. navigator.mozGetUserMedia(constraints, success, error);
  100. } else if (navigator.getUserMedia) {
  101. //旧版API
  102. navigator.getUserMedia(constraints, success, error);
  103. }
  104. }
  105. const video = document.querySelector("video.uni-video-video");
  106. let canvas = document.querySelector("canvas.uni-canvas-canvas");
  107. const action = document.querySelector("#action");
  108. let context = canvas.getContext("2d");
  109. function success(stream) {
  110. //兼容webkit核心浏览器
  111. let CompatibleURL = window.URL || window.webkitURL;
  112. //将视频流设置为video元素的源
  113. console.log(stream);
  114. //video.src = CompatibleURL.createObjectURL(stream);
  115. video.srcObject = stream;
  116. video.play();
  117. }
  118. function error(error) {
  119. console.log(`访问用户媒体设备失败${error.name}, ${error.message}`);
  120. }
  121. if (
  122. navigator.mediaDevices.getUserMedia ||
  123. navigator.getUserMedia ||
  124. navigator.webkitGetUserMedia ||
  125. navigator.mozGetUserMedia
  126. ) {
  127. //调用用户媒体设备, 访问摄像头
  128. getUserMedia(
  129. {
  130. audio: false,
  131. video: true,
  132. },
  133. success,
  134. error
  135. );
  136. } else {
  137. alert("不支持访问用户媒体");
  138. }
  139. action.addEventListener("click", function () {
  140. uni.showToast({
  141. title: "准备好了吗?",
  142. icon: "success",
  143. });
  144. setTimeout(() => {
  145. let i = 3;
  146. const timer = setInterval(() => {
  147. uni.showLoading({
  148. title: i,
  149. });
  150. i--;
  151. console.log(i);
  152. if (i == 0) {
  153. clearInterval(timer);
  154. setTimeout(() => {
  155. uni.hideLoading();
  156. canvas.width = 1530;
  157. canvas.height = 950;
  158. context.drawImage(video, 0, 0);
  159. const dataURL = canvas.toDataURL("image/png");
  160. CimgSrc.value = dataURL;
  161. UimgSrc.value = "";
  162. setTimeout(() => {
  163. isShowCanvas.value = false;
  164. isSuccess.value = true;
  165. }, 10);
  166. }, 1000);
  167. }
  168. }, 1100);
  169. }, 1000);
  170. });
  171. // 备用方案
  172. // action.addEventListener("click", function () {
  173. // context.drawImage(video, -50, -50, 310, 220);
  174. // const dataURL = canvas.toDataURL("image/png");
  175. // imgSrc.value = dataURL;
  176. // setTimeout(() => {
  177. // isShowCanvas.value = false;
  178. // isSuccess.value = true;
  179. // }, 10);
  180. // console.log(dataURL);
  181. // });
  182. };
  183. const takePicture = () => {
  184. console.log("Take Picture !");
  185. };
  186. // 确认照片
  187. const confirmPhoto = () => {
  188. if (UimgSrc.value) {
  189. uni.navigateTo({
  190. url: `/pages/createing/index?imageUrl=${UimgSrc.value}`,
  191. });
  192. }
  193. };
  194. // 不满意,重新拍一张
  195. const reTry = () => {
  196. isSuccess.value = false;
  197. isUpload.value = false;
  198. isShowCanvas.value = true;
  199. CimgSrc.value = "";
  200. UimgSrc.value = "";
  201. setTimeout(() => {
  202. startCamera();
  203. }, 10);
  204. };
  205. // 点击上传照片按钮
  206. const uploadImg = async () => {
  207. const UserId = localStorage.getItem("UserId");
  208. try {
  209. const res = await getImageQrcode(UserId);
  210. QRCodeUrl.value = res.data.wxQrcode;
  211. showQrCode.value = true;
  212. // 成功展示二维码之后,轮询获取上传照片状态
  213. timer.value = setInterval(() => {
  214. refreshUploadStatus(res.data.id);
  215. }, 1000);
  216. console.log(res, "res");
  217. } catch (error) {
  218. console.log(error, "error");
  219. }
  220. };
  221. // 刷新状态,直到返回用户上传的图片url
  222. const refreshUploadStatus = async (id) => {
  223. try {
  224. const res = await findImage(id);
  225. console.log(res, "res");
  226. if (res.data.image) {
  227. clearInterval(timer.value);
  228. uni.showToast({
  229. title: "上传成功!",
  230. icon: "success",
  231. });
  232. showQrCode.value = false;
  233. UimgSrc.value = res.data.image;
  234. CimgSrc.value = "";
  235. isShowCanvas.value = false;
  236. isSuccess.value = true;
  237. isUpload.value = true;
  238. }
  239. } catch (error) {
  240. console.log(error, "error");
  241. }
  242. };
  243. // 点击取消,关闭二维码弹窗并取消轮询
  244. const cancelUplaod = () => {
  245. showQrCode.value = false;
  246. clearInterval(timer.value);
  247. };
  248. onLoad((options) => {
  249. console.log(options, "options");
  250. modelUrl.value = options.modelUrl;
  251. });
  252. onMounted(() => {
  253. console.log(this);
  254. clearInterval(timer.value);
  255. startCamera();
  256. });
  257. </script>
  258. <style lang="scss" scoped>
  259. .page {
  260. width: 100vw;
  261. height: 100vh;
  262. padding: 0;
  263. .top {
  264. display: flex;
  265. width: 100%;
  266. height: 32%;
  267. .example {
  268. width: 60%;
  269. height: 100%;
  270. color: #000;
  271. background-color: #fff;
  272. }
  273. .model {
  274. position: relative;
  275. width: 40%;
  276. height: 100%;
  277. background-color: #000000;
  278. img {
  279. position: absolute;
  280. top: 50%;
  281. left: 50%;
  282. transform: translate(-50%, -50%);
  283. width: 100%;
  284. height: 100%;
  285. }
  286. }
  287. }
  288. .bottom {
  289. position: relative;
  290. width: 100%;
  291. height: 68%;
  292. video {
  293. width: 100%;
  294. height: 100%;
  295. }
  296. .selectImg {
  297. position: absolute;
  298. left: 65rpx;
  299. bottom: 75rpx;
  300. width: 68rpx;
  301. height: 68rpx;
  302. border: 5rpx solid #ffffff;
  303. border-radius: 5rpx;
  304. z-index: 99;
  305. img {
  306. position: absolute;
  307. left: 50%;
  308. bottom: 50%;
  309. transform: translate(-50%, 50%);
  310. width: 70%;
  311. height: 70%;
  312. }
  313. .uploadText {
  314. position: absolute;
  315. left: 50%;
  316. bottom: -40rpx;
  317. width: 150%;
  318. font-size: 20rpx;
  319. transform: translateX(-40%);
  320. }
  321. }
  322. #action {
  323. position: absolute;
  324. left: 50%;
  325. bottom: 45rpx;
  326. width: 120rpx;
  327. height: 120rpx;
  328. transform: translateX(-50%);
  329. background-color: #ffffff;
  330. border-radius: 60rpx;
  331. z-index: 99;
  332. .circleInside {
  333. position: absolute;
  334. left: 50%;
  335. bottom: 50%;
  336. transform: translate(-50%, 50%);
  337. width: 100rpx;
  338. height: 100rpx;
  339. background-color: #ffffff;
  340. border-radius: 50%;
  341. border: 6rpx solid #000;
  342. }
  343. }
  344. .confirm {
  345. position: absolute;
  346. left: 50%;
  347. bottom: 75rpx;
  348. width: 80rpx;
  349. height: 80rpx;
  350. // border: 5rpx solid #ffffff;
  351. transform: translateX(-50%);
  352. border-radius: 60rpx;
  353. z-index: 99;
  354. img {
  355. position: absolute;
  356. left: 50%;
  357. bottom: 50%;
  358. transform: translate(-50%, 50%);
  359. width: 100%;
  360. height: 100%;
  361. }
  362. .uploadText {
  363. position: absolute;
  364. left: 50%;
  365. bottom: -40rpx;
  366. width: 150%;
  367. font-size: 20rpx;
  368. transform: translateX(-32%);
  369. }
  370. }
  371. .reTry {
  372. position: absolute;
  373. right: 65rpx;
  374. bottom: 75rpx;
  375. width: 68rpx;
  376. height: 68rpx;
  377. border: 5rpx solid #ffffff;
  378. border-radius: 5rpx;
  379. z-index: 99;
  380. img {
  381. position: absolute;
  382. left: 50%;
  383. bottom: 50%;
  384. transform: translate(-50%, 50%);
  385. width: 70%;
  386. height: 70%;
  387. }
  388. .uploadText {
  389. position: absolute;
  390. left: 50%;
  391. bottom: -40rpx;
  392. width: 150%;
  393. font-size: 20rpx;
  394. transform: translateX(-40%);
  395. }
  396. }
  397. .preview {
  398. position: relative;
  399. width: 100%;
  400. height: 100%;
  401. z-index: 1;
  402. .fromCamera {
  403. position: absolute;
  404. top: 110rpx;
  405. width: 120%;
  406. height: 60%;
  407. }
  408. .fromUpload {
  409. position: absolute;
  410. top: 110rpx;
  411. left: 50%;
  412. transform: translateX(-50%);
  413. width: 45%;
  414. }
  415. }
  416. }
  417. .overlay {
  418. .content {
  419. width: 100%;
  420. height: 100vh;
  421. display: flex;
  422. flex-direction: column;
  423. align-items: center;
  424. text-align: center;
  425. .imageBox {
  426. position: relative;
  427. margin-top: 200rpx;
  428. width: 500rpx;
  429. height: 500rpx;
  430. border-radius: 30rpx;
  431. background-color: #fff;
  432. .mask {
  433. position: absolute;
  434. width: 500rpx;
  435. height: 500rpx;
  436. border-radius: 30rpx;
  437. background-color: rgba($color: #000000, $alpha: 0.7);
  438. z-index: 2;
  439. }
  440. image {
  441. width: 500rpx;
  442. height: 500rpx;
  443. border-radius: 30rpx;
  444. background-color: #fff;
  445. }
  446. }
  447. text {
  448. margin-top: 20rpx;
  449. font-weight: 900;
  450. font-size: 32rpx;
  451. }
  452. // .orangeBtn {
  453. // margin-top: 100rpx;
  454. // }
  455. }
  456. }
  457. }
  458. </style>