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); |
|