1 | /*
|
---|
2 | * ext-shapes.js
|
---|
3 | *
|
---|
4 | * Licensed under the Apache License, Version 2
|
---|
5 | *
|
---|
6 | * Copyright(c) 2010 Christian Tzurcanu
|
---|
7 | * Copyright(c) 2010 Alexis Deveria
|
---|
8 | *
|
---|
9 | */
|
---|
10 |
|
---|
11 | methodDraw.addExtension("shapes", function() {
|
---|
12 |
|
---|
13 |
|
---|
14 | var current_d, cur_shape_id;
|
---|
15 | var canv = methodDraw.canvas;
|
---|
16 | var cur_shape;
|
---|
17 | var start_x, start_y;
|
---|
18 | var svgroot = canv.getRootElem();
|
---|
19 | var lastBBox = {};
|
---|
20 |
|
---|
21 | // This populates the category list
|
---|
22 | var categories = {
|
---|
23 | basic: 'Basic',
|
---|
24 | object: 'Objects',
|
---|
25 | symbol: 'Symbols',
|
---|
26 | arrow: 'Arrows',
|
---|
27 | flowchart: 'Flowchart',
|
---|
28 | nature: 'Nature',
|
---|
29 | game: 'Cards & Chess',
|
---|
30 | dialog_balloon: 'Dialog balloons',
|
---|
31 | music: 'Music',
|
---|
32 | weather: 'Weather & Time',
|
---|
33 | ui: 'User Interface',
|
---|
34 | social: 'Social Web'
|
---|
35 | };
|
---|
36 |
|
---|
37 | var library = {
|
---|
38 | 'basic': {
|
---|
39 | data: {
|
---|
40 | "star_points_5": "m1,116.58409l113.82668,0l35.17332,-108.13487l35.17334,108.13487l113.82666,0l-92.08755,66.83026l35.17514,108.13487l-92.08759,-66.83208l-92.08757,66.83208l35.17515,-108.13487l-92.08758,-66.83026z",
|
---|
41 | 'donut': 'm1,150l0,0c0,-82.29042 66.70958,-149 149,-149l0,0c39.51724,0 77.41599,15.69816 105.35889,43.64108c27.94293,27.94293 43.64111,65.84165 43.64111,105.35892l0,0c0,82.29041 -66.70958,149 -149,149l0,0c-82.29041,0 -149,-66.70959 -149,-149zm74.5,0l0,0c0,41.1452 33.35481,74.5 74.5,74.5c41.14522,0 74.5,-33.3548 74.5,-74.5c0,-41.1452 -33.3548,-74.5 -74.5,-74.5l0,0c-41.14519,0 -74.5,33.35481 -74.5,74.5z',
|
---|
42 | "triangle": "m1,280.375l149,-260.75l149,260.75z",
|
---|
43 | "right_triangle": "m1,299l0,-298l298,298z",
|
---|
44 | "diamond": "m1,150l149,-149l149,149l-149,149l-149,-149z",
|
---|
45 | "pentagon": "m1.00035,116.97758l148.99963,-108.4053l148.99998,108.4053l-56.91267,175.4042l-184.1741,0l-56.91284,-175.4042z",
|
---|
46 | "hexagon": "m1,149.99944l63.85715,-127.71428l170.28572,0l63.85713,127.71428l-63.85713,127.71428l-170.28572,0l-63.85715,-127.71428z",
|
---|
47 | "septagon1": "m0.99917,191.06511l29.51249,-127.7108l119.48833,-56.83673l119.48836,56.83673l29.51303,127.7108l-82.69087,102.41679l-132.62103,0l-82.69031,-102.41679z",
|
---|
48 | "heptagon": "m1,88.28171l87.28172,-87.28171l123.43653,0l87.28172,87.28171l0,123.43654l-87.28172,87.28172l-123.43653,0l-87.28172,-87.28172l0,-123.43654z",
|
---|
49 | "decagon": "m1,150.00093l28.45646,-88.40318l74.49956,-54.63682l92.08794,0l74.50002,54.63682l28.45599,88.40318l-28.45599,88.40318l-74.50002,54.63681l-92.08794,0l-74.49956,-54.63681l-28.45646,-88.40318z",
|
---|
50 | "dodecagon": "m1,110.07421l39.92579,-69.14842l69.14842,-39.92579l79.85159,0l69.14842,39.92579l39.92578,69.14842l0,79.85159l-39.92578,69.14842l-69.14842,39.92578l-79.85159,0l-69.14842,-39.92578l-39.92579,-69.14842l0,-79.85159z",
|
---|
51 | "trapezoid": "m1,299l55.875,-298l186.25001,0l55.87498,298z",
|
---|
52 | "dialog_balloon_1": "m0.99786,35.96579l0,0c0,-19.31077 15.28761,-34.96524 34.14583,-34.96524l15.52084,0l0,0l74.50001,0l139.68748,0c9.05606,0 17.74118,3.68382 24.14478,10.24108c6.40356,6.55726 10.00107,15.45081 10.00107,24.72416l0,87.41311l0,0l0,52.44785l0,0c0,19.31078 -15.2876,34.96524 -34.14584,34.96524l-139.68748,0l-97.32507,88.90848l22.82506,-88.90848l-15.52084,0c-18.85822,0 -34.14583,-15.65446 -34.14583,-34.96524l0,0l0,-52.44785l0,0z",
|
---|
53 | 'heart': 'm150,73c61,-175 300,0 0,225c-300,-225 -61,-400 0,-225z',
|
---|
54 | "cylinder": "m299.0007,83.77844c0,18.28676 -66.70958,33.11111 -149.00002,33.11111m149.00002,-33.11111l0,0c0,18.28676 -66.70958,33.11111 -149.00002,33.11111c-82.29041,0 -148.99997,-14.82432 -148.99997,-33.11111m0,0l0,0c0,-18.28674 66.70956,-33.1111 148.99997,-33.1111c82.29044,0 149.00002,14.82436 149.00002,33.1111l0,132.44449c0,18.28674 -66.70958,33.11105 -149.00002,33.11105c-82.29041,0 -148.99997,-14.82431 -148.99997,-33.11105z",
|
---|
55 | "arrow_up": "m1.49805,149.64304l148.50121,-148.00241l148.50121,148.00241l-74.25061,0l0,148.71457l-148.5012,0l0,-148.71457z",
|
---|
56 | "arrow_u_turn": "m1.00059,299.00055l0,-167.62497l0,0c0,-72.00411 58.37087,-130.37499 130.375,-130.37499l0,0l0,0c34.57759,0 67.73898,13.7359 92.18906,38.18595c24.45006,24.45005 38.18593,57.61144 38.18593,92.18904l0,18.625l37.24997,0l-74.49995,74.50002l-74.50002,-74.50002l37.25,0l0,-18.625c0,-30.8589 -25.0161,-55.87498 -55.87498,-55.87498l0,0l0,0c-30.85892,0 -55.875,25.01608 -55.875,55.87498l0,167.62497z",
|
---|
57 | "arrow_left_up": "m0.99865,224.5l74.50004,-74.5l0,37.25l111.74991,0l0,-111.75l-37.25,0l74.5,-74.5l74.5,74.5l-37.25,0l0,186.25l-186.24989,0l0,37.25l-74.50005,-74.5z",
|
---|
58 | "plaque": "m-0.00197,49.94376l0,0c27.5829,0 49.94327,-22.36036 49.94327,-49.94327l199.76709,0l0,0c0,27.5829 22.36037,49.94327 49.94325,49.94327l0,199.7671l0,0c-27.58289,0 -49.94325,22.36034 -49.94325,49.94325l-199.76709,0c0,-27.58292 -22.36037,-49.94325 -49.94327,-49.94325z",
|
---|
59 | "page": "m249.3298,298.99744l9.9335,-39.73413l39.73413,-9.93355l-49.66763,49.66768l-248.33237,0l0,-298.00001l298.00001,0l0,248.33234",
|
---|
60 | "cross": "m0.99844,99.71339l98.71494,0l0,-98.71495l101.26279,0l0,98.71495l98.71495,0l0,101.2628l-98.71495,0l0,98.71494l-101.26279,0l0,-98.71494l-98.71494,0z",
|
---|
61 | "divide": "m150,0.99785l0,0c25.17819,0 45.58916,20.41097 45.58916,45.58916c0,25.17821 -20.41096,45.58916 -45.58916,45.58916c-25.17822,0 -45.58916,-20.41093 -45.58916,-45.58916c0,-25.1782 20.41093,-45.58916 45.58916,-45.58916zm0,296.25203c-25.17822,0 -45.58916,-20.41095 -45.58916,-45.58917c0,-25.17819 20.41093,-45.58916 45.58916,-45.58916c25.17819,0 45.58916,20.41096 45.58916,45.58916c0,25.17822 -20.41096,45.58917 -45.58916,45.58917zm-134.06754,-193.71518l268.13507,0l0,91.17833l-268.13507,0z",
|
---|
62 | "minus": "m0.99887,102.39503l297.49445,0l0,95.2112l-297.49445,0z",
|
---|
63 | "times": "m1.00089,73.36786l72.36697,-72.36697l76.87431,76.87368l76.87431,-76.87368l72.36765,72.36697l-76.87433,76.87431l76.87433,76.87431l-72.36765,72.36765l-76.87431,-76.87433l-76.87431,76.87433l-72.36697,-72.36765l76.87368,-76.87431l-76.87368,-76.87431z"
|
---|
64 |
|
---|
65 |
|
---|
66 | },
|
---|
67 | buttons: []
|
---|
68 | }
|
---|
69 | };
|
---|
70 |
|
---|
71 | var cur_lib = library.basic;
|
---|
72 |
|
---|
73 | var mode_id = 'shapelib';
|
---|
74 |
|
---|
75 | function loadIcons() {
|
---|
76 | $('#shape_buttons').empty();
|
---|
77 |
|
---|
78 | // Show lib ones
|
---|
79 | $('#shape_buttons').append(cur_lib.buttons);
|
---|
80 | }
|
---|
81 |
|
---|
82 | function loadLibrary(cat_id) {
|
---|
83 |
|
---|
84 | var lib = library[cat_id];
|
---|
85 |
|
---|
86 | if(!lib) {
|
---|
87 | $('#shape_buttons').html('Loading...');
|
---|
88 | $.getJSON('extensions/shapelib/' + cat_id + '.json', function(result, textStatus) {
|
---|
89 | cur_lib = library[cat_id] = {
|
---|
90 | data: result.data,
|
---|
91 | size: result.size,
|
---|
92 | fill: result.fill
|
---|
93 | }
|
---|
94 | makeButtons(cat_id, result);
|
---|
95 | loadIcons();
|
---|
96 | });
|
---|
97 | return;
|
---|
98 | }
|
---|
99 |
|
---|
100 | cur_lib = lib;
|
---|
101 | if(!lib.buttons.length) makeButtons(cat_id, lib);
|
---|
102 | loadIcons();
|
---|
103 | }
|
---|
104 |
|
---|
105 | function makeButtons(cat, shapes) {
|
---|
106 | var size = cur_lib.size || 300;
|
---|
107 | var fill = cur_lib.fill || false;
|
---|
108 | var off = size * .05;
|
---|
109 | var vb = [-off, -off, size + off*2, size + off*2].join(' ');
|
---|
110 | var stroke = fill ? 0: (size/30);
|
---|
111 |
|
---|
112 | var shape_icon = new DOMParser().parseFromString(
|
---|
113 | '<svg xmlns="http://www.w3.org/2000/svg"><svg viewBox="' + vb + '"><path fill="#333" stroke="transparent" stroke-width="' + stroke + '" /><\/svg><\/svg>',
|
---|
114 | 'text/xml');
|
---|
115 |
|
---|
116 | var width = 40;
|
---|
117 | var height = 40;
|
---|
118 | shape_icon.documentElement.setAttribute('width', width);
|
---|
119 | shape_icon.documentElement.setAttribute('height', height);
|
---|
120 | var svg_elem = $(document.importNode(shape_icon.documentElement,true));
|
---|
121 |
|
---|
122 | var data = shapes.data;
|
---|
123 |
|
---|
124 | cur_lib.buttons = [];
|
---|
125 |
|
---|
126 | for(var id in data) {
|
---|
127 | var path_d = data[id];
|
---|
128 | var icon = svg_elem.clone();
|
---|
129 | icon.find('path').attr('d', path_d);
|
---|
130 |
|
---|
131 | var icon_btn = icon.wrap('<div class="tool_button">').parent().attr({
|
---|
132 | id: mode_id + '_' + id,
|
---|
133 | title: id
|
---|
134 | });
|
---|
135 |
|
---|
136 |
|
---|
137 | // Store for later use
|
---|
138 | cur_lib.buttons.push(icon_btn[0]);
|
---|
139 | }
|
---|
140 |
|
---|
141 | }
|
---|
142 |
|
---|
143 |
|
---|
144 | return {
|
---|
145 | svgicons: "extensions/ext-shapes.xml",
|
---|
146 | buttons: [{
|
---|
147 | id: "tool_shapelib",
|
---|
148 | type: "mode_flyout", // _flyout
|
---|
149 | position: 6,
|
---|
150 | title: "Shape library",
|
---|
151 | icon: "extensions/ext-shapes.png",
|
---|
152 | events: {
|
---|
153 | "click": function() {
|
---|
154 | canv.setMode(mode_id);
|
---|
155 | }
|
---|
156 | }
|
---|
157 | }],
|
---|
158 | callback: function() {
|
---|
159 |
|
---|
160 |
|
---|
161 | var btn_div = $('<div id="shape_buttons">');
|
---|
162 | $('#tools_shapelib > *').wrapAll(btn_div);
|
---|
163 |
|
---|
164 | var shower = $('#tools_shapelib_show');
|
---|
165 |
|
---|
166 |
|
---|
167 | loadLibrary('basic');
|
---|
168 |
|
---|
169 | // Do mouseup on parent element rather than each button
|
---|
170 | $('#shape_buttons').mouseup(function(evt) {
|
---|
171 | var btn = $(evt.target).closest('div.tool_button');
|
---|
172 |
|
---|
173 | if(!btn.length) return;
|
---|
174 |
|
---|
175 | var copy = btn.children().clone().attr({width: 24, height: 24});
|
---|
176 | shower.children(':not(.flyout_arrow_horiz)').remove();
|
---|
177 | shower
|
---|
178 | .append(copy)
|
---|
179 | .attr('data-curopt', '#' + btn[0].id) // This sets the current mode
|
---|
180 | .mouseup();
|
---|
181 | canv.setMode(mode_id);
|
---|
182 |
|
---|
183 | cur_shape_id = btn[0].id.substr((mode_id+'_').length);
|
---|
184 | current_d = cur_lib.data[cur_shape_id];
|
---|
185 |
|
---|
186 | $('.tools_flyout').fadeOut();
|
---|
187 |
|
---|
188 | });
|
---|
189 |
|
---|
190 | //
|
---|
191 | var shape_cats = $('<div id="shape_cats">');
|
---|
192 | var cat_str = '';
|
---|
193 |
|
---|
194 | $.each(categories, function(id, label) {
|
---|
195 | cat_str += '<div data-cat=' + id + '>' + label + '</div>';
|
---|
196 | });
|
---|
197 |
|
---|
198 | shape_cats.html(cat_str).children().bind('mouseup', function() {
|
---|
199 | var catlink = $(this);
|
---|
200 | catlink.siblings().removeClass('current');
|
---|
201 | catlink.addClass('current');
|
---|
202 |
|
---|
203 | loadLibrary(catlink.attr('data-cat'));
|
---|
204 | // Get stuff
|
---|
205 |
|
---|
206 | return false;
|
---|
207 | });
|
---|
208 |
|
---|
209 | shape_cats.children().eq(0).addClass('current');
|
---|
210 |
|
---|
211 | $('#tools_shapelib').prepend(shape_cats);
|
---|
212 |
|
---|
213 | shower.mouseup(function() {
|
---|
214 | canv.setMode(current_d ? mode_id : 'select');
|
---|
215 | });
|
---|
216 |
|
---|
217 |
|
---|
218 | $('#tool_shapelib').remove();
|
---|
219 |
|
---|
220 | var h = $('#tools_shapelib').height();
|
---|
221 | $('#tools_shapelib').css({
|
---|
222 | 'margin-top': -(h/2),
|
---|
223 | 'margin-left': 3
|
---|
224 | });
|
---|
225 |
|
---|
226 |
|
---|
227 | },
|
---|
228 | mouseDown: function(opts) {
|
---|
229 | var mode = canv.getMode();
|
---|
230 | if(mode !== mode_id) return;
|
---|
231 |
|
---|
232 | var e = opts.event;
|
---|
233 | var x = start_x = opts.start_x;
|
---|
234 | var y = start_y = opts.start_y;
|
---|
235 | var cur_style = canv.getStyle();
|
---|
236 | cur_shape = canv.addSvgElementFromJson({
|
---|
237 | "element": "path",
|
---|
238 | "curStyles": true,
|
---|
239 | "attr": {
|
---|
240 | "d": current_d,
|
---|
241 | "id": canv.getNextId(),
|
---|
242 | "opacity": cur_style.opacity / 2,
|
---|
243 | "style": "pointer-events:none"
|
---|
244 | }
|
---|
245 | });
|
---|
246 | cur_shape.setAttribute("d", current_d);
|
---|
247 | // Make sure shape uses absolute values
|
---|
248 | if(/[a-z]/.test(current_d)) {
|
---|
249 | current_d = cur_lib.data[cur_shape_id] = canv.pathActions.convertPath(cur_shape);
|
---|
250 | cur_shape.setAttribute('d', current_d);
|
---|
251 | canv.pathActions.fixEnd(cur_shape);
|
---|
252 | }
|
---|
253 |
|
---|
254 | cur_shape.setAttribute('transform', "translate(" + x + "," + y + ") scale(0.005) translate(" + -x + "," + -y + ")");
|
---|
255 | // console.time('b');
|
---|
256 | canv.recalculateDimensions(cur_shape);
|
---|
257 | var tlist = canv.getTransformList(cur_shape);
|
---|
258 | lastBBox = cur_shape.getBBox();
|
---|
259 | totalScale = {
|
---|
260 | sx: 1,
|
---|
261 | sy: 1
|
---|
262 | };
|
---|
263 | return {
|
---|
264 | started: true
|
---|
265 | }
|
---|
266 | // current_d
|
---|
267 | },
|
---|
268 | mouseMove: function(opts) {
|
---|
269 | var mode = canv.getMode();
|
---|
270 | if(mode !== mode_id) return;
|
---|
271 |
|
---|
272 | var zoom = canv.getZoom();
|
---|
273 | var evt = opts.event
|
---|
274 |
|
---|
275 | var x = opts.mouse_x/zoom;
|
---|
276 | var y = opts.mouse_y/zoom;
|
---|
277 |
|
---|
278 | var tlist = canv.getTransformList(cur_shape),
|
---|
279 | box = cur_shape.getBBox(),
|
---|
280 | left = box.x, top = box.y, width = box.width,
|
---|
281 | height = box.height;
|
---|
282 | var dx = (x-start_x), dy = (y-start_y);
|
---|
283 |
|
---|
284 | var newbox = {
|
---|
285 | 'x': Math.min(start_x,x),
|
---|
286 | 'y': Math.min(start_y,y),
|
---|
287 | 'width': Math.abs(x-start_x),
|
---|
288 | 'height': Math.abs(y-start_y)
|
---|
289 | };
|
---|
290 |
|
---|
291 | var ts = null,
|
---|
292 | tx = 0, ty = 0,
|
---|
293 | sy = height ? (height+dy)/height : 1,
|
---|
294 | sx = width ? (width+dx)/width : 1;
|
---|
295 |
|
---|
296 | var sx = newbox.width / lastBBox.width;
|
---|
297 | var sy = newbox.height / lastBBox.height;
|
---|
298 |
|
---|
299 | sx = sx || 1;
|
---|
300 | sy = sy || 1;
|
---|
301 |
|
---|
302 | // Not perfect, but mostly works...
|
---|
303 |
|
---|
304 | if(x < start_x) {
|
---|
305 | tx = lastBBox.width;
|
---|
306 | }
|
---|
307 | if(y < start_y) ty = lastBBox.height;
|
---|
308 |
|
---|
309 | // update the transform list with translate,scale,translate
|
---|
310 | var translateOrigin = svgroot.createSVGTransform(),
|
---|
311 | scale = svgroot.createSVGTransform(),
|
---|
312 | translateBack = svgroot.createSVGTransform();
|
---|
313 |
|
---|
314 | translateOrigin.setTranslate(-(left+tx), -(top+ty));
|
---|
315 | if(evt.shiftKey) {
|
---|
316 | replaced = true
|
---|
317 | var max = Math.min(Math.abs(sx), Math.abs(sy));
|
---|
318 | sx = max * (sx < 0 ? -1 : 1);
|
---|
319 | sy = max * (sy < 0 ? -1 : 1);
|
---|
320 | if (totalScale.sx != totalScale.sy) {
|
---|
321 | var multiplierX = (totalScale.sx > totalScale.sy) ? 1 : totalScale.sx/totalScale.sy;
|
---|
322 | var multiplierY = (totalScale.sy > totalScale.sx) ? 1 : totalScale.sy/totalScale.sx;
|
---|
323 | sx *= multiplierY
|
---|
324 | sy *= multiplierX
|
---|
325 | }
|
---|
326 | }
|
---|
327 | totalScale.sx *= sx;
|
---|
328 | totalScale.sy *= sy;
|
---|
329 | scale.setScale(sx,sy);
|
---|
330 | translateBack.setTranslate(left+tx, top+ty);
|
---|
331 | var N = tlist.numberOfItems;
|
---|
332 | tlist.appendItem(translateBack);
|
---|
333 | tlist.appendItem(scale);
|
---|
334 | tlist.appendItem(translateOrigin);
|
---|
335 |
|
---|
336 | canv.recalculateDimensions(cur_shape);
|
---|
337 | lastBBox = cur_shape.getBBox();
|
---|
338 | },
|
---|
339 | mouseUp: function(opts) {
|
---|
340 | var mode = canv.getMode();
|
---|
341 | if(mode !== mode_id) return;
|
---|
342 |
|
---|
343 | if(opts.mouse_x == start_x && opts.mouse_y == start_y) {
|
---|
344 | return {
|
---|
345 | keep: false,
|
---|
346 | element: cur_shape,
|
---|
347 | started: false
|
---|
348 | }
|
---|
349 | }
|
---|
350 | canv.setMode("select")
|
---|
351 | return {
|
---|
352 | keep: true,
|
---|
353 | element: cur_shape,
|
---|
354 | started: false
|
---|
355 | }
|
---|
356 | }
|
---|
357 | }
|
---|
358 | });
|
---|