一、使用组件前的准备
因为组件用的是jQuery和canvas绘图,所以我们要提前在自己的项目里进行下载和引用,我这里用的是vue2.0,不知道如何在vue里面使用jQuery的小伙伴可以看之前分享过得如何在vue里使用jQuery;
二、新建imgVer.js
function imgVer(Config) { var el = eval(Config.el); var w = Config.width; var h = Config.height; var imgLibrary = Config.img; var PL_Size = 48; var padding = 20; var MinN_X = padding + PL_Size; var MaxN_X = w - padding - PL_Size - PL_Size / 6; var MaxN_Y = padding; var MinN_Y = h - padding - PL_Size - PL_Size / 6; var bi = Config.lan; function RandomNum(minNum, maxNum) { switch (arguments.length) { case 1: return parseInt(Math.random() * minNum + 1, 10); break; case 2: return parseInt(Math.random() * (maxNum - minNum + 1) + minNum, 10); break; default: return 0; break; } } function lang(lnum, bi) { if (!bi) { bi = "cn"; } var cn = new Array(); cn["lan1"] = "按住左邊滑塊,拖動完成上方拼圖"; cn["lan2"] = "驗證通過"; cn["lan3"] = "驗證失敗"; cn["lan4"] = "拖動滑塊將懸浮圖像正確拼合"; var en = new Array(); en["lan1"] = "Drag slider to finish the puzzle."; en["lan2"] = "Success"; en["lan3"] = "Fail"; en["lan4"] = "Complete the puzzle correctly."; return eval(bi)[lnum]; } var imgRandom = RandomNum(1, imgLibrary.length) - 1; var imgSrc = imgLibrary[imgRandom]; if (Config.randtox) { var X = Number(Config.randtox); } else { var X = RandomNum(MinN_X, MaxN_X); } var Y = RandomNum(MinN_Y, MaxN_Y); var left_Num = -X + 10; var html = '<div class="imgver_box"><div class="imgver_bg"></div><div class="imgver_main">'; html += '<div style="position:relative;padding:16px 16px 28px;border:1px solid #ddd;background:#f2ece1;border-radius:16px;">'; html += '<div style="position:relative;overflow:hidden;width:' + w + 'px;">'; html += '<div style="position:relative;width:' + w + "px;height:" + h + 'px;">'; html += '<img id="scream" src="' + imgSrc + '" style="width:' + w + "px;height:" + h + 'px;">'; html += '<canvas id="puzzleBox" width="' + w + '" height="' + h + '" style="position:absolute;left:0;top:0;z-index:22;"></canvas>'; html += "</div>"; html += '<div class="puzzle-lost-box" style="position:absolute;width:' + w + "px;height:" + h + "px;top:0;left:" + left_Num + 'px;z-index:111;">'; html += '<canvas id="puzzleShadow" width="' + w + '" height="' + h + '" style="position:absolute;left:0;top:0;z-index:22;"></canvas>'; html += '<canvas id="puzzleLost" width="' + w + '" height="' + h + '" style="position:absolute;left:0;top:0;z-index:33;"></canvas>'; html += "</div>"; html += '<p class="ver-tips"></p>'; html += "</div>"; html += '<div class="re-btn"><a></a></div>'; html += "</div>"; html += "<br>"; html += '<div style="position:relative;width:' + w + 'px;margin:auto;">'; html += '<div style="border:1px solid #c3c3c3;border-radius:24px;background:#ece4dd;box-shadow:0 1px 1px rgba(12,10,10,0.2) inset;">'; html += '<div style="padding-left:26px;"><p style="font-size:12px;color:#486c80;line-height:28px;text-align:center;">' + lang("lan1", bi) + "</p></div>"; html += "</div>"; html += '<div class="slider-btn"></div>'; html += "</div>"; html += "</div></div>"; el.html(html); var d = PL_Size / 3; var c = document.getElementById("puzzleBox"); var ctx = c.getContext("2d"); ctx.globalCompositeOperation = "xor"; ctx.shadowBlur = 10; ctx.shadowColor = "#fff"; ctx.shadowOffsetX = 3; ctx.shadowOffsetY = 3; ctx.fillStyle = "rgba(0,0,0,0.7)"; ctx.beginPath(); ctx.lineWidth = "1"; ctx.strokeStyle = "rgba(0,0,0,0)"; ctx.moveTo(X, Y); ctx.lineTo(X + d, Y); ctx.bezierCurveTo(X + d, Y - d, X + 2 * d, Y - d, X + 2 * d, Y); ctx.lineTo(X + 3 * d, Y); ctx.lineTo(X + 3 * d, Y + d); ctx.bezierCurveTo( X + 2 * d, Y + d, X + 2 * d, Y + 2 * d, X + 3 * d, Y + 2 * d ); ctx.lineTo(X + 3 * d, Y + 3 * d); ctx.lineTo(X, Y + 3 * d); ctx.closePath(); ctx.stroke(); ctx.fill(); var c_l = document.getElementById("puzzleLost"); var c_s = document.getElementById("puzzleShadow"); var ctx_l = c_l.getContext("2d"); var ctx_s = c_s.getContext("2d"); var img = new Image(); img.src = imgSrc; img.onload = function() { ctx_l.drawImage(img, 0, 0, w, h); }; ctx_l.beginPath(); ctx_l.strokeStyle = "rgba(0,0,0,0)"; ctx_l.moveTo(X, Y); ctx_l.lineTo(X + d, Y); ctx_l.bezierCurveTo(X + d, Y - d, X + 2 * d, Y - d, X + 2 * d, Y); ctx_l.lineTo(X + 3 * d, Y); ctx_l.lineTo(X + 3 * d, Y + d); ctx_l.bezierCurveTo( X + 2 * d, Y + d, X + 2 * d, Y + 2 * d, X + 3 * d, Y + 2 * d ); ctx_l.lineTo(X + 3 * d, Y + 3 * d); ctx_l.lineTo(X, Y + 3 * d); ctx_l.closePath(); ctx_l.stroke(); ctx_l.shadowBlur = 10; ctx_l.shadowColor = "black"; ctx_l.clip(); ctx_s.beginPath(); ctx_s.lineWidth = "1"; ctx_s.strokeStyle = "rgba(0,0,0,0)"; ctx_s.moveTo(X, Y); ctx_s.lineTo(X + d, Y); ctx_s.bezierCurveTo(X + d, Y - d, X + 2 * d, Y - d, X + 2 * d, Y); ctx_s.lineTo(X + 3 * d, Y); ctx_s.lineTo(X + 3 * d, Y + d); ctx_s.bezierCurveTo( X + 2 * d, Y + d, X + 2 * d, Y + 2 * d, X + 3 * d, Y + 2 * d ); ctx_s.lineTo(X + 3 * d, Y + 3 * d); ctx_s.lineTo(X, Y + 3 * d); ctx_s.closePath(); ctx_s.stroke(); ctx_s.shadowBlur = 20; ctx_s.shadowColor = "black"; ctx_s.fill(); var moveStart = ""; $(".slider-btn").mousedown(function(e) { e = e || window.event; $(this).addClass("slider-hover"); moveStart = e.pageX; }); $(".slider-btn").on("touchstart", function(e) { var touch = e.originalEvent.targetTouches[0]; moveStart = touch.pageX; }); onmousemove = function(e) { e = e || window.event; var moveX = e.pageX; var d = moveX - moveStart; if (moveStart == "") { } else { if (d < 0 || d > w - padding - PL_Size) { } else { $(".slider-btn").css({ left: d + "px", transition: "inherit" }); $("#puzzleLost").css({ left: d + "px", transition: "inherit" }); $("#puzzleShadow").css({ left: d + "px", transition: "inherit" }); } } }; $(".slider-btn").on("touchmove", function(e) { var touch = e.originalEvent.targetTouches[0]; $(this).addClass("slider-hover"); var moveX = touch.pageX; var d = moveX - moveStart; if (moveStart == "") { } else { if (d < 0 || d > w - padding - PL_Size) { } else { $(".slider-btn").css({ left: d + "px", transition: "inherit" }); $("#puzzleLost").css({ left: d + "px", transition: "inherit" }); $("#puzzleShadow").css({ left: d + "px", transition: "inherit" }); } } }); onmouseup = function(e) { e = e || window.event; var moveEnd_X = e.pageX - moveStart; pizzend(moveEnd_X); }; $(".slider-btn").on("touchend", function(e) { var touch = e.originalEvent.changedTouches[0]; var moveEnd_X = touch.pageX - moveStart; pizzend(moveEnd_X); }); function pizzend(moveEnd_X) { var ver_Num = X - 10; var deviation = 5; var Min_left = ver_Num - deviation; var Max_left = ver_Num + deviation; if (moveStart == "") { } else { if (Max_left > moveEnd_X && moveEnd_X > Min_left) { $(".ver-tips").html( '<i class="success"></i><span style="color:#42ca6b;">' + lang("lan2", bi) + "</span><span></span>" ); $(".ver-tips").addClass("slider-tips"); $(".puzzle-lost-box").addClass("imgver_hidden"); $("#puzzleBox").addClass("imgver_hidden"); setTimeout(function() { $(".ver-tips").removeClass("slider-tips"); //imgVer(Config); }, 2000); Config.success(); } else { $(".ver-tips").html( '<i class="fail"></i><span style="color:red;">' + lang("lan3", bi) + ':</span><span style="margin-left:4px;">' + lang("lan4", bi) + "</span>" ); $(".ver-tips").addClass("slider-tips"); setTimeout(function() { $(".ver-tips").removeClass("slider-tips"); }, 2000); Config.error(); } } setTimeout(function() { $(".slider-btn").css({ left: "0", transition: "left 0.5s" }); $("#puzzleLost").css({ left: "0", transition: "left 0.5s" }); $("#puzzleShadow").css({ left: "0", transition: "left 0.5s" }); }, 1000); $(".slider-btn").removeClass("slider-hover"); moveStart = ""; $(".re-btn a").on("click", function() { imgVer(Config); }); } } export default imgVer;
这里导出后我直接在main.js做的全局挂载方便使用
1. import imgVer from "./js/imgver"; 2. 3. 4. Vue.prototype.$imgVer = imgVer;
二、imgVer.css文件
@charset "utf-8"; #imgver { -moz-user-select: none; -webkit-user-select: none; -ms-user-select: none; -khtml-user-select: none; user-select: none; } .slider-btn, .re-btn a, .ver-tips i { background-image: url(../images/imgver/sprite.png); } .imgver_box { width: 100%; height: 100%; position: fixed; top: 0; left: 0; z-index: 10000; } .imgver_bg { width: 100%; height: 100%; background: rgba(0, 0, 0, 0.7); position: absolute; top: 0; left: 0; cursor: pointer; } .imgver_main { display: inline-block; position: absolute; top: 50%; margin-top: -103px; left: 50%; margin-left: -147px; } .slider-btn { position: absolute; width: 44px; height: 44px; left: 0; top: -7px; z-index: 12; cursor: pointer; background-position: 0 0; transition: inherit; } .slider-hover { background-position: 0 -44px; } .ver-tips { position: absolute; left: 0; bottom: -22px; background: rgba(255, 255, 255, 0.9); height: 22px; line-height: 22px; font-size: 12px; width: 100%; margin: 0; text-align: left; padding: 0 8px; transition: all 0.4s; } .slider-tips { bottom: 0; } .ver-tips i { display: inline-block; width: 22px; height: 22px; vertical-align: top; } .ver-tips i.success { background-position: 4px -122px; } .ver-tips i.fail { background-position: 4px -146px; } .ver-tips span { display: inline-block; vertical-align: top; line-height: 22px; color: #455; } .active-tips { display: block; } .imgver_hidden { display: none; } .re-btn { position: absolute; left: 0; bottom: 0; height: 28px; padding: 0 16px; } .re-btn a { display: inline-block; width: 14px; height: 14px; margin: 7px 0; background-position: 0 -88px; cursor: pointer; } .re-btn a:hover { background-position: 0 -102px; }
三、layout.css 文件
@charset "utf-8"; body, input, textarea, select, button { font-family: "Arial", "PingFangSC-Light", "Microsoft Yahei", "宋体", sans-serif; } body { font-size: 12px; color: #000; } a { color: #000; text-decoration: none; } a:focus { outline: 0; -moz-outline: none; } /*for ff*/ a:hover { text-decoration: none; color: #ad1f24; } body, div, dl, dt, dd, ul, ol, li, h1, h2, h3, h4, h5, h6, pre, code, form, fieldset, legend, input, button, textarea, area, blockquote, th, td, p { margin: 0; padding: 0; } img, a img, button { border: 0; } table { border-collapse: collapse; } li { list-style-type: none; } input, textarea, select, button { outline: none; } input, textarea { resize: none; -webkit-appearance: none; border-radius: 0; border: 1px solid #ddd; width: 100%; box-sizing: border-box; min-height: 30px; } button[type="submit"], input[type="submit"] { cursor: pointer; }
样式文件我这里也是直接在main.js里面做的全局导入,方便使用;
import Vue from "vue"; import imgVer from "./js/imgver"; import "./assets/css/imgver.css"; import "./assets/css/layout.css"; Vue.config.productionTip = false; Vue.use(ElementUI); Vue.prototype.$axios = axios; Vue.prototype.$imgVer = imgVer;
四、验证码背景图
位置随意即可
Tips:
这个sprite.psd文件下面有链接,大家可以下载
五、页面内使用
·1.HTML
<van-form @submit="register" validate-first> <div class="flex"> <label>Home No.</label> <div> <div class="select-flex"> <el-select @change="getHouseNumber" class="select-phone" v-model="datas.selectHouseNumber" placeholder="Please select" > <el-option v-for="item in areaCode" :key="item.areaCode" :value="item.areaCode" :label="item.areaCode" > </el-option> </el-select> <van-field v-model="datas.houseNumber" type="number" :rules="[ { validator: validateHouseNumber, message: houseNumberMessage, }, ]" class="field-phoneNumber" /> </div> </div> </div> <div class="flex"> <label>Email</label> <van-field v-model="datas.email" :rules="[ { validator: validateEmail, message: 'Please enter a valid email', }, ]" class="field" /> </div> </van-form> <!-- 核心代码 --> <div id="imgver"></div>
2.methods中
register() { //核心代码 this.$imgVer({ el: '$("#imgver")', width: "260", height: "116", img: [ require("@/assets/images/imgver/ver-1.png"), require("@/assets/images/imgver/ver-2.png"), require("@/assets/images/imgver/ver-3.png"), require("@/assets/images/imgver/ver-4.png"), require("@/assets/images/imgver/ver-5.png"), require("@/assets/images/imgver/ver-6.png"), ], //中英文切换 lan: "en", //'cn' or 'en' success: () => { //成功的回调 this.goRegister(); }, error: function () { return false; }, }); },
3.效果图
源码是可以进行后端验证的,今天给大家分享的用法只是在前端做随机;源码地址