rverify
Version:
A lightweight image rotation verification plugin.
305 lines (271 loc) • 12.6 kB
JavaScript
/*
* RVerify.js
* (c) 2020 Feng L.H.
* Released under the MIT License.
*/
;(function (root, factory) {
if (typeof define === 'function' && define.amd) {
define(factory);
} else if (typeof exports === 'object') {
module.exports = factory();
} else {
root.RVerify = factory();
}
})(this, function () {
'use strict';
var RVerify = {};
RVerify.version = '0.1.3';
var Settings = {
mask: 0.5,
maskClosable: false,
closeIcon:
'<svg t="1590331085919" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3734" width="20" height="20"><path d="M512 451.67l225.835-225.835a42.667 42.667 0 0 1 60.33 60.33L572.331 512l225.834 225.835a42.667 42.667 0 0 1-60.33 60.33L512 572.331 286.165 798.165a42.667 42.667 0 1 1-60.33-60.33L451.669 512 225.835 286.165a42.667 42.667 0 0 1 60.33-60.33L512 451.669z" p-id="3735" fill="#8a8a8a"></path></svg>',
sliderIcon:
'<svg t="1590338601818" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6547" width="20" height="20"><path d="M512.299934 1023.800044c-10.797617 0-21.595234-3.999117-29.993381-11.797396-17.496139-16.496359-18.195984-44.090269-1.799602-61.586408l412.508958-437.10353c8.398147-8.898036 8.298169-23.894726-0.599868-32.692784L481.606708 74.409578c-17.096227-16.896271-17.296183-44.490181-0.299934-61.586408 16.896271-16.896271 44.390203-17.196205 61.586408-0.299934l410.809333 406.11037c42.290666 41.790777 43.590379 111.075485 2.699404 154.465909l-412.508958 437.003552c-8.69808 9.097992-20.195543 13.696977-31.593027 13.696977z" p-id="6548"></path><path d="M86.093999 924.821889c-10.697639 0-21.495256-3.999117-29.793425-11.897374-17.496139-16.496359-18.295962-44.090269-1.799603-61.586408l315.930274-334.626147c8.398147-9.097992 8.298169-24.094682-0.599868-32.792762L55.500751 173.587689c-16.996249-16.896271-17.196205-44.490181-0.299934-61.686386 16.896271-16.996249 44.390203-17.296183 61.586408-0.199956L431.017873 422.032856c42.290666 41.790777 43.490402 111.075485 2.799382 154.465909l-315.930273 334.626147c-8.69808 9.097992-20.195543 13.696977-31.792983 13.696977z" p-id="6549"></path></svg>',
extraIcon:
'<svg t="1590289223124" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2770" width="15" height="15"><path d="M512.002558 64.24521c-247.292176 0-447.75786 200.464661-447.75786 447.756837 0 247.287059 200.464661 447.752744 447.75786 447.752744 247.286036 0 447.75172-200.464661 447.75172-447.752744C959.754279 264.710894 759.288594 64.24521 512.002558 64.24521zM512.010745 735.87586c-20.602224 0-37.319977-16.718777-37.319977-37.323047 0-20.597107 16.717753-37.319977 37.319977-37.319977 20.60427 0 37.297464 16.72287 37.297464 37.319977C549.308209 719.158107 532.613992 735.87586 512.010745 735.87586zM549.308209 567.969733c0 20.600177-16.693194 37.293371-37.297464 37.293371-20.602224 0-37.319977-16.693194-37.319977-37.293371L474.690768 325.420581c0-20.605294 16.717753-37.297464 37.319977-37.297464 20.60427 0 37.297464 16.693194 37.297464 37.297464L549.308209 567.969733z" p-id="2771" fill="#4E6EF2"></path></svg>',
tolerance: 10,
duration: 500,
title: '身份验证',
text: '拖动滑块,使图片角度为正',
extra: null,
extraColor: '#4E6EF2',
extraLink: 'https://github.com/zpfz',
zIndex: 9999,
album: [],
};
var checkFlag = false;
// Configure
RVerify.configure = function (options) {
checkFlag = true;
var key, value;
for (key in options) {
value = options[key];
if (value !== undefined && options.hasOwnProperty(key)){
Settings[key] = value;
}
}
return this;
};
// Action
RVerify.action = function (callback) {
if (!checkFlag){
throw new Error('Please make sure RVerify.configure method is executed before RVerify.action');
}
if (Settings.extra !== null && typeof Settings.extra !== 'undefined') {
var _extra;
_extra =
'<div class="rv-extra"><span>' +
Settings.extraIcon +
'</span><a href="' +
Settings.extraLink +
'" target="_blank" rel="noopener noreferrer">' +
Settings.extra +
'</a></div>';
} else {
_extra = '';
}
var modal =
'<div class="rv-root"><div class="rv-mask"></div><div class="rv-wrap"><div class="rv-close">' +
Settings.closeIcon +
'</div><div class="rv-title">' +
Settings.title +
'</div><div class="rv-content"><div class="rv-text">' +
Settings.text +
'</div><div class="rv-image"><img src="' +
getRandomImg(Settings.album) +
'" draggable="false" class="rv-img"><div class="rv-image-mask"><svg t="1590812400512" class="rv-image-mask-success" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2647" width="80" height="80"><path d="M927.97968 108.360629a50.575037 50.575037 0 0 0-69.085501 18.517689l-391.898737 678.933747-316.000056-182.409708A50.575037 50.575037 0 0 0 100.427574 711.005546l359.812488 207.690002a50.553362 50.553362 0 0 0 69.078276-18.517689L946.504593 177.44613a50.575037 50.575037 0 0 0-18.524913-69.085501z" fill="#ffffff" p-id="2648"></path></svg><svg t="1590815914523" class="rv-image-mask-error" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3574" width="80" height="80"><path d="M441.23 511.44L79.4 149.62c-17.44-19.25-16.72-48.81 1.65-67.18 18.38-18.37 47.93-19.1 67.18-1.65l361.83 361.82L871.89 80.79a48.718 48.718 0 0 1 47.95-14.55 48.725 48.725 0 0 1 35.43 35.43 48.728 48.728 0 0 1-14.54 47.95L578.89 511.44l361.83 361.83a48.734 48.734 0 0 1 14.54 47.95 48.709 48.709 0 0 1-35.43 35.43 48.768 48.768 0 0 1-47.95-14.55L510.06 580.27 148.23 942.1c-19.25 17.44-48.8 16.72-67.18-1.65-18.37-18.37-19.09-47.93-1.65-67.18l361.83-361.83z" p-id="3575" fill="#ffffff"></path></svg></div></div><div class="rv-control"><div class="rv-bar">' +
'</div><div class="rv-slider">' +
Settings.sliderIcon +
'</div></div>' +
_extra +
'</div></div></div>';
var createNode = document.createElement('div');
createNode.innerHTML = modal;
$('body').appendChild(createNode);
var root = $('.rv-root'),
bar = $('.rv-bar'),
slider = $('.rv-slider'),
close = $('.rv-close'),
img = $('.rv-img'),
control = $('.rv-control'),
wrap = $('.rv-wrap'),
mask = $('.rv-mask'),
maskImg = $('.rv-image-mask'),
maskSuccess = $('.rv-image-mask-success'),
maskError = $('.rv-image-mask-error'),
footer = $('.rv-extra'),
html = $('html');
var distance = bar.offsetWidth - slider.offsetWidth;
// Flag
var result = 0;
// Check isMobile and bind different events
var touchMove,
inMobile = isMobile(),
downX,
touching = false;
if (isMobile()) {
slider.ontouchstart = touchStart;
document.ontouchmove = touchMove;
document.ontouchend = touchEnd;
} else {
slider.onmousedown = touchStart;
document.onmousemove = touchMove;
document.onmouseup = touchEnd;
}
// Init
// add touch-action style in <html></html>
html.setAttribute('style', 'touch-action:pan-y !important;');
mask.style['background-color'] = 'rgba(0, 0, 0,' + Settings.mask + ')';
mask.style['z-index'] = Settings.zIndex;
wrap.style['z-index'] = Settings.zIndex;
img.style.transform = 'rotate(' + RandomAngle(Settings.tolerance) + 'deg)';
if (Settings.extra !== null && typeof Settings.extra !== 'undefined') {
footer.style.color = Settings.extraColor;
}
var currentAngle = getImgAngle();
// Close
close.onclick = function () {
result = 2;
root.parentNode.remove();
// remove touch-action style in <html></html>
html.removeAttribute('style');
callback(result);
};
// Mask
mask.onclick = function () {
if (Settings.maskClosable == true) {
result = 2;
root.parentNode.remove();
// remove touch-action style in <html></html>
html.removeAttribute('style');
callback(result);
}
};
// Touch Move
function touchMove(e) {
if (!touching) return;
var e = e || window.event;
var moveX = inMobile ? e.touches[0].clientX : e.clientX;
var offsetX = moveX - downX;
var targetAngle = (offsetX / distance) * 360;
if (offsetX > distance) {
offsetX = distance;
} else if (offsetX < 0) {
offsetX = 0;
} else {
slider.style.left = offsetX + 'px';
targetAngle = currentAngle + targetAngle;
img.style.transform = 'rotate(' + targetAngle + 'deg)';
}
}
// Touch Start
function touchStart(e) {
// Clear transition
slider.style.transition = '';
img.style.transition = '';
slider.classList.add('rv-slider-normal');
var e = e || window.event;
downX = inMobile ? e.touches[0].clientX : e.clientX;
touching = true;
}
// Touch End
function touchEnd() {
slider.classList.remove('rv-slider-normal');
if (!touching) return;
if (ReturnResult(getImgAngle())) {
maskImg.style.cssText = 'visibility: visible;opacity: 1';
maskSuccess.style.cssText = 'visibility: visible;opacity: 1';
slider.style['pointer-events'] = 'none';
slider.classList.add('rv-slider-success');
// Call back
setTimeout(function () {
result = 1;
root.parentNode.remove();
// remove touch-action style in <html></html>
html.removeAttribute('style');
callback(result);
}, Settings.duration);
} else {
maskImg.style.cssText = 'visibility: visible;opacity: 1';
maskError.style.cssText = 'visibility: visible;opacity: 1';
slider.style['pointer-events'] = 'none';
control.style.animation = 'shake .15s infinite';
slider.classList.add('rv-slider-error');
setTimeout(function () {
img.src = getRandomImg(Settings.album);
// maskImg.style.cssText = '';
maskImg.removeAttribute('style');
// maskError.style.cssText = '';
maskError.removeAttribute('style');
slider.classList.remove('rv-slider-error');
// control.style.animation = '';
control.removeAttribute('style');
slider.style.left = 0;
img.style.transform = 'rotate(' + RandomAngle(Settings.tolerance) + 'deg)';
currentAngle = getImgAngle();
slider.style.transition =
'background .2s ease-in-out,border-color .2s ease-in-out,box-shadow .2s ease-in-out,left .5s ease-in-out';
img.style.transition = 'transform .5s ease-in-out';
slider.style['pointer-events'] = '';
}, 500);
callback(result);
}
touching = false;
}
};
// Random number
function getRandomNumber(a, b) {
return Math.round(Math.random() * (b - a) + a);
}
// Random image
function getRandomImg(imgArr) {
return imgArr[getRandomNumber(0, imgArr.length - 1)];
}
// Random interval
function RandomAngle(tolerance) {
if (tolerance < 5 || tolerance > 45) {
console.error('Please make sure the tolerance value is between 5°~45°.');
} else {
return (
Math.floor(Math.random() * (360 - tolerance - 1 - (tolerance + 1))) +
(tolerance + 1)
);
}
}
// Get image angle
function getImgAngle() {
return parseFloat(
$('.rv-img').style['transform'].replace(/[^0-9\\.\\^0-9]/gi, '')
);
}
// Check result
function ReturnResult(angle) {
if (angle > 360) {
angle = angle - 360;
return VerifyAngle(angle);
} else {
return VerifyAngle(angle);
}
}
// Verify angle
function VerifyAngle(angle) {
if (angle <= Settings.tolerance || angle >= 360 - Settings.tolerance) {
return true;
} else {
return false;
}
}
// Check isMobile
function isMobile() {
return 'ontouchstart' in window;
}
// Global query selector
var $ = function (selector) {
return document.querySelector(selector);
};
if (typeof window !== 'undefined') {
window.RVerify = RVerify;
}
return RVerify;
});