shouyu.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513
  1. <template>
  2. <view class="container">
  3. <view class="loading" v-if="loadingState" :class="[loadingOutAnime?'loadingOut':'']">
  4. <view class="loadingBox" v-if="loadPointState">
  5. <span class="span1"></span>
  6. <span class="span2"></span>
  7. <span class="span3"></span>
  8. <span class="span4"></span>
  9. <span class="span5"></span>
  10. <span class="span6"></span>
  11. </view>
  12. <image class="loadingText" @load="loadImgEnd" :src="loadingText" mode="aspectFit"></image>
  13. </view>
  14. <view class="changeAudio" :class="[audioState?'changeAudioPlay':'']" @click="changeAudio">
  15. <image :src="audioImgA" v-show="audioState" mode="aspectFit"></image>
  16. <image :src="audioImgB" v-show="!audioState" mode="aspectFit"></image>
  17. </view>
  18. <view class="imgLayer" v-show="openControlState">
  19. <view class="imgLayerContent">
  20. <image :src="imgPath" show-menu-by-longpress='1' mode="widthFix"></image>
  21. </view>
  22. <view class="imgLayerTips">
  23. <image :src="tipsImgPath" mode="aspectFill"></image>
  24. </view>
  25. </view>
  26. <view class="videoLayer" v-show="!openControlState">
  27. <view class="videoContent">
  28. <video id="myVideoBg" :src="videoBgPath" :controls="false" :muted="true" objectFit='cover'
  29. :show-progress='false' :enable-progress-gesture='false' :show-play-btn='false'
  30. :show-fullscreen-btn='false' @loadedmetadata="videoLoadingEnd"></video>
  31. </view>
  32. <view class="addText">
  33. <input type="text" class="inputLabel" v-model="inputText" @input="inputChange">
  34. </view>
  35. <view class="viewSpan span1">{{inputText[0]}}</view>
  36. <view class="viewSpan span2">{{inputText[1]}}</view>
  37. <view class="viewSpan span3">{{inputText[2]}}</view>
  38. <view class="viewSpan span4">{{inputText[3]}}</view>
  39. <view class="viewSpan submit" @click="submitText">
  40. </view>
  41. </view>
  42. </view>
  43. </template>
  44. <script>
  45. import request from "@/utils/request.js"
  46. export default {
  47. data() {
  48. return {
  49. loadPointState:false,
  50. audioImgA: "https://dadu.oss-cn-hangzhou.aliyuncs.com/static/shouyu/audioOn.png",
  51. audioImgB: "https://dadu.oss-cn-hangzhou.aliyuncs.com/static/shouyu/audioOff.png",
  52. audioState: true,
  53. loadingText: "https://dadu.oss-cn-hangzhou.aliyuncs.com/static/loading.jpg",
  54. loadingState: true, //当前加载状态
  55. loadingOutAnime: false, //加载退场动画
  56. tipsImgPath: "https://dadu.oss-cn-hangzhou.aliyuncs.com/static/shouyu/tips.png", //用来提示的文字
  57. openid: "",
  58. personCount: "", //当前是第几个访问
  59. imgPath: "", //已经打开的图片数据
  60. openControlState: false, //是否进行添加还是直接展示
  61. videoBgPath: "https://dadu.oss-cn-hangzhou.aliyuncs.com/static/shouyu/bg2.mp4",
  62. videoCtx: "",
  63. inputText: "",
  64. }
  65. },
  66. methods: {
  67. login() {
  68. uni.login({
  69. provider: 'weixin', //使用微信登录
  70. success: async (loginRes) => {
  71. let res = await request({
  72. url: "/api/login",
  73. method: "GET",
  74. data: {
  75. code: loginRes.code
  76. },
  77. })
  78. if (res.data.changeState != undefined) {
  79. this.openControlState = true
  80. this.loadingOutAnime = true
  81. let lT = setTimeout(()=>{
  82. this.loadingState = false
  83. },2000)
  84. this.imgPath = `https://dadu.ispush.com/${res.data.imgPath}?t=${new Date().getTime()}`
  85. } else {
  86. this.personCount = res.data.person_index + 1
  87. }
  88. this.openid = res.data.openid
  89. }
  90. });
  91. },
  92. loadImgEnd(e){
  93. this.loadPointState = true
  94. },
  95. videoLoadingEnd(ev) {
  96. let t1 = setTimeout(() => {
  97. this.loadingOutAnime = true
  98. this.videoCtx.play()
  99. }, 1000)
  100. let t2 = setTimeout(() => {
  101. this.loadingState = false
  102. clearTimeout(t2)
  103. }, 2500)
  104. },
  105. createAudio() {
  106. this.innerAudioContext = uni.createInnerAudioContext()
  107. this.innerAudioContext.loop = true
  108. this.innerAudioContext.src = `${this.$g.baseUrl}/static/shouyu/audio.mp3`
  109. },
  110. changeAudio() {
  111. if (this.audioState) {
  112. this.innerAudioContext.pause()
  113. } else {
  114. this.innerAudioContext.play()
  115. }
  116. this.audioState = !this.audioState
  117. },
  118. inputChange() {
  119. if (this.inputText.length > 4) {
  120. this.inputText = ""
  121. uni.showToast({
  122. title: '最多录入四个字',
  123. duration: 2000
  124. });
  125. }
  126. },
  127. isChn(str) {
  128. var reg = /^[\u4E00-\u9FA5]+$/;
  129. if (!reg.test(str)) {
  130. return false;
  131. } else {
  132. return true;
  133. }
  134. },
  135. async submitText() {
  136. if (this.inputText.length == 1) {
  137. this.inputText = ""
  138. uni.showToast({
  139. title: '至少录入两个字',
  140. duration: 2000
  141. });
  142. return
  143. }
  144. if (this.inputText[0] == "" && this.inputText[1] == "") {
  145. uni.showToast({
  146. title: '不能录入空字符',
  147. duration: 2000
  148. });
  149. }
  150. let isCh = this.isChn(this.inputText)
  151. if (!isCh) {
  152. this.inputText = ""
  153. uni.showToast({
  154. title: '只能输入中文字符',
  155. duration: 2000
  156. });
  157. return
  158. }
  159. uni.showLoading({
  160. title: '生成中'
  161. });
  162. let res = await request({
  163. url: "/api/createImg",
  164. method: "GET",
  165. data: {
  166. "openid": this.openid,
  167. "text": this.inputText,
  168. "count": Number(this.personCount)
  169. },
  170. })
  171. if (res.data.createState != true) {
  172. uni.showToast({
  173. title: '网络延迟请重试',
  174. duration: 2000
  175. });
  176. uni.hideLoading();
  177. return
  178. }
  179. uni.hideLoading();
  180. this.openControlState = true
  181. this.imgPath = `https://dadu.ispush.com/${res.data.imgPath}?t=${new Date().getTime()}`
  182. }
  183. },
  184. onReady() {
  185. this.videoCtx = uni.createVideoContext('myVideoBg')
  186. },
  187. onLoad() {
  188. uni.hideHomeButton()
  189. this.createAudio()
  190. this.login()
  191. },
  192. onHide() {
  193. this.audioState = false
  194. this.innerAudioContext.pause()
  195. },
  196. onShow() {
  197. this.audioState = true
  198. if (this.innerAudioContext) {
  199. this.innerAudioContext.play()
  200. }
  201. },
  202. onUnload() {
  203. this.innerAudioContext.stop()
  204. this.innerAudioContext.destroy()
  205. }
  206. }
  207. </script>
  208. <style scoped>
  209. .container {
  210. position: relative;
  211. width: 100vw;
  212. height: 100vh;
  213. }
  214. .container .loading {
  215. position: absolute;
  216. top: 0;
  217. left: 0;
  218. width: 100vw;
  219. height: 100vh;
  220. z-index: 999999;
  221. background: #4c4c4c;
  222. display: flex;
  223. justify-content: center;
  224. align-items: center;
  225. }
  226. .container .loading .loadingBox {
  227. position: absolute;
  228. width: 105rpx;
  229. height: 41rpx;
  230. display: flex;
  231. top: 345rpx;
  232. left: 459rpx;
  233. z-index: 1;
  234. opacity: 0;
  235. justify-content: space-around;
  236. align-items: center;
  237. animation: 0.8s loadingBoxAnime 0.5s linear forwards;
  238. }
  239. @keyframes loadingBoxAnime{
  240. from{opacity: 0;}
  241. to{opacity: 1;}
  242. }
  243. .container .loading .loadingBox span {
  244. width: 8rpx;
  245. height: 8rpx;
  246. background: #c8841a;
  247. border-radius: 50%;
  248. }
  249. .container .loading .loadingBox .span1 {
  250. animation: 0.8s spanAnime 0.2s alternate infinite;
  251. }
  252. .container .loading .loadingBox .span2 {
  253. animation: 0.8s spanAnime 0.4s alternate infinite;
  254. }
  255. .container .loading .loadingBox .span3 {
  256. animation: 0.8s spanAnime 0.6s alternate infinite;
  257. }
  258. .container .loading .loadingBox .span4 {
  259. animation: 0.8s spanAnime 0.8s alternate infinite;
  260. }
  261. .container .loading .loadingBox .span5 {
  262. animation: 0.8s spanAnime 1s alternate infinite;
  263. }
  264. .container .loading .loadingBox .span6 {
  265. animation: 0.8s spanAnime 1.2s alternate infinite;
  266. }
  267. @keyframes spanAnime {
  268. from {
  269. transform: scale(1.5);
  270. }
  271. to {
  272. transform: scale(0.7);
  273. }
  274. }
  275. .container .loading .loadingBox .loadingRotate {
  276. animation: 1s loadingRotateAnime linear infinite;
  277. }
  278. .container .loading .loadingText {
  279. position: absolute;
  280. top: 0%;
  281. left: 0%;
  282. width: 750rpx;
  283. height: 1624rpx;
  284. will-change: transform;
  285. }
  286. @keyframes loadingRotateAnime {
  287. from {
  288. transform: rotate(0deg);
  289. }
  290. to {
  291. transform: rotate(360deg);
  292. }
  293. }
  294. .container .loadingOut {
  295. animation: 1s loadingOutAnime 1s linear forwards;
  296. }
  297. @keyframes loadingOutAnime {
  298. from {
  299. opacity: 1;
  300. }
  301. to {
  302. opacity: 0;
  303. }
  304. }
  305. .container .changeAudio {
  306. position: absolute;
  307. right: 55rpx;
  308. top: 55rpx;
  309. width: 47rpx;
  310. height: 47rpx;
  311. z-index: 9999;
  312. }
  313. .container .changeAudio image {
  314. width: 100%;
  315. height: 100%;
  316. }
  317. .container .changeAudioPlay {
  318. animation: 1s changeAudioAnime linear infinite;
  319. }
  320. @keyframes changeAudioAnime {
  321. from {
  322. transform: rotate(0deg);
  323. }
  324. to {
  325. transform: rotate(360deg);
  326. }
  327. }
  328. .container .imgLayer {
  329. position: absolute;
  330. z-index: 999;
  331. width: 100vw;
  332. height: 100vh;
  333. left: 0;
  334. top: 0;
  335. animation: 1s imgLayerAnime linear forwards;
  336. }
  337. @keyframes imgLayerAnime {
  338. from {
  339. opacity: 0;
  340. transform: scale(1.1);
  341. }
  342. to {
  343. opacity: 1;
  344. transform: scale(1);
  345. }
  346. }
  347. .container .imgLayer .imgLayerContent {
  348. position: absolute;
  349. width: 750rpx;
  350. height: 1624rpx;
  351. left: 0;
  352. top: 0;
  353. }
  354. .container .imgLayer .imgLayerContent image {
  355. width: 100%;
  356. height: 100%;
  357. will-change: transform;
  358. }
  359. .container .imgLayer .imgLayerTips {
  360. position: absolute;
  361. left: 390rpx;
  362. top: 1220rpx;
  363. width: 323rpx;
  364. height: 27rpx;
  365. z-index: 99;
  366. transform: translateX(-50%);
  367. animation: 1s imgLayerTipsAnime linear alternate infinite;
  368. pointer-events: none;
  369. }
  370. /* @media screen and (max-height: 1400px) {
  371. .container .imgLayer .imgLayerTips {
  372. top: 85%;
  373. }
  374. } */
  375. .container .imgLayer .imgLayerTips image {
  376. width: 100%;
  377. height: 100%;
  378. }
  379. @keyframes imgLayerTipsAnime {
  380. from {
  381. opacity: 0.5;
  382. }
  383. to {
  384. opacity: 1;
  385. }
  386. }
  387. .container .videoLayer {
  388. position: absolute;
  389. z-index: 999;
  390. left: 0;
  391. top: 0;
  392. width: 100vw;
  393. height: 100vh;
  394. }
  395. .container .videoLayer .videoContent {
  396. position: absolute;
  397. top: 0;
  398. left: 0;
  399. width: 750rpx;
  400. height: 1624rpx;
  401. }
  402. .container .videoLayer .videoContent video {
  403. width: 100%;
  404. height: 100%;
  405. }
  406. .container .videoLayer .addText {
  407. position: absolute;
  408. left: 320rpx;
  409. top: 415rpx;
  410. width: 155rpx;
  411. height: 695rpx;
  412. font-size: 120rpx;
  413. display: flex;
  414. flex-direction: column;
  415. justify-content: start;
  416. box-sizing: border-box;
  417. z-index: 9999;
  418. }
  419. .container .videoLayer .addText .inputLabel {
  420. position: absolute;
  421. left: 0;
  422. top: 0;
  423. width: 155rpx;
  424. height: 695rpx;
  425. opacity: 0;
  426. color: rgba(0, 0, 0, 0);
  427. }
  428. .container .videoLayer .addText .inputLabel input:focus {
  429. border-color: transparent;
  430. /* 将边框颜色设置为透明 */
  431. background-color: #fff;
  432. /* 将背景色设置为白色 */
  433. caret-color: transparent;
  434. }
  435. .container .videoLayer .viewSpan {
  436. position: absolute;
  437. width: 155rpx;
  438. height: 155rpx;
  439. left: 318rpx;
  440. font-size: 120rpx;
  441. display: flex;
  442. justify-content: center;
  443. align-items: center;
  444. }
  445. .container .videoLayer .span1 {
  446. top: 410rpx;
  447. }
  448. .container .videoLayer .span2 {
  449. top: 590rpx;
  450. }
  451. .container .videoLayer .span3 {
  452. top: 770rpx;
  453. }
  454. .container .videoLayer .span4 {
  455. top: 950rpx;
  456. }
  457. .container .videoLayer .submit {
  458. position: absolute;
  459. left: 520rpx;
  460. top: 930rpx;
  461. width: 80rpx;
  462. height: 170rpx;
  463. }
  464. </style>