src/pyams_content/skin/resources/js/jquery-canvasAreaDraw.js
changeset 1070 ea0c7ac589c4
parent 1069 abd11be23718
child 1071 e202798d3732
equal deleted inserted replaced
1069:abd11be23718 1070:ea0c7ac589c4
     1 (function ($) {
       
     2 
       
     3 	$.fn.canvasAreaDraw = function (options) {
       
     4 
       
     5 		this.each(function (index, element) {
       
     6 			init.apply(element, [index, element, options]);
       
     7 		});
       
     8 
       
     9 	}
       
    10 
       
    11 	var init = function (index, input, options) {
       
    12 
       
    13 		var points, activePoint, settings;
       
    14 		var $reset, $canvas, ctx, image;
       
    15 		var draw, mousedown, stopdrag, move, moveall, resize, reset, rightclick, record;
       
    16 		var dragpoint;
       
    17 		var startpoint = false;
       
    18 
       
    19 		settings = $.extend({
       
    20 								imageUrl: $(this).attr('data-image-url')
       
    21 							}, options);
       
    22 
       
    23 		var v = $(input).val().replace(/[^0-9\,]/ig, '');
       
    24 		if (v.length) {
       
    25 			points = v.split(',').map(function (point) {
       
    26 				return parseInt(point, 10);
       
    27 			});
       
    28 		} else {
       
    29 			points = [];
       
    30 		}
       
    31 
       
    32 		// $reset = $('<button type="button" class="btn"><i class="icon-trash"></i>Очистить</button>');
       
    33 		$reset = $('<i class="fa fa-fw fa-trash"></i>');
       
    34 		$canvas = $('<canvas>');
       
    35 		ctx = $canvas[0].getContext('2d');
       
    36 
       
    37 		image = new Image();
       
    38 		resize = function () {
       
    39 			$canvas.attr('height', image.height).attr('width', image.width);
       
    40 			draw();
       
    41 		};
       
    42 		$(image).load(resize);
       
    43 		image.src = settings.imageUrl;
       
    44 		if (image.loaded) {
       
    45 			resize();
       
    46 		}
       
    47 		$canvas.css({background: 'url(' + image.src + ')'});
       
    48 
       
    49 		if (input.type !== 'hidden') {
       
    50 			$(input).after('<br />');
       
    51 		}
       
    52 		$(input).after($canvas, '<br />', $reset);
       
    53 
       
    54 		reset = function () {
       
    55 			points = [];
       
    56 			draw();
       
    57 		};
       
    58 
       
    59 		move = function (e) {
       
    60 			if (!e.offsetX) {
       
    61 				e.offsetX = (e.pageX - $(e.target).offset().left);
       
    62 				e.offsetY = (e.pageY - $(e.target).offset().top);
       
    63 			}
       
    64 			points[activePoint] = Math.round(e.offsetX);
       
    65 			points[activePoint + 1] = Math.round(e.offsetY);
       
    66 			draw();
       
    67 		};
       
    68 
       
    69 		moveall = function (e) {
       
    70 			if (!e.offsetX) {
       
    71 				e.offsetX = (e.pageX - $(e.target).offset().left);
       
    72 				e.offsetY = (e.pageY - $(e.target).offset().top);
       
    73 			}
       
    74 			if (!startpoint) {
       
    75 				startpoint = {x: Math.round(e.offsetX), y: Math.round(e.offsetY)};
       
    76 			}
       
    77 			var sdvpoint = {x: Math.round(e.offsetX), y: Math.round(e.offsetY)};
       
    78 			for (var i = 0; i < points.length; i++) {
       
    79 				points[i] = (sdvpoint.x - startpoint.x) + points[i];
       
    80 				points[++i] = (sdvpoint.y - startpoint.y) + points[i];
       
    81 			}
       
    82 			startpoint = sdvpoint;
       
    83 			draw();
       
    84 		};
       
    85 
       
    86 		stopdrag = function () {
       
    87 			$(this).off('mousemove');
       
    88 			record();
       
    89 			activePoint = null;
       
    90 		};
       
    91 
       
    92 		rightclick = function (e) {
       
    93 			e.preventDefault();
       
    94 			if (!e.offsetX) {
       
    95 				e.offsetX = (e.pageX - $(e.target).offset().left);
       
    96 				e.offsetY = (e.pageY - $(e.target).offset().top);
       
    97 			}
       
    98 			var x = e.offsetX, y = e.offsetY;
       
    99 			for (var i = 0; i < points.length; i += 2) {
       
   100 				dis = Math.sqrt(Math.pow(x - points[i], 2) + Math.pow(y - points[i + 1], 2));
       
   101 				if (dis < 6) {
       
   102 					points.splice(i, 2);
       
   103 					draw();
       
   104 					record();
       
   105 					return false;
       
   106 				}
       
   107 			}
       
   108 			return false;
       
   109 		};
       
   110 
       
   111 		mousedown = function (e) {
       
   112 			var x, y, dis, lineDis, insertAt = points.length;
       
   113 
       
   114 			if (e.which === 3) {
       
   115 				return false;
       
   116 			}
       
   117 
       
   118 			e.preventDefault();
       
   119 			if (!e.offsetX) {
       
   120 				e.offsetX = (e.pageX - $(e.target).offset().left);
       
   121 				e.offsetY = (e.pageY - $(e.target).offset().top);
       
   122 			}
       
   123 			x = e.offsetX;
       
   124 			y = e.offsetY;
       
   125 
       
   126 			if (points.length >= 6) {
       
   127 				var c = getCenter();
       
   128 				ctx.fillRect(c.x - 4, c.y - 4, 8, 8);
       
   129 				dis = Math.sqrt(Math.pow(x - c.x, 2) + Math.pow(y - c.y, 2));
       
   130 				if (dis < 6) {
       
   131 					startpoint = false;
       
   132 					$(this).on('mousemove', moveall);
       
   133 					return false;
       
   134 				}
       
   135 			}
       
   136 
       
   137 			for (var i = 0; i < points.length; i += 2) {
       
   138 				dis = Math.sqrt(Math.pow(x - points[i], 2) + Math.pow(y - points[i + 1], 2));
       
   139 				if (dis < 6) {
       
   140 					activePoint = i;
       
   141 					$(this).on('mousemove', move);
       
   142 					return false;
       
   143 				}
       
   144 			}
       
   145 
       
   146 			for (var i = 0; i < points.length; i += 2) {
       
   147 				if (i > 1) {
       
   148 					lineDis = dotLineLength(
       
   149 						x, y,
       
   150 						points[i], points[i + 1],
       
   151 						points[i - 2], points[i - 1],
       
   152 						true
       
   153 					);
       
   154 					if (lineDis < 6) {
       
   155 						insertAt = i;
       
   156 					}
       
   157 				}
       
   158 			}
       
   159 
       
   160 			points.splice(insertAt, 0, Math.round(x), Math.round(y));
       
   161 			activePoint = insertAt;
       
   162 			$(this).on('mousemove', move);
       
   163 
       
   164 			draw();
       
   165 			record();
       
   166 
       
   167 			return false;
       
   168 		};
       
   169 
       
   170 		draw = function () {
       
   171 			ctx.canvas.width = ctx.canvas.width;
       
   172 
       
   173 			record();
       
   174 			if (points.length < 2) {
       
   175 				return;
       
   176 			}
       
   177 			ctx.globalCompositeOperation = 'destination-over';
       
   178 			ctx.fillStyle = 'rgb(255,255,255)';
       
   179 			ctx.strokeStyle = 'rgb(255,20,20)';
       
   180 			ctx.lineWidth = 1;
       
   181 			if (points.length >= 6) {
       
   182 				var c = getCenter();
       
   183 				ctx.fillRect(c.x - 4, c.y - 4, 8, 8);
       
   184 			}
       
   185 			ctx.beginPath();
       
   186 			ctx.moveTo(points[0], points[1]);
       
   187 			for (var i = 0; i < points.length; i += 2) {
       
   188 				ctx.fillRect(points[i] - 2, points[i + 1] - 2, 4, 4);
       
   189 				ctx.strokeRect(points[i] - 2, points[i + 1] - 2, 4, 4);
       
   190 				if (points.length > 2 && i > 1) {
       
   191 					ctx.lineTo(points[i], points[i + 1]);
       
   192 				}
       
   193 			}
       
   194 			ctx.closePath();
       
   195 			ctx.fillStyle = 'rgba(255,0,0,0.3)';
       
   196 			ctx.fill();
       
   197 			ctx.stroke();
       
   198 
       
   199 		};
       
   200 
       
   201 		record = function () {
       
   202 			$(input).val(points.join(','));
       
   203 		};
       
   204 
       
   205 		getCenter = function () {
       
   206 			var ptc = [];
       
   207 			for (i = 0; i < points.length; i++) {
       
   208 				ptc.push({x: points[i], y: points[++i]});
       
   209 			}
       
   210 			var first = ptc[0], last = ptc[ptc.length - 1];
       
   211 			if (first.x != last.x || first.y != last.y) ptc.push(first);
       
   212 			var twicearea = 0,
       
   213 				x = 0, y = 0,
       
   214 				nptc = ptc.length,
       
   215 				p1, p2, f;
       
   216 			for (var i = 0, j = nptc - 1; i < nptc; j = i++) {
       
   217 				p1 = ptc[i];
       
   218 				p2 = ptc[j];
       
   219 				f = p1.x * p2.y - p2.x * p1.y;
       
   220 				twicearea += f;
       
   221 				x += ( p1.x + p2.x ) * f;
       
   222 				y += ( p1.y + p2.y ) * f;
       
   223 			}
       
   224 			f = twicearea * 3;
       
   225 			return {x: x / f, y: y / f};
       
   226 		};
       
   227 
       
   228 		$(input).on('change', function () {
       
   229 			var v = $(input).val().replace(/[^0-9\,]/ig, '');
       
   230 			if (v.length) {
       
   231 				points = v.split(',').map(function (point) {
       
   232 					return parseInt(point, 10);
       
   233 				});
       
   234 			} else {
       
   235 				points = [];
       
   236 			}
       
   237 			draw();
       
   238 		});
       
   239 
       
   240 		$(document).find($reset).click(reset);
       
   241 		$(document).find($canvas).on('mousedown', mousedown);
       
   242 		$(document).find($canvas).on('contextmenu', rightclick);
       
   243 		$(document).find($canvas).on('mouseup', stopdrag);
       
   244 
       
   245 	};
       
   246 
       
   247 	$(document).ready(function () {
       
   248 		$('.canvas-area[data-image-url]').canvasAreaDraw();
       
   249 	});
       
   250 
       
   251 	var dotLineLength = function (x, y, x0, y0, x1, y1, o) {
       
   252 		function lineLength(x, y, x0, y0) {
       
   253 			return Math.sqrt((x -= x0) * x + (y -= y0) * y);
       
   254 		}
       
   255 
       
   256 		if (o && !(o = function (x, y, x0, y0, x1, y1) {
       
   257 				if (!(x1 - x0)) return {x: x0, y: y};
       
   258 				else if (!(y1 - y0)) return {x: x, y: y0};
       
   259 				var left, tg = -1 / ((y1 - y0) / (x1 - x0));
       
   260 				return {
       
   261 					x: left = (x1 * (x * tg - y + y0) + x0 * (x * -tg + y - y1)) / (tg * (x1 - x0) + y0 - y1),
       
   262 					y: tg * left - tg * x + y
       
   263 				};
       
   264 			}(x, y, x0, y0, x1, y1), o.x >= Math.min(x0, x1) && o.x <= Math.max(x0, x1) && o.y >= Math.min(y0, y1) && o.y <= Math.max(y0, y1))) {
       
   265 			var l1 = lineLength(x, y, x0, y0), l2 = lineLength(x, y, x1, y1);
       
   266 			return l1 > l2 ? l2 : l1;
       
   267 		}
       
   268 		else {
       
   269 			var a = y0 - y1, b = x1 - x0, c = x0 * y1 - y0 * x1;
       
   270 			return Math.abs(a * x + b * y + c) / Math.sqrt(a * a + b * b);
       
   271 		}
       
   272 	};
       
   273 })(jQuery);