123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303 |
- /**
- * 手势锁屏插件
- * varstion 1.0.5
- * by Houfeng
- * Houfeng@DCloud.io
- */
- (function($, doc) {
- var touchSupport = ('ontouchstart' in document);
- var startEventName = touchSupport ? $.EVENT_START : 'mousedown';
- var moveEventName = touchSupport ? $.EVENT_MOVE : 'mousemove';
- var endEventName = touchSupport ? $.EVENT_END : 'mouseup';
- var lockerHolderClassName = $.className('locker-holder');
- var lockerClassName = $.className('locker');
- var styleHolder = doc.querySelector('head') || doc.querySelector('body');
- styleHolder.innerHTML += "<style>.mui-locker-holder{overflow:hidden;position:relative;padding:0px;}.mui-locker-holder canvas{width:100%;height:100%;}</style>";
- var times = 2;
- function getElementLeft(element) {
- var actualLeft = element.offsetLeft;
- var current = element.offsetParent;
- while (current !== null) {
- actualLeft += current.offsetLeft;
- current = current.offsetParent;
- }
- return actualLeft;
- }
- function getElementTop(element) {
- var actualTop = element.offsetTop;
- var current = element.offsetParent;
- while (current !== null) {
- actualTop += current.offsetTop;
- current = current.offsetParent;
- }
- return actualTop;
- }
- //定义 Locker 类
- var Locker = $.Locker = $.Class.extend({
- R: 26,
- CW: 400,
- CH: 320,
- OffsetX: 30,
- OffsetY: 30,
- /**
- * 构造函数
- * */
- init: function(holder, options) {
- var self = this;
- if (!holder) {
- throw "构造 Locker 时缺少容器元素";
- }
- self.holder = holder;
- //
- options = options || {};
- options.callback = options.callback || options.done || $.noop;
- options.times = options.times || times;
- self.options = options;
- self.holder.innerHTML = '<canvas></canvas>';
- //
- self.holder.classList.add(lockerHolderClassName);
- //初始化
- var canvas = self.canvas = $.qsa('canvas', self.holder)[0];
- canvas.on = canvas.addEventListener || function(name, handler, capture) {
- canvas.attachEvent('on' + name, handler, capture);
- };
- canvas.off = canvas.removeEventListener || function(name, handler, capture) {
- canvas.detachEvent('on' + name, handler, capture);
- };
- //
- if (self.options.width) self.holder.style.width = self.options.width + 'px';
- if (self.options.height) self.holder.style.height = self.options.height + 'px';
- self.CW = self.options.width || self.holder.offsetWidth || self.CW;
- self.CH = self.options.height || self.holder.offsetHeight || self.CH;
- //处理 “宽、高” 等数值, 全部扩大 times 倍
- self.R *= self.options.times;
- self.CW *= self.options.times;
- self.CH *= self.options.times;
- self.OffsetX *= self.options.times;
- self.OffsetY *= self.options.times;
- //
- canvas.width = self.CW;
- canvas.height = self.CH;
- var cxt = self.cxt = canvas.getContext("2d");
- //两个圆之间的外距离 就是说两个圆心的距离去除两个半径
- var X = (self.CW - 2 * self.OffsetX - self.R * 2 * 3) / 2;
- var Y = (self.CH - 2 * self.OffsetY - self.R * 2 * 3) / 2;
- self.pointLocationArr = self.caculateNinePointLotion(X, Y);
- self.initEvent(canvas, cxt, self.holder);
- //console.log(X);
- self.draw(cxt, self.pointLocationArr, [], null);
- setTimeout(function() {
- self.draw(cxt, self.pointLocationArr, [], null);
- }, 0);
- },
- /**
- * 计算
- */
- caculateNinePointLotion: function(diffX, diffY) {
- var self = this;
- var Re = [];
- for (var row = 0; row < 3; row++) {
- for (var col = 0; col < 3; col++) {
- var Point = {
- X: (self.OffsetX + col * diffX + (col * 2 + 1) * self.R),
- Y: (self.OffsetY + row * diffY + (row * 2 + 1) * self.R)
- };
- Re.push(Point);
- }
- }
- return Re;
- },
- /**
- * 绘制
- */
- draw: function(cxt, _PointLocationArr, _LinePointArr, touchPoint) {
- var self = this;
- var R = self.R;
- if (_LinePointArr.length > 0) {
- cxt.beginPath();
- for (var i = 0; i < _LinePointArr.length; i++) {
- var pointIndex = _LinePointArr[i];
- cxt.lineTo(_PointLocationArr[pointIndex].X, _PointLocationArr[pointIndex].Y);
- }
- cxt.lineWidth = (self.options.lindeWidth || 2) * self.options.times;
- cxt.strokeStyle = self.options.lineColor || "#999"; //连结线颜色
- cxt.stroke();
- cxt.closePath();
- if (touchPoint != null) {
- var lastPointIndex = _LinePointArr[_LinePointArr.length - 1];
- var lastPoint = _PointLocationArr[lastPointIndex];
- cxt.beginPath();
- cxt.moveTo(lastPoint.X, lastPoint.Y);
- cxt.lineTo(touchPoint.X, touchPoint.Y);
- cxt.stroke();
- cxt.closePath();
- }
- }
- for (var i = 0; i < _PointLocationArr.length; i++) {
- var Point = _PointLocationArr[i];
- cxt.fillStyle = self.options.ringColor || "#888"; //圆圈边框颜色
- cxt.beginPath();
- cxt.arc(Point.X, Point.Y, R, 0, Math.PI * 2, true);
- cxt.closePath();
- cxt.fill();
- cxt.fillStyle = self.options.fillColor || "#f3f3f3"; //圆圈填充颜色
- cxt.beginPath();
- cxt.arc(Point.X, Point.Y, R - ((self.options.ringWidth || 2) * self.options.times), 0, Math.PI * 2, true);
- cxt.closePath();
- cxt.fill();
- if (_LinePointArr.indexOf(i) >= 0) {
- cxt.fillStyle = self.options.pointColor || "#777"; //圆圈中心点颜色
- cxt.beginPath();
- cxt.arc(Point.X, Point.Y, R - ((self.options.pointWidth || 16) * self.options.times), 0, Math.PI * 2, true);
- cxt.closePath();
- cxt.fill();
- }
- }
- },
- isPointSelect: function(touches, linePoint) {
- var self = this;
- for (var i = 0; i < self.pointLocationArr.length; i++) {
- var currentPoint = self.pointLocationArr[i];
- var xdiff = Math.abs(currentPoint.X - touches.elementX);
- var ydiff = Math.abs(currentPoint.Y - touches.elementY);
- var dir = Math.pow((xdiff * xdiff + ydiff * ydiff), 0.5);
- if (dir < self.R) {
- if (linePoint.indexOf(i) < 0) {
- linePoint.push(i);
- }
- break;
- }
- }
- },
- initEvent: function(canvas, cxt, holder) {
- var self = this;
- var linePoint = [];
- var isDown = false; //针对鼠标事件
- //start
- self._startHandler = function(e) {
- e.point = event.changedTouches ? event.changedTouches[0] : event;
- e.point.elementX = (e.point.pageX - getElementLeft(holder)) * self.options.times;
- e.point.elementY = (e.point.pageY - getElementTop(holder)) * self.options.times;
- self.isPointSelect(e.point, linePoint);
- isDown = true;
- };
- canvas.on(startEventName, self._startHandler, false);
- //move
- self._moveHanlder = function(e) {
- if (!isDown) return;
- e.preventDefault();
- e.point = event.changedTouches ? event.changedTouches[0] : event;
- e.point.elementX = (e.point.pageX - getElementLeft(holder)) * self.options.times;
- e.point.elementY = (e.point.pageY - getElementTop(holder)) * self.options.times;
- var touches = e.point;
- self.isPointSelect(touches, linePoint);
- cxt.clearRect(0, 0, self.CW, self.CH);
- self.draw(cxt, self.pointLocationArr, linePoint, {
- X: touches.elementX,
- Y: touches.elementY
- });
- };
- canvas.on(moveEventName, self._moveHanlder, false);
- //end
- self._endHandler = function(e) {
- e.point = event.changedTouches ? event.changedTouches[0] : event;
- e.point.elementX = (e.point.pageX - getElementLeft(holder)) * self.options.times;
- e.point.elementY = (e.point.pageY - getElementTop(holder)) * self.options.times;
- cxt.clearRect(0, 0, self.CW, self.CH);
- self.draw(cxt, self.pointLocationArr, linePoint, null);
- //事件数据
- var eventData = {
- sender: self,
- points: linePoint
- };
- /*
- * 回调完成事件
- *
- * 备注:
- * 比较理想的做法是为 Locker 的实例启用事件机制,比如 locker.on('done',handler);
- * 在 mui 没有完整的公共事件模块前,此版本中 locker 实例暂通过 options.callback 处理
- */
- self.options.callback(eventData);
- //触发声明的DOM的自定义事件(暂定 done 为事件名,可以考虑更有针对的事件名 )
- $.trigger(self.holder, 'done', eventData);
- //-
- linePoint = [];
- isDown = false;
- };
- canvas.on(endEventName, self._endHandler, false);
- },
- pointLocationArr: [],
- /**
- * 清除图形
- * */
- clear: function() {
- var self = this;
- //self.pointLocationArr = [];
- if (self.cxt) {
- self.cxt.clearRect(0, 0, self.CW, self.CH);
- self.draw(self.cxt, self.pointLocationArr, [], {
- X: 0,
- Y: 0
- });
- }
- },
- /**
- * 释放资源
- * */
- dispose: function() {
- var self = this;
- self.cxt = null;
- self.canvas.off(startEventName, self._startHandler);
- self.canvas.off(moveEventName, self._moveHandler);
- self.canvas.off(endEventName, self._endHandler);
- self.holder.innerHTML = '';
- self.canvas = null;
- }
- });
- //添加 locker 插件
- $.fn.locker = function(options) {
- //遍历选择的元素
- this.each(function(i, element) {
- if (element.locker) return;
- if (options) {
- element.locker = new Locker(element, options);
- } else {
- var optionsText = element.getAttribute('data-locker-options');
- var _options = optionsText ? JSON.parse(optionsText) : {};
- _options.lineColor = element.getAttribute('data-locker-line-color') || _options.lineColor;
- _options.ringColor = element.getAttribute('data-locker-ring-color') || _options.ringColor;
- _options.fillColor = element.getAttribute('data-locker-fill-color') || _options.fillColor;
- _options.pointColor = element.getAttribute('data-locker-point-color') || _options.pointColor;
- _options.width = element.getAttribute('data-locker-width') || _options.width;
- _options.height = element.getAttribute('data-locker-height') || _options.height;
- element.locker = new Locker(element, _options);
- }
- });
- return this[0] ? this[0].locker : null;
- };
- //自动处理 class='mui-locker' 的 dom
- try {
- $('.' + lockerClassName).locker();
- } catch (ex) {}
- $.ready(function() {
- $('.' + lockerClassName).locker();
- });
- }(mui, document));
|