"Based Pattern Lock Example"
Bootstrap 4.1.1 Snippet by Shailesh Kushwaha

<link href="//maxcdn.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css"> <script src="//maxcdn.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js"></script> <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> <!------ Include the above in your HEAD tag ----------> <!doctype html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <title>SVG Based Pattern Lock Example</title> <link href="https://www.jqueryscript.net/css/jquerysctipttop.css" rel="stylesheet" type="text/css"> <style media="screen"> * { box-sizing: border-box; } html, body { padding: 0; margin: 0; height: 100vh; max-height: 100vh; overflow: hidden; } body { font-family: 'Varela Round', sans-serif; background-color: #fafafa; } .container { margin: 150px auto; height: 100%; } h1 { text-align: center; margin: 0; height: 15vh; line-height: 15vh; text-align: center; font-size: 6vh; } #lock { width: 100%; height: calc(100% - 15vh); padding-bottom: 12vh; min-height: 120px; } .stars { margin: auto; display: block; } </style> <link rel="stylesheet" href="styles.css"> </head> <body> <div id="jquery-script-menu"> <div class="jquery-script-center"> <div class="jquery-script-clear"></div> </div> </div> <div class="container"> <h1>SVG Based Pattern Lock Example</h1> <svg class="patternlock" id="lock" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg"> <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> </div> <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script> <script src="patternlock.js"></script> <script type="text/javascript"> var e = document.getElementById('lock') var p = new PatternLock(e, { onPattern: function() { this.success() } }); </script> </body> <script type="text/javascript"> var _gaq = _gaq || []; _gaq.push(['_setAccount', 'UA-36251023-1']); _gaq.push(['_setDomainName', 'jqueryscript.net']); _gaq.push(['_trackPageview']); (function() { var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); })(); </script> </html>
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); } }
'use strict'; var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } (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 === 'undefined' ? 'undefined' : _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 _scrollKeys; var svgns = 'http://www.w3.org/2000/svg'; var moveEvent = 'touchmove mousemove'; var scrollKeys = (_scrollKeys = { 37: true, // left 38: true, // up 39: true, // right 40: true, // down 32: true }, _defineProperty(_scrollKeys, '38', true), _defineProperty(_scrollKeys, 34, true), _defineProperty(_scrollKeys, 35, true), _defineProperty(_scrollKeys, 36, true), _scrollKeys); function vibrate() { navigator.vibrate = navigator.vibrate || navigator.webkitVibrate || navigator.mozVibrate || navigator.msVibrate; if (navigator.vibrate) { window.navigator.vibrate(25); } } function PatternLock(element, options) { var svg = $(element); var self = this; var root = svg[0]; var dots = svg.find('.lock-dots circle'); var lines = svg.find('.lock-lines'); var actives = svg.find('.lock-actives'); var pt = root.createSVGPoint(); var code = []; var currentline = void 0; var currenthandler = void 0; options = Object.assign(PatternLock.defaults, options || {}); svg.on('touchstart mousedown', function (e) { clear(); e.preventDefault(); disableScroll(); svg.on(moveEvent, discoverDot); var endEvent = e.type == 'touchstart' ? 'touchend' : 'mouseup'; $(document).one(endEvent, function (e) { end(); }); }); // Exported methods Object.assign(this, { clear: clear, success: success, error: error, getPattern: getPattern }); function success() { svg.removeClass('error'); svg.addClass('success'); } function error() { svg.removeClass('success'); svg.addClass('error'); } function getPattern() { return parseInt(code.map(function (i) { return dots.index(i) + 1; }).join('')); } function end() { enableScroll(); stopTrack(currentline); currentline && currentline.remove(); svg.off(moveEvent, discoverDot); var 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 (var i = 0; i < code.length; i++) { if (code[i] === target) { return true; } } return false; } function isAvailable(target) { for (var 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; var pos = svgPosition(e.target, e); line.setAttribute('x2', pos.x); line.setAttribute('y2', pos.y); return false; }; } function discoverDot(e, target) { if (!target) { var _getMousePos = getMousePos(e), x = _getMousePos.x, y = _getMousePos.y; target = document.elementFromPoint(x, y); } var cx = target.getAttribute('cx'); var 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; var x = target.getAttribute('cx'); var y = target.getAttribute('cy'); line.setAttribute('x2', x); line.setAttribute('y2', y); } function beginTrack(target) { code.push(target); var x = target.getAttribute('cx'); var 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) { var _getMousePos2 = getMousePos(e), x = _getMousePos2.x, y = _getMousePos2.y; pt.x = x;pt.y = y; return pt.matrixTransform(element.getScreenCTM().inverse()); } } PatternLock.defaults = { onPattern: function onPattern() {}, vibrate: true }; return PatternLock; });

Related: See More


Questions / Comments: