Marketcard.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  1. <template><page-meta :root-font-size="fontSize+'px'"></page-meta>
  2. <home-base :show="false" >
  3. <view class="div home-marketcard">
  4. <view class="div marketcard-logo">
  5. <image mode="aspectFit" class="img" :src="marketcardlogo">
  6. </view>
  7. <view class="div scratchcard-bg">
  8. <view class="div scratchcard" :style="'width:'+cardWidth+'px; height:'+cardHeight+'px'">
  9. <canvas :style="'width:'+cardWidth+'px;height:'+cardHeight+'px'" @mousedown="touchstart"
  10. @mousemove="touchmove" @mouseup="touchend" @touchstart="touchstart"
  11. @touchmove="touchmove" @touchend="touchend" ref="canvas" canvas-id="scratch-card" class="scratchcard-overlay"></canvas>
  12. <view class="div scratchcard-content">
  13. <view class="div" v-if="isResult">
  14. <view class="div result-area" :class="drawResult?'suc':'fail'">
  15. <view class="div face-area"></view>
  16. <view class="div result-content-wap">
  17. <view class="p result-title">{{drawTitle}}</view>
  18. <view class="p result-content">{{drawContent}}</view>
  19. </view>
  20. </view>
  21. </view>
  22. </view>
  23. </view>
  24. </view>
  25. <view class="div marketcard-info" v-if="marketmanage_info">
  26. <view class="div title">活动名称:</view>
  27. <view class="div content">{{marketmanage_info.marketmanage_name}}</view>
  28. <view class="div title">活动介绍:</view>
  29. <view class="div content">{{marketmanage_info.marketmanage_detail}}</view>
  30. <view class="div title">活动有效时间:</view>
  31. <view class="div content">
  32. {{marketmanage_info.marketmanage_begintime_text}}至{{marketmanage_info.marketmanage_endtime_text}}</view>
  33. <view class="div title">活动奖项设置:</view>
  34. <view class="div content">
  35. <view class="div" v-for="(marketmanageaward,index) in marketmanageaward_list" :key="index">
  36. {{marketmanageaward.marketmanageaward_level}}等奖{{marketmanageaward.marketmanageaward_probability}}%:{{marketmanageaward.marketmanageaward_text}}
  37. </view>
  38. </view>
  39. </view>
  40. <view class="div btn-wrapper">
  41. <view class="div btn">
  42. <view class="div common-btn ds-button-large" @click="reset" v-if="canDraw">再刮一次</view>
  43. <view class="div common-btn ds-button-large" v-else>机会用完了</view>
  44. </view>
  45. <view class="div btn">
  46. <view class="div common-btn ds-button-large" @click="goLog">刮奖记录</view>
  47. </view>
  48. </view>
  49. </view>
  50. </home-base>
  51. </template>
  52. <script>
  53. import {getFontSize} from '@/util/common'
  54. import { env } from '../../../static/config'
  55. import HomeBase from '../HomeBase'
  56. import {
  57. getMarketmanageInfo,
  58. addMarketmanagelog
  59. } from '../../../api/homeMarketmanage'
  60. import {
  61. mapState
  62. } from 'vuex'
  63. let ctx = null;
  64. export default {
  65. name: 'Marketcard',
  66. data() {
  67. return {
  68. scrollTop: 0,
  69. marketmanage_id: 0,
  70. marketmanage_info: false,
  71. marketmanageaward_list: false,
  72. cardWidth: 260,
  73. cardHeight: 132,
  74. startX: null,
  75. startY: null,
  76. computing: false,
  77. complete: false,
  78. isScrape: false,
  79. ready: false,
  80. isResult: false,
  81. drawResult: false,
  82. drawTitle: '真遗憾,未中奖',
  83. drawContent: '哎呀,肯定姿势不对!',
  84. canDraw: false,
  85. marketcardlogo: env.SITE_URL+'/uploads/home/h5/home/home-marketcard-logo.png'
  86. }
  87. },
  88. components: {
  89. HomeBase,
  90. },
  91. computed:{
  92. fontSize(){
  93. return getFontSize()
  94. },
  95. ...mapState({
  96. isOnline: state => state.member.isOnline,
  97. token: state => state.member.token
  98. })
  99. },
  100. onLoad: function(option) {
  101. this.marketmanage_id = option.marketmanage_id
  102. if (!this.marketmanage_id) {
  103. uni.showToast({
  104. icon: 'none',
  105. title: '参数错误'
  106. })
  107. return
  108. }
  109. getMarketmanageInfo(this.marketmanage_id, this.token).then(res => {
  110. this.marketmanage_info = res.result.marketmanage_info
  111. this.marketmanageaward_list = res.result.marketmanageaward_list
  112. this.canDraw = res.result.can_draw
  113. this.drawContent = this.marketmanage_info.marketmanage_failed
  114. if (!this.canDraw) {
  115. uni.showToast({
  116. icon: 'none',
  117. title: res.message
  118. })
  119. }
  120. }).catch(function(error) {
  121. uni.showToast({
  122. icon: 'none',
  123. title: error.message
  124. })
  125. })
  126. },
  127. onPageScroll: function(e) { //nvue暂不支持滚动监听,可用bindingx代替
  128. this.scrollTop = e.scrollTop
  129. },
  130. methods: {
  131. goLog() {
  132. uni.navigateTo({
  133. url: '/pages/member/marketmanagelog/Marketmanagelog'
  134. })
  135. },
  136. initCanvas() {
  137. this.computing = false;
  138. this.complete = false;
  139. this.isScrape = false;
  140. this.ready = false;
  141. ctx.clearRect(0, 0, this.cardWidth, this.cardHeight);
  142. //绘制画布
  143. ctx.setFillStyle('#eee');
  144. ctx.fillRect(0, 0, this.cardWidth, this.cardHeight);
  145. this.ready = true;
  146. //绘制文字水印
  147. this.fillWatermark();
  148. ctx.draw();
  149. },
  150. /**
  151. * 绘制文字水印
  152. */
  153. fillWatermark: function(e) {
  154. var watermark = '刮一刮'
  155. var watermarkSize = 14
  156. var width = watermark.length * watermarkSize;
  157. ctx.save();
  158. ctx.rotate(-10 * Math.PI / 180);
  159. let x = 0;
  160. let y = 0;
  161. let i = 0;
  162. while ((x <= this.cardWidth * 5 || y <= this.cardHeight * 5) && i < 300) {
  163. ctx.setFillStyle('#999');
  164. ctx.setFontSize(watermarkSize);
  165. ctx.fillText(watermark, x, y);
  166. x += width + width * 1.6;
  167. if (x > this.cardWidth && y <= this.cardHeight) {
  168. x = -Math.random() * 100;
  169. y += watermarkSize * 3;
  170. }
  171. i++;
  172. }
  173. ctx.restore();
  174. },
  175. touchstart: function(e) {
  176. if (!this.canDraw) {
  177. return;
  178. }
  179. this.startX = e.touches[0].x;
  180. this.startY = e.touches[0].y;
  181. },
  182. touchend: function(e) {
  183. this.getFilledPercentage();
  184. },
  185. touchmove: function(e) {
  186. if (this.complete || !this.canDraw) {
  187. return;
  188. }
  189. // ctx.globalCompositeOperation = 'destination-out';
  190. ctx.moveTo(this.startX, this.startY);
  191. // ctx.beginPath();
  192. // ctx.arc(this.startX, this.startY, 20, 0, Math.PI * 20);
  193. // ctx.fill();
  194. ctx.clearRect(this.startX, this.startY, 20, 20);
  195. ctx.draw(true);
  196. //记录移动点位
  197. this.startX = e.touches[0].x;
  198. this.startY = e.touches[0].y;
  199. },
  200. getFilledPercentage: function(e) {
  201. if (this.computing) {
  202. return;
  203. }
  204. this.computing = true;
  205. ctx.moveTo(0, 0);
  206. ctx.clearRect(0, 0, this.cardWidth, this.cardHeight);
  207. ctx.stroke();
  208. ctx.draw(true);
  209. uni.canvasGetImageData({
  210. canvasId: 'scratch-card',
  211. x: 0,
  212. y: 0,
  213. width: this.cardWidth,
  214. height: this.cardHeight,
  215. success: (res) => {
  216. let pixels = res.data;
  217. let transPixels = [];
  218. for (let i = 0; i < pixels.length; i += 4) {
  219. if (pixels[i + 3] < 128) {
  220. transPixels.push(pixels[i + 3]);
  221. }
  222. }
  223. var percent = (transPixels.length / (pixels.length / 4) * 100).toFixed(2);
  224. if (percent >= 10) {
  225. this.addMarketmanagelog();
  226. }
  227. this.computing = false;
  228. console.log(percent)
  229. },
  230. fail: function(e) {
  231. console.log(e);
  232. },
  233. }, this);
  234. },
  235. reset() {
  236. // 重置
  237. this.isScrape = false
  238. this.drawResult = false
  239. this.isFinished = false
  240. this.isResult = false
  241. this.initCanvas()
  242. this.drawImage()
  243. this.drawTitle = '真遗憾,未中奖'
  244. this.drawContent = this.marketmanage_info.marketmanage_failed
  245. },
  246. addMarketmanagelog() {
  247. this.complete = true;
  248. if (this.isScrape) {
  249. return;
  250. }
  251. this.isScrape = true;
  252. // 消耗刮卡机会
  253. addMarketmanagelog(this.marketmanage_id).then(res => {
  254. this.canDraw = res.result.can_draw
  255. this.isResult = true
  256. if (res.result.draw_result) { // 中奖
  257. this.drawResult = true
  258. this.drawTitle = '恭喜你,获得' + res.result.draw_info.marketmanageaward_level + '等奖'
  259. this.drawContent = res.result.draw_info.marketmanageaward_text
  260. }
  261. }).catch(function(error) {
  262. uni.showToast({
  263. icon: 'none',
  264. title: error.message
  265. })
  266. })
  267. },
  268. },
  269. mounted() {
  270. ctx = uni.createCanvasContext("scratch-card", this);
  271. this.initCanvas()
  272. }
  273. }
  274. </script>
  275. <style scoped lang="scss">
  276. .home-marketcard {
  277. background-color: #f81213;
  278. background-image: url(../../../static/image/home/home-marketcard-bg.png);
  279. background-repeat: repeat-x;
  280. position: fixed;
  281. width: 100%;
  282. height: 100%;
  283. overflow-y: auto;
  284. }
  285. .marketcard-logo {
  286. text-align: center;
  287. .img {
  288. width: 14rem;
  289. height: 5.5rem;
  290. margin-top: 1rem;
  291. }
  292. }
  293. .scratchcard-bg {
  294. width: 274px;
  295. height: 132px;
  296. padding: 7px 0;
  297. margin: 1rem auto 0;
  298. position: relative;
  299. background: url(../../../static/image/home/home-marketcard-wrapper.png) no-repeat;
  300. background-size: 100%
  301. }
  302. .scratchcard {
  303. position: relative;
  304. display: block;
  305. margin-left: 7px;
  306. }
  307. .scratchcard>* {
  308. position: absolute;
  309. width: 100%;
  310. height: 100%;
  311. display: block;
  312. }
  313. .scratchcard-overlay {
  314. z-index: 1;
  315. }
  316. .marketcard-info {
  317. color: #fff;
  318. padding: 0 1rem;
  319. margin-top: 1rem;
  320. font-size: $fontSize;
  321. .content {
  322. margin-bottom: 1rem;
  323. }
  324. }
  325. .btn-wrapper {
  326. display: flex;
  327. padding: .75rem;
  328. .btn {
  329. padding: .25rem;
  330. flex: 1
  331. }
  332. }
  333. .home-marketcard .result-area {
  334. background-color: #f1d183;
  335. position: absolute;
  336. display: table;
  337. width: 260px;
  338. height: 132px;
  339. line-height: 1.5em;
  340. color: #e03021;
  341. text-align: center;
  342. font-weight: bold;
  343. top: 0;
  344. }
  345. .home-marketcard .result-area .result-content-wap {
  346. display: table-cell;
  347. vertical-align: middle;
  348. word-break: break-all;
  349. padding: 0 20px
  350. }
  351. .home-marketcard .result-area .face-area {
  352. position: absolute;
  353. top: 27px;
  354. left: 8px;
  355. width: 76px;
  356. height: 76px;
  357. background-size: cover
  358. }
  359. .home-marketcard .result-area .result-title {
  360. font-size: $h1
  361. }
  362. .home-marketcard .result-area .result-content {
  363. font-size: 1.1rem;
  364. margin-top: 5px
  365. }
  366. .home-marketcard .result-area.suc .result-content-wap,
  367. .home-marketcard .result-area.fail .result-content-wap {
  368. width: 150px;
  369. text-align: left
  370. }
  371. .home-marketcard .result-area.suc .face-area {
  372. background-image: url("../../../static/image/home/home-marketcard-suc.png")
  373. }
  374. .home-marketcard .result-area.suc .result-title {
  375. font-size: $subFontSize;
  376. color: #4e3735
  377. }
  378. .home-marketcard .result-area.suc .result-content {
  379. font-size: $h1;
  380. color: #e03021
  381. }
  382. .home-marketcard .result-area.fail .face-area {
  383. background-image: url("../../../static/image/home/home-marketcard-fail.png")
  384. }
  385. .home-marketcard .result-area.fail .result-title {
  386. font-size: $h2;
  387. color: #372f2f
  388. }
  389. .home-marketcard .result-area.fail .result-content {
  390. font-size: $subFontSize;
  391. color: #584c3c
  392. }
  393. </style>