반응형
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>authentication</title>
</head>
<script src="https://code.jquery.com/jquery-3.6.2.js" integrity="sha256-pkn2CUZmheSeyssYw3vMp1+xyub4m+e+QK4sQskvuo4=" crossorigin="anonymous"></script>
<link rel="stylesheet" href="./resource/css/pattern_lock.css">
<script src="./resource/js/pattern_lock.js" charset="utf-8"></script>
<body>
<!-- 패턴-->
<svg class="patternlock" id="lock" viewBox="0 0 100 100">
<g class="lock-actives"></g>
<g class="lock-lines"></g>
<g class="lock-dots">
<circle cx="20" cy="20" r="2"/>
<circle cx="50" cy="20" r="2"/>
<circle cx="80" cy="20" r="2"/>
<circle cx="20" cy="50" r="2"/>
<circle cx="50" cy="50" r="2"/>
<circle cx="80" cy="50" r="2"/>
<circle cx="20" cy="80" r="2"/>
<circle cx="50" cy="80" r="2"/>
<circle cx="80" cy="80" r="2"/>
</g>
</svg>
<button onClick="clearPattern()"> Clear </button>
</body>
<script>
/** 패턴 핸들러 **/
let lock = new PatternLock("#lock", {
onPattern: (pattern) => {
console.log(pattern); // 입력한 패턴 값
if(pattern === 123){
lock.success();
}else{
lock.error();
}
},
vibrate: false // 진동 on / off
});
let clearPattern = () =>{
lock.clear();
}
let getPattern = () =>{
lock.getPattern();
}
</script>
</html>
index.html
(function (factory) {
var global = Function('return this')() || (0, eval)('this');
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(['jquery'], function($) {
return factory($, global)
});
} else if (typeof exports === 'object') {
// Node. Does not work with strict CommonJS, but
// only CommonJS-like environments that support module.exports,
// like Node.
module.exports = factory(require('jquery'), global);
} else {
// Browser globals (global is window)
global.PatternLock = factory(global.jQuery, global);
}
}(function ($, window) {
var svgns = 'http://www.w3.org/2000/svg'
var moveEvent = 'touchmove mousemove'
var scrollKeys = {
37: true, // left
38: true, // up
39: true, // right
40: true, // down
32: true, // spacebar
38: true, // pageup
34: true, // pagedown
35: true, // end
36: true, // home
};
function vibrate() {
navigator.vibrate = navigator.vibrate || navigator.webkitVibrate || navigator.mozVibrate || navigator.msVibrate;
if (navigator.vibrate) {
window.navigator.vibrate(25)
}
}
function PatternLock(element, options) {
let svg = $(element)
let self = this
let root = svg[0]
let dots = svg.find('.lock-dots circle')
let lines = svg.find('.lock-lines')
let actives = svg.find('.lock-actives')
var pt = root.createSVGPoint();
let code = []
let currentline
let currenthandler
options = Object.assign(PatternLock.defaults, options || {})
svg.on('touchstart mousedown', (e) => {
clear()
e.preventDefault()
disableScroll()
svg.on(moveEvent, discoverDot)
let endEvent = e.type == 'touchstart' ? 'touchend' : 'mouseup';
$(document).one(endEvent, (e) => {
end()
})
})
// Exported methods
Object.assign(this, {
clear,
success,
error,
getPattern,
})
function success() {
svg.removeClass('error')
svg.addClass('success')
}
function error() {
svg.removeClass('success')
svg.addClass('error')
}
function getPattern() {
return parseInt(code.map((i) => dots.index(i)+1).join(''))
}
function end() {
enableScroll()
stopTrack(currentline)
currentline && currentline.remove()
svg.off(moveEvent, discoverDot)
let val = options.onPattern.call(self, getPattern())
if (val === true) {
success()
} else if (val === false) {
error()
}
}
function clear() {
code = []
currentline = undefined
currenthandler = undefined
svg.removeClass('success error')
lines.empty()
actives.empty()
}
function preventDefault(e) {
e = e || window.event;
if (e.preventDefault)
e.preventDefault();
e.returnValue = false;
}
function preventDefaultForScrollKeys(e) {
if (scrollKeys[e.keyCode]) {
preventDefault(e);
return false;
}
}
function disableScroll() {
if (window.addEventListener) // older FF
window.addEventListener('DOMMouseScroll', preventDefault, false);
window.onwheel = preventDefault; // modern standard
window.onmousewheel = document.onmousewheel = preventDefault; // older browsers, IE
window.ontouchmove = preventDefault; // mobile
document.onkeydown = preventDefaultForScrollKeys;
}
function enableScroll() {
if (window.removeEventListener)
window.removeEventListener('DOMMouseScroll', preventDefault, false);
window.onmousewheel = document.onmousewheel = null;
window.onwheel = null;
window.ontouchmove = null;
document.onkeydown = null;
}
function isUsed(target) {
for (let i = 0; i < code.length; i++) {
if (code[i] === target) {
return true
}
}
return false
}
function isAvailable(target) {
for (let i = 0; i < dots.length; i++) {
if (dots[i] === target) {
return true
}
}
return false
}
function updateLine(line) {
return function(e) {
e.preventDefault()
if (currentline !== line) return
let pos = svgPosition(e.target, e)
line.setAttribute('x2', pos.x)
line.setAttribute('y2', pos.y)
return false
}
}
function discoverDot(e, target) {
if (!target) {
let {x, y} = getMousePos(e)
target = document.elementFromPoint(x, y);
}
let cx = target.getAttribute('cx')
let cy = target.getAttribute('cy')
if (isAvailable(target) && !isUsed(target)) {
stopTrack(currentline, target)
currentline = beginTrack(target)
}
}
function stopTrack(line, target) {
if (line === undefined) return
if (currenthandler) {
svg.off('touchmove mousemove', currenthandler)
}
if (target === undefined) return
let x = target.getAttribute('cx')
let y = target.getAttribute('cy')
line.setAttribute('x2', x)
line.setAttribute('y2', y)
}
function beginTrack(target) {
code.push(target)
let x = target.getAttribute('cx')
let y = target.getAttribute('cy')
var line = createNewLine(x, y)
var marker = createNewMarker(x, y)
actives.append(marker)
currenthandler = updateLine(line)
svg.on('touchmove mousemove', currenthandler)
lines.append(line);
if(options.vibrate) vibrate()
return line
}
function createNewMarker(x, y) {
var marker = document.createElementNS(svgns, "circle")
marker.setAttribute('cx', x)
marker.setAttribute('cy', y)
marker.setAttribute('r', 6)
return marker
}
function createNewLine(x1, y1, x2, y2) {
var line = document.createElementNS(svgns, "line")
line.setAttribute('x1', x1)
line.setAttribute('y1', y1)
if (x2 === undefined || y2 == undefined) {
line.setAttribute('x2', x1)
line.setAttribute('y2', y1)
} else {
line.setAttribute('x2', x2)
line.setAttribute('y2', y2)
}
return line
}
function getMousePos(e) {
return {
x: e.clientX || e.originalEvent.touches[0].clientX,
y :e.clientY || e.originalEvent.touches[0].clientY
}
}
function svgPosition(element, e) {
let {x, y} = getMousePos(e)
pt.x = x; pt.y = y;
return pt.matrixTransform(element.getScreenCTM().inverse());
}
}
PatternLock.defaults = {
onPattern: () => {},
vibrate: true,
}
return PatternLock
}));
pattern_lock.js
svg.patternlock g.lock-lines line {
stroke-width: 1.5;
stroke: black;
opacity: 0.5;
}
svg.patternlock g.lock-dots circle {
stroke: transparent;
fill: black;
stroke-width: 13.5;
}
svg.patternlock g.lock-actives circle {
fill: black;
opacity: .2;
animation: lock-activate-dot .15s 0s ease 1;
transform-origin: center;
}
svg.patternlock g.lock-lines line {
stroke-width: 1.5;
stroke-linecap: round;
}
svg.patternlock.success g.lock-actives circle {
fill: green;
}
svg.patternlock.error g.lock-actives circle {
fill: red;
}
@keyframes lock-activate-dot {
0% {
transform: scale(0);
}
75% {
transform: scale(1.1);
}
100% {
transform: scale(1.0);
}
}
pattern_lock.css
출처 : https://github.com/tympanix/pattern-lock-js
자세한 문서는 위에 깃허브 참조하시면 됩니다.
반응형
'[JavaScript] > [JavaScript Code]' 카테고리의 다른 글
[JavaScript Code] "문자 → 숫자", "숫자 → 문자" 간단하게 바꾸기 (0) | 2023.09.20 |
---|---|
[JavaScript Code] Blob (임시 이미지 파일 경로 생성) (0) | 2023.09.20 |
[JavaScript Code] JSTL ajax로 다시 그려주기 (0) | 2022.12.18 |
[JavaScript Code] 링크 눌러서 이동시 뒤로가기 막기 (0) | 2022.12.18 |
[JavaScript Code] a(앵커)태그에 function(함수) 사용하기 (javascript:function) (0) | 2022.12.11 |