前言
最近在研究圖片滑動解鎖 登錄,說是要用阿里的那個驗證,但是還是想自己手寫下這個Demo
效果圖是這樣的:
本來是想用canvas 來實現的,但是類,后來還想用css 和圖片來代替canvas
其實思路就這樣的:
那個缺陷的滑塊位置 是隨機的 根據 圖片的寬高 產生 隨機 數當然是定位 : left,top.,然后距離最左邊的距離 moveToLeft,
最后滑動的距離和這個距離作比較,看看是否相等 。。然后就好了......
vue 中滑動開始 start 開始計算時間 - 》 想右滑動的距離等於滑塊滑動的距離
思路其實也不難,就放上代碼吧:
<template> <section class="code_bg"> <div class="slide-box"> <div class="slide-img-block"> <div class="slide-img-div"> <div class="slide-img-nopadding"> <img class="slide-img" id="slideImg" :src="img"> <div class="slide-block" id="slideBlock"></div> <div class="slide-box-shadow" id="cutBlock"></div> </div> </div> </div> <div class="scroll-background slide-img-hint-info" id="slideHintInfo" style="height: 0px;"> <div class="slide-img-hint"> <div class="scroll-background slide-icon" id="slideIcon"></div> <div class="slide-text"> <span class="slide-text-type greenColor" id="slideType">驗證通過:</span> <span class="slide-text-content" id="slideContent">用時0.4s</span> </div> </div> </div> <i class="iconfont icon-refresh" @click="resImg"></i> <!-- 滑塊 --> <div class="slideBox" ref="slideBox"> <div class='slide' @touchstart="touchStart($event)" @touchmove="touchMove($event)" @touchend="touchEnd($event)" :style="{'left':moveToLeft+'px'}" ref="slide"> <i class="iconfont "></i></div> <div class="slideBg" :style="{'width':moveToLeft+'px'}"></div> <div class="textBg" v-show="moveToLeft>0">拖動左邊滑塊完成上方拼圖</div> <span class="default" v-show="moveToLeft===0">拖動左邊滑塊完成上方拼圖</span> </div> </div> </section> </template> <script> export default { name: "slideBox", data() { return { msg: "滑動", moveToLeft: 0, //滑動距離 starX: 0, //初始距離 slideBoxWidth: 0, slideWidth: 0, resultX: "", slideBlock: "", cutBlock: "", imgWidth: "", imgHeight: "", slideIcon: "", // 圖標 slideType: "", // 失敗 slideContent: "", //正文 slideHintInfo: "", //彈出 isSuccess: true, startTamp: "", //開始時間 endTamp: "", //結束時間 timer: "", // 用時解開 img: "", // 圖片 imgList: [ "http://www.keaitupian.net/uploads/allimg/170120/1A12A959-0.jpg", "http://www.keaitupian.net/uploads/allimg/150409/15124TD2-3.jpg", "http://www.keaitupian.net/uploads/allimg/150409/15124U2E-0.jpg", "http://www.keaitupian.net/uploads/allimg/150409/15124RI8-4.jpg", "http://www.keaitupian.net/uploads/allimg/170120/1A5142649-1.jpg", "http://www.keaitupian.net/uploads/allimg/161207/1_161207173815_3.jpg", "http://www.keaitupian.net/uploads/allimg/161207/1_161207173815_4.jpg", "http://www.keaitupian.net/uploads/allimg/160804/09321051Z-0.jpg", "http://www.keaitupian.net/uploads/allimg/160804/0932105013-1.jpg" ] }; }, mounted() { let _this = this; setTimeout(() => { this.$loading.close(); }, 500); _this.slideBoxWidth = _this.$refs.slideBox.clientWidth; _this.slideWidth = _this.$refs.slide.clientWidth; _this.cutBlock = document.getElementById("cutBlock"); // 裁剪區域 _this.slideBlock = document.getElementById("slideBlock"); // 裁剪的圖片 _this.imgWidth = document.getElementById("slideImg").offsetWidth; // 圖片寬 _this.imgHeight = document.getElementById("slideImg").offsetHeight; // 圖片高 _this.slideIcon = document.getElementById("slideIcon"); // 正確、失敗的圖標 _this.slideType = document.getElementById("slideType"); // 正確、失敗 _this.slideContent = document.getElementById("slideContent"); // 正確、失敗的正文 _this.slideHintInfo = document.getElementById("slideHintInfo"); // 彈出 _this.resImg(); }, methods: { touchStart(e) { let _this = this; console.log("zzzz:" + e.targetTouches[0].pageX); let starX = e.targetTouches[0].pageX; _this.starX = starX; _this.startTamp = new Date().valueOf(); if (_this.isSuccess) { _this.cutImg(); } }, touchMove(e) { let _this = this; console.log("yyyy:" + e.targetTouches[0].pageX); let ToLeft = e.targetTouches[0].pageX - _this.starX; //變化后的坐標減去初始坐標 let slideBoxW = Math.floor(_this.slideBoxWidth - _this.slideWidth - 1); //計算大盒子寬度 if (ToLeft < 0) { ToLeft = 0; //滑塊不能超出大盒子左邊 _this.slideBlock.style.left = "0px"; } if (ToLeft >= 0 && ToLeft <= slideBoxW) { _this.slideBlock.style.left = ToLeft + "px"; } if (ToLeft > slideBoxW) { ToLeft = slideBoxW; //滑塊不能超出大盒子右邊 } _this.moveToLeft = ToLeft; console.log("離開的" + _this.resultX); }, touchEnd() { let _this = this; let ToLeft = _this.moveToLeft; if (_this.resultX > ToLeft - 4 && _this.resultX < ToLeft + 4) { _this.isSuccess = true; _this.endTamp = new Date().valueOf(); _this.timer = ((_this.endTamp - _this.startTamp) / 1000).toFixed(1); // 裁剪圖片(拼圖的一塊) _this.slideBlock.style.opacity = "0"; // _this.slideBlock.style.transition = "opacity 0.6s"; // 裁剪的區域(黑黑的那一塊) _this.cutBlock.style.opacity = "0"; _this.cutBlock.style.transition = "opacity 0.6s"; // 正確彈出的圖標 _this.slideType.className = "slide-text-type greenColor"; _this.slideType.innerHTML = "驗證通過:"; _this.slideContent.innerHTML = "用時" + _this.timer + "s"; setTimeout(function() { _this.cutBlock.style.display = "none"; _this.slideBlock.style.left = "0px"; //_this.reToNewImg(); _this.$toast({ message: "驗證通過" }); }, 600); //_this.options.success && _this.options.success(); } else { _this.isSuccess = false; // 設置樣式 // 裁剪圖片(拼圖的一塊) _this.slideBlock.style.left = "0px"; // 錯誤彈出的圖標 _this.slideType.className = "slide-text-type redColor"; _this.slideType.innerHTML = "驗證失敗:"; _this.slideContent.innerHTML = "拖動滑塊將懸浮圖像正確拼合"; _this.slideBlock.style.left = "0px"; _this.resImg(); } // 設置樣式 _this.slideHintInfo.style.height = "22px"; setTimeout(function() { _this.slideHintInfo.style.height = "0px"; }, 1300); //離開的時候回到初始位置 _this.moveToLeft = 0; }, cutImg() { var _this = this; _this.cutBlock.style.display = "block"; var cutWidth = _this.cutBlock.offsetWidth; // 裁剪區域寬 var cutHeight = _this.cutBlock.offsetHeight; // 裁剪區域高 // left _this.resultX = Math.floor( Math.random() * (_this.imgWidth - cutWidth * 2 - 4) + cutWidth ); // top var cutTop = Math.floor( Math.random() * (_this.imgHeight - cutHeight * 2) + cutHeight ); // 設置樣式 _this.cutBlock.style.cssText = "top:" + cutTop + "px;" + "left:" + _this.resultX + "px; display: block;"; _this.slideBlock.style.top = cutTop + "px"; _this.slideBlock.style.backgroundPosition = "-" + _this.resultX + "px -" + cutTop + "px"; _this.slideBlock.style.opacity = "1"; }, resImg() { let _this = this; _this.isSuccess = true; let newImg = _this.imgList[Math.round(Math.random() * 8)]; _this.img = newImg; _this.slideBlock.style.backgroundImage = "url(" + newImg + ")"; _this.slideBlock.style.opacity = "0"; _this.cutBlock.style.display = "none"; } } }; </script> <style lang="scss" scoped> // 上面的滑塊 .code_bg { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background-color: rgba(0, 0, 0, 0.5); z-index: 20; // 圖片 .slide-box { display: block; position: relative; top: 25%; background: #fff; padding: 5% 0; .slide-btn { height: 44px; width: 44px; background-position: 0 -84px; cursor: pointer; display: block; position: absolute; left: 0; top: -9px; -moz-box-shadow: none; box-shadow: none; border-radius: 13px; z-index: 399; } .icon-refresh { display: block; font-size: 0.4rem; margin-left: 6%; margin-top: 1%; color: #d0caec; } .slide-img-div { width: 100%; height: 3rem; padding: 0 5%; position: relative; border-left: 1px solid #fff; border-right: 1px solid #fff; img { width: 100%; height: 100%; } .slide-box-shadow { display: none; position: absolute; width: 0.8rem; height: 0.8rem; border-radius: 4px; background-color: rgba(0, 0, 0, 0.3); box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.8) inset; } .slide-block { opacity: 0; position: absolute; top: 0; left: 2px; width: 0.8rem; height: 0.8rem; border-radius: 0.08rem; background-repeat: no-repeat; background-attachment: scroll; border: 1px solid rgba(255, 255, 0, 0.8); background-size: 100% 3rem; box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.4), 0 0 10px 0 rgba(90, 90, 90, 0.4); box-sizing: border-box; z-index: 10; } .slide-img-nopadding { position: relative; width: 100%; height: 100%; } } .slide-icon { float: left; height: 22px; width: 26px; } .slide-img-hint { -webkit-font-smoothing: subpixel-antialiased; font-size: 12px !important; line-height: 22px !important; margin: 0 auto; position: relative; } .slide-text { text-align: left !important; color: #4b3f33; } .slide-img-hint-info { height: 22px; width: 260px; background-position: 0 -674px; height: 0; overflow: hidden; position: absolute; bottom: 1px; transition: height 0.3s; z-index: 11; } .redColor { color: red; } .greenColor { color: green; } } // 滑塊 .slideBox { z-index: 20; height: 0.89rem; border: 1px solid #d5d3e2; margin: 0.1rem 0 0.2rem 0; line-height: 0.89rem; background: #d0caec; color: #fff; font-size: 16px; position: relative; top: 30%; width: 90%; left: 5%; .slide { height: .86rem; width: 0.8rem; background: #fff; position: absolute; top: 0px; left: 0; i { width: 0; height: 0; border-width: 10px; border-style: dashed dashed dashed solid; border-color: transparent transparent transparent #d0caec; position: absolute; top: 50%; left: 50%; margin: -0.2rem 0 0 -0.05rem; } } .slideBg { height: 0.89rem; background: linear-gradient( to top right, #cddc39 0%, #8bc34a 25%, #ffeb3b 100% ); } .textBg { height: 0.89rem; width: 100%; text-align: center; position: absolute; top: 0; } .default { height: 0.89rem; position: absolute; top: 0; left: 15%; width: 70%; text-align: center; } } } </style>
好啦 ,就先這樣吧