一、使用组件前的准备
因为组件用的是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做的全局挂载方便使用
import imgVer from "./js/imgver";
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.效果图
源码是可以进行后端验证的,今天给大家分享的用法只是在前端做随机;源码地址