├── LICENSE
├── README.md
├── app.html
├── css
├── bootstrap.min.css
├── styles.css
└── subjx.css
├── js
├── bezier.js
├── booleans.js
├── clipper.min.js
├── clipperUtils.js
├── colorAdmin.js
├── controllerEvent.js
├── conversion.js
├── editBezier.js
├── flatten.js
├── imagetracer.min.js
├── imagetracer_v1.2.6.js
├── js.cookie.min.js
├── menuLeft.js
├── openFile.js
├── opentype.min.js
├── panZoom.js
├── panels.js
├── path-data-polyfill.min.js
├── pathseg.js
├── polyClip.js
├── rough.js
├── selection.js
├── subjx.min.js
└── utils.js
└── tools.html
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ArtDraw
2 | ## SVG editor online - Vector drawing and graphics editor
3 | 
4 |
5 | This project uses javascript, HTML, to create a graphical editor for designing vector images in SVG format.
6 | This project was not intended for use in NodeJS.
7 |
8 | The central idea of the project is to create a simple editor that has a large number of tools that allow creating functional designs, like those made with commercial programs.
9 |
10 | The project is in a continuous phase of development, this can be considered the initial version. There are still many tools to be developed, surely bugs to be corrected. This editor works on an SVG object, not Canvas. So the performance is not so perfect, but that doesn't mean it's not usable, or it's not capable of generating complex files. Still try not to abuse the nodes in the SVG paths.
11 |
12 |
13 |
14 | ## SVG Editor Tools
15 |
16 |
17 | Left Bar Tools Top Bar Tools
18 |
19 |
20 |
21 | Freehand pencil tool
22 | Polygon pencil tool
23 | Ovals Tool
24 | Rectangles Tool
25 | Text Tool
26 | Cliparts
27 |
28 |
29 |
30 |
31 | File Menu Options
32 | Setttings
33 | Size Document
34 | Z.Order Shapes
35 | Mirror Tool
36 | Group Shapes
37 | Combine Shapes
38 | Grid align tool
39 |
40 |
41 |
42 |
43 |
44 | Right Bar Tools and Panels Assistants
45 |
46 |
47 |
48 | Arrays panel
49 | Edit nodes bezier
50 | Border Round
51 | Align Tool
52 | Boolean operations Tool
53 | Offset Tool
54 |
55 |
56 |
57 |
58 | Trace image to vectors
59 | Color and gradients panel
60 | Clip mask panel
61 | Rough style panel
62 | Backgrounds panel
63 | Filter effects panel
64 |
65 |
66 |
67 |
68 | xxxxxxx
69 |
70 |
71 |
72 | Freehand Pencil Tool
73 | Polygon Pencil Tool
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 | This is your typical freehand pencil tool. The smoothing factor is adjustable from configuration.
83 | This Tool draws a polygon with straight segments. By clicking on the red starting point, it closes automatically.
84 |
85 |
86 |
87 | xxxx
88 |
89 |
90 |
91 | Ovals Pencil Tool
92 | Rectangle Pencil Tool
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 | Simple and essential tool. Just draw circles starting from the center..
102 | This tool makes rectangles, just rectangles and squares, and rectangles.
103 |
104 |
105 |
106 | xxx
107 |
108 |
109 |
110 | Text Tool
111 | Clipparts Tool
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 | The Text tool allows you to create 2 types. Simple and vector text with the OpenType library. Artdraw includes more than 500 GoogleFonts.
121 | Enter the clipparts gallery and select the design of your liking. Insert it to the document. Then you can modify size, colors, etc.
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
--------------------------------------------------------------------------------
/css/styles.css:
--------------------------------------------------------------------------------
1 | html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video { margin: 0; padding: 0; border: 0; font-size: 100%; font: inherit; vertical-align: baseline; } /* HTML5 display-role reset for older browsers */ article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section { display: block; } body { line-height: 1; } ol, ul { list-style: none; } blockquote, q { quotes: none; } blockquote:before, blockquote:after, q:before, q:after { content: ''; content: none; } table { border-collapse: collapse; border-spacing: 0; }
2 | span,h1,h2,h3,h4,h5,h6,p{cursor: default;}
3 | @media print {
4 | #ruleLeftG, #infoPanel, #ruleTopG, .xcontainer, #containerLeftMenu, #transformXY, #gridLinesV, #gridLinesH, #leftSideBar, #colorPalette, #infoXY, #AYUDA, .sjx-svg-wrapper, .toolPanel { display:none; }
5 | #workMain{stroke: #b5b5b5;}
6 | [filter=url(#groupborder)]{filter:none}
7 | }
8 |
9 | :root{--background-color: #212529;--background-hover: #ff0066;--text-color: #fafafb; --text-color-inv: #fafafb; --border-color:#404040;--menu-hover:#5a5a5a; --clBlack:black; --clWhite:white}
10 |
11 | *{box-sizing:border-box}
12 | html,body{font-family:poppins,sans-serif;font-size:62.5%;font-weight:500}
13 | body{font-family:poppins,sans-serif;font-size:1.4rem;color:var(--text-color);height:100%;overflow:hidden;background-color:var(--background-color)}
14 | .cur-default {cursor: default;}
15 | span, p, h1, h2, h3, h4, image, td, input[type="text"]{-webkit-user-select: none;-moz-user-select: none;-ms-user-select: none;user-select: none;}
16 | b{font-weight:bold;}
17 |
18 |
19 | .bgBN, .bgBN p, .bgBN span, .bgBN h3, .bgBN label, .bgBN td{ background-color: white; color:black; }
20 | .bgLight{background-color:var(--background-hover) !important; color: var(--text-color-inv) !important}
21 | .bgdark{background-color:var(--background-color) !important;color:var(--text-color) !important;}
22 | .clWhite{color:var(--clWhite)} .clBlack{color:var(--clBlack)}
23 | .clModeA{background-color:var(--background-color) !important;color:var(--text-color) !important;}
24 | .clModeB{background-color:var(--background-hover) !important;color:var(--text-color-inv) !important;}
25 |
26 | .cl--bkc{color:var(--background-color);}
27 | .cl--txc{color:var(--text-color);}
28 | .cl--bkh{color:var(--background-hover);}
29 | .cl--txcinv{color:var(--text-color-inv);}
30 | .cl--bc{color:var(--border-color);}
31 |
32 | #divWeb {
33 | height:100vh;
34 | display: grid;
35 | grid-template-columns: 42px 16px 1fr;
36 | grid-template-rows: 30px 16px 1fr;
37 | grid-column-gap: 0px;
38 | grid-row-gap: 0px;
39 | }
40 | #divTopMenu { grid-area: 1 / 2 / 2 / 4; overflow:hidden; }
41 | #divLeftMenu { grid-area: 2 / 1 / 4 / 2; }
42 | #divCanvas { grid-area: 3 / 3 / 4 / 4; overflow:hidden; }
43 | #divRulerCanvasTop{ grid-area: 2 / 3 / 3 / 4; border-bottom: 1px solid black; overflow:hidden; }
44 | #divRulerCanvasLeft{ grid-area: 3 / 2 / 4 / 3; border-right: 1px solid black; overflow:hidden; }
45 |
46 | #divPalette { height: 24px; position:fixed;bottom:0;background:aliceblue;margin:0 0 0 42px;padding:0px;overflow-y:scroll;scroll-snap-type:y mandatory; }
47 |
48 |
49 | ul#liPalette{list-style: none;margin:0;padding:0px;}
50 | ul#liPalette li{width: 24px; height: 24px; display: inline-block;margin:0px;padding:0px;scroll-snap-align:start;}
51 | ul#liPalette li:first-child{background: var(--background-color);cursor: pointer;}
52 | ul#liPalette li:first-child:hover{background:red;}
53 |
54 | .features-list ul li ul { display:none; list-style-type:none; width:125px; padding:0px; margin-top:3px; margin-left:-5px; }
55 | .features-list ul li:hover ul { display:block; }
56 | .features-list ul li:hover ul li { background-color:#555555; width:125px; height:30px; display:inline-block; }
57 | .features-list li ul { display: none; margin-top: 10px; padding: 0; list-style-type: none; width:82px; height:76px; margin-left: 38px; overflow-y: hidden; }
58 | .features-list li:hover ul { display: block; }
59 | .features-list li:hover .sub-menu{ position: relative; margin-top: -31px; }
60 | .sub-menu li{ top: 0; width: 36px; height: 38px; white-space: nowrap; z-index:1; float:left;margin-right: 4px;padding:4px; }
61 | .sub-menu li:hover{
62 | color:var(--text-color);background:var(--background-hover);transition:.5s ease
63 | }
64 |
65 |
66 | .w-100{width:100% !important;} .w-75{width:75% !important;} .w-66{width:66.66% !important;} .w-60{width:60% !important;} .w-50{width:50% !important;} .w-40{width:40% !important;} .w-35{width:35% !important;} .w-33{width:33.33% !important;} .w-25{width:25% !important;} .w-20{width:20% !important;} .w-15{width:15% !important;} .w-0{width:0px !important;}
67 | .h-100{height:100% !important;} .h-75{height:75% !important;} .h-66{height:66.66% !important;} .h-60{height:60% !important;} .h-50{height:50% !important;} .h-33{height:33.33% !important;} .h-25{height:25% !important;} .h-20{height:20% !important;} .h-15{height:15% !important;} .h-0{height:0px !important;}
68 | .di-flex{display:inline-flex !important} .di-block{display:inline-block !important}
69 | .d-flex{display:flex !important} .d-block{display:block !important}
70 |
71 | .p-0{padding:0px;} .pt-0{padding-top:0px} .pr-0{padding-right:0px} .pb-0{padding-bottom:0px} .pl-0{padding-left:0px} .px-0{padding-left:0px;padding-right:0px} .py-0{padding-top:0px;padding-bottom:0px}
72 | .p-1{padding:0.25rem;} .pt-1{padding-top:0.25rem} .pr-1{padding-right:0.25rem} .pb-1{padding-bottom:0.25rem} .pl-1{padding-left:0.25rem} .px-1{padding-left:0.25rem;padding-right:0.25rem} .py-1{padding-top:0.25rem;padding-bottom:0.25rem}
73 | .p-2{padding:0.5rem;} .pt-2{padding-top:0.5rem} .pr-2{padding-right:0.5rem} .pb-2{padding-bottom:0.5rem} .pl-2{padding-left:0.5rem} .px-2{padding-left:0.5rem;padding-right:0.5rem} .py-2{padding-top:0.5rem;padding-bottom:0.5rem}
74 | .p-3{padding:0.75rem;} .pt-3{padding-top:0.75rem} .pr-3{padding-right:0.75rem} .pb-3{padding-bottom:0.75rem} .pl-3{padding-left:0.75rem} .px-3{padding-left:0.75rem;padding-right:0.75rem} .py-3{padding-top:0.75rem;padding-bottom:0.75rem}
75 | .p-4{padding:1rem;} .pt-4{padding-top:1rem} .pr-4{padding-right:1rem} .pb-4{padding-bottom:1rem} .pl-4{padding-left:1rem} .px-4{padding-left:1rem;padding-right:1rem} .py-4{padding-top:15rem;padding-bottom:1rem}
76 |
77 | .m-0{margin:0px;} .mt-0{margin-top:0px} .mr-0{margin-right:0px} .mb-0{margin-bottom:0px} .ml-0{margin-left:0px} .mx-0{margin-left:0px;margin-right:0px} .my-0{margin-top:0px;margin-bottom:0px}
78 | .m-1{margin:0.25rem;} .mt-1{margin-top:0.25rem} .mr-1{margin-right:0.25rem} .mb-1{margin-bottom:0.25rem} .ml-1{margin-left:0.25rem} .mx-1{margin-left:0.25rem;margin-right:0.25rem} .my-1{margin-top:0.25rem;margin-bottom:0.25rem}
79 | .m-2{margin:0.5rem;} .mt-2{margin-top:0.5rem} .mr-2{margin-right:0.5rem} .mb-2{margin-bottom:0.5rem} .ml-2{margin-left:0.5rem} .mx-2{margin-left:0.5rem;margin-right:0.5rem} .my-2{margin-top:0.5rem;margin-bottom:0.5rem}
80 | .m-3{margin:0.75rem;} .mt-3{margin-top:0.75rem} .mr-3{margin-right:0.75rem} .mb-3{margin-bottom:0.75rem} .ml-3{margin-left:0.75rem} .mx-3{margin-left:0.75rem;margin-right:0.75rem} .my-3{margin-top:0.75rem;margin-bottom:0.75rem}
81 | .m-4{margin:1rem;} .mt-4{margin-top:1rem} .mr-4{margin-right:1rem} .mb-4{margin-bottom:1rem} .ml-4{margin-left:1rem} .mx-4{margin-left:1rem;margin-right:1rem} .my-4{margin-top:1rem;margin-bottom:1rem}
82 |
83 | .font-size-1{font-size:1.25rem} .font-size-2{font-size:1.5rem} .font-size-3{font-size:2rem} .font-size-4{font-size:2.5rem} .font-size-5{font-size:3.0rem} .font-size-6{font-size:3.5rem}
84 | .hide{display: none;}
85 | .border{border:1px solid var(--border-color); } .border-top{border-top:1px solid var(--border-color); } .border-right{border-right:1px solid var(--border-color); } .border-bottom{border-bottom:1px solid var(--border-color); } .border-left{border-left:1px solid var(--border-color); }
86 |
87 | .text-left{text-align:left;} .text-center{text-align:center;} .text-right{text-align:right;}
88 | .float-left{float:left;}.float-right{float:right;} .margin-auto{margin:auto;}
89 | .bold{font-weight:bold;}
90 |
91 | .icon{display: inline-block;width: 0; height: 0; }
92 | .icon:before, .icon:after { content: ''; }
93 | .play-down { border-left: solid 11px var(--text-color-inv); border-top: solid 7px transparent; border-bottom: solid 7px transparent; transform: rotate(90deg); }
94 | .play-right { border-left: solid 11px var(--text-color); border-top: solid 7px transparent; border-bottom: solid 7px transparent; transform: rotate(125deg); }
95 | .play-left { border-left: solid 11px var(--text-color); border-top: solid 7px transparent; border-bottom: solid 7px transparent; transform: rotate(300deg); }
96 |
97 | .lead{font-size:1.5rem;font-weight:300}
98 | .container{color:#000}
99 | .side-bar{width:23.2rem;height:100%;/*padding:2.1rem 1.2rem;*/ ;padding:.25rem;background-color:var(--background-color);position:fixed;transition:all .5s ease;top:26px;}
100 | .side-bar.side-right{right:0}
101 | .logo-name-wrapper{position:relative;margin-bottom:2.1rem;display:flex;font-size:1.2rem}
102 | .logo-name{display:flex;align-items:center}
103 | .logo-name__name{margin-left:.9rem;white-space:nowrap}
104 | .logo-name__button{position:absolute;top:50%;right:0;font-size:1.8rem;transform:translateY(-50%);background-color:transparent;border:none;cursor:pointer}
105 | .logo-name__icon{font-size:1.8rem;color:var(--text-color)}
106 |
107 | .features-list{padding-bottom:1rem;list-style:none}
108 | .features-item{display:inline-block;align-items:center;position:relative;padding:.5rem;margin-bottom:0.6rem;color:var(--text-color);cursor:pointer;transition:.5s ease}
109 | .features-item2{align-items:center;position:relative;color:var(--text-color);cursor:pointer;transition:.5s ease}
110 | .features-item:hover, .features-item.sel, .features-item2:hover, .features-item2.sel {color:var(--text-color-inv);background:var(--background-hover);transition:.5s ease}
111 | .features-item:hover .svgss{stroke:var(--text-color-inv) !important;}
112 | .features-item:hover .svgff{fill:var(--text-color-inv) !important;}
113 | .features-item-icon{font-size:2rem}
114 | .features-item-text{margin-left:1.5rem;transition:opacity .6s ease;opacity:1}
115 |
116 |
117 |
118 | .tooltip{position:absolute;top:-2.1rem;left:6.4rem;background-color:var(--background-color);color:var(--text-color);border-radius:.4rem;padding:.5rem .9rem;font-size:1.4rem;transition:0s;opacity:0;display:none;box-shadow:0 5px 10px rgba(0,0,0,.2)}
119 |
120 | .side-bar.collapse .message:hover .tooltip,.features-item:hover .tooltip,.category-item:hover .tooltip,.chat-new-btn:hover .tooltip{top:50%;transform:translateY(-50%);transition:all .5s ease;opacity:1}
121 | .side-bar.collapse{ /*width:6.4rem*/ width:4.7rem }
122 | .side-bar.collapse .tooltip{display:block}
123 | .side-bar.collapse .logo-name,.side-bar.collapse .category-header,.side-bar.collapse .chat-header,.side-bar.collapse .chat-new-btn-text,.side-bar.collapse .features-item-text,.side-bar.collapse .inbox-number,.side-bar.collapse .category-item-text,.side-bar.collapse .category-item-number,.side-bar.collapse .message-text,.side-bar.collapse .chat-item-name,.side-bar.collapse .chat-item-number,.side-bar.collapse .chat-item-status{opacity:0;pointer-events:none}
124 | .side-bar.collapse .message-text{opacity:0;pointer-events:none;transform:translateX(0)}
125 | .side-bar.collapse .message-icon{transform:translateX(0)}
126 | .side-bar.collapse .logo-name__button{right:.5rem}.side-bar.collapse .inbox-icon .status,.side-bar.collapse .chat-item-avatar-wrapper::before{opacity:1}
127 |
128 | .svgIcon{width:28px;height:28px;color:white;pointer-events:none;}
129 | .svgIcon path{fill:var(--border-color);stroke:var(--text-color);/*stroke-width:1.35;*/}
130 | .svgIconTopMenu{width: 20px;height:28px;color:white;pointer-events:none;}
131 | .svgIcon24{width:24px;height:24px;color:white;pointer-events:none;}
132 | #areaWorker tspan, .unselect{-webkit-user-select: none;-moz-user-select: none;-ms-user-select: none;user-select: none;}
133 |
134 | .panelTool{background:white;padding:12px;margin-right:8px;}
135 | .side-bar.collapse .panelTool{display:none;}
136 | table tr:not(:last-child):after { border-bottom:1px solid red; }
137 | table td{vertical-align: middle;}
138 | table .space-1 td{padding-bottom:0.25rem} table .space-2 td{padding-bottom:0.5rem} table .space-3 td{padding-bottom:0.75rem} table .space-4 td{padding-bottom:1rem}
139 |
140 | .topMenu {list-style-type: none;margin: 0;padding: 0;overflow: hidden;background-color: var(--background-color);}
141 | .topMenu li {float: left;}
142 | .topMenu li a, .dropbtn {display:inline-block;color:white;text-align:center;padding:8px 16px;text-decoration: none;user-select: none;}
143 | .topMenu li a:hover, .dropdown:hover .dropbtn {background-color: var(--background-hover);}
144 | .topMenu li a:hover .svgff{fill:var(--text-color-inv) !important;}
145 | .topMenu li a:hover .svgss{stroke:var(--text-color-inv) !important;}
146 | .topMenu li.dropdown {display: inline-block;}
147 | .topMenu .dropdown-content {display: none;position:absolute;background-color: var(--background-color);min-width: 160px;box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);z-index: 1;}
148 | .topMenu .dropdown-content a { color:var(--text-color);padding: 12px 16px;text-decoration: none;display: block;text-align: left;}
149 | .topMenu .dropdown-content a:hover {background-color: var(--background-hover);color: var(--text-color-inv)}
150 | .topMenu .dropdown:hover .dropdown-content { display: block;}
151 |
152 | input[type="radio"]{width: 24px; height: 24px; transition: 0.5s all linear; accent-color: var(--background-hover);margin:0;}
153 | input[type="checkbox"]{width: 24px; height: 24px; transition: 0.5s all linear; accent-color: var(--background-hover);margin:0;}
154 | input[type="text"]{ padding: 4px 6px; }
155 | select{ padding: 4px 6px; }
156 | label.horizontal{display: inline-block; height: 27px; padding: 6px;}
157 |
158 | .dropSelect{ position: relative; }
159 | .dropSelect-menu{ position: absolute;inset: 0px auto auto 0px;margin: 0px;transform: translate(0px, 36px); font-size: 18px; border-radius: 0.375rem; border-width: 1px; border-radius: calc(0.375rem - 1px); color: white; text-align: left; list-style: none; background-color: var(--background-color); top: 0; min-width: 10rem; width: 190px; padding: 6px; border: 1px solid var(--border-color); z-index: 1000; display: none; }
160 | .dropSelect-menu.show{display: block;}
161 | .dropSelect-item { display: block; width: 100%; padding: 4px 8px; clear: both; font-weight: 400; color: var(--text-color); text-align: inherit; text-decoration: none; white-space: nowrap; background-color: transparent; border: 0; }
162 | .dropSelect-item:hover{background-color: var(--menu-hover);}
163 |
164 | button{background-color: var(--background-hover);padding: 0.75rem 1rem;border-radius: 6px;color: var(--text-color-inv);border:1px solid var(--border-color); }
165 | button:hover{filter: grayscale(0.25); cursor:pointer;}
166 |
167 | .fbasier {font-family: "Basiersquare", sans-serif;}
168 | .ffiras {font-family: "Fira Sans", sans-serif;}
169 | .fsofia {font-family: "Sofia", sans-serif;}
170 | .faudio {font-family: "Audiowide", sans-serif;}
171 | .fakaya {font-family: "Akaya Kanadaka", sans-serif;}
172 | .ffking {font-family: "Fancy King", sans-serif;}
173 |
174 | #infoXY{position: absolute;bottom: 28;right: 20;color: white;background: #2e2d2da1;padding: 2px 4px;user-select: none;width: 180px !important;height: 18px !important;overflow: hidden;}
175 |
176 | .frmModal {display: none; position: fixed; z-index: 1; align-items: center; left: 0;top: 0;width: 100%; height: 100%;overflow: auto;background-color: rgb(0,0,0);background-color: rgba(0,0,0,0.4); }
177 | .modal-content {background-color: #fefefe;margin: auto;padding: 0px;border: 1px solid #888;width: 80%;
178 | -webkit-animation-name: animatetop;-webkit-animation-duration: 0.4s; animation-name: animatetop; animation-duration: 0.4s}
179 | .modal-header { padding: 8px 16px; background-color: var(--background-hover); color: var(--text-color-inv ); }
180 | .modal-header h2{font-size:1.75vw;}
181 | .modal-body {padding: 8px 16px;background-color: white;color: black ;}
182 | .modal-footer { padding: 8px 16px; background-color: white;color: black ; border-top: 1px solid var(--border-color); }
183 | .closeModal { color: var(--text-hover);float: right;font-weight: bold; }
184 | span.closeModal{font-size: 28px;}
185 | .closeModal:hover, .close:focus { color:var(--background-color);text-decoration: none;cursor: pointer; }
186 | @-webkit-keyframes animatetop { from {top:-300px; opacity:0} to {top:0; opacity:1} }
187 | @keyframes animatetop { from {top:-300px; opacity:0} to {top:0; opacity:1} }
188 |
189 | .toolPanel{position:absolute;top:3px !important;right:200px !important;border-right:1.5px solid var(--border-color);width: 200px;/*max-width:200;*/overflow:hidden; }
190 | .toolPanel.rightf{right:0px !important;}
191 |
192 | .tab {overflow: hidden; border-bottom: 1px solid var(--border-color); }
193 | .tab button {border-bottom-left-radius: 0;border-bottom-right-radius: 0;border-top-left-radius: 12px;border-top-right-radius: 12px;margin-right: 1px; }
194 | .tab button.active {background-color: var(--background-hover);color: var(--text-color);}
195 | .tabcontent {padding: 6px 12px;border: 1px solid var(--border-color); border-top: none;height:220px;max-height:220px;overflow-y: scroll; }
196 | .tabcontent:not(.active) {display: none;}
197 | .oneTHshp{ display:inline-block; width:72px; height:72px; margin:4px; padding:2px;border:1px solid #c0c0c0; }
198 | .oneTHshp.active{ border:1px solid var(--background-hover) }
199 | .oneTHshp svg{ pointer-events:none; width:100% !important; height:100% !important; }
200 | .contSufix{display:inline-block;width:auto;position: relative;}
201 | .contSufix .prefix{top: -6;left: 0;color: #000000;font-weight: bold;font-size: 1.15rem;position: absolute;background: white;z-index: 9;}
202 | .contSufix .sufix{top: 6;right: 3;color: #7c7b7b;font-weight: bold;font-size: 1.15rem;position: absolute;}
203 | .extraTool, .toolOps{display:none;}
204 | .toolPathTypeCut:hover{border: 2px solid var(--background-hover);border-radius: 2px;}
205 | .toolPathTypeCut.selected{border: 4px solid var(--background-hover);border-radius: 8px;}
206 |
207 | .gCodeIcon{width:24px;height:24px;float:right;margin-left:6px;cursor:pointer;}
208 | .unGok:hover{background:red}
209 | #AYUDA{position: absolute;bottom: 32;left: 80;color: white;background: #2e2d2da1;padding: 24px;user-select: none;}
210 |
211 | .dialog-ovelay { position: absolute; top: 0; left: 0; right: 0; bottom: 0; background-color: rgba(0, 0, 0, 0.50); z-index: 999999}
212 | .dialog-ovelay .dialog { width: 400px; margin: 100px auto 0; background-color: #fff; box-shadow: 0 0 20px rgba(0,0,0,.2); border-radius: 3px; overflow: hidden}
213 | .dialog-ovelay .dialog header { padding: 10px 8px; background-color: #f6f7f9; border-bottom: 1px solid #e5e5e5}
214 | .dialog-ovelay .dialog header h3 { font-size: 14px; font-weight:bold; margin: 0; color: #555; display: inline-block}
215 | .dialog-ovelay .dialog header .fa-close { float: right; color: #c4c5c7; cursor: pointer; transition: all .5s ease; padding: 0 2px; border-radius: 1px }
216 | .dialog-ovelay .dialog header .fa-close:hover { color: #b9b9b9}
217 | .dialog-ovelay .dialog header .fa-close:active { box-shadow: 0 0 5px #673AB7; color: #a2a2a2}
218 | .dialog-ovelay .dialog .dialog-msg { padding: 12px 10px}
219 | .dialog-ovelay .dialog .dialog-msg p{ margin: 0; font-size: 15px; color: #333}
220 | .dialog-ovelay .dialog footer { border-top: 1px solid #e5e5e5; padding: 8px 10px}
221 | .dialog-ovelay .dialog footer .controls { direction: rtl }
222 | .dialog-ovelay .dialog footer .controls .button { padding: 5px 15px; border-radius: 3px }
223 | .button { cursor: pointer }
224 | .button-default { background-color: rgb(248, 248, 248); border: 1px solid rgba(204, 204, 204, 0.5); color: #5D5D5D;}
225 | .button-danger { background-color: #f44336; border: 1px solid #d32f2f; color: #f5f5f5}
226 | .link { padding: 5px 10px; cursor: pointer}
227 |
228 | #infoPathTB, #infoPathTB td, #infoPathTB th{border:1px solid black}
229 | #infoPathTB td{padding:4px;}
230 | #infoPathTB td.g{background: #d9d8d8;}
231 | #infoPathTB td.n{font-weight:bold;}
232 | #infoPathTB td.c{text-align:center;}
233 | #infoPathTB td.u{text-transform: uppercase;}
234 |
235 | .clr-picker{display:none;flex-wrap:wrap;position:absolute;width:200px;z-index:1000;border-radius:10px;background-color:#fff;justify-content:space-between;box-shadow:0 0 5px rgba(0,0,0,.05),0 5px 20px rgba(0,0,0,.1);-moz-user-select:none;-webkit-user-select:none;user-select:none}.clr-picker.clr-open,.clr-picker[data-inline=true]{display:flex}.clr-picker[data-inline=true]{position:relative}.clr-gradient{position:relative;width:100%;height:100px;margin-bottom:15px;border-radius:3px 3px 0 0;background-image:linear-gradient(rgba(0,0,0,0),#000),linear-gradient(90deg,#fff,currentColor);cursor:pointer}.clr-marker{position:absolute;width:12px;height:12px;margin:-6px 0 0 -6px;border:1px solid #fff;border-radius:50%;background-color:currentColor;cursor:pointer}.clr-picker input[type=range]::-webkit-slider-runnable-track{width:100%;height:8px}.clr-picker input[type=range]::-webkit-slider-thumb{width:8px;height:8px;-webkit-appearance:none}.clr-picker input[type=range]::-moz-range-track{width:100%;height:8px;border:0}.clr-picker input[type=range]::-moz-range-thumb{width:8px;height:8px;border:0}.clr-hue{background-image:linear-gradient(to right,red 0,#ff0 16.66%,#0f0 33.33%,#0ff 50%,#00f 66.66%,#f0f 83.33%,red 100%)}.clr-alpha,.clr-hue{position:relative;width:calc(100% - 40px);height:8px;margin:5px 20px;border-radius:4px}.clr-alpha span{display:block;height:100%;width:100%;border-radius:inherit;background-image:linear-gradient(90deg,rgba(0,0,0,0),currentColor)}.clr-alpha input,.clr-hue input{position:absolute;width:calc(100% + 16px);height:16px;left:-8px;top:-4px;margin:0;background-color:transparent;opacity:0;cursor:pointer;appearance:none;-webkit-appearance:none}.clr-alpha div,.clr-hue div{position:absolute;width:16px;height:16px;left:0;top:50%;margin-left:-8px;transform:translateY(-50%);border:2px solid #fff;border-radius:50%;background-color:currentColor;box-shadow:0 0 1px #888;pointer-events:none}.clr-alpha div:before{content:'';position:absolute;height:100%;width:100%;left:0;top:0;border-radius:50%;background-color:currentColor}.clr-format{display:none;order:1;width:calc(100% - 40px);margin:0 20px 20px}.clr-segmented{display:flex;position:relative;width:100%;margin:0;padding:0;border:1px solid #ddd;border-radius:15px;box-sizing:border-box;color:#999;font-size:12px}.clr-segmented input,.clr-segmented legend{position:absolute;width:100%;height:100%;margin:0;padding:0;border:0;left:0;top:0;opacity:0;pointer-events:none}.clr-segmented label{flex-grow:1;padding:4px 0;text-align:center;cursor:pointer}.clr-segmented label:first-of-type{border-radius:10px 0 0 10px}.clr-segmented label:last-of-type{border-radius:0 10px 10px 0}.clr-segmented input:checked+label{color:#fff;background-color:#666}.clr-swatches{order:2;width:calc(100% - 32px);margin:0 16px}.clr-swatches div{display:flex;flex-wrap:wrap;padding-bottom:12px;justify-content:center}.clr-swatches button{position:relative;width:20px;height:20px;margin:0 4px 6px 4px;border:0;border-radius:50%;color:inherit;text-indent:-1000px;white-space:nowrap;overflow:hidden;cursor:pointer}.clr-swatches button:after{content:'';display:block;position:absolute;width:100%;height:100%;left:0;top:0;border-radius:inherit;background-color:currentColor;box-shadow:inset 0 0 0 1px rgba(0,0,0,.1)}input.clr-color{order:1;width:calc(100% - 80px);height:32px;margin:15px 20px 20px 0;padding:0 10px;border:1px solid #ddd;border-radius:16px;color:#444;background-color:#fff;font-family:sans-serif;font-size:14px;text-align:center;box-shadow:none}input.clr-color:focus{outline:0;border:1px solid #1e90ff}.clr-clear{display:none;order:2;height:24px;margin:0 20px 20px auto;padding:0 20px;border:0;border-radius:12px;color:#fff;background-color:#666;font-family:inherit;font-size:12px;font-weight:400;cursor:pointer}.clr-preview{position:relative;width:32px;height:32px;margin:15px 0 20px 20px;border:0;border-radius:50%;overflow:hidden;cursor:pointer}.clr-preview:after,.clr-preview:before{content:'';position:absolute;height:100%;width:100%;left:0;top:0;border:1px solid #fff;border-radius:50%}.clr-preview:after{border:0;background-color:currentColor;box-shadow:inset 0 0 0 1px rgba(0,0,0,.1)}.clr-alpha div,.clr-color,.clr-hue div,.clr-marker{box-sizing:border-box}.clr-field{display:inline-block;position:relative;color:transparent}.clr-field button{position:absolute;width:30px;height:100%;right:0;top:50%;transform:translateY(-50%);border:0;color:inherit;text-indent:-1000px;white-space:nowrap;overflow:hidden;pointer-events:none}.clr-field button:after{content:'';display:block;position:absolute;width:100%;height:100%;left:0;top:0;border-radius:inherit;background-color:currentColor;box-shadow:inset 0 0 1px rgba(0,0,0,.5)}.clr-alpha,.clr-alpha div,.clr-field button,.clr-preview:before,.clr-swatches button{background-image:repeating-linear-gradient(45deg,#aaa 25%,transparent 25%,transparent 75%,#aaa 75%,#aaa),repeating-linear-gradient(45deg,#aaa 25%,#fff 25%,#fff 75%,#aaa 75%,#aaa);background-position:0 0,4px 4px;background-size:8px 8px}.clr-marker:focus{outline:0}.clr-keyboard-nav .clr-alpha input:focus+div,.clr-keyboard-nav .clr-hue input:focus+div,.clr-keyboard-nav .clr-marker:focus,.clr-keyboard-nav .clr-segmented input:focus+label{outline:0;box-shadow:0 0 0 2px #1e90ff,0 0 2px 2px #fff}.clr-picker[data-alpha=false] .clr-alpha{display:none}.clr-picker[data-minimal=true]{padding-top:16px}.clr-picker[data-minimal=true] .clr-alpha,.clr-picker[data-minimal=true] .clr-color,.clr-picker[data-minimal=true] .clr-gradient,.clr-picker[data-minimal=true] .clr-hue,.clr-picker[data-minimal=true] .clr-preview{display:none}.clr-dark{background-color:#444}.clr-dark .clr-segmented{border-color:#777}.clr-dark .clr-swatches button:after{box-shadow:inset 0 0 0 1px rgba(255,255,255,.3)}.clr-dark input.clr-color{color:#fff;border-color:#777;background-color:#555}.clr-dark input.clr-color:focus{border-color:#1e90ff}.clr-dark .clr-preview:after{box-shadow:inset 0 0 0 1px rgba(255,255,255,.5)}.clr-dark .clr-alpha,.clr-dark .clr-alpha div,.clr-dark .clr-preview:before,.clr-dark .clr-swatches button{background-image:repeating-linear-gradient(45deg,#666 25%,transparent 25%,transparent 75%,#888 75%,#888),repeating-linear-gradient(45deg,#888 25%,#444 25%,#444 75%,#888 75%,#888)}.clr-picker.clr-polaroid{border-radius:6px;box-shadow:0 0 5px rgba(0,0,0,.1),0 5px 30px rgba(0,0,0,.2)}.clr-picker.clr-polaroid:before{content:'';display:block;position:absolute;width:16px;height:10px;left:20px;top:-10px;border:solid transparent;border-width:0 8px 10px 8px;border-bottom-color:currentColor;box-sizing:border-box;color:#fff;filter:drop-shadow(0 -4px 3px rgba(0,0,0,.1));pointer-events:none}.clr-picker.clr-polaroid.clr-dark:before{color:#444}.clr-picker.clr-polaroid.clr-left:before{left:auto;right:20px}.clr-picker.clr-polaroid.clr-top:before{top:auto;bottom:-10px;transform:rotateZ(180deg)}.clr-polaroid .clr-gradient{width:calc(100% - 20px);height:120px;margin:10px;border-radius:3px}.clr-polaroid .clr-alpha,.clr-polaroid .clr-hue{width:calc(100% - 30px);height:10px;margin:6px 15px;border-radius:5px}.clr-polaroid .clr-alpha div,.clr-polaroid .clr-hue div{box-shadow:0 0 5px rgba(0,0,0,.2)}.clr-polaroid .clr-format{width:calc(100% - 20px);margin:0 10px 15px}.clr-polaroid .clr-swatches{width:calc(100% - 12px);margin:0 6px}.clr-polaroid .clr-swatches div{padding-bottom:10px}.clr-polaroid .clr-swatches button{width:22px;height:22px}.clr-polaroid input.clr-color{width:calc(100% - 60px);margin:10px 10px 15px 0}.clr-polaroid .clr-clear{margin:0 10px 15px auto}.clr-polaroid .clr-preview{margin:10px 0 15px 10px}.clr-picker.clr-large{width:275px}.clr-large .clr-gradient{height:150px}.clr-large .clr-swatches button{width:22px;height:22px}.clr-picker.clr-pill{width:380px;padding-left:180px;box-sizing:border-box}.clr-pill .clr-gradient{position:absolute;width:180px;height:100%;left:0;top:0;margin-bottom:0;border-radius:3px 0 0 3px}.clr-pill .clr-hue{margin-top:20px}
236 | #clr-color-preview{display:none}
237 | #clr-color-value{display:none}
238 | .clr-field{margin:12px 8px;}
239 | .mixColor{height:16px; background:rgb(172, 218, 8);width:100%;cursor: crosshair;position:relative;border-radius:5px;}
240 | .markColorDeg{border:1px solid rgb(0, 0, 0);background: gray; height:32px;width:12px;position:absolute;display:block;border-radius: 9px;top:-4px;left:-2px;cursor: e-resize;}
241 | .markColorDeg.sel{border:1px solid rgb(255, 255, 255);box-shadow: 0px 0px 6px 3px black; -webkit-animation: blink 2s infinite;-moz-animation:blink 2s infinite;-ms-animation:blink 2s infinite;;}
242 | li.fillStyle, li.linejoin, li.linecap, li.paint-order, li#controllerFillLineal, li#controllerBorderLineal{display: inline-block;padding: 0.5rem;cursor:pointer;transition: .5s ease;}
243 | li.fillStyle.sel, li.linejoin.sel, li.linecap.sel, li.paint-order.sel, li#controllerFillLineal.sel, #controllerBorderLineal.sel{color: var(--text-color);background: var(--background-hover);transition: .5s ease;}
244 | li.fillStyle:hover, li.linejoin:hover, li.linecap:hover, li.paint-order:hover, li#controllerFillLineal:hover, #controllerBorderLineal:hover{color: var(--text-color);background: var(--background-hover);transition: .5s ease;}
245 | ul#styleBorderLine svg{pointer-events: none;}
246 |
247 |
248 | @-webkit-keyframes blink {0%{ border-color:rgb(48, 48, 48); }50% { border-color:rgb(180, 180, 180);}100% { border-color:rgb(48, 48, 48); } }
249 | @-moz-keyframes blink {0% { border-color:rgb(48, 48, 48); } 50% { border-color:rgb(180, 180, 180);}100% { border-color:rgb(48, 48, 48); } }
250 | @-ms-keyframes blink {0% { border-color:rgb(48, 48, 48); }50% { border-color:rgb(180, 180, 180);}100% { border-color:rgb(48, 48, 48); } }
251 |
252 | .font-select {position:relative;margin-bottom:8px;}
253 | .font-select span {
254 | background-color: var(--background-color);
255 | display: inline-block;
256 | padding: 12px 8px;
257 | font-weight: 700;
258 | font-family: Corben;
259 | font-size: 16px;
260 | cursor: pointer;
261 | transition: all 0.2s ease-in 0s;
262 | box-shadow: rgba(0, 0, 0, 0.14) 0px 2px 2px 0px, rgba(0, 0, 0, 0.12) 0px 3px 1px -2px, rgba(0, 0, 0, 0.2) 0px 1px 5px 0px;
263 | border-radius: 2px;
264 | margin-top: 5px;
265 | width:100%;
266 | border: 1px solid var(--menu-hover);
267 | }
268 | .font-select span:hover{background-color: var(--background-hover);}
269 | .fs-drop {max-height: 210px;overflow-y: scroll;position: absolute; background-color: #fff;z-index: 2;box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.12), 0 1px 5px 0 rgba(0, 0, 0, 0.2); left: 0;top: 50px;border-radius: 4px;}
270 | .fs-results { padding: 0; background: white; color: black; width: 160px; max-width: 160px;}
271 | .fs-results li.sel {background: var(--background-hover);color: var(--text-color);}
272 | .fs-results li {list-style: none;padding: 10px 6px;border-bottom: 1px solid #e5e5e5;cursor: pointer;transition:0.2s ease-in;white-space: nowrap;overflow: hidden;}
273 | .fs-results li:hover { background-color:#ddd;}
274 |
275 | #svgWorkerArea.wait{
276 | cursor: url("data:image/svg+xml,%3Csvg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' width='48px' height='48px' viewBox='0 0 512 512' style='enable-background:new 0 0 512.011 512.011;' xml:space='preserve'%3E %3Cpath fill='DeepSkyBlue' d='M434.215,344.467L92.881,3.134c-4.16-4.171-10.914-4.179-15.085-0.019 c-2.011,2.006-3.139,4.731-3.134,7.571v490.667c0.003,4.382,2.685,8.316,6.763,9.92c4.081,1.603,8.727,0.545,11.712-2.667 l135.509-145.92h198.016c5.891,0.011,10.675-4.757,10.686-10.648C437.353,349.198,436.226,346.473,434.215,344.467z'/%3E %3C/svg%3E"), pointer;
277 | }
278 |
279 | #fontSelectDiv{display: grid;
280 | grid-template-columns: repeat(3, 1fr);
281 | grid-template-rows: repeat(6, 1fr);
282 | grid-column-gap: 0px;
283 | grid-row-gap: 0px;
284 | }
285 | #frmSelectFont .oneFont{height:80px;width: 256px;display: inline-block;border: 1px solid #c0c0c0;margin: 2px;border-radius: 3px;position:relative;padding: 2px 2px 0px 2px;cursor:pointer;}
286 | #frmSelectFont .oneFont div{background-image: url(https://artdraw.org/svg/fonts/fonts.webp);height:62px;width: 250px;min-width:250px;pointer-events: none;}
287 | #frmSelectFont span{position:absolute;bottom: 4px;left: 0;right: 0;margin: auto;text-align:center;font-family: monospace;font-weight: 600;pointer-events: none;}
288 | #panelRough .clr-field{margin: 6px 0;float: right;}
289 | .menuTopSVGparent {
290 | display: grid;
291 | grid-template-columns: 30px 1fr;
292 | grid-template-rows: 32px;
293 | grid-column-gap: 0px;
294 | grid-row-gap: 0px;
295 | pointer-events: none;
296 | }
297 | .menuTopSVGparent .divIcon { grid-area: 1 / 1 / 2 / 2;pointer-events:none; }
298 | .menuTopSVGparent .divText { grid-area: 1 / 2 / 2 / 3;display:grid;align-items:center;pointer-events: none; }
299 | .topMenu li.sel {background: var(--background-hover);color: var(--text-color);}
300 | #panelWaves .clr-field{margin: 4px 4px;}
301 |
302 | .wrapper{ /*visibility: hidden;*/ position: absolute; width: 140px; border-radius: 3px; background: var(--background-color); box-shadow: 0 12px 35px rgba(0,0,0,0.1); }
303 | .wrapper .menu{ padding: 10px 12px; }
304 | .content .item{ list-style: none; font-size: 16px; height: 22px; display: flex; width: 100%; cursor: pointer; align-items: center; border-radius: 3px; margin-bottom: 2px; padding: 0; }
305 | .content .item:hover{ background: var(--background-hover); }
306 | .content .item span{ margin-left: 8px; font-size: 14px; }
307 | .content .setting{ display: flex; margin-top: -5px; padding: 5px 12px; border-top: 1px solid #ccc; }
308 | .content .share{ position: relative; justify-content: space-between; }
309 | .share .share-menu{ display:none; position: absolute; background: var(--background-color); width: 140px; right: -140px; top: -35px; padding: 13px; pointer-events: none; border-radius: 3px; box-shadow: 0 5px 10px rgba(0,0,0,0.08); transition: 0.2s ease; }
310 | .share:hover .share-menu{ display:block; pointer-events: auto; }
311 | .content .item.disabled{ background: var(--menu-hover); }
312 | .content .item.disabled .share-menu{right: -1400px;}
313 | .content .item span{pointer-events: none;cursor: pointer;}
314 |
315 | .ctxMenuSVG { display: grid; grid-template-columns: 24px 1fr; grid-template-rows: 24px; grid-column-gap: 0px; grid-row-gap: 0px; pointer-events: none;}
316 | .ctxMenuSVG .ctxDivIcon { grid-area: 1 / 1 / 2 / 2; pointer-events: none;}
317 | .ctxSvgIcon { width: 20px; height: 24px; color: white; pointer-events: none;}
318 | .ctxMenuSVG .ctxDivText { grid-area: 1 / 2 / 2 / 3; display: grid; align-items: center; pointer-events: none;}
319 |
320 | input:disabled, button:disabled {
321 | background: #c4c4c4;
322 | border: #c4c4c4;
323 | color:white;
324 | }
325 |
326 | #listMandala1{background: white;
327 | height: 186px;
328 | overflow-y: scroll;
329 | overflow-x: hidden;
330 | width: 100%;
331 | list-style-type: none;}
332 | #listMandala1 li{width: 58px;height:58px;float: left;}
333 | #listMandala1 li svg{width: 56px;height:56px;pointer-events:none;}
334 | #listMandala1 li svg path{stroke:black;stroke-width:0.5;fill-rule: evenodd;}
335 | #listMandala1 svg.sel > path{fill:red;stroke:red;}
336 |
337 |
--------------------------------------------------------------------------------
/css/subjx.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sysmaya/artdraw/33d5506a86e8519a0656afa3219f0bde9c59ebb9/css/subjx.css
--------------------------------------------------------------------------------
/js/booleans.js:
--------------------------------------------------------------------------------
1 | function selection2clipper(useSelItem){
2 | var rta='', clip1='';
3 | var ttSel=document.querySelectorAll(".cosito.selectable").length;
4 | //console.log("TTsek:"+ttSel);
5 | [...document.querySelectorAll(".cosito.selectable")].forEach((element, index, array) => {
6 | var selItem=e.getAttribute("selItem");
7 | if( (useSelItem==1 && selItem==1) || (useSelItem==99 && selItem==ttSel) ){
8 | clip1=getClipperPath(element.id, 1);
9 | }else{
10 | rta+=getClipperPath(element.id, 1);
11 | }
12 |
13 | });
14 | rta = rta.replaceAll("][", ",");
15 | rta=JSON.parse(rta) ;
16 | console.log(clip1);
17 | console.log(rta);
18 |
19 | }
20 |
21 | function booleanMergePreview(){
22 | //se requieen 2 elementos. No 1, ni 3 ni 4...
23 | removeAllFromSelection(".preview");
24 | if( document.querySelectorAll(".cosito.selectable").length<2){
25 | return;
26 | }
27 | var cliptype;
28 | var tipeMerge=document.querySelector("input[type='radio'][name=boolTP]:checked").value;
29 | if(tipeMerge=='INTERSECTION') cliptype = ClipperLib.ClipType.ctIntersection;
30 | else if(tipeMerge=='UNION') cliptype = ClipperLib.ClipType.ctUnion;
31 | else if(tipeMerge=='DIFFERENCE') cliptype = ClipperLib.ClipType.ctDifference;
32 | else if(tipeMerge=='XOR') cliptype = ClipperLib.ClipType.ctXor;
33 |
34 | var cpr=null, path1="";
35 | cpr = new ClipperLib.Clipper();
36 | cpr.Clear();
37 | var scale=100;
38 |
39 | var rta="", cta=0;
40 | var ttSel=document.querySelectorAll(".selectable").length;
41 | [...document.querySelectorAll(".selectable")].forEach((element, index, array) => {
42 | cta++;
43 | var id=element.id;
44 | if(cta==1){
45 | path1=getClipperPath(id, 0);
46 | ClipperLib.JS.ScaleUpPaths(path1, scale);
47 | cpr.AddPaths(path1, ClipperLib.PolyType.ptSubject, true);
48 | }else{
49 | rta+=getClipperPath(id, 1);
50 | }
51 | });
52 | rta = rta.replaceAll("][", ",");
53 | rta=JSON.parse(rta) ;
54 |
55 | var cleandelta = 0.1; // 0.1 should be the appropriate delta in different cases
56 | ClipperLib.JS.ScaleUpPaths(rta, scale);
57 | rta = ClipperLib.Clipper.SimplifyPolygons(rta, ClipperLib.PolyFillType.pftNonZero);
58 | rta = ClipperLib.JS.Clean(rta, cleandelta * scale);
59 | cpr.AddPaths(rta, ClipperLib.PolyType.ptClip, true);
60 |
61 | var solution_paths = new ClipperLib.Paths();
62 |
63 | var subjectFillType=1;
64 | var clipFillType=1;
65 | cpr.Execute( cliptype, solution_paths, subjectFillType, clipFillType);
66 | var rtaf=paths2string(solution_paths, scale) ;
67 | drawSolutionPreview(rtaf, "blue", 1, "url(#patternBool)");
68 |
69 | e.setAttribute("stroke-linejoin", "round");
70 | e.setAttribute("stroke-linecap", "round");
71 | }
72 |
73 | function booleanOffsetPreview(){
74 | //esta es exclusiva para dibujar por el usuario. dibuja la vista previa del borde
75 | removeAllFromSelection(".preview");
76 | if( document.querySelectorAll(".cosito.selectable").length==0){
77 | return;
78 | }
79 | var _typeOffset=document.querySelector("input[name='offsetPath']").checked;
80 | var offset=document.getElementById("offsetPathDis").value;
81 |
82 | offset=Math.abs(offset)*100;
83 | if(_typeOffset==2)offset=offset*-1;
84 | var rta='', scale=100;
85 |
86 | [...document.querySelectorAll(".selectable")].forEach((element, index, array) => {
87 | var id=element.id;
88 | rta+=getClipperPath(id, 1);
89 | });
90 | rta = rta.replaceAll("][", ",");
91 | rta=JSON.parse(rta) ;
92 |
93 | var cleandelta = 0.1; // 0.1 should be the appropriate delta in different cases
94 | ClipperLib.JS.ScaleUpPaths(rta, scale);
95 | rta = ClipperLib.Clipper.SimplifyPolygons(rta, ClipperLib.PolyFillType.pftNonZero);
96 | rta = ClipperLib.JS.Clean(rta, cleandelta * scale);
97 |
98 | var co = new ClipperLib.ClipperOffset( 2, 0.25 );
99 | co.Clear();
100 | co.AddPaths( rta, ClipperLib.JoinType.jtRound, ClipperLib.EndType.etClosedPolygon);
101 |
102 | var solution_paths = new ClipperLib.Paths();
103 | co.Execute(solution_paths, offset);
104 |
105 | var rtaf=paths2string(solution_paths, scale) ;
106 | drawSolutionPreview(rtaf, "blue", 1, "none");
107 |
108 | var e=document.querySelector(".preview");
109 | var doki=reducePathSmooth( e.id, 0.1, 0.01, false );
110 | e.dSet( doki );
111 |
112 | e.setAttribute("stroke-linejoin", "round");
113 | e.setAttribute("stroke-linecap", "round");
114 | }
115 |
116 | function booleanOffset(offset, _typeOffset, _delete, _draw, _outMode, _eid){
117 | //esta es exclusiva para generar Paths de corte
118 | //console.log("Offset:"+offset+' TypeOffset:'+_typeOffset+' Delete:'+_delete+" draw:"+_draw+" OutMode:"+_outMode+" eid:"+_eid);
119 | offset=Math.abs(offset)*100;
120 | if(_typeOffset==2)offset=offset*-1;
121 | var rta='', scale=100;
122 |
123 | if(_eid && _eid!='undefined'){
124 | rta+=getClipperPath(_eid, 1);
125 | }else{
126 | [...document.querySelectorAll(".selectable")].forEach((element, index, array) => {
127 | var id=element.id;
128 | rta+=getClipperPath(id, 1);
129 | });
130 | }
131 |
132 | rta = rta.replaceAll("][", ",");
133 | rta=JSON.parse(rta) ;
134 |
135 | var cleandelta = 0.1; // 0.1 should be the appropriate delta in different cases
136 |
137 | ClipperLib.JS.ScaleUpPaths(rta, scale);
138 | rta = ClipperLib.Clipper.SimplifyPolygons(rta, ClipperLib.PolyFillType.pftNonZero);
139 | rta = ClipperLib.JS.Clean(rta, cleandelta * scale);
140 |
141 | var co = new ClipperLib.ClipperOffset( 2, 0.25 );
142 | co.Clear();
143 | co.AddPaths( rta, ClipperLib.JoinType.jtRound, ClipperLib.EndType.etClosedPolygon);
144 |
145 | var solution_paths = new ClipperLib.Paths();
146 | co.Execute(solution_paths, offset);
147 |
148 | var rtaf=paths2string(solution_paths, scale) ;
149 | if(_draw==true) drawSolution(rtaf);
150 | if(_delete==true ) removeAllFromSelection(".toRemove");
151 | if(_outMode==1)return rtaf;
152 | }
153 |
154 | function booleanMerge(tipeMerge, el1, el2, outMode){
155 | //se requieen 2 elementos. No 1, ni 3 ni 4...
156 | //outMode 0=return elemento, crae nuevo elemento path *** outMode1=return path string no crea nada
157 | var cliptype;
158 | if(tipeMerge=='INTERSECTION') cliptype = ClipperLib.ClipType.ctIntersection;
159 | else if(tipeMerge=='UNION') cliptype = ClipperLib.ClipType.ctUnion;
160 | else if(tipeMerge=='DIFFERENCE') cliptype = ClipperLib.ClipType.ctDifference;
161 | else if(tipeMerge=='XOR') cliptype = ClipperLib.ClipType.ctXor;
162 |
163 | var cpr=null;
164 | cpr = new ClipperLib.Clipper();
165 | cpr.Clear();
166 | var scale=100, pass=1;
167 |
168 | var id1=el1.getAttribute('id');
169 | var path1=getClipperPath(id1, 0);
170 | ClipperLib.JS.ScaleUpPaths(path1, scale);
171 | cpr.AddPaths(path1, ClipperLib.PolyType.ptSubject, true);
172 |
173 | var id2=el2.getAttribute('id');
174 | var path2=getClipperPath(id2, 0);
175 | ClipperLib.JS.ScaleUpPaths(path2, scale);
176 | cpr.AddPaths(path2, ClipperLib.PolyType.ptClip, true);
177 |
178 | console.log('merge.'+tipeMerge);
179 | var solution_paths = new ClipperLib.Paths();
180 | //ClipperLib.PolyFillType.pftEvenOdd=0 ClipperLib.PolyFillType.pftNonZero=1
181 | //ClipperLib.PolyFillType.pftPositive=2 ClipperLib.PolyFillType.pftNegative=3
182 | var subjectFillType=1;
183 | var clipFillType=1;
184 | cpr.Execute( cliptype, solution_paths, subjectFillType, clipFillType);
185 | var rtaf=paths2string(solution_paths, scale) ;
186 | if(outMode==0){
187 | drawSolution(rtaf);
188 | return;
189 | }
190 | return rtaf;
191 | }
192 |
193 | function getClipperPath(id, _return){
194 | //_return==0 array ==1 string;
195 | var points=null ;
196 | flattenSimple( id );
197 | var p2p=path2Poly( document.getElementById(id) );
198 | points=JSON.parse('['+JSON.stringify(p2p.pClipper)+']');
199 |
200 | //console.log( '['+JSON.stringify(p2p.pClipper)+']' );
201 | if (_return==0 || _return=='0' ) return points;
202 | return '['+JSON.stringify(p2p.pClipper)+']';
203 | }
204 |
205 | function drawSolutionPreview(rtaf,strokeColor, strokeWidth, fillColor){
206 | const rpaths = rtaf.split("M");
207 | var i, tx='', p='', path=null;
208 | for( i=0; i3 ){
210 | p='M'+rpaths[i].toString();
211 | path=createSVGElement("path", false, createID() );
212 | path.setAttribute('d', p );
213 | path.setAttribute('class', 'preview' );
214 | path.setAttribute('stroke', strokeColor );
215 | path.setAttribute('vector-effect', 'non-scaling-stroke' );
216 | path.setAttribute('stroke-width', strokeWidth );
217 | path.setAttribute('fill', fillColor );
218 | _hnd['svgHandler'].appendChild( path );
219 | }
220 | }
221 | }
222 |
223 | function drawSolution(rtaf){
224 | const rpaths = rtaf.split("M");
225 | var i, tx='', p='', path=null;
226 | for( i=0; i3 ){
228 | p='M'+rpaths[i].toString();
229 | p='M'+rpaths[i].toString();
230 | path=createSVGElement("path", false, createID() );
231 | path.setAttribute('d', p );
232 | path.setAttribute('class', 'cosito selectable' );
233 | path.setAttribute('stroke', '#000000' );
234 | path.setAttribute('vector-effect', 'non-scaling-stroke' );
235 | path.setAttribute('stroke-width', '1' );
236 | path.setAttribute('fill', colorA );
237 | path.setAttribute('fill-opacity', '0.25' );
238 | _hnd['svgHandler'].appendChild( path );
239 | }
240 | }
241 | //console.log(rtaf);
242 | //makeSelection(true);
243 | //return path;
244 | }
245 |
246 | function wavesDraw(){
247 | removeAllFromSelection(".preview");
248 | var hwave=Number(document.getElementById("wavesHeight").value);
249 | var wwave=Number(document.getElementById("wavesWidth").value);
250 | var balance=Number(document.getElementById("wavesBalance").value);
251 | var levels=Number(document.getElementById("waveLevels").value);
252 | var waves=Number(document.getElementById("wavePeaks").value);
253 | var noise=Number(document.getElementById("waveNoise").value);
254 | var amplitude=Number(document.getElementById("waveAmplitude").value);
255 | var stack=Number(document.getElementById("waveStack").value);
256 | var border=Number(document.getElementById("wavesBorder").value);
257 | var center=centerScreen();
258 | var X=center[0]-(wwave/2);
259 | var Y=center[1]+(hwave/2);
260 | var mxY=9999999;
261 | var colorBack= document.getElementById("waveColorBack").value;
262 | var colorStar=parseColor( document.getElementById("waveColorStar").value, 'ARRAYD');
263 | var colorEnd=parseColor( document.getElementById("waveColorEnd").value, 'ARRAYD');
264 |
265 | for(var f=0; f500000 )modeStack=false;
275 |
276 | if(modeStack==true){
277 | var stky=hY+stackZ;
278 | var points=X+","+Y+" "+X+","+stky+" ";
279 | mxY=stky;
280 | }else{
281 | var points=X+","+Y+" "+X+","+hY+" ";
282 | mxY=hY;
283 | }
284 |
285 | var disX=Number(wwave/(waves+1));
286 | var px=X, flag=false, sizew=(hwavef*amplitude)/100;
287 | for(var i=0; i500000 )zx=zx*-1;
303 | if( Math.floor(Math.random() * 1000000)>500000 )zy=zy*-1;
304 | var pxx=px+zx;
305 | var pyy=py+zy;
306 | //bolita(pxx, pyy, 3, "red");
307 | var perDisX=( (pxx-X)/wwave)*100;
308 | if(modeStack==true){
309 | perDisX=100-perDisX;
310 | pyy=pyy+ ((perDisX/100)*stackZ);
311 | }else{
312 | pyy=pyy+ ((perDisX/100)*stackZ);
313 | }
314 | if(pyy>=Y){
315 | pyy=Y-2;
316 | }
317 | if(pyy1){
352 | var disN=px-pxAnt;
353 | segments[n]['values'][2]=px-(disN/2);
354 | }
355 | if(n {
408 | element.hide();
409 | });
410 | sTool='';
411 |
412 | controlPointZ("new");
413 | }
414 |
415 | function loadScript(url, id, callback) {
416 | // thanks ChatGPT
417 | if (document.getElementById(id)) {
418 | console.log('El script ya se ha cargado anteriormente');
419 | return;
420 | }
421 |
422 | // crear un nuevo elemento script
423 | var script = document.createElement('script');
424 | script.src = url;
425 | script.id = id;
426 | document.body.appendChild(script);
427 | script.onload = callback;
428 | }
--------------------------------------------------------------------------------
/js/clipperUtils.js:
--------------------------------------------------------------------------------
1 | /////////////// CLIPPER UTILS
2 | // PATH tuto OK https://css-tricks.com/svg-path-syntax-illustrated-guide/
3 | // ver paths https://svg-path-visualizer.netlify.app/
4 | //crear nuevo path en base a transformaciones https://github.com/fontello/svgpath
5 | // manejo fuentes SVG https://github.com/kartsims/easysvg aplica matrix transformacion al path OJO PHP ??
6 | // APLICAR TRANSFORMACIONES al PATH perfecto !! http://jsfiddle.net/nrjvmqur/ flatten(document.getElementById('svg'));
7 | //http://output.jsbin.com/ivomiq/7.
8 | //convertir path a poligonos https://github.com/Phrogz/svg-path-to-polygons
9 | // manejode fuentes texto OPENTYPEJS https://stackoverflow.com/questions/71252755/create-svg-path-using-svg-js-and-opentype-js
10 | function convertPolyToPath(points){
11 | // HACK convierte un path x,y x,y ... a formato ML00Z
12 | points = points.split(/\s+|,/);
13 | var x0=points.shift(), y0=points.shift();
14 | var pathdata = 'M'+x0+','+y0+'L'+points.join(' ');
15 | pathdata+='z';
16 | return pathdata;
17 | }
18 |
19 | function normalize_clipper_poly(polystr, quiet) {
20 | //convierte un PATH SIN CURVAS al formato clipper
21 | if (typeof (polystr) != "string") return false;
22 | polystr = polystr.trim();
23 | var np, txt;
24 | if (polystr.substr(0, 1).toUpperCase() === "M") {
25 | np = svgpath_to_clipper_polygons(polystr);
26 | if (np === false) {
27 | txt = "Unable to parse SVG path string.\n";
28 | txt += "Click OK to continue.\n";
29 | if (!quiet) alert(txt);
30 | return false;
31 | }
32 | else return JSON.stringify(np);
33 | }
34 | polystr = polystr.replace(/[\s,]+/g, ",");
35 | if (polystr.substr(0, 1) !== "[") polystr = "[" + polystr;
36 | if (polystr.substr(-1, 1) !== "]") polystr = polystr + "]";
37 | try {
38 | polystr = polystr.replace(/X/gi, '"X"').replace(/Y/gi, '"Y"').replace(/""/g, '"'); // if " is missing
39 | var poly = JSON.parse(polystr);
40 | }
41 | catch (err) {
42 | txt = "Unable to parse polygon string.\n";
43 | txt += "Error: " + err.message + "\n";
44 | txt += "Click OK to continue.\n";
45 | if (!quiet) alert(txt);
46 | return false;
47 | }
48 | // if only points without "X" and "Y"
49 | var temp_n = [],
50 | i;
51 | if (isArray(poly) && poly.length && typeof (poly[0]) == "number") {
52 | var len = poly.length;
53 | for (i = 0; i < len; i = i + 2) {
54 | temp_n.push({
55 | X: poly[i],
56 | Y: poly[i + 1]
57 | });
58 | }
59 | poly = temp_n;
60 | }
61 | // if an array of array of points without "X" and "Y"
62 | var temp_n2 = [],
63 | i, j, len, len2;
64 | if (isArray(poly) && poly.length && isArray(poly[0]) && typeof (poly[0][0]) != "undefined" &&
65 | typeof (poly[0][0].X) == "undefined" &&
66 | typeof (poly[0][0].x) == "undefined") {
67 | len2 = poly.length;
68 | for (j = 0; j < len2; j++) {
69 | temp_n = [];
70 | len = poly[j].length;
71 | for (i = 0; i < len; i = i + 2) {
72 | temp_n.push({
73 | X: poly[j][i],
74 | Y: poly[j][i + 1]
75 | });
76 | }
77 | temp_n2.push(temp_n);
78 | }
79 | poly = temp_n2;
80 | }
81 | // if not array of arrays, convert to array of arrays
82 | if (isArray(poly) && poly.length > 0 && !isArray(poly[0])) poly = [poly];
83 | var pp, n = [
84 | []
85 | ],
86 | m, pm, x, y;
87 | np = [
88 | []
89 | ];
90 | for (i = 0, m = poly.length; i < m; i++) {
91 | np[i] = [];
92 | for (j = 0, pm = poly[i].length; j < pm; j++) {
93 | pp = {};
94 | y = null;
95 | x = null;
96 | if (typeof (poly[i][j].X) != "undefined" && !isNaN(Number(poly[i][j].X))) x = Number(poly[i][j].X);
97 | else if (typeof (poly[i][j].x) != "undefined" && !isNaN(Number(poly[i][j].x))) x = Number(poly[i][j].x);
98 | if (typeof (poly[i][j].Y) != "undefined" && !isNaN(Number(poly[i][j].Y))) y = Number(poly[i][j].Y);
99 | else if (typeof (poly[i][j].y) != "undefined" && !isNaN(Number(poly[i][j].y))) y = Number(poly[i][j].y);
100 | if (y !== null && x !== null) {
101 | pp.X = x;
102 | pp.Y = y;
103 | np[i].push(pp);
104 | }
105 | else {
106 | txt = "Unable to parse polygon string.\n";
107 | txt += "Error: Coordinates are not in a right form.\n";
108 | txt += "Click OK to continue.\n";
109 | if (!quiet) alert(txt);
110 | return false;
111 | };
112 | }
113 | }
114 | return JSON.stringify(np);
115 | }
116 | // helper function for normalize_clipper_poly()
117 | function svgpath_to_clipper_polygons(d) {
118 | //console.log("Esta funcion se llama por usar Poligonos que empiezan con M 8como paths");
119 | //console.log(d);
120 | var arr;
121 | d = d.trim();
122 | arr = Raphael.parsePathString(d); // str to array
123 | arr = Raphael._pathToAbsolute(arr); // mahvstcsqz -> uppercase
124 | var str = Array.prototype.concat.apply([], arr).join(" ");
125 | var paths = str.replace(/M/g, '|M').split("|");
126 | var k, polygons_arr = [],
127 | polygon_arr = [];
128 | for (k = 0; k < paths.length; k++) {
129 | if (paths[k].trim() === "") continue;
130 | arr = Raphael.parsePathString(paths[k].trim());
131 | polygon_arr = [];
132 | var i = 0,
133 | j, m = arr.length,
134 | letter = "",
135 | x = 0,
136 | y = 0,
137 | pt = {},
138 | subpath_start = {};
139 | subpath_start.x = "";
140 | subpath_start.y = "";
141 | for (; i < m; i++) {
142 | letter = arr[i][0].toUpperCase();
143 | if (letter != "M" && letter != "L" && letter != "Z") continue;
144 | if (letter != "Z") {
145 | for (j = 1; j < arr[i].length; j = j + 2) {
146 | if (letter == "V") y = arr[i][j];
147 | else if (letter == "H") x = arr[i][j];
148 | else {
149 | x = arr[i][j];
150 | y = arr[i][j + 1];
151 | }
152 | pt = {};
153 | pt.X = null;
154 | pt.Y = null;
155 | if (typeof (x) != "undefined" && !isNaN(Number(x))) pt.X = Number(x);
156 | if (typeof (y) != "undefined" && !isNaN(Number(y))) pt.Y = Number(y);
157 | if (pt.X !== null && pt.Y !== null) {
158 | polygon_arr.push(pt);
159 | }
160 | else {
161 | return false;
162 | }
163 | }
164 | }
165 | if ((letter != "Z" && subpath_start.x === "") || letter == "M") {
166 | subpath_start.x = x;
167 | subpath_start.y = y;
168 | }
169 | if (letter == "Z") {
170 | x = subpath_start.x;
171 | y = subpath_start.y;
172 | }
173 | }
174 | polygons_arr.push(polygon_arr);
175 | }
176 | return polygons_arr;
177 | }
178 |
179 | function round_to(num, dec){
180 | if (typeof (num) == "undefined" || typeof (dec) == "undefined" || isNaN(dec)){
181 | alert("Cannot round other than number");
182 | return false;
183 | }
184 | else return Math.round(num * Math.pow(10, dec)) / Math.pow(10, dec);
185 | }
--------------------------------------------------------------------------------
/js/controllerEvent.js:
--------------------------------------------------------------------------------
1 | function setupListeners(){
2 | document.addEventListener("mouseup", masterClick, false);
3 | document.addEventListener("keydown", masterKeyDown, false);
4 | document.addEventListener("keyup", masterKeyUp, false);
5 | document.addEventListener("dblclick", masterDBLclick, false);
6 | _hnd['svgHandler'].addEventListener("mousedown", controllerEventMouseDown, false);
7 | _hnd['svgHandler'].addEventListener("mousemove", controllerEventMouseMove, false);
8 | //$(window).bind('mousewheel DOMMouseScroll', function (event) { controllerEventWheel(event); } );
9 | window.addEventListener('mousewheel', controllerEventWheel);
10 | window.addEventListener('DOMMouseScroll', controllerEventWheel);
11 | window.addEventListener("resize", updateRuler);
12 |
13 | document.addEventListener('contextmenu', function(evt) {
14 | evt.preventDefault();
15 | }, false);
16 |
17 | document.onchange = function(evt){
18 | //evt = evt || window.event;
19 | var mck = evt.target.getAttribute("change");
20 | if( mck!=null)fnCall(mck, evt);
21 | }
22 |
23 | contextMenu = document.querySelector(".wrapper"),
24 | shareMenu = contextMenu.querySelectorAll(".share-menu");
25 |
26 | _hnd['svgHandler'].addEventListener("contextmenu", e => {
27 | e.preventDefault();
28 | let x = e.offsetX, y = e.offsetY;
29 |
30 | x+=48; y+=42;
31 | var r=showRightMenu();
32 | if(r==false)return;
33 |
34 | contextMenu.style.left = `${x}px`;
35 | contextMenu.style.top = `${y}px`;
36 | //contextMenu.style.visibility = "visible";
37 | visibilityForSelection(".wrapper", "block");
38 | });
39 | //document.addEventListener("click", () => contextMenu.style.visibility = "hidden");
40 |
41 | }
42 |
43 | function masterKeyDown(evt){
44 | //evt = evt || window.event;
45 | var ctrlDown = evt.ctrlKey||evt.metaKey; // Mac support
46 | _evtMsg['keycode']=evt.keyCode;
47 | if (evt.ctrlKey && evt.keyCode == 90)controlZundo(); // CTRZ Z
48 | if (ctrlDown && (evt.keyCode == 67))toClipboard(false); // CTRL C
49 | if (ctrlDown && (evt.keyCode == 86))pasteClipboard(evt); // CTRL V
50 | if (ctrlDown && (evt.keyCode == 88))toClipboard(true); // CTRL X
51 | if ( evt.keyCode == 33 )MCKapplyZorder(false, "forward"); // PageUP
52 | if ( evt.keyCode == 34 )MCKapplyZorder(false, "backward"); // PageDown
53 | if (ctrlDown && (evt.keyCode == 71)){evt.preventDefault();MCKbtnGroupClick(true); } // CTRL G
54 | if (ctrlDown && (evt.keyCode == 80)){evt.preventDefault();OpenImageNewTab(true); } // CTRL P
55 | if( evt.keyCode == 27 )restoreKeys(); // ESC
56 | if( evt.keyCode == 46 )deleteSeleccion(); // DELETE
57 | if( evt.keyCode == 113 ){evt.preventDefault(); zoomMore(evt); } // F2 ZoomMore
58 | if( evt.keyCode == 114 ){evt.preventDefault(); zoomMinus(evt); } // F3 ZoomMinus
59 | }
60 | function masterKeyUp(evt){
61 | _evtMsg['keycode']=null;
62 | }
63 |
64 | function masterClick(evt){
65 | if( _evtMsg['waitFor']!=null ){
66 | fnCall(_evtMsg['waitFor'], evt);
67 | _evtMsg['waitFor']=null;
68 | return;
69 | }
70 | visibilityForSelection(".wrapper", "none");
71 | drawPolygon(evt,'click');
72 | dragScreen(evt, 'up');
73 | drawSelector(evt, 'up');
74 | var mck = evt.target.getAttribute("mouseUp");
75 | if( mck!=null)fnCall(mck, evt);
76 | }
77 |
78 | function masterDBLclick(evt){
79 | //evt = evt || window.event;
80 | var dbck = evt.target.getAttribute("DblClick");
81 | if( dbck!=null)fnCall(dbck, evt);
82 | }
83 |
84 | /*function controllerEventClick(evt){ //toda el area SVG
85 | drawPolygon(evt,'click');
86 | }*/
87 |
88 | function controllerEventMouseMove(evt){
89 | mouseMoveAreaWork(evt);
90 | if( evt.shiftKey){
91 | var r=dragScreen(evt, 'move');
92 | if(r==true)return;
93 | }
94 | drawSelector(evt, 'move');
95 | drawPolygon(evt,'move');
96 | }
97 |
98 | function controllerEventWheel(evt){
99 | zoom(evt);
100 | }
101 |
102 | function controllerEventMouseDown(evt){
103 | //contextMenu.style.visibility = "hidden";
104 | dragScreen(evt, 'down');
105 | drawSelector(evt, 'down');
106 | //if(_evtMsg['jxWork']==true && evt.button==2)duplicateSelection();
107 | var MouseDown = evt.target.getAttribute("MouseDown");
108 | if( MouseDown!=null){
109 | fnCall(MouseDown, evt);
110 | return;
111 | }
112 | }
113 |
114 | /*function controllerEventMouseUp(evt){
115 | dragScreen(evt, 'up');
116 | drawSelector(evt, 'up');
117 | }*/
118 |
119 | function addListenerFunSelector( _event, _selector, _fun){
120 | [...document.querySelectorAll(_selector)].forEach((element, index, array) => {
121 | element.addEventListener(_event, _fun , false);
122 | });
123 | }
124 |
125 | function listAllEventListeners() {
126 | const allElements = Array.prototype.slice.call(document.querySelectorAll('*'));
127 | allElements.push(document);
128 | allElements.push(window);
129 | const types = [];
130 |
131 | for (let ev in window) {
132 | if (/^on/.test(ev)) types[types.length] = ev;
133 | }
134 |
135 | let elements = [];
136 | for (let i = 0; i < allElements.length; i++) {
137 | const currentElement = allElements[i];
138 | for (let j = 0; j < types.length; j++) {
139 | if (typeof currentElement[types[j]] === 'function') {
140 | elements.push({
141 | "node": currentElement,
142 | "type": types[j],
143 | "func": currentElement[types[j]].toString(),
144 | });
145 | }
146 | }
147 | }
148 | return elements.sort(function(a,b) {
149 | return a.type.localeCompare(b.type);
150 | });
151 | }
152 | function spy(){
153 | console.table(listAllEventListeners());
154 | }
155 |
156 | function spy2(){
157 | var cta=0;
158 | Array.from(document.querySelectorAll("*")).forEach(element => {
159 | const events = getEventListeners(element);
160 | if (Object.keys(events).length !== 0) {
161 | console.log(element, events);
162 | cta++;
163 | }
164 | });
165 | console.log("Total Listeners:"+cta);
166 | }
167 |
168 | function fnCall(fn, ...args){
169 | let func = (typeof fn =="string")?window[fn]:fn;
170 | if (typeof func == "function") func(...args);
171 | else throw new Error(`${fn} is Not a function!`);
172 | }
173 |
174 |
--------------------------------------------------------------------------------
/js/conversion.js:
--------------------------------------------------------------------------------
1 | ////////////// CONVERSION UTILS
2 | function shape2path(idshape, _class){
3 | //solo x compatibilidad, todas las convesiones se hacen OK x flattenSimple. resolviendo transforms
4 | flattenSimple(idshape);
5 | var e=document.getElementById(idshape);
6 | e.classList=_class;
7 | return e;
8 | }
9 |
10 | function flattenSimple(_id){
11 | var e=document.getElementById(_id);
12 | if( e.setPathData ){
13 | var p =e.getPathData({normalize: true});
14 | e.setPathData( p );
15 | }
16 | var newPath = flatten(e, true, false, false, 1); //4 decimals
17 | }
18 |
19 | function rPoly2Path(_r){
20 | var d='M';
21 | for(var i=0; i<_r.length; i++){
22 | d+=_r[i][0]+','+_r[i][1]+' ';
23 | }
24 | d=d.trim();
25 | return d;
26 | }
27 |
28 | function path2Poly(_e){
29 | var step;
30 | if( _workSetup['units']=='mm' ){
31 | step=0.85;
32 | }else{
33 | step=0.079375;
34 | }
35 | var segments = _e.getPathData({normalize: true});
36 | //console.log(segments);
37 | var rPoints=[], lastPoint=[], d='';
38 |
39 | for(var i=0; i { }, 10);
41 | if(i==0){
42 | rPoints.push( [ segments[0].values[0], segments[0].values[1] ] );
43 | lastPoint=[ segments[0].values[0], segments[0].values[1] ];
44 | d='M'+segments[0].values[0]+' '+segments[0].values[1]+', ';
45 | }else{
46 | var type=segments[i].type;
47 | if(type=='L'){
48 | rPoints.push( [ segments[i].values[0], segments[i].values[1] ] );
49 | lastPoint=[ segments[i].values[0], segments[i].values[1] ];
50 | d+=segments[i].values[0]+' '+segments[i].values[1]+', ';
51 | }
52 | if(type=='Z'){
53 | rPoints.push( [ segments[0].values[0], segments[0].values[1] ] );
54 | lastPoint=[ segments[0].values[0], segments[0].values[1] ];
55 | d+=segments[0].values[0]+' '+segments[0].values[1];
56 | }
57 | if(type=='C'){
58 | if( segments[i-1].values[4]==segments[i].values[0] && segments[i-1].values[5]==segments[i].values[1] &&
59 | segments[i].values[2]==segments[i].values[4] && segments[i].values[3]==segments[i].values[5] ){
60 | rPoints.push( [ segments[i].values[4], segments[i].values[5] ] );
61 | lastPoint=[ segments[i].values[4], segments[i].values[5] ];
62 | d+=segments[i].values[4]+' '+segments[i].values[5]+', ';
63 | }else{
64 | var pt='M'+lastPoint[0]+' '+lastPoint[1];
65 | pt+='C'+segments[i].values[0]+' '+segments[i].values[1]+' '+segments[i].values[2]+' '+segments[i].values[3]+' '+segments[i].values[4]+' '+segments[i].values[5];
66 | var p=createSVGElement('path', true, 'ps234' );
67 | p.setAttributeNS(null, 'd', pt);
68 | var lenp=p.getTotalLength();
69 |
70 | for( var j=0; j<=lenp; j+=step){
71 | var point = p.getPointAtLength(j);
72 | var pz=[ point.x, point.y ];
73 | rPoints.push( pz );
74 | d+=pz[0]+' '+pz[1]+', ';
75 | }
76 | rPoints.push( [segments[i].values[4], segments[i].values[5]] );
77 | d+=segments[i].values[4]+' '+segments[i].values[5]+', ';
78 |
79 | lastPoint=[ segments[i].values[4], segments[i].values[5] ];
80 | }
81 |
82 | }
83 | }
84 | }
85 | d=d.replace(/, $/, '');
86 |
87 | //quitar puntos repetidos
88 | var rPointsTMP=[];
89 | rPointsTMP.push(rPoints[0]);
90 | var l=rPoints.length-1;
91 | for( i=1; i { }, 10);
93 | if( rPoints[i][0]!=rPoints[i-1][0] || rPoints[i][1]!=rPoints[i-1][1] ){
94 | rPointsTMP.push(rPoints[i]);
95 | }
96 | }
97 | rPointsTMP.push(rPoints[rPoints.length-1]);
98 | rPoints=rPointsTMP;
99 |
100 | var d2, pClipper=[], pointsOK=[];
101 | pClipper.push( { "X":rPoints[0][0], "Y":rPoints[0][1]} ) ;
102 |
103 | pointsOK.push(rPoints[0]);
104 | d2='M'+rPoints[0][0]+' '+rPoints[0][1]+', ';
105 | for( i=1; i { }, 10);
107 | if( (rPoints[i-1][0] == rPoints[i][0] && rPoints[i][0] == rPoints[i+1][0]) ||
108 | (rPoints[i-1][1] == rPoints[i][1] && rPoints[i][1] == rPoints[i+1][1]) /*||
109 | pointOnLine(rPoints[i-1], rPoints[i+1], rPoints[i]) == true*/ ){
110 |
111 | }else{
112 | pointsOK.push( rPoints[i] );
113 | d2+=rPoints[i][0]+' '+rPoints[i][1]+', ';
114 | pClipper.push( { "X":rPoints[i][0], "Y":rPoints[i][1]} ) ;
115 | }
116 | }
117 | pointsOK.push(rPoints[rPoints.length-1]);
118 | d2+=rPoints[rPoints.length-1][0]+' '+rPoints[rPoints.length-1][1];
119 | pClipper.push( { "X":rPoints[rPoints.length-1][0], "Y":rPoints[rPoints.length-1][1]} ) ;
120 |
121 | _output={
122 | pClipper:pClipper,
123 | pointsOK:pointsOK,
124 | rPoints:rPoints,
125 | pathOK:d2
126 | }
127 | /*console.log(pClipper);
128 | console.log(pointsOK);
129 | console.log(rPoints);
130 | console.log(d2);*/
131 |
132 | return _output;
133 | }
134 |
135 | function pointOnLine(pt1, pt2, pt3) {
136 | d1=distance( pt1[0], pt1[1], pt2[0], pt2[1] );
137 | d2=distance( pt1[0], pt1[1], pt3[0], pt3[1] );
138 | d3=distance( pt3[0], pt3[1], pt2[0], pt2[1] );
139 | var s = (d1 + d2 + d3)/2;
140 | var area = Math.sqrt(s*((s-d1)*(s-d2)*(s-d3)));
141 | console.log('area:'+area);
142 | return area<0.001 ? true : false;
143 | }
144 |
145 | function __insertPointInPath(_path, _addPoint, _disClick){
146 | //disClick es la distancia donde esta el punto a insertar. se usa xra encontrar el nodo donde insertar el pto
147 | //console.log( "__insertPointInPath" );
148 | //console.log( _path );
149 | //console.log( _addPoint );
150 | //console.log( "disClick:"+ _disClick );
151 | var pdata=_path.getAttributeNS(null, "d"); //console.log(pdata);
152 | var segments = _path.getPathData({normalize: true});
153 | var npos=_path.getPathSegAtLength(_disClick);
154 | /*var pInicio=segments[npos];
155 | var controlPoints=null;
156 | if( npos== 1)controlPoints=[[segments[npos-1].values[0], segments[npos-1].values[1]], [pInicio.values[0],pInicio.values[1]], [pInicio.values[2],pInicio.values[3]], [pInicio.values[4],pInicio.values[5]]];
157 | else controlPoints=[[segments[npos-1].values[4], segments[npos-1].values[5]], [pInicio.values[0],pInicio.values[1]], [pInicio.values[2],pInicio.values[3]], [pInicio.values[4],pInicio.values[5]]];
158 | var target=[ _addPoint.x, _addPoint.y ];
159 | var b=findBestBezierTangent( target, controlPoints );
160 | console.log( "findBestBezierTangent: target:"+target+" controlPoints:" );
161 | console.log( controlPoints );
162 | console.log(b);
163 | var r = { type: "C", values: [ b[0][0], b[0][1] , b[3][0], b[3][1] , b[5][0], b[5][1] ] };
164 | segments.splice( npos, 0, r );
165 | segments[npos+1].values[0] = b[4][0];
166 | segments[npos+1].values[1] = b[4][1];
167 | segments[npos+1].values[2] = b[2][0];
168 | segments[npos+1].values[3] = b[2][1];*/
169 |
170 | var r = { type: "L", values: [ _addPoint.x, _addPoint.y ] };
171 | segments.splice( npos, 0, r );
172 | _path.setPathData( segments );
173 | }
174 |
175 | function insertPointInPath(_path, _addPoint, _lenTab){
176 | var maxDistance=9999999999;
177 | //console.log(_path);
178 | var lenPath=_path.getTotalLength();
179 | var step=0, disClick=null;;
180 | if( _workSetup['units']=='mm' ){
181 | step=0.1;
182 | }else{
183 | step=0.01;
184 | }
185 | //console.log("units:"+_workSetup['units']+" step:"+step);
186 | for( var i=1; i70 && per<130 ){
203 | __insertPointInPath(_path, point1, disClick-_lenTab/2 );
204 | __insertPointInPath(_path, point2, disClick+_lenTab/2 );
205 | _tabPoints.push( { "point1":{"X":point1.x, "Y":point1.y}, "point2":{"X":point2.x, "Y":point2.y} } );
206 |
207 | // }
208 | }
209 |
210 | function createTabsPath(_path){
211 | var tabPoints=[];
212 | var idGtabs=_path.getAttribute("idGtabs");
213 | var spath=idGtabs.replace( 'tabs-', '' );
214 |
215 | [...document.querySelectorAll(".oneTab."+spath)].forEach((element, index, array) => {
216 | var idNodeTab=element.id;
217 | element.classList.remove("hide");
218 | var bbox=transformedBoundingBox(idNodeTab);
219 | var cx=bbox.x+(bbox.width/2);
220 | var cy=bbox.y+(bbox.height/2);
221 | tabPoints.push( [cx, cy] );
222 | element.classList.add("hide");
223 | });
224 | _tabPoints=[]; //llimpiar array para comenzar de cero
225 |
226 | for(var i=0; i10 ){
239 | console.log(t);
240 | }
241 | }
242 |
243 |
244 | createShapes2Cut(_path, _grouPath);
245 | _path.setAttribute("work", JSON.stringify( _pathConfig ) );
246 |
247 | setTimeout(() => {
248 | document.getElementById('btnCutJobSave').style.display ='';
249 | document.getElementById('btnCutJobCancel').style.display ='';
250 | document.getElementById('preloadCutJob').style.display ='none';
251 | }, 1500);
252 | return;
253 | }
254 |
255 | function createShapes2Cut(_e, _grouPath){
256 | var idPathCutA, tag=_e.tagName, id=_e.id;
257 | var d=null,pAp=null, pathA=null;
258 |
259 | if(tag=="g"){
260 | var spath=id.replace( 'tabs-', '' );
261 | pathA=document.getElementById(spath);
262 | id=spath;
263 | }else{
264 | pathA=_e;
265 | }
266 |
267 | if( _pathConfig['offsetDir'] !=3){
268 | d=booleanOffset(_pathConfig._toolSelect.toolPassDepth, _pathConfig.offsetDir, false, false, 1, id);
269 | drawCutPathA(d);
270 | }else{
271 | var r=path2Poly(pathA);
272 | drawCutPathA(r.pathOK);
273 | }
274 | function drawCutPathA(_d){
275 | idPathCutA=createID("gPath");
276 | pathA=createSVGElement("path", false, idPathCutA);
277 | pathA.setAttributeNS(null, 'd', _d );
278 | pathA.setAttributeNS(null, "marker-end", 'url(#pointCut)' );
279 | pathA.setAttribute("id", idPathCutA );
280 | pathA.setAttribute("class", 'gPath '+_grouPath );
281 | pathA.setAttribute("groupcut", _grouPath );
282 | _hnd['svgHandler'].appendChild( pathA );
283 | }
284 |
285 | var useTabs=false;
286 | if( _pathConfig.useTabs==true ){
287 | var totalTabs=document.querySelectorAll(".oneTab."+spath).length;
288 | if(totalTabs>0){
289 | pathA.setAttribute("idGtabs", _e.id );
290 | createTabsPath(pathA); //inserta los tabs al pathRojo y crea array _tabPoints
291 | pathA.setAttribute("tabs", JSON.stringify( _tabPoints ) );
292 | useTabs=true;
293 | //console.log( pbp. )
294 | }
295 | }
296 | pathA.setAttribute("work", JSON.stringify( _pathConfig ) );
297 |
298 | var _path2Cut={
299 | pathA:pathA, // e svg final. linea roja.
300 | pAp:pAp, // 4 arrays. Clipper, pathOK, pointsOK, rPoints devueltos x path2poly
301 | useTabs:useTabs
302 | }
303 | return _path2Cut;
304 | }
305 |
306 | function paths2string (paths, scale) {
307 | // Converts Paths to SVG path string and scales down the coordinates
308 | var svgpath = "", i, j;
309 | if (!scale) scale = 1;
310 | for(i = 0; i < paths.length; i++) {
311 | for(j = 0; j < paths[i].length; j++){
312 | if (!j) svgpath += "M";
313 | else svgpath += "L";
314 | svgpath += (paths[i][j].X / scale) + ", " + (paths[i][j].Y / scale);
315 | }
316 | svgpath += "Z";
317 | }
318 | if (svgpath=="") svgpath = "M0,0";
319 | return svgpath;
320 | }
321 |
322 |
--------------------------------------------------------------------------------
/js/editBezier.js:
--------------------------------------------------------------------------------
1 | function closeEditNodes(){
2 | document.querySelectorAll(".editNode").forEach(el => el.remove());
3 | document.querySelectorAll(".editNodeSub").forEach(el => el.remove());
4 | document.querySelectorAll(".nodeLine").forEach(el => el.remove());
5 | [...document.getElementsByClassName('editableNodes')].forEach((element, index, array) => {
6 | element.onmousemove=null;
7 | element.ondblclick=null;
8 | element.onmouseleave=null;
9 | });
10 | [...document.getElementsByClassName('cosito')].forEach((element, index, array) => {
11 | element.classList.remove('editableNodes');
12 | });
13 | _evtMsg['isEditNodes']=false;
14 | }
15 |
16 | function activateEditNodes(){
17 | //console.log("activateEditNodes");
18 | //console.log( _selector['SELTOOL'] );
19 |
20 | var id=document.querySelector(".cosito.selectable").id;
21 | flattenSimple(id);
22 |
23 | var pathEditNodes = document.getElementById(id);
24 | var segments = pathEditNodes.getPathData({normalize: true});
25 | pathEditNodes.classList.add( 'editableNodes' );
26 |
27 | var updateP=false, lpth=segments.length;
28 | if( trunc(segments[ lpth-1 ]['values'][4],1)==trunc(segments[ lpth-2 ]['values'][4],1) &&
29 | trunc(segments[ lpth-1 ]['values'][5],1)==trunc(segments[ lpth-2 ]['values'][5],1) &&
30 | trunc(segments[ lpth-1 ]['values'][2],1)==trunc(segments[ lpth-1 ]['values'][4],1) &&
31 | trunc(segments[ lpth-1 ]['values'][3],1)==trunc(segments[ lpth-1 ]['values'][5],1) ){
32 | segments.pop();
33 | updateP=true;
34 | }
35 |
36 | if( segments.length>1 ){
37 | for( index=0; index0){
39 | var p0=trunc(segments[index]['values'][0], 1);
40 | var p1=trunc(segments[index]['values'][1], 1);
41 | var p2=trunc(segments[index]['values'][2], 1);
42 | var p3=trunc(segments[index]['values'][3], 1);
43 | var p4=trunc(segments[index]['values'][4], 1);
44 | var p5=trunc(segments[index]['values'][5], 1);
45 |
46 | if( p2==p4 && p3==p5 ){
47 | if(index==1){
48 | var ant4=trunc(segments[index-1]['values'][0], 1);
49 | var ant5=trunc(segments[index-1]['values'][1], 1);
50 | }else{
51 | var ant4=trunc(segments[index-1]['values'][4], 1);
52 | var ant5=trunc(segments[index-1]['values'][5], 1);
53 | }
54 |
55 | if( p0==ant4 && p1==ant5 ){
56 | var pm=midpoint(ant4, ant5, p4, p5);
57 | segments[index]['values'][2]=pm[0];
58 | segments[index]['values'][3]=pm[1];
59 | //bolita( pm[0], pm[1], 3, "red" ); //nodo trasero
60 | updateP=true;
61 | }
62 | }
63 | }
64 | }
65 | }
66 | if( segments.length>1 ){
67 | for( index=0; index1 ){
110 | for( index=0; index Math.hypot(x2 - x1, y2 - y1);
215 | var d=distance( helperPoints[5][0], helperPoints[5][1], _target[0], _target[1] );
216 | helperPoints.push(d);
217 | return helperPoints;
218 | }
219 |
220 | //bolita( bestr[0][0], bestr[0][1], 3, '#00e3ff' );
221 | //bolita( bestr[1][0], bestr[1][1], 3, '#3286c9' ); // este punto no se usa
222 | //bolita( bestr[2][0], bestr[2][1], 3, '#3286c9' );
223 | //bolita( bestr[3][0], bestr[3][1], 1, 'red' );
224 | //bolita( bestr[4][0], bestr[4][1], 1, 'orange' );
225 | //bolita( bestr[5][0], bestr[5][1], 3, 'fuchsia' );
226 | //console.log('BEST:'+bestd);
227 | //console.log(bestr);
228 | return bestr;
229 | }
230 |
231 | function __drawNode(x, y, type, index, subE, idPath, classN, isRoot, owner ){
232 | var idTMP=createID('editNode');
233 | var circle=createSVGElement('circle');
234 | circle.setAttributeNS(null, 'cx', x);
235 | circle.setAttributeNS(null, 'cy', y);
236 | circle.setAttributeNS(null, 'r', '1%'); //0.5ch
237 | circle.setAttribute("type", type );
238 | circle.setAttribute("index", index );
239 | circle.setAttribute("subE", subE );
240 | circle.setAttribute("idPath", idPath );
241 | circle.setAttribute("class", classN );
242 | circle.setAttribute("isRoot", isRoot );
243 | if(owner && owner!==null)circle.setAttribute("owner", owner );
244 | circle.setAttribute("id", idTMP );
245 | _hnd['svgHandler'].appendChild( circle );
246 | _evtMsg['lastID']=idTMP;
247 | return circle;
248 | }
249 |
250 | function __drawLine(x1, y1, x2, y2, owner, sOwner ){
251 | var idTMP=createID('lineNode');
252 | var linea=createSVGElement('line');
253 | linea.setAttributeNS(null, 'x1', x1); linea.setAttributeNS(null, 'y1', y1);
254 | linea.setAttributeNS(null, 'x2', x2); linea.setAttributeNS(null, 'y2', y2);
255 | linea.setAttributeNS(null, 'style', 'stroke:#707070;stroke-width:0.5px;vector-effect:non-scaling-stroke;pointer-events:none;' );
256 | linea.setAttribute("class", 'nodeLine' );
257 | linea.setAttribute("owner", owner );
258 | linea.setAttribute("sOwner", sOwner );
259 | linea.setAttribute("id", idTMP );
260 | _hnd['svgHandler'].appendChild( linea );
261 | return linea;
262 | }
263 |
264 | function drawNode(x, y, type, index, subE, idPath, classN, isRoot, owner ){
265 | var circle=__drawNode(x, y, type, index, subE, idPath, classN, isRoot, owner);
266 | var idNode=circle.id;
267 |
268 | //click(circle);
269 | function click(){
270 | //console.log('click:'+idNode+' isRoot:'+isRoot+' selNodeIndex:'+_evtMsg['selNodeIndex'] );
271 | if(_evtMsg['selNodeIndex']!==idNode && isRoot==1 ){
272 | [...document.getElementsByClassName('editNodeSub')].forEach((element, index, array) => {
273 | element.remove();
274 | });
275 | [...document.querySelectorAll('line.nodeLine')].forEach((element, index, array) => {
276 | element.remove();
277 | });
278 |
279 | //console.log('DISTINTO:'+isRoot);
280 | _evtMsg['selNodeIndex']=idNode;
281 |
282 | var path = document.getElementById(idPath);
283 | var segments = path.getPathData({normalize: true});
284 | var segment=segments[index];
285 |
286 | [...document.getElementsByClassName('editNode')].forEach((element, index, array) => {
287 | element.classList.remove('sel');
288 | });
289 | circle.classList.add("sel");
290 |
291 | var n1=null, n2=null, sbx=null, sby=null;
292 | if(index==0){
293 | x=segment.values[0]; y=segment.values[1];
294 | sbx=segments[index+1].values[0]; sby=segments[index+1].values[1];
295 | n1=drawNode(sbx, sby, segment.type, 1, 0, idPath, 'editNodeSub', 0, idNode );
296 | __drawLine( x, y, sbx, sby, idNode, _evtMsg['lastID'] );
297 | }else if(index==segments.length-1){
298 | sbx=segment.values[2]; sby=segment.values[3];
299 | n1=drawNode(sbx, sby, segment.type, index, 2, idPath, 'editNodeSub', 0, idNode );
300 | __drawLine( x, y, sbx, sby, idNode, _evtMsg['lastID'] );
301 | //console.log(segment);
302 | //console.log(segments[index+1]);
303 | }else{
304 | sbx=segment.values[2]; sby=segment.values[3];
305 | n1=drawNode(sbx, sby, segment.type, index, 2, idPath, 'editNodeSub', 0, idNode );
306 | __drawLine( x, y, sbx, sby, idNode, _evtMsg['lastID'] );
307 | sbx=segments[index+1].values[0]; sby=segments[index+1].values[1];
308 | n2=drawNode(sbx, sby, segment.type, index+1, 0, idPath, 'editNodeSub', 0, idNode );
309 | __drawLine( x, y, sbx, sby, idNode, _evtMsg['lastID'] );
310 | }
311 |
312 | }
313 | }
314 |
315 | drag(circle);
316 | function drag(e){
317 | e.onmousedown = dragMouseDown;
318 | function dragMouseDown(e) {
319 | e = e || window.event;
320 | e.preventDefault();
321 | document.onmouseup = closeDragElement;
322 | document.onmousemove = elementDrag;
323 | }
324 | function closeDragElement(){
325 | document.onmouseup = null;
326 | document.onmousemove = null;
327 | click();
328 | }
329 | function elementDrag(){
330 | _evtMsg['isDrawSelector']=false;
331 | var path = document.getElementById(idPath);
332 | circle.setAttributeNS(null, 'cx', _evtMsg['mousePOS'].x);
333 | circle.setAttributeNS(null, 'cy', _evtMsg['mousePOS'].y);
334 | //recalcular el path
335 | console.log("drag Node Bezier");
336 | var pathData = path.getPathData({normalize: true});
337 | pathData[index].values[subE]= _evtMsg['mousePOS'].x; x=_evtMsg['mousePOS'].x;
338 | pathData[index].values[subE+1]=_evtMsg['mousePOS'].y; y=_evtMsg['mousePOS'].y;
339 | path.setPathData(pathData);
340 | //dibujar lineas
341 | if( isRoot==1 ){
342 | var els=document.querySelectorAll("line[owner='"+circle.id+"']" );
343 | [...els].forEach((element, index, array) => {
344 | element.setAttributeNS(null, 'x1', _evtMsg['mousePOS'].x);
345 | element.setAttributeNS(null, 'y1', _evtMsg['mousePOS'].y);
346 | });
347 | }else{
348 | var els=document.querySelectorAll("line[sOwner='"+circle.id+"']" );
349 | [...els].forEach((element, index, array) => {
350 | element.setAttributeNS(null, 'x2', _evtMsg['mousePOS'].x);
351 | element.setAttributeNS(null, 'y2', _evtMsg['mousePOS'].y);
352 | });
353 | }
354 | }
355 | }
356 | }
357 |
358 | // reduce Path Points - return points array funciona 3/4 ...
359 | function simplifyPath (_id, tolerance, highestQuality) {
360 | var r=path2Poly( document.getElementById(_id) );
361 | var points=r["pointsOK"];
362 | //console.log(points);
363 |
364 | if (points.length <= 2) return points;
365 | var sqTolerance = tolerance !== undefined ? tolerance * tolerance : 1;
366 | points = highestQuality ? points : simplifyRadialDist(points, sqTolerance);
367 | points = simplifyDouglasPeucker(points, sqTolerance);
368 |
369 | function getSqDist (p1, p2) {
370 | var dx = p2[0] - p1[0];
371 | var dy = p2[1] - p1[1];
372 | return dx * dx + dy * dy;
373 | }
374 |
375 | function getSqSegDist (p, p1, p2) {
376 | var x = p1[0];
377 | var y = p1[1];
378 | var dx = p2[0] - x;
379 | var dy = p2[1] - y;
380 |
381 | if (dx !== 0 || dy !== 0) {
382 | var t = ((p[0] - x) * dx + (p[1] - y) * dy) / (dx * dx + dy * dy);
383 | if (t > 1) {
384 | x = p2[0];
385 | y = p2[1];
386 | } else if (t > 0) {
387 | x += dx * t;
388 | y += dy * t;
389 | }
390 | }
391 | dx = p[0] - x;
392 | dy = p[1] - y;
393 | return dx * dx + dy * dy;
394 | }
395 |
396 | function simplifyRadialDist (points, sqTolerance) {
397 | var prevPoint = points[0];
398 | var newPoints = [prevPoint];
399 | var point;
400 |
401 | for (var i = 1, len = points.length; i < len; i++) {
402 | point = points[i];
403 | if (getSqDist(point, prevPoint) > sqTolerance) {
404 | newPoints.push(point);
405 | prevPoint = point;
406 | }
407 | }
408 |
409 | if (prevPoint !== point) newPoints.push(point);
410 | return newPoints;
411 | }
412 |
413 | function simplifyDPStep (points, first, last, sqTolerance, simplified) {
414 | var maxSqDist = sqTolerance;
415 | var index;
416 |
417 | for (var i = first + 1; i < last; i++) {
418 | var sqDist = getSqSegDist(points[i], points[first], points[last]);
419 | if (sqDist > maxSqDist) {
420 | index = i;
421 | maxSqDist = sqDist;
422 | }
423 | }
424 |
425 | if (maxSqDist > sqTolerance) {
426 | if (index - first > 1) simplifyDPStep(points, first, index, sqTolerance, simplified);
427 | simplified.push(points[index]);
428 | if (last - index > 1) simplifyDPStep(points, index, last, sqTolerance, simplified);
429 | }
430 | }
431 |
432 | function simplifyDouglasPeucker (points, sqTolerance) {
433 | var last = points.length - 1;
434 |
435 | var simplified = [points[0]];
436 | simplifyDPStep(points, 0, last, sqTolerance, simplified);
437 | simplified.push(points[last]);
438 |
439 | return simplified;
440 | }
441 | return points;
442 | }
443 |
444 | function reducePathSmooth(_id, tolerance, _smoothing, drawTMP){
445 | var points = simplifyPath( _id, tolerance, true );
446 |
447 | var lineProperties = (pointA, pointB) => {
448 | var lengthX = pointB[0] - pointA[0]
449 | var lengthY = pointB[1] - pointA[1]
450 | return {
451 | length: Math.sqrt(Math.pow(lengthX, 2) + Math.pow(lengthY, 2)),
452 | angle: Math.atan2(lengthY, lengthX)
453 | }
454 | }
455 |
456 | var controlPointCalc = (current, previous, next, reverse) => {
457 | var c = current;
458 | var p = previous ? previous : c;
459 | var n = next ? next : c;
460 | //const smoothing = 0.05;
461 | var smoothing = _smoothing !== undefined ? _smoothing : 0.1;
462 | var o = lineProperties(p, n);
463 | var rev = reverse ? Math.PI : 0;
464 |
465 | var x = c[0] + Math.cos(o.angle + rev) * o.length * smoothing;
466 | var y = c[1] + Math.sin(o.angle + rev) * o.length * smoothing;
467 |
468 | return [x, y];
469 | }
470 |
471 | var svgPathRender = points => {
472 | var d = points.reduce((acc, e, i, a) => {
473 | if (i > 0) {
474 | var cs = controlPointCalc(a[i - 1], a[i - 2], e);
475 | var ce = controlPointCalc(e, a[i - 1], a[i + 1], true);
476 | return `${acc} C ${cs[0]},${cs[1]} ${ce[0]},${ce[1]} ${e[0]},${e[1]}`
477 | } else {
478 | return `${acc} M ${e[0]},${e[1]}`
479 | }
480 | },'')
481 |
482 | //return ` `
483 | return d;
484 | }
485 | var ptmp=svgPathRender(points);
486 |
487 | if(drawTMP==true){
488 | var newID=createID("path");
489 | var epath=createSVGElement("path", true, newID);
490 | addClassForSelection("#"+newID, "pathTMP");
491 | epath.setAttributeNS( null, "d", ptmp );
492 | _hnd['svgHandler'].appendChild( epath );
493 | }
494 | return ptmp;
495 | }
496 |
497 | function paperReduceNodes(id, tolerance, draw){ //tolerance default 2.5
498 | paper.install(window);
499 | let newCanvas = document.createElement('canvas');
500 | paper.setup( newCanvas );
501 |
502 | var e=document.getElementById(id);
503 | //console.log("paperReduceNodes Anodes:"+countNodes("#"+e.id) );
504 | var base=new Path( e.dGet() );
505 | base.simplify(tolerance);
506 | //e.dSet(base.pathData);
507 | var nid=createID();
508 | if(draw) SVGdraw("path", {"id":nid, "d":base.pathData, "class":"preview", "stroke":"blue", "stroke-width":1, "fill":"none" } );
509 | //console.log("Bnodes:"+countNodes("#"+nid) );
510 |
511 | return base.pathData;
512 | }
513 |
514 | function countNodes(_query){
515 | var ttotal=0;
516 | function getAllDescendants(node) {
517 | var all = [];
518 | getDescendants(node);
519 |
520 | function getDescendants(node) {
521 | for (var i = 0; i < node.childNodes.length; i++) {
522 | var child = node.childNodes[i];
523 | var tag=node.tagName;
524 | getDescendants(child);
525 | all.push(child);
526 | }
527 | }
528 | return all;
529 | }
530 |
531 | function ttNodes(id){
532 | var e = document.getElementById(id);
533 | var segments = e.getPathData({normalize: true});
534 | return segments.length;
535 | }
536 |
537 | Array.prototype.forEach.call(document.querySelectorAll( _query ), function(node) {
538 | var id=node.id;
539 | var tag=node.tagName;
540 |
541 | if(tag!="g"){
542 | if(tag=="path")ttotal+=ttNodes(id);
543 | //console.log(tag+" -- "+id);
544 | }else{
545 | var ch=getAllDescendants(node);
546 | ch.forEach(function(item){
547 | var xid=item.id;
548 | var xtag=item.tagName;
549 | if(xtag=="path")ttotal+=ttNodes(xid);
550 | //console.log("** "+xtag+" -- "+xid);
551 | });
552 | //console.log(ch);
553 | }
554 | });
555 | //console.log("Total Nodes:"+ttotal);
556 | return ttotal;
557 | }
558 |
559 | function reducePath(_id, _draw){
560 | var c=isShapeCombined(_id);
561 | var dok='', path=document.getElementById(_id).dGet();
562 | if( c==false){
563 | dok=inflexionPoints(path, 0.5, 6 );
564 | }else{
565 | var paths = path.split(/(?=[Mm])/);
566 | for( var i=0; i 3) {
639 | uPoints.shift();
640 | }
641 | }
642 |
643 | function getDir(){
644 | if (uPoints.length < 3)return 0;
645 | if( uPoints[0]['y']pip ){ // 12 1
646 | if( uPoints[0]['x']>uPoints[1]['x'] && uPoints[1]['x']>uPoints[2]['x'] && uPoints[0]['x']-uPoints[2]['x']>pip ){ // 1.5 2
647 | return 2;
648 | }else if( uPoints[0]['x']pip ){ // 10.5 8
649 | return 8;
650 | }
651 | return 1;
652 | }else if( uPoints[0]['y']>uPoints[1]['y'] && uPoints[1]['y']>uPoints[2]['y'] && uPoints[0]['y']-uPoints[2]['y']>pip ){ // 6 5
653 | if( uPoints[0]['x']>uPoints[1]['x'] && uPoints[1]['x']>uPoints[2]['x'] && uPoints[0]['x']-uPoints[2]['x']>pip ){ // 4.5 4
654 | return 4;
655 | }else if( uPoints[0]['x']pip ){ // 7.5 6
656 | return 6;
657 | }
658 | return 5;
659 | }else if( uPoints[0]['x']>uPoints[1]['x'] && uPoints[1]['x']>uPoints[2]['x'] && uPoints[0]['x']-uPoints[2]['x']>pip ){ // 3 3
660 | if( uPoints[0]['y']pip ){ // 1.5 2
661 | return 2;
662 | }else if( uPoints[0]['y']>uPoints[1]['y'] && uPoints[1]['y']>uPoints[2]['y'] && uPoints[0]['y']-uPoints[2]['y']>pip ){ // 4.5 4
663 | return 4;
664 | }
665 | return 3;
666 | }else if( uPoints[0]['x']pip ){ // 9 7
667 | if( uPoints[0]['y']pip ){ // 10.5 8
668 | return 8;
669 | }else if( uPoints[0]['y']>uPoints[1]['y'] && uPoints[1]['y']>uPoints[2]['y'] && uPoints[0]['y']-uPoints[2]['y']>pip ){ // 7.5 6
670 | return 6;
671 | }
672 | return 7;
673 | }
674 | return 0;
675 | }
676 | }
677 |
678 |
679 |
680 |
--------------------------------------------------------------------------------
/js/imagetracer.min.js:
--------------------------------------------------------------------------------
1 | //https://github.com/jankovicsandras/imagetracerjs
2 | !function(){"use strict";function t(){var t=this;this.totalNodes=0,this.totalPaths=0,this.pathStr="",this.versionnumber="1.2.6",this.imageToSVG=function(e,n,s){s=t.checkoptions(s),t.loadImage(e,(function(e){n(t.imagedataToSVG(t.getImgdata(e),s))}),s)},this.imagedataToSVG=function(e,n){n=t.checkoptions(n);var s=t.imagedataToTracedata(e,n);return t.getsvgstring(s,n)},this.imageToTracedata=function(e,n,s){s=t.checkoptions(s),t.loadImage(e,(function(e){n(t.imagedataToTracedata(t.getImgdata(e),s))}),s)},this.imagedataToTracedata=function(e,n){n=t.checkoptions(n);var s=t.colorquantization(e,n);if(0===n.layering)for(var o={layers:[],palette:s.palette,width:s.array[0].length-2,height:s.array.length-2},r=0;r0&&(e=t.blur(e,n.blurradius,n.blurdelta)),h=0;h0)for(l=0;l0&&(c[l]={r:Math.floor(p[l].r/p[l].n),g:Math.floor(p[l].g/p[l].n),b:Math.floor(p[l].b/p[l].n),a:Math.floor(p[l].a/p[l].n)}),p[l].n/ue.data[d]?c[l].r-e.data[d]:e.data[d]-c[l].r)+(c[l].g>e.data[d+1]?c[l].g-e.data[d+1]:e.data[d+1]-c[l].g)+(c[l].b>e.data[d+2]?c[l].b-e.data[d+2]:e.data[d+2]-c[l].b)+(c[l].a>e.data[d+3]?c[l].a-e.data[d+3]:e.data[d+3]-c[l].a))t.y!=e[o].y>t.y&&t.x<(e[o].x-e[s].x)*(t.y-e[s].y)/(e[o].y-e[s].y)+e[s].x?!n:n;return n},this.pathscan_combined_lookup=[[[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1]],[[0,1,0,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[0,2,-1,0]],[[-1,-1,-1,-1],[-1,-1,-1,-1],[0,1,0,-1],[0,0,1,0]],[[0,0,1,0],[-1,-1,-1,-1],[0,2,-1,0],[-1,-1,-1,-1]],[[-1,-1,-1,-1],[0,0,1,0],[0,3,0,1],[-1,-1,-1,-1]],[[13,3,0,1],[13,2,-1,0],[7,1,0,-1],[7,0,1,0]],[[-1,-1,-1,-1],[0,1,0,-1],[-1,-1,-1,-1],[0,3,0,1]],[[0,3,0,1],[0,2,-1,0],[-1,-1,-1,-1],[-1,-1,-1,-1]],[[0,3,0,1],[0,2,-1,0],[-1,-1,-1,-1],[-1,-1,-1,-1]],[[-1,-1,-1,-1],[0,1,0,-1],[-1,-1,-1,-1],[0,3,0,1]],[[11,1,0,-1],[14,0,1,0],[14,3,0,1],[11,2,-1,0]],[[-1,-1,-1,-1],[0,0,1,0],[0,3,0,1],[-1,-1,-1,-1]],[[0,0,1,0],[-1,-1,-1,-1],[0,2,-1,0],[-1,-1,-1,-1]],[[-1,-1,-1,-1],[-1,-1,-1,-1],[0,1,0,-1],[0,0,1,0]],[[0,1,0,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[0,2,-1,0]],[[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1]]],this.pathscan=function(e,n){for(var s,o=[],r=0,a=0,i=0,l=0,h=e[0].length,c=e.length,g=0,d=!0,p=!1,u=0;uo[r].boundingbox[2]&&(o[r].boundingbox[2]=i-1),l-1o[r].boundingbox[3]&&(o[r].boundingbox[3]=l-1),s=t.pathscan_combined_lookup[e[l][i]][g],e[l][i]=s[0],g=s[1],i+=s[2],l+=s[3],i-1===o[r].points[0].x&&l-1===o[r].points[0].y)if(d=!0,o[r].points.lengthe[2]&&t[3]>e[3]},this.batchpathscan=function(e,n){var s=[];for(var o in e)e.hasOwnProperty(o)&&(s[o]=t.pathscan(e[o],n));return s},this.internodes=function(e,n){var s,o,r=[],a=0,i=0,l=0,h=0,c=0;for(s=0;s0&&(r[s].points[r[s].points.length-1].linesegment=t.getdirection(r[s].points[r[s].points.length-1].x,r[s].points[r[s].points.length-1].y,e[s].points[o].x,e[s].points[o].y)),r[s].points.push({x:e[s].points[o].x,y:e[s].points[o].y,linesegment:t.getdirection(e[s].points[o].x,e[s].points[o].y,(e[s].points[o].x+e[s].points[i].x)/2,(e[s].points[o].y+e[s].points[i].y)/2)})),r[s].points.push({x:(e[s].points[o].x+e[s].points[i].x)/2,y:(e[s].points[o].y+e[s].points[i].y)/2,linesegment:t.getdirection((e[s].points[o].x+e[s].points[i].x)/2,(e[s].points[o].y+e[s].points[i].y)/2,(e[s].points[i].x+e[s].points[l].x)/2,(e[s].points[i].y+e[s].points[l].y)/2)});return r},this.testrightangle=function(t,e,n,s,o,r){return t.points[s].x===t.points[e].x&&t.points[s].x===t.points[n].x&&t.points[s].y===t.points[o].y&&t.points[s].y===t.points[r].y||t.points[s].y===t.points[e].y&&t.points[s].y===t.points[n].y&&t.points[s].x===t.points[o].x&&t.points[s].x===t.points[r].x},this.getdirection=function(t,e,n,s){return ts?7:0:t>n?es?5:4:es?6:8},this.batchinternodes=function(e,n){var s=[];for(var o in e)e.hasOwnProperty(o)&&(s[o]=t.internodes(e[o],n));return s},this.tracepath=function(e,n,s){var o,r,a,i=0,l={segments:[]};for(l.boundingbox=e.boundingbox,l.holechildren=e.holechildren,l.isholepath=e.isholepath;i0?a:e.points.length}return l},this.fitseq=function(e,n,s,o,r){if(r>e.points.length||r<0)return[];var a,i,l,h=o,c=0,g=!0,d=r-o;d<0&&(d+=e.points.length);for(var p,u=(e.points[r].x-e.points[o].x)/d,m=(e.points[r].y-e.points[o].y)/d,f=(o+1)%e.points.length;f!=r;)(p=f-o)<0&&(p+=e.points.length),a=e.points[o].x+u*p,i=e.points[o].y+m*p,(l=(e.points[f].x-a)*(e.points[f].x-a)+(e.points[f].y-i)*(e.points[f].y-i))>n&&(g=!1),l>c&&(h=f,c=l),f=(f+1)%e.points.length;if(g)return[{type:"L",x1:e.points[o].x,y1:e.points[o].y,x2:e.points[r].x,y2:e.points[r].y}];var y=h;g=!0,c=0;var b=(y-o)/d,x=(1-b)*(1-b),w=2*(1-b)*b,v=b*b,M=(x*e.points[o].x+v*e.points[r].x-e.points[y].x)/-w,k=(x*e.points[o].y+v*e.points[r].y-e.points[y].y)/-w;for(f=o+1;f!=r;)w=2*(1-(b=(f-o)/d))*b,v=b*b,a=(x=(1-b)*(1-b))*e.points[o].x+w*M+v*e.points[r].x,i=x*e.points[o].y+w*k+v*e.points[r].y,(l=(e.points[f].x-a)*(e.points[f].x-a)+(e.points[f].y-i)*(e.points[f].y-i))>s&&(g=!1),l>c&&(h=f,c=l),f=(f+1)%e.points.length;if(g)return[{type:"Q",x1:e.points[o].x,y1:e.points[o].y,x2:M,y2:k,x3:e.points[r].x,y3:e.points[r].y}];var q=y;return t.fitseq(e,n,s,o,q).concat(t.fitseq(e,n,s,q,r))},this.batchtracepaths=function(e,n,s){var o=[];for(var r in e)e.hasOwnProperty(r)&&o.push(t.tracepath(e[r],n,s));return o},this.batchtracelayers=function(e,n,s){var o=[];for(var r in e)e.hasOwnProperty(r)&&(o[r]=t.batchtracepaths(e[r],n,s));return o},this.roundtodec=function(t,e){return+t.toFixed(e)},this.svgpathstring=function(e,n,s,o){var r,a=e.layers[n],i=a[s],l="";if(o.linefilter&&i.segments.length<3)return l;if(l='=0;r--)l+=c.segments[r].type+" ",c.segments[r].hasOwnProperty("x3")&&(l+=c.segments[r].x2*o.scale+" "+c.segments[r].y2*o.scale+" "),l+=c.segments[r].x1*o.scale+" "+c.segments[r].y1*o.scale+" ";else for(c.segments[c.segments.length-1].hasOwnProperty("x3")?l+="M "+t.roundtodec(c.segments[c.segments.length-1].x3*o.scale)+" "+t.roundtodec(c.segments[c.segments.length-1].y3*o.scale)+" ":l+="M "+t.roundtodec(c.segments[c.segments.length-1].x2*o.scale)+" "+t.roundtodec(c.segments[c.segments.length-1].y2*o.scale)+" ",r=c.segments.length-1;r>=0;r--)l+=c.segments[r].type+" ",c.segments[r].hasOwnProperty("x3")&&(l+=t.roundtodec(c.segments[r].x2*o.scale)+" "+t.roundtodec(c.segments[r].y2*o.scale)+" "),l+=t.roundtodec(c.segments[r].x1*o.scale)+" "+t.roundtodec(c.segments[r].y1*o.scale)+" ";l+="Z "}for(l+='" />',r=0;r ',l+=' ',l+=' ',l+=' '),!i.segments[r].hasOwnProperty("x3")&&o.lcpr&&(l+=' ');for(h=0;h ',l+=' ',l+=' ',l+=' '),!c.segments[r].hasOwnProperty("x3")&&o.lcpr&&(l+=' ')}}return l},this.getsvgstring=function(e,n){n=t.checkoptions(n);for(var s=e.width*n.scale,o=e.height*n.scale,r="',a=0;a"},this.compareNumbers=function(t,e){return t-e},this.torgbastr=function(t){return"rgba("+t.r+","+t.g+","+t.b+","+t.a+")"},this.tosvgcolorstr=function(t,e){return'fill="rgb('+t.r+","+t.g+","+t.b+')" stroke="rgb('+t.r+","+t.g+","+t.b+')" stroke-width="'+e.strokewidth+'" opacity="'+t.a/255+'" '},this.appendSVGString=function(t,e){var n;e?(n=document.getElementById(e))||((n=document.createElement("div")).id=e,document.body.appendChild(n)):(n=document.createElement("div"),document.body.appendChild(n)),n.innerHTML+=t;var s=document.getElementById("svgInfo");"undefined"!=s&&(s.innerHTML="("+this.totalPaths+" Paths, "+this.totalNodes+" Nodes)")},this.gks=[[.27901,.44198,.27901],[.135336,.228569,.272192,.228569,.135336],[.086776,.136394,.178908,.195843,.178908,.136394,.086776],[.063327,.093095,.122589,.144599,.152781,.144599,.122589,.093095,.063327],[.049692,.069304,.089767,.107988,.120651,.125194,.120651,.107988,.089767,.069304,.049692]],this.blur=function(e,n,s){var o,r,a,i,l,h,c,g,d,p={width:e.width,height:e.height,data:[]};if((n=Math.floor(n))<1)return e;n>5&&(n=5),(s=Math.abs(s))>1024&&(s=1024);var u=t.gks[n-1];for(r=0;r0&&o+a0&&r+as&&(p.data[i]=e.data[i],p.data[i+1]=e.data[i+1],p.data[i+2]=e.data[i+2],p.data[i+3]=e.data[i+3]);return p},this.loadImage=function(t,e,n){var s=new Image;n&&n.corsenabled&&(s.crossOrigin="Anonymous"),s.onload=function(){var t=document.createElement("canvas");t.width=s.width,t.height=s.height,t.getContext("2d").drawImage(s,0,0),e(t)},s.src=t,this.totalNodes=0,this.totalPaths=0,this.pathStr=""},this.getImgdata=function(t){return t.getContext("2d").getImageData(0,0,t.width,t.height)},this.specpalette=[{r:0,g:0,b:0,a:255},{r:128,g:128,b:128,a:255},{r:0,g:0,b:128,a:255},{r:64,g:64,b:128,a:255},{r:192,g:192,b:192,a:255},{r:255,g:255,b:255,a:255},{r:128,g:128,b:192,a:255},{r:0,g:0,b:192,a:255},{r:128,g:0,b:0,a:255},{r:128,g:64,b:64,a:255},{r:128,g:0,b:128,a:255},{r:168,g:168,b:168,a:255},{r:192,g:128,b:128,a:255},{r:192,g:0,b:0,a:255},{r:255,g:255,b:255,a:255},{r:0,g:128,b:0,a:255}],this.drawLayers=function(e,n,s,o){var r,a,i,l,h,c;for(h in s=s||1,o?(c=document.getElementById(o))||((c=document.createElement("div")).id=o,document.body.appendChild(c)):(c=document.createElement("div"),document.body.appendChild(c)),e)if(e.hasOwnProperty(h)){r=e[h][0].length,a=e[h].length;var g=document.createElement("canvas");g.width=r*s,g.height=a*s;var d=g.getContext("2d");for(l=0;l {
55 | element.hide();
56 | });
57 | sTool='';
58 | }else{
59 | if( checkID('imageFonts')==false ){
60 | var head = document.querySelector('head');
61 | var link = ' ';
62 | head.insertAdjacentHTML('beforeend', link);
63 | }
64 | if( checkID('scriptOpenType')==false ){
65 | loadScript('https://artdraw.org/svg/js/opentype.min.js', 'scriptOpenType', function() {
66 | document.getElementById("preloadScriptOpenType").hide();
67 | document.getElementById("drawText").show();
68 | });
69 | }
70 | selecTool(id, 'panelText', 'DRAW TEXT');
71 | selectText();
72 | }
73 | }
74 |
75 | function MCKbtnShapesClick(event){
76 | showModal("frmImportShapes");
77 | }
78 |
79 |
80 |
--------------------------------------------------------------------------------
/js/panels.js:
--------------------------------------------------------------------------------
1 | addListenerFunSelector( "click", "#btnEditNodes", btnEditNodesClick);
2 | function btnEditNodesClick(){
3 | if( _selector['SELTOOL']!="SELROJO" ){
4 | MCKbtnSelectClick();
5 | return;
6 | }
7 |
8 | var e=document.querySelectorAll(".cosito.selectable")[0];
9 | if( e.tagName=="g" ){
10 | Confirm("Shape has Tabs", "Edit Nodes delete all Tabs.", "CONTINUE", "CANCEL", confirmDeleteTabs);
11 | function confirmDeleteTabs(){
12 |
13 | }
14 | return;
15 | }else{
16 | _selector['SELTOOL']="EDITBEZIER";
17 | HideSelector();
18 | activateEditNodes();
19 | Ayuda("ESC, CTR, ALT Key ==> Exit Node Edit");
20 | }
21 |
22 | };
23 |
24 | function MCKbtnToPathClick(event){
25 | deletePreviewTMP();
26 | var id=event.target.id;
27 | document.getElementById("infoPanel").hide();
28 | selecTool(id, 'panelToolpath', 'TOOLPATH');
29 | };
30 |
31 | /////////// SHOW PANELS tool-type-select
32 | function MCKbtnOpenConfigureToolClick(){
33 | showModal("frmConfigureTool");
34 | }
35 |
36 | function MCKOpenPublishForm(event){
37 | if( IS_USER==true ){
38 | visibilityForSelection( "button[mouseup=publishWeb]", "flex" );
39 | visibilityForSelection( "button[mouseup=publishWeb] + p", "none" );
40 | }else{
41 | visibilityForSelection( "button[mouseup=publishWeb]", "none" );
42 | visibilityForSelection( "button[mouseup=publishWeb] + p", "block" );
43 | }
44 | showModal("frmPublisWeb");
45 | }
46 |
47 |
48 | function MCKbtnGroupClick(event){
49 | var ttItems=document.querySelectorAll(".selectable").length;
50 | if(ttItems==1){
51 | var tag= document.querySelectorAll(".selectable")[0].tagName;
52 | var id= document.querySelectorAll(".selectable")[0].id;
53 | if(tag=="g"){
54 | flattenSimple(id);
55 | unGroupElements( id, 'cosito selectable' );
56 | makeSelection(true);
57 | controlPointZ("ungroup", null, id);
58 | removeClassFromSelection("#liGroup", "sel");
59 | return;
60 | }
61 | }
62 | if( ttItems<2 ){
63 | Dialog("Group Elements", "To Group, Select 2 or more objects To Ungroup, Select a Group", " OK ");
64 | return;
65 | }
66 | groupElements('selectable', false, 'cosito selectable', true, "grouped");
67 | controlPointZ("group");
68 | addClassForSelection("#liGroup", "sel");
69 | }
70 |
71 | function MCKbtnCombineClick(){
72 | HideSelector();
73 | var e= combinePaths('selectable', true, true, null);
74 | HideSelector();
75 | makeSelection(true);
76 | }
77 |
78 | function MCKselectLineStyleClick(event){
79 | var dashPoints=event.target.querySelectorAll("svg line")[0].style['stroke-dasharray'];
80 | [...document.querySelectorAll("#svgWorkerArea .selectable")].forEach((element, index, array) => {
81 | element.setAttributeNS( null, "stroke-dasharray", dashPoints );
82 | element.style['stroke-dasharray'] = dashPoints;
83 | });
84 | document.getElementById("styleBorderLine").toggleClass('show');
85 | };
86 |
87 | function toggleInfoPanelClick(event){
88 | if( checkVisibility( document.querySelector("#InfoPanel .card-body") )==true ){
89 | document.querySelector("#InfoPanel .card-body").slideUp(250);
90 | }else{
91 | document.querySelector("#InfoPanel .card-body").slideDown(250);
92 | }
93 | };
94 |
95 |
96 | function fontSelect(event){
97 | //console.log(event.target) ;
98 | event.stopPropagation();
99 | document.getElementById("font").value="/fonts/"+event.target.getAttribute("font");
100 | var font=document.getElementById("font").value;
101 |
102 | var arrayUrl = font.split('/');
103 | var ff = arrayUrl[arrayUrl.length - 1];
104 | ff = ff.split(".")[0];
105 | ff = ff.replace("-", " ");
106 | var src="url(https://artdraw.org/svg"+font+")";
107 |
108 | var myfont = new FontFace(ff, src );
109 | myfont.load().then(function(loadedFont) {
110 | document.fonts.add(loadedFont);
111 | document.getElementById("selectFontBtn").style.fontFamily = ff;
112 | }).catch(function(error) {
113 | // error occurred
114 | });
115 |
116 | closeModal("frmSelectFont");
117 | };
118 | function MCKmodeDrawText(event){
119 | if(event.target.getAttribute("value")=='1' ){
120 | document.getElementById("textSimpleControls").show();
121 | }else{
122 | document.getElementById("textSimpleControls").hide();
123 | }
124 | //console.log(event.target);
125 | }
126 | function MCKtextAlignClick(event){
127 | var attr=event.target.getAttribute("rel-atr");
128 | if( attr=="bold" || attr=="italic" ){
129 | event.target.classList.toggle("sel");
130 | }else{
131 | removeClassFromSelection( "#textSimpleControls .align", "sel" );
132 | event.target.classList.toggle("sel");
133 | }
134 |
135 | }
136 | function MCKdrawTextClick(){
137 | var font=document.getElementById("font").value;
138 | var text=document.getElementById("txt2path").value;
139 |
140 | if( radioValue("textMode")=='2' ){
141 | drawTextOpenType(font, text);
142 | }else{
143 | drawTextGoogleFonts(font, text);
144 | }
145 | //drawText();
146 | }
147 |
148 | function MCKbtnOutlClick(event){
149 | deletePreviewTMP();
150 | var id=event.target.id;
151 | if( checkVisibility( document.getElementById("panelOffset") )==true ){
152 | removeClassFromSelection(".btnTool.sel", "sel");
153 | [...document.querySelectorAll(".toolPanel")].forEach((element, index, array) => {
154 | element.hide();
155 | });
156 | sTool='';
157 | }else{
158 | selecTool(id, 'panelOffset', 'BORDER OFFSET');
159 | booleanOffsetPreview();
160 | }
161 | }
162 |
163 | function MCKapplyOffsetClick(){
164 | if( document.querySelectorAll('.preview').length==0 ){
165 | Dialog("No Offset", "Select object for border Offset", "OK");
166 | return;
167 | }
168 | var reduce=document.getElementById('offsetReduceNodes').checked; document.querySelectorAll('.preview');
169 | if(reduce==true){
170 | var id=document.querySelector(".preview").id;
171 | var dok=reducePath(id, false);
172 | document.getElementById(id).dSet(dok);
173 | }
174 | var delOffset=document.getElementById('offsetPathDel').checked;
175 | if( delOffset==true ){
176 | removeAllFromSelection(".cosito.selectable");
177 | }else{
178 | removeClassFromSelection(".cosito", "selectable");
179 | }
180 |
181 | addClassForSelection('.preview', 'cosito selectable');
182 | setAttributeForSelection('.preview', {"fill":colorA, "fill-opacity":"0.25", "stroke":"#000000"} );
183 | removeClassFromSelection(".preview", "preview");
184 | makeSelection(true);
185 | booleanOffsetPreview();
186 |
187 | controlPointZ( "new", ".cosito.selectable" );
188 | }
189 |
190 | function MCKbtnBooleanClick(event){
191 | var id=event.target.id;
192 | var e=document.getElementById("panelBoolean");
193 | if( checkVisibility( e )==true ){
194 | removeClassFromSelection(".btnTool.sel", "sel");
195 | e.slideUp(250);
196 | sTool='';
197 | }else{
198 | selecTool(id, 'panelBoolean', 'BOOLEANS');
199 | booleanMergePreview();
200 | }
201 | }
202 |
203 | function MCKapplyBooleanClick(){
204 | if( document.querySelectorAll('.preview').length==0 ){
205 | Dialog("No Boolean", "Select object for Boolean merge", "OK");
206 | return;
207 | }
208 | var reduce=document.getElementById('booleanReduceNodes').checked; document.querySelectorAll('.preview');
209 | if(reduce==true){
210 | var id=document.querySelector(".preview").id;
211 | var dok=reducePath(id, false);
212 | document.getElementById(id).dSet(dok);
213 | }
214 | var delOrigen=document.getElementById('booleanDeleteOriginal').checked;
215 | if( delOrigen==true ){
216 | removeAllFromSelection(".cosito.selectable");
217 | }else{
218 | removeClassFromSelection(".cosito", "selectable");
219 | }
220 |
221 | addClassForSelection('.preview', 'cosito selectable');
222 | setAttributeForSelection('.preview', {"fill":colorA, "fill-opacity":"0.25", "stroke":"#000000"} );
223 | removeClassFromSelection(".preview", "preview");
224 | makeSelection(true);
225 | booleanMergePreview();
226 |
227 | controlPointZ( "new", ".cosito.selectable" );
228 | }
229 |
230 | function MCKbtnRoundClick(event){
231 | deletePreviewTMP();
232 | var id=event.target.id;
233 | if( checkVisibility( document.getElementById("panelRound") )==true ){
234 | removeClassFromSelection(".btnTool.sel", "sel");
235 | [...document.querySelectorAll(".toolPanel")].forEach((element, index, array) => {
236 | element.hide();
237 | });
238 | sTool='';
239 | }else{
240 | selecTool(id, 'panelRound', 'ROUND CORNERS');
241 | roundBBoxPreview();
242 | }
243 | }
244 |
245 | function MCKapplyRoundClick(){
246 | if( document.querySelectorAll('.preview').length==0 ){
247 | Dialog("No Round Border", "Select object for Round Borders", "OK");
248 | return;
249 | }
250 | var delOrigen=document.getElementById('roundBorderOriginalDel').checked;
251 | if( delOrigen==true ){
252 | removeAllFromSelection(".cosito.selectable");
253 | }else{
254 | removeClassFromSelection(".cosito", "selectable");
255 | }
256 |
257 | addClassForSelection('.preview', "cosito selectable");
258 | setAttributeForSelection( '.preview', { "fill":colorA, "fill-opacity":"0.25", "stroke":"#000000" } )
259 |
260 | removeClassFromSelection(".preview", "preview");
261 | makeSelection(true);
262 | }
263 | //// ALIGN TOOL
264 | function MCKbtnAlignTClick(event){
265 | deletePreviewTMP();
266 | var id=event.target.id;
267 | if( checkVisibility( document.getElementById("panelAlign") )==true ){
268 | removeClassFromSelection(".btnTool.sel", "sel");
269 | [...document.querySelectorAll(".toolPanel")].forEach((element, index, array) => {
270 | element.hide();
271 | });
272 | sTool='';
273 | }else{
274 | selecTool(id, 'panelAlign', 'ALIGN TOOL');
275 | alignShapesPreview();
276 | }
277 | }
278 |
279 | function MCKapplyAlignClick(event){
280 | if( document.querySelectorAll(".selectable").length==0 ){
281 | return;
282 | }
283 | alignShapesPreview(true);
284 | makeSelection(true);
285 | }
286 | //// FLIP MIRROR
287 | function MCKapplyMirrorClick(event){
288 | if( document.querySelectorAll(".selectable").length==0 )return;
289 | var mirrorType=event.target.getAttribute("mirrorType");
290 | if( mirrorType=='vertical' ){
291 | flipXSelection(".selectable");
292 | }else{
293 | flipYSelection(".selectable");
294 | }
295 | }
296 | /*function xxxMCKapplyMirrorClick(event){
297 | var ttItems=document.querySelectorAll(".selectable").length ;
298 | if( ttItems==0 ){
299 | Dialog("Flip Mirror", "First select an object to apply Flip Mirror", "OK");
300 | return
301 | };
302 | var mirrorType=event.target.getAttribute("mirrorType");
303 | var e=null, i=null, eflip=null, idFlip=null;
304 | if( ttItems==1 ){
305 | idFlip=document.querySelector(".selectable").id;
306 | //eflip = document.getElementById(id);
307 | }else{
308 | idFlip=groupElements('selectable', 1, 'groupTMP cosito', false, 'groupItemTMP');
309 | }
310 |
311 | flattenSimple( idFlip );
312 | eflip = document.getElementById(idFlip);
313 | var bbox=eflip.getBBox();
314 | var cx=(bbox.x*2) + (bbox.width);
315 | var cy=(bbox.y*2) + (bbox.height);
316 |
317 | var matrix = mirrorType == 'vertical' ? 'matrix(-1,0,0,1,'+cx+',0)' : 'matrix(1,0,0,-1,0,'+cy+')';
318 | eflip.setAttribute("transform", matrix );
319 | flattenSimple( idFlip );
320 | unGroupElements( idFlip, "cosito" );
321 | }*/
322 | //// Z-ORDER
323 | function MCKapplyZorder(event, shortcut){
324 | var z, ttItems=document.querySelectorAll(".selectable").length;
325 | if( ttItems==0 ){
326 | Dialog("Z Order", "First select an object to change its positionZ", "OK");
327 | return
328 | };
329 |
330 | if( event!=false){
331 | z=event.target.getAttribute("toposition");
332 | }else{
333 | z=shortcut;
334 | }
335 |
336 |
337 | if( z=="front" ){
338 | //SVG('.selectable').front();
339 | [...document.querySelectorAll('.selectable')].forEach((element, index, array) => {
340 | element.front();
341 | });
342 | }else if( z=="forward" ){
343 | //SVG('.selectable').forward();
344 | [...document.querySelectorAll('.selectable')].forEach((element, index, array) => {
345 | element.forward();
346 | });
347 | }else if( z=="backward" ){
348 | //SVG('.selectable').backward();
349 | [...document.querySelectorAll('.selectable')].forEach((element, index, array) => {
350 | element.backward();
351 | });
352 | }else if( z=="back" ){
353 | //SVG('.selectable').back();
354 | [...document.querySelectorAll('.selectable')].forEach((element, index, array) => {
355 | element.back();
356 | });
357 | }
358 |
359 | UpdateZorderDoc();
360 | makeSelection(true);
361 | }
362 | //// TRACE IMAGE
363 | function MCKbtnTraceImageClick(){
364 | var ttItems=document.querySelectorAll(".selectable").length;
365 | if( ttItems==0 ){
366 | Dialog( "Image to Vectors", "First select an Image to convert to vectors. You can import images from your local drive or from a URL.", "OKI");
367 | return;
368 | }
369 | document.getElementById("frameTrace").src="https://artdraw.org/svg/trace.html";
370 | showModal("frmTraceDialog");
371 | }
372 |
373 | function callBackTrace(){
374 | var seles=document.getElementsByClassName('selectable');
375 | if(seles.length>0){
376 | var imgDataForTrace=seles[0].getAttribute("xlink:href");
377 | return imgDataForTrace;
378 | }
379 | return false;
380 | }
381 |
382 | function __showModal(event){
383 | //console.log(event);
384 | var idModal=event.target.getAttribute("idModal");
385 | if(!idModal || idModal===null || idModal=='undefined')return;
386 | showModal(idModal);
387 | }
388 | function showModal(_idModal){
389 | var modal = document.getElementById(_idModal);
390 | modal.style.display = "flex";
391 |
392 | addListenerFunSelector( "click", "#"+_idModal+" .closeModal", closeModal );
393 | function closeModal(event) {
394 | modal.style.display = "none";
395 | }
396 |
397 | var force=getAttributeFromID(_idModal, "force");
398 | if( Number(force)!==1 ){
399 | window.onclick = function(event) {
400 | if (event.target == modal) {
401 | modal.style.display = "none";
402 | }
403 | }
404 | }
405 | }
406 | function closeModal(_idModal){
407 | var modal = document.getElementById(_idModal);
408 | modal.style.display = "none";
409 | }
410 |
411 | function MCKshowUserLogin(event){
412 | if( IS_USER==true ){
413 | showModal("frmUserLogin");
414 | }else{
415 | OAUTHclient.requestAccessToken();
416 | }
417 | }
418 |
419 | function CloseGoogleSession(){
420 | Cookies.remove('SVGuserMail');
421 | Cookies.remove('SVGuserHash');
422 | IS_USER=false;
423 | checkLogin();
424 | closeModal("frmUserLogin");
425 | }
426 |
427 | function MCKbtnSaveJobConfigClick(){
428 | var w=document.getElementById("jobW").value;
429 | var h=document.getElementById("jobH").value;
430 | var thk=document.getElementById("jobThick").value;
431 | var zsf=document.getElementById("jobZsafe").value;
432 | var zp=radioValue('zeroPos');
433 | var zpz=radioValue('zeroPosZ');
434 | var u=radioValue('unitSwitch');
435 | updateWorkSetup(w, h, thk, zp, zpz, u, zsf);
436 | setupJobSize(true);
437 | }
438 |
439 | function updateWorkSetup(w, h, thk, zp, zpz, u, zsf){
440 | _workSetup['width']=w;
441 | _workSetup['height']=h;
442 | _workSetup['thick']=thk;
443 | _workSetup['zeroPos']=zp;
444 | _workSetup['zeroPosZ']=zpz;
445 | _workSetup['units']=u;
446 | _workSetup['zSafe']=zsf;
447 | _hnd['svgHandler'].setAttribute( "worksetup", JSON.stringify(_workSetup) );
448 |
449 | localStorage.setItem("ws-width", w );
450 | localStorage.setItem("ws-height", h );
451 | localStorage.setItem("ws-thick", thk );
452 | localStorage.setItem("ws-zeroPos", zp);
453 | localStorage.setItem("ws-zeroPosZ", zpz);
454 | localStorage.setItem("ws-units", u);
455 | }
456 |
457 | //addListenerFunSelector( "click", "#btnTabs", btnTabsClick );
458 | function MCKbtnTabsClick(event){
459 | //console.log("draw tabs");
460 | if( _selector['SELTOOL']=='DRAWTABS' ){
461 | _selector['SELTOOL']='SELROJO';
462 | closeEditTabs();
463 | return;
464 | }
465 | if( _selector['SELTOOL']=='EDITBEZIER' ){
466 | closeEditNodes();
467 | }
468 |
469 | var e=document.querySelectorAll(".cosito.selectable")[0];
470 | var tag=e.tagName;
471 | if(tag=="g"){
472 | var idg=e.id;
473 | flattenSimple( idg );
474 | var path=idg.replace( 'tabs-', '' );
475 | e=document.getElementById(path);
476 | groupRemoveElement("tabs-"+path, e );
477 | e.classList.add("cosito");
478 | removeClassFromSelection(".oneTab."+path, "hide");
479 | }else{
480 | var idf=e.id;
481 | flattenSimple( idf );
482 | e=document.getElementById(idf);
483 | }
484 |
485 | _selector['HND']=e;
486 | e.classList.add("tabsEdit");
487 | e.classList.remove("selectable");
488 | _selector['SELTOOL']='DRAWTABS';
489 | HideSelector();
490 | drawTabs(e);
491 | console.log( _selector['SELTOOL'] )
492 | };
493 |
494 | function openRoughPanel(event){//makeRough
495 | deletePreviewTMP();
496 | var id=event.target.id;
497 | if( checkVisibility( document.getElementById("panelRough") )==true ){
498 | removeClassFromSelection(".btnTool.sel", "sel");
499 | [...document.querySelectorAll(".toolPanel")].forEach((element, index, array) => {
500 | element.hide();
501 | });
502 | sTool='';
503 | }else{
504 | sTool='panelRough';
505 | selecTool(id, 'panelRough', 'ROUGH PANEL');
506 | previewRough();
507 | }
508 | }
509 |
510 | function MCKopenWavesEditor(){
511 | deletePreviewTMP();
512 | var id=event.target.id;
513 | if( checkVisibility( document.getElementById("panelWaves") )==true ){
514 | removeClassFromSelection(".btnTool.sel", "sel");
515 | [...document.querySelectorAll(".toolPanel")].forEach((element, index, array) => {
516 | element.hide();
517 | });
518 | sTool='';
519 | }else{
520 | sTool='panelWaves';
521 | selecTool(id, 'panelWaves', 'ROUGH PANEL');
522 | document.getElementById("wavesWidth").value=_workSetup['width']/2;
523 | document.getElementById("wavesHeight").value=_workSetup['height']/2;
524 | wavesDraw();
525 | }
526 | }
527 |
528 | function MCKopenRotateEditor(event){
529 | deletePreviewTMP();
530 | var id=event.target.id;
531 | if( checkVisibility( document.getElementById("panelArray") )==true ){
532 | removeClassFromSelection(".btnTool.sel", "sel");
533 | [...document.querySelectorAll(".toolPanel")].forEach((element, index, array) => {
534 | element.hide();
535 | });
536 | sTool='';
537 | }else{
538 | sTool='panelArray';
539 | selecTool(id, 'panelArray', 'ARRAY PANEL');
540 | mainPanelArray();
541 | }
542 | }
543 |
544 | function MCKopenEffectsEditor(){
545 | deletePreviewTMP();
546 | var id=event.target.id;
547 | if( checkVisibility( document.getElementById("panelEffects") )==true ){
548 | restoreFilters();
549 | removeClassFromSelection(".btnTool.sel", "sel");
550 | [...document.querySelectorAll(".toolPanel")].forEach((element, index, array) => {
551 | element.hide();
552 | });
553 | sTool='';
554 | }else{
555 | sTool='panelEffects';
556 | selecTool(id, 'panelEffects', 'EFFECTS PANEL');
557 | loadFilter();
558 | }
559 | }
560 |
561 |
562 |
--------------------------------------------------------------------------------
/js/path-data-polyfill.min.js:
--------------------------------------------------------------------------------
1 | // https://github.com/jarek-foksa/path-data-polyfill
2 | SVGPathElement.prototype.getPathData&&SVGPathElement.prototype.setPathData||function(){var e={Z:"Z",M:"M",L:"L",C:"C",Q:"Q",A:"A",H:"H",V:"V",S:"S",T:"T",z:"Z",m:"m",l:"l",c:"c",q:"q",a:"a",h:"h",v:"v",s:"s",t:"t"},t=function(e){this._string=e,this._currentIndex=0,this._endIndex=this._string.length,this._prevCommand=null,this._skipOptionalSpaces()},s=-1!==window.navigator.userAgent.indexOf("MSIE ");t.prototype={parseSegment:function(){var t=this._string[this._currentIndex],s=e[t]?e[t]:null;if(null===s){if(null===this._prevCommand)return null;if(null===(s=("+"===t||"-"===t||"."===t||t>="0"&&t<="9")&&"Z"!==this._prevCommand?"M"===this._prevCommand?"L":"m"===this._prevCommand?"l":this._prevCommand:null))return null}else this._currentIndex+=1;this._prevCommand=s;var a=null,r=s.toUpperCase();return"H"===r||"V"===r?a=[this._parseNumber()]:"M"===r||"L"===r||"T"===r?a=[this._parseNumber(),this._parseNumber()]:"S"===r||"Q"===r?a=[this._parseNumber(),this._parseNumber(),this._parseNumber(),this._parseNumber()]:"C"===r?a=[this._parseNumber(),this._parseNumber(),this._parseNumber(),this._parseNumber(),this._parseNumber(),this._parseNumber()]:"A"===r?a=[this._parseNumber(),this._parseNumber(),this._parseNumber(),this._parseArcFlag(),this._parseArcFlag(),this._parseNumber(),this._parseNumber()]:"Z"===r&&(this._skipOptionalSpaces(),a=[]),null===a||a.indexOf(null)>=0?null:{type:s,values:a}},hasMoreData:function(){return this._currentIndex"9")&&"."!==this._string[this._currentIndex])return null;for(var i=this._currentIndex;this._currentIndex="0"&&this._string[this._currentIndex]<="9";)this._currentIndex+=1;if(this._currentIndex!==i)for(var l=this._currentIndex-1,h=1;l>=i;)t+=h*(this._string[l]-"0"),l-=1,h*=10;if(this._currentIndex=this._endIndex||this._string[this._currentIndex]<"0"||this._string[this._currentIndex]>"9")return null;for(;this._currentIndex="0"&&this._string[this._currentIndex]<="9";)s*=10,a+=(this._string.charAt(this._currentIndex)-"0")/s,this._currentIndex+=1}if(this._currentIndex!==u&&this._currentIndex+1=this._endIndex||this._string[this._currentIndex]<"0"||this._string[this._currentIndex]>"9")return null;for(;this._currentIndex="0"&&this._string[this._currentIndex]<="9";)e*=10,e+=this._string[this._currentIndex]-"0",this._currentIndex+=1}var v=t+a;return v*=r,e&&(v*=Math.pow(10,n*e)),u===this._currentIndex?null:(this._skipOptionalSpacesOrDelimiter(),v)},_parseArcFlag:function(){if(this._currentIndex>=this._endIndex)return null;var e=null,t=this._string[this._currentIndex];if(this._currentIndex+=1,"0"===t)e=0;else{if("1"!==t)return null;e=1}return this._skipOptionalSpacesOrDelimiter(),e}};var a=function(e){if(!e||0===e.length)return[];var s=new t(e),a=[];if(s.initialCommandIsMoveTo())for(;s.hasMoreData();){var r=s.parseSegment();if(null===r)break;a.push(r)}return a},r=SVGPathElement.prototype.setAttribute,n=SVGPathElement.prototype.removeAttribute,u=window.Symbol?Symbol():"__cachedPathData",i=window.Symbol?Symbol():"__cachedNormalizedPathData",l=function(e,t,s,a,r,n,u,i,h,v){var p,_,c,o,d,y=function(e,t,s){return{x:e*Math.cos(s)-t*Math.sin(s),y:e*Math.sin(s)+t*Math.cos(s)}},x=(p=u,Math.PI*p/180),I=[];if(v)_=v[0],c=v[1],o=v[2],d=v[3];else{var f=y(e,t,-x);e=f.x,t=f.y;var m=y(s,a,-x),g=(e-(s=m.x))/2,b=(t-(a=m.y))/2,M=g*g/(r*r)+b*b/(n*n);M>1&&(r*=M=Math.sqrt(M),n*=M);var S=r*r,V=n*n,A=S*V-S*b*b-V*g*g,P=S*b*b+V*g*g,C=(i===h?-1:1)*Math.sqrt(Math.abs(A/P));o=C*r*b/n+(e+s)/2,d=C*-n*g/r+(t+a)/2,_=Math.asin(parseFloat(((t-d)/n).toFixed(9))),c=Math.asin(parseFloat(((a-d)/n).toFixed(9))),ec&&(_-=2*Math.PI),!h&&c>_&&(c-=2*Math.PI)}var N=c-_;if(Math.abs(N)>120*Math.PI/180){var E=c,D=s,O=a;c=h&&c>_?_+120*Math.PI/180*1:_+120*Math.PI/180*-1,s=o+r*Math.cos(c),a=d+n*Math.sin(c),I=l(s,a,D,O,r,n,u,0,h,[c,E,o,d])}N=c-_;var L=Math.cos(_),G=Math.sin(_),k=Math.cos(c),T=Math.sin(c),Z=Math.tan(N/4),w=4/3*r*Z,H=4/3*n*Z,Q=[e,t],z=[e+w*G,t-H*L],F=[s+w*T,a-H*k],q=[s,a];if(z[0]=2*Q[0]-z[0],z[1]=2*Q[1]-z[1],v)return[z,F,q].concat(I);I=[z,F,q].concat(I);for(var j=[],R=0;R0&&(t+=" "),t+=n.type,n.values&&n.values.length>0&&(t+=" "+n.values.join(" "))}this.setAttribute("d",t)}},SVGRectElement.prototype.getPathData=function(e){var t=this.x.baseVal.value,s=this.y.baseVal.value,a=this.width.baseVal.value,r=this.height.baseVal.value,n=this.hasAttribute("rx")?this.rx.baseVal.value:this.ry.baseVal.value,u=this.hasAttribute("ry")?this.ry.baseVal.value:this.rx.baseVal.value;n>a/2&&(n=a/2),u>r/2&&(u=r/2);var i=[{type:"M",values:[t+n,s]},{type:"H",values:[t+a-n]},{type:"A",values:[n,u,0,0,1,t+a,s+u]},{type:"V",values:[s+r-u]},{type:"A",values:[n,u,0,0,1,t+a-n,s+r]},{type:"H",values:[t+n]},{type:"A",values:[n,u,0,0,1,t,s+r-u]},{type:"V",values:[s+u]},{type:"A",values:[n,u,0,0,1,t+n,s]},{type:"Z",values:[]}];return i=i.filter((function(e){return"A"!==e.type||0!==e.values[0]&&0!==e.values[1]})),e&&!0===e.normalize&&(i=v(i)),i},SVGCircleElement.prototype.getPathData=function(e){var t=this.cx.baseVal.value,s=this.cy.baseVal.value,a=this.r.baseVal.value,r=[{type:"M",values:[t+a,s]},{type:"A",values:[a,a,0,0,1,t,s+a]},{type:"A",values:[a,a,0,0,1,t-a,s]},{type:"A",values:[a,a,0,0,1,t,s-a]},{type:"A",values:[a,a,0,0,1,t+a,s]},{type:"Z",values:[]}];return e&&!0===e.normalize&&(r=v(r)),r},SVGEllipseElement.prototype.getPathData=function(e){var t=this.cx.baseVal.value,s=this.cy.baseVal.value,a=this.rx.baseVal.value,r=this.ry.baseVal.value,n=[{type:"M",values:[t+a,s]},{type:"A",values:[a,r,0,0,1,t,s+r]},{type:"A",values:[a,r,0,0,1,t-a,s]},{type:"A",values:[a,r,0,0,1,t,s-r]},{type:"A",values:[a,r,0,0,1,t+a,s]},{type:"Z",values:[]}];return e&&!0===e.normalize&&(n=v(n)),n},SVGLineElement.prototype.getPathData=function(){return[{type:"M",values:[this.x1.baseVal.value,this.y1.baseVal.value]},{type:"L",values:[this.x2.baseVal.value,this.y2.baseVal.value]}]},SVGPolylineElement.prototype.getPathData=function(){for(var e=[],t=0;t {
7 | element.hide();
8 | });
9 | sTool='';
10 | removeClipMakEditor(true);
11 | restoreMask();
12 | }else{
13 | sTool='panelClip';
14 | setupClipMaster();
15 | selecTool(id, 'panelClip', 'MASK OBJECT');
16 | }
17 | }
18 |
19 | function setupClipMaster(){
20 | if(sTool!='panelClip')return;
21 | removeClipMakEditor(true);
22 | var ttSel=document.querySelectorAll(".cosito.selectable").length;
23 | if(ttSel==0 || ttSel>1){
24 | visibilityForSelection("#clipMaskNO", "block");
25 | visibilityForSelection("#clipMaskOK", "none");
26 | visibilityForSelection("#maskStyles", "none");
27 | restoreMask();
28 | return;
29 | }
30 | visibilityForSelection("#clipMaskNO", "none");
31 | visibilityForSelection("#clipMaskOK", "block");
32 | visibilityForSelection("#maskStyles", "block");
33 |
34 | if(ttSel==1){
35 | var shape=document.querySelectorAll(".cosito.selectable")[0];
36 | var cp=shape.getAttributeNS(null, "clip-path");
37 |
38 | if(cp!=null){
39 | visibilityForSelection("#clipMaskApply", "block");
40 | visibilityForSelection("#clipMaskDelete", "block");
41 |
42 | var points=polyClip2Points(cp);
43 | points=points["points"];
44 | drawPolygonMask(points);
45 | drawClipMask();
46 |
47 | var mask=shape.getAttributeNS( null, "clip-path" );
48 | shape.removeAttributeNS( null, "clip-path");
49 | shape.setAttribute("masktmp", mask);
50 | }else{
51 | visibilityForSelection("#clipMaskApply", "none");
52 | visibilityForSelection("#clipMaskDelete", "none");
53 | }
54 | }
55 | }
56 |
57 | function saveClipMask(){
58 | var mask=polyPoints2Array();
59 | mask="polygon("+mask["mask"]+")";
60 |
61 | var shape=document.querySelectorAll(".cosito.selectable")[0];
62 | shape.setAttributeNS( null, "clip-path", mask );
63 | shape.removeAttribute( "masktmp");
64 |
65 | removeAllFromSelection(".polyClip");
66 | removeAllFromSelection(".polyClipPoly");
67 | visibilityForSelection("#clipMaskDelete", "block");
68 |
69 | removeClassFromSelection(".btnTool.sel", "sel");
70 | [...document.querySelectorAll(".toolPanel")].forEach((element, index, array) => {
71 | element.hide();
72 | });
73 | sTool='';
74 | console.log("guardar mascara");
75 | }
76 |
77 | function removeClipMask(){
78 | var e=document.querySelectorAll(".cosito.selectable")[0];
79 | e.removeAttributeNS( null, "clip-path");
80 | e.removeAttribute( "masktmp");
81 |
82 | removeClipMakEditor(true);
83 | visibilityForSelection("#clipMaskApply", "none");
84 | visibilityForSelection("#clipMaskDelete", "none");
85 | removeClassFromSelection(".btnTool.sel", "sel");
86 | [...document.querySelectorAll(".toolPanel")].forEach((element, index, array) => {
87 | element.hide();
88 | });
89 | sTool='';
90 | }
91 |
92 | function restoreMask(){
93 | [...document.querySelectorAll("[masktmp]")].forEach((element, index, array) => {
94 | var masktmp=element.getAttribute("masktmp");
95 | element.removeAttribute("masktmp");
96 | element.setAttributeNS(null, "clip-path", masktmp);
97 | });
98 | }
99 |
100 | function removeClipMakEditor(all){
101 | if(all==true)removeAllFromSelection(".polyClipPoly");
102 | removeAllFromSelection(".polyClip");
103 | }
104 |
105 | function polyPoints2Array(){ //polygon points to array/Mask%
106 | var shape=document.querySelectorAll(".cosito.selectable")[0];
107 | var poly=document.getElementById("polyMaskEdit");
108 |
109 | var bb=transformedBoundingBox(shape.id);
110 | var points=poly.getAttributeNS(null, "points");
111 | points=points.trim();
112 | var pointsr= points.split(' ').map(function(item) {
113 | var rt=item.trim();
114 | var sp=rt.split(',').map(function(item) { return Number(item); }) ;
115 | return sp ;
116 | });
117 | var mask='';
118 | for( var i=0; i0 ){ mask = /\(([^()]*)\)/.exec(mask); mask=mask[1]; }
136 | var e=document.querySelectorAll(".cosito.selectable")[0];
137 | var bb=transformedBoundingBox(e.id);
138 |
139 | var r=mask.split(',').map(function(item) {
140 | var rt=item.trim();
141 | rt=rt.replaceAll('%','');
142 | var p=rt.split(' ').map(function(item) { return Number(item); }) ;
143 | return p ;
144 | });
145 |
146 | var points='', pointsr=[];
147 | r.forEach(function(item, index, arr){
148 | item[0] = trunc(((item[0]/100)*bb.width)+bb.x, 2); //(0.5) x 200
149 | item[1] = trunc(((item[1]/100)*bb.height)+bb.y, 2);
150 | points+=item[0]+','+item[1]+' ';
151 | pointsr.push( [ item[0], item[1] ] );
152 | });
153 |
154 | var out={
155 | points:points,
156 | pointsr:pointsr
157 | };
158 | return out;
159 | }
160 |
161 | function drawPolygonMask(points){
162 | removeAllFromSelection(".polyClipPoly");
163 | var newID="polyMaskEdit"; // createID("polyClip");
164 | var poly=createSVGElement( "polygon", false, newID );
165 | poly.setAttribute("points", points);
166 | poly.setAttribute("class", "polyClipPoly");
167 | poly.setAttribute("fill", "url(#patternBool)");
168 | poly.setAttribute("style", "pointer-events:none;");
169 | _hnd['svgHandler'].appendChild( poly );
170 | return poly;
171 | }
172 |
173 | function applyClipMask(event){ //click boton selector de mascaras preset
174 | var mask=event.target.getAttribute("st");
175 | var points=polyClip2Points(mask);
176 | points=points["points"];
177 |
178 | drawPolygonMask(points);
179 | drawClipMask();
180 | visibilityForSelection("#clipMaskApply", "block");
181 | var cp=document.querySelectorAll(".cosito.selectable")[0].getAttributeNS(null, "clip-path");
182 | if(cp!=null && cp.length>8){
183 | visibilityForSelection("#clipMaskDelete", "block");
184 | }else{
185 | visibilityForSelection("#clipMaskDelete", "none");
186 | }
187 | }
188 |
189 | function drawClipMask(){
190 | removeAllFromSelection(".polyClip");
191 | var mask=polyPoints2Array();
192 | mask=mask["mask"];
193 |
194 | var pts=polyClip2Points(mask);
195 | var pointsr=pts['pointsr'];
196 |
197 | var upoint;
198 | pointsr.forEach(function(item, index, arr){
199 | if(index==0){
200 | upoint=[ item[0], item[1] ];
201 | }else{
202 | drawLineClip(upoint[0], upoint[1], item[0], item[1], index-1, index);
203 | upoint=[ item[0], item[1] ];
204 | }
205 | });
206 | drawLineClip(upoint[0], upoint[1], pointsr[0][0], pointsr[0][1], pointsr.length-1, 0 );
207 |
208 | pointsr.forEach(function(item, index, arr){
209 | drawPointClip(item[0], item[1], index );
210 | });
211 |
212 | function drawLineClip(x1, y1, x2, y2, point1, point2){
213 | var idLine=createID("lineClip");
214 | var segment=createSVGElement( "line", false, idLine );
215 | segment.setAttribute("x1", x1 );
216 | segment.setAttribute("y1", y1 );
217 | segment.setAttribute("x2", x2 );
218 | segment.setAttribute("y2", y2 );
219 | segment.setAttribute("point1", point1 );
220 | segment.setAttribute("point2", point2 );
221 | segment.setAttribute("class", "polyClip line");
222 | segment.setAttribute("DblClick", "addNodePolyClip" );
223 | segment.setAttribute("style", "stroke-linecap:round;stroke-linejoin:round;stroke:black;stroke-width:0.75%;cursor:crosshair;" );
224 | _hnd['svgHandler'].appendChild( segment );
225 | }
226 |
227 | function drawPointClip(x,y, pos){
228 | var idNode=createID("nodeClip");
229 | var nodo=bolita(x,y, "0.5rem", "red");
230 | nodo.setAttribute("class", "polyClip node");
231 | nodo.setAttribute("id", idNode);
232 | nodo.setAttribute("pos", pos);
233 | nodo.setAttribute("MouseDown", "updateNodePolyClip");
234 | _hnd['svgHandler'].appendChild( nodo );
235 | }
236 | }
237 |
238 | function updateNodePolyClip(evt){
239 | var poly=document.getElementById("polyMaskEdit");
240 | var pointsr=polyPoints2Array();
241 | pointsr=pointsr["pointsr"];
242 |
243 | document.onmousemove=function(){
244 | evt.target.setAttributeNS(null, "cx", _evtMsg['mousePOS']['x']);
245 | evt.target.setAttributeNS(null, "cy", _evtMsg['mousePOS']['y']);
246 | var pos=evt.target.getAttribute("pos");
247 | pointsr[pos][0]=_evtMsg['mousePOS']['x'];
248 | pointsr[pos][1]=_evtMsg['mousePOS']['y'];
249 | var pointsOK= pointsr.join( ' ' );
250 | poly.setAttributeNS(null, "points", pointsOK);
251 | setAttributeForSelection("line.polyClip[point1='"+pos+"']", "x1", _evtMsg['mousePOS']['x'] );
252 | setAttributeForSelection("line.polyClip[point1='"+pos+"']", "y1", _evtMsg['mousePOS']['y'] );
253 | setAttributeForSelection("line.polyClip[point2='"+pos+"']", "x2", _evtMsg['mousePOS']['x'] );
254 | setAttributeForSelection("line.polyClip[point2='"+pos+"']", "y2", _evtMsg['mousePOS']['y'] );
255 | };
256 | document.onmouseup=function(){
257 | document.onmousemove=null;
258 | document.onmouseup=null;
259 | };
260 | }
261 |
262 | function addNodePolyClip(evt){
263 | var line=evt.target;
264 | var p1=line.getAttribute("point1");
265 | var p2=line.getAttribute("point2");
266 |
267 | var poly=document.getElementById("polyMaskEdit");
268 | var pointsr=polyPoints2Array();
269 | pointsr=pointsr["pointsr"];
270 | var point=[ _evtMsg['mousePOS']['x'], _evtMsg['mousePOS']['y'] ];
271 |
272 | if( p2>p1 ){
273 | pointsr.insert( p2, point );
274 | }else{
275 | pointsr.push( point );
276 | }
277 | var pointsOK= pointsr.join( ' ' );
278 | poly.setAttributeNS(null, "points", pointsOK);
279 |
280 | drawClipMask();
281 | }
282 |
283 |
--------------------------------------------------------------------------------
/js/rough.js:
--------------------------------------------------------------------------------
1 | var rough=function(){"use strict";function t(t,e,s){if(t&&t.length){const[n,a]=e,o=Math.PI/180*s,h=Math.cos(o),r=Math.sin(o);t.forEach((t=>{const[e,s]=t;t[0]=(e-n)*h-(s-a)*r+n,t[1]=(e-n)*r+(s-a)*h+a}))}}function e(t){const e=t[0],s=t[1];return Math.sqrt(Math.pow(e[0]-s[0],2)+Math.pow(e[1]-s[1],2))}function s(e,s){const n=s.hachureAngle+90;let a=s.hachureGap;a<0&&(a=4*s.strokeWidth),a=Math.max(a,.1);const o=[0,0];if(n)for(const s of e)t(s,o,n);const h=function(t,e){const s=[];for(const e of t){const t=[...e];t[0].join(",")!==t[t.length-1].join(",")&&t.push([t[0][0],t[0][1]]),t.length>2&&s.push(t)}const n=[];e=Math.max(e,.1);const a=[];for(const t of s)for(let e=0;et.ymine.ymin?1:t.xe.x?1:t.ymax===e.ymax?0:(t.ymax-e.ymax)/Math.abs(t.ymax-e.ymax))),!a.length)return n;let o=[],h=a[0].ymin;for(;o.length||a.length;){if(a.length){let t=-1;for(let e=0;eh);e++)t=e;a.splice(0,t+1).forEach((t=>{o.push({s:h,edge:t})}))}if(o=o.filter((t=>!(t.edge.ymax<=h))),o.sort(((t,e)=>t.edge.x===e.edge.x?0:(t.edge.x-e.edge.x)/Math.abs(t.edge.x-e.edge.x))),o.length>1)for(let t=0;t=o.length)break;const s=o[t].edge,a=o[e].edge;n.push([[Math.round(s.x),h],[Math.round(a.x),h]])}h+=e,o.forEach((t=>{t.edge.x=t.edge.x+e*t.edge.islope}))}return n}(e,a);if(n){for(const s of e)t(s,o,-n);!function(e,s,n){const a=[];e.forEach((t=>a.push(...t))),t(a,s,n)}(h,o,-n)}return h}class n{constructor(t){this.helper=t}fillPolygons(t,e){return this._fillPolygons(t,e)}_fillPolygons(t,e){const n=s(t,e);return{type:"fillSketch",ops:this.renderLines(n,e)}}renderLines(t,e){const s=[];for(const n of t)s.push(...this.helper.doubleLineOps(n[0][0],n[0][1],n[1][0],n[1][1],e));return s}}class a extends n{fillPolygons(t,n){let a=n.hachureGap;a<0&&(a=4*n.strokeWidth),a=Math.max(a,.1);const o=s(t,Object.assign({},n,{hachureGap:a})),h=Math.PI/180*n.hachureAngle,r=[],i=.5*a*Math.cos(h),c=.5*a*Math.sin(h);for(const[t,s]of o)e([t,s])&&r.push([[t[0]-i,t[1]+c],[...s]],[[t[0]+i,t[1]-c],[...s]]);return{type:"fillSketch",ops:this.renderLines(r,n)}}}class o extends n{fillPolygons(t,e){const s=this._fillPolygons(t,e),n=Object.assign({},e,{hachureAngle:e.hachureAngle+90}),a=this._fillPolygons(t,n);return s.ops=s.ops.concat(a.ops),s}}class h{constructor(t){this.helper=t}fillPolygons(t,e){const n=s(t,e=Object.assign({},e,{hachureAngle:0}));return this.dotsOnLines(n,e)}dotsOnLines(t,s){const n=[];let a=s.hachureGap;a<0&&(a=4*s.strokeWidth),a=Math.max(a,.1);let o=s.fillWeight;o<0&&(o=s.strokeWidth/2);const h=a/4;for(const r of t){const t=e(r),i=t/a,c=Math.ceil(i)-1,l=t-c*a,u=(r[0][0]+r[1][0])/2-a/4,p=Math.min(r[0][1],r[1][1]);for(let t=0;t{const h=e(t),r=Math.floor(h/(n+a)),i=(h+a-r*(n+a))/2;let c=t[0],l=t[1];c[0]>l[0]&&(c=t[1],l=t[0]);const u=Math.atan((l[1]-c[1])/(l[0]-c[0]));for(let t=0;t{const o=e(t),h=Math.round(o/(2*s));let r=t[0],i=t[1];r[0]>i[0]&&(r=t[1],i=t[0]);const c=Math.atan((i[1]-r[1])/(i[0]-r[0]));for(let t=0;tn%2?t+s:t+e));o.push({key:"C",data:t}),e=t[4],s=t[5];break}case"Q":o.push({key:"Q",data:[...r]}),e=r[2],s=r[3];break;case"q":{const t=r.map(((t,n)=>n%2?t+s:t+e));o.push({key:"Q",data:t}),e=t[2],s=t[3];break}case"A":o.push({key:"A",data:[...r]}),e=r[5],s=r[6];break;case"a":e+=r[5],s+=r[6],o.push({key:"A",data:[r[0],r[1],r[2],r[3],r[4],e,s]});break;case"H":o.push({key:"H",data:[...r]}),e=r[0];break;case"h":e+=r[0],o.push({key:"H",data:[e]});break;case"V":o.push({key:"V",data:[...r]}),s=r[0];break;case"v":s+=r[0],o.push({key:"V",data:[s]});break;case"S":o.push({key:"S",data:[...r]}),e=r[2],s=r[3];break;case"s":{const t=r.map(((t,n)=>n%2?t+s:t+e));o.push({key:"S",data:t}),e=t[2],s=t[3];break}case"T":o.push({key:"T",data:[...r]}),e=r[0],s=r[1];break;case"t":e+=r[0],s+=r[1],o.push({key:"T",data:[e,s]});break;case"Z":case"z":o.push({key:"Z",data:[]}),e=n,s=a}return o}function g(t){const e=[];let s="",n=0,a=0,o=0,h=0,r=0,i=0;for(const{key:c,data:l}of t){switch(c){case"M":e.push({key:"M",data:[...l]}),[n,a]=l,[o,h]=l;break;case"C":e.push({key:"C",data:[...l]}),n=l[4],a=l[5],r=l[2],i=l[3];break;case"L":e.push({key:"L",data:[...l]}),[n,a]=l;break;case"H":n=l[0],e.push({key:"L",data:[n,a]});break;case"V":a=l[0],e.push({key:"L",data:[n,a]});break;case"S":{let t=0,o=0;"C"===s||"S"===s?(t=n+(n-r),o=a+(a-i)):(t=n,o=a),e.push({key:"C",data:[t,o,...l]}),r=l[0],i=l[1],n=l[2],a=l[3];break}case"T":{const[t,o]=l;let h=0,c=0;"Q"===s||"T"===s?(h=n+(n-r),c=a+(a-i)):(h=n,c=a);const u=n+2*(h-n)/3,p=a+2*(c-a)/3,f=t+2*(h-t)/3,d=o+2*(c-o)/3;e.push({key:"C",data:[u,p,f,d,t,o]}),r=h,i=c,n=t,a=o;break}case"Q":{const[t,s,o,h]=l,c=n+2*(t-n)/3,u=a+2*(s-a)/3,p=o+2*(t-o)/3,f=h+2*(s-h)/3;e.push({key:"C",data:[c,u,p,f,o,h]}),r=t,i=s,n=o,a=h;break}case"A":{const t=Math.abs(l[0]),s=Math.abs(l[1]),o=l[2],h=l[3],r=l[4],i=l[5],c=l[6];if(0===t||0===s)e.push({key:"C",data:[n,a,i,c,i,c]}),n=i,a=c;else if(n!==i||a!==c){k(n,a,i,c,t,s,o,h,r).forEach((function(t){e.push({key:"C",data:t})})),n=i,a=c}break}case"Z":e.push({key:"Z",data:[]}),n=o,a=h}s=c}return e}function M(t,e,s){return[t*Math.cos(s)-e*Math.sin(s),t*Math.sin(s)+e*Math.cos(s)]}function k(t,e,s,n,a,o,h,r,i,c){const l=(u=h,Math.PI*u/180);var u;let p=[],f=0,d=0,g=0,b=0;if(c)[f,d,g,b]=c;else{[t,e]=M(t,e,-l),[s,n]=M(s,n,-l);const h=(t-s)/2,c=(e-n)/2;let u=h*h/(a*a)+c*c/(o*o);u>1&&(u=Math.sqrt(u),a*=u,o*=u);const p=a*a,k=o*o,y=p*k-p*c*c-k*h*h,m=p*c*c+k*h*h,w=(r===i?-1:1)*Math.sqrt(Math.abs(y/m));g=w*a*c/o+(t+s)/2,b=w*-o*h/a+(e+n)/2,f=Math.asin(parseFloat(((e-b)/o).toFixed(9))),d=Math.asin(parseFloat(((n-b)/o).toFixed(9))),td&&(f-=2*Math.PI),!i&&d>f&&(d-=2*Math.PI)}let y=d-f;if(Math.abs(y)>120*Math.PI/180){const t=d,e=s,r=n;d=i&&d>f?f+120*Math.PI/180*1:f+120*Math.PI/180*-1,p=k(s=g+a*Math.cos(d),n=b+o*Math.sin(d),e,r,a,o,h,0,i,[d,t,g,b])}y=d-f;const m=Math.cos(f),w=Math.sin(f),x=Math.cos(d),P=Math.sin(d),v=Math.tan(y/4),O=4/3*a*v,S=4/3*o*v,L=[t,e],T=[t+O*w,e-S*m],D=[s+O*P,n-S*x],A=[s,n];if(T[0]=2*L[0]-T[0],T[1]=2*L[1]-T[1],c)return[T,D,A].concat(p);{p=[T,D,A].concat(p);const t=[];for(let e=0;e2){const a=[];for(let e=0;e2*Math.PI&&(f=0,d=2*Math.PI);const g=2*Math.PI/i.curveStepCount,M=Math.min(g/2,(d-f)/2),k=E(M,c,l,u,p,f,d,1,i);if(!i.disableMultiStroke){const t=E(M,c,l,u,p,f,d,1.5,i);k.push(...t)}return h&&(r?k.push(...I(c,l,c+u*Math.cos(f),l+p*Math.sin(f),i),...I(c,l,c+u*Math.cos(d),l+p*Math.sin(d),i)):k.push({op:"lineTo",data:[c,l]},{op:"lineTo",data:[c+u*Math.cos(f),l+p*Math.sin(f)]})),{type:"path",ops:k}}function S(t,e){const s=[];for(const n of t)if(n.length){const t=e.maxRandomnessOffset||0,a=n.length;if(a>2){s.push({op:"move",data:[n[0][0]+A(t,e),n[0][1]+A(t,e)]});for(let o=1;o500?.4:-.0016668*i+1.233334;let l=a.maxRandomnessOffset||0;l*l*100>r&&(l=i/10);const u=l/2,p=.2+.2*T(a);let f=a.bowing*a.maxRandomnessOffset*(n-e)/200,d=a.bowing*a.maxRandomnessOffset*(t-s)/200;f=A(f,a,c),d=A(d,a,c);const g=[],M=()=>A(u,a,c),k=()=>A(l,a,c),b=a.preserveVertices;return o&&(h?g.push({op:"move",data:[t+(b?0:M()),e+(b?0:M())]}):g.push({op:"move",data:[t+(b?0:A(l,a,c)),e+(b?0:A(l,a,c))]})),h?g.push({op:"bcurveTo",data:[f+t+(s-t)*p+M(),d+e+(n-e)*p+M(),f+t+2*(s-t)*p+M(),d+e+2*(n-e)*p+M(),s+(b?0:M()),n+(b?0:M())]}):g.push({op:"bcurveTo",data:[f+t+(s-t)*p+k(),d+e+(n-e)*p+k(),f+t+2*(s-t)*p+k(),d+e+2*(n-e)*p+k(),s+(b?0:k()),n+(b?0:k())]}),g}function _(t,e,s){const n=[];n.push([t[0][0]+A(e,s),t[0][1]+A(e,s)]),n.push([t[0][0]+A(e,s),t[0][1]+A(e,s)]);for(let a=1;a3){const o=[],h=1-s.curveTightness;a.push({op:"move",data:[t[1][0],t[1][1]]});for(let e=1;e+21&&a.push(s)}else a.push(s);a.push(t[e+3])}else{const n=.5,o=t[e+0],h=t[e+1],r=t[e+2],i=t[e+3],c=j(o,h,n),l=j(h,r,n),u=j(r,i,n),p=j(c,l,n),f=j(l,u,n),d=j(p,f,n);F([o,c,p,d],0,s,a),F([d,f,u,i],0,s,a)}var o,h;return a}function V(t,e){return Z(t,0,t.length,e)}function Z(t,e,s,n,a){const o=a||[],h=t[e],r=t[s-1];let i=0,c=1;for(let n=e+1;ni&&(i=e,c=n)}return Math.sqrt(i)>n?(Z(t,e,c+1,n,o),Z(t,c,s,n,o)):(o.length||o.push(h),o.push(r)),o}function Q(t,e=.15,s){const n=[],a=(t.length-1)/3;for(let s=0;s0?Z(n,0,n.length,s):n}const H="none";class N{constructor(t){this.defaultOptions={maxRandomnessOffset:2,roughness:1,bowing:1,stroke:"#000",strokeWidth:1,curveTightness:0,curveFitting:.95,curveStepCount:9,fillStyle:"hachure",fillWeight:-1,hachureAngle:-41,hachureGap:-1,dashOffset:-1,dashGap:-1,zigzagOffset:-1,seed:0,disableMultiStroke:!1,disableMultiStrokeFill:!1,preserveVertices:!1},this.config=t||{},this.config.options&&(this.defaultOptions=this._o(this.config.options))}static newSeed(){return Math.floor(Math.random()*2**31)}_o(t){return t?Object.assign({},this.defaultOptions,t):this.defaultOptions}_d(t,e,s){return{shape:t,sets:e||[],options:s||this.defaultOptions}}line(t,e,s,n,a){const o=this._o(a);return this._d("line",[y(t,e,s,n,o)],o)}rectangle(t,e,s,n,a){const o=this._o(a),h=[],r=w(t,e,s,n,o);if(o.fill){const a=[[t,e],[t+s,e],[t+s,e+n],[t,e+n]];"solid"===o.fillStyle?h.push(S([a],o)):h.push(L([a],o))}return o.stroke!==H&&h.push(r),this._d("rectangle",h,o)}ellipse(t,e,s,n,a){const o=this._o(a),h=[],r=P(s,n,o),i=v(t,e,o,r);if(o.fill)if("solid"===o.fillStyle){const s=v(t,e,o,r).opset;s.type="fillPath",h.push(s)}else h.push(L([i.estimatedPoints],o));return o.stroke!==H&&h.push(i.opset),this._d("ellipse",h,o)}circle(t,e,s,n){const a=this.ellipse(t,e,s,s,n);return a.shape="circle",a}linearPath(t,e){const s=this._o(e);return this._d("linearPath",[m(t,!1,s)],s)}arc(t,e,s,n,a,o,h=!1,r){const i=this._o(r),c=[],l=O(t,e,s,n,a,o,h,!0,i);if(h&&i.fill)if("solid"===i.fillStyle){const h=Object.assign({},i);h.disableMultiStroke=!0;const r=O(t,e,s,n,a,o,!0,!1,h);r.type="fillPath",c.push(r)}else c.push(function(t,e,s,n,a,o,h){const r=t,i=e;let c=Math.abs(s/2),l=Math.abs(n/2);c+=A(.01*c,h),l+=A(.01*l,h);let u=a,p=o;for(;u<0;)u+=2*Math.PI,p+=2*Math.PI;p-u>2*Math.PI&&(u=0,p=2*Math.PI);const f=(p-u)/h.curveStepCount,d=[];for(let t=u;t<=p;t+=f)d.push([r+c*Math.cos(t),i+l*Math.sin(t)]);return d.push([r+c*Math.cos(p),i+l*Math.sin(p)]),d.push([r,i]),L([d],h)}(t,e,s,n,a,o,i));return i.stroke!==H&&c.push(l),this._d("arc",c,i)}curve(t,e){const s=this._o(e),n=[],a=x(t,s);if(s.fill&&s.fill!==H&&t.length>=3){const e=Q(function(t,e=0){const s=t.length;if(s<3)throw new Error("A curve must have at least three points.");const n=[];if(3===s)n.push(G(t[0]),G(t[1]),G(t[2]),G(t[2]));else{const s=[];s.push(t[0],t[0]);for(let e=1;e{r.length>=4&&o.push(...Q(r,e)),r=[]},c=()=>{i(),o.length&&(a.push(o),o=[])};for(const{key:t,data:e}of n)switch(t){case"M":c(),h=[e[0],e[1]],o.push(h);break;case"L":i(),o.push([e[0],e[1]]);break;case"C":if(!r.length){const t=o.length?o[o.length-1]:h;r.push([t[0],t[1]])}r.push([e[0],e[1]]),r.push([e[2],e[3]]),r.push([e[4],e[5]]);break;case"Z":i(),o.push([h[0],h[1]])}if(c(),!s)return a;const l=[];for(const t of a){const e=V(t,s);e.length&&l.push(e)}return l}(t,1,h?4-4*s.simplification:(1+s.roughness)/2);return a&&("solid"===s.fillStyle?n.push(S(r,s)):n.push(L(r,s))),o&&(h?r.forEach((t=>{n.push(m(t,!1,s))})):n.push(function(t,e){const s=g(d(f(t))),n=[];let a=[0,0],o=[0,0];for(const{key:t,data:h}of s)switch(t){case"M":{const t=1*(e.maxRandomnessOffset||0),s=e.preserveVertices;n.push({op:"move",data:h.map((n=>n+(s?0:A(t,e))))}),o=[h[0],h[1]],a=[h[0],h[1]];break}case"L":n.push(...I(o[0],o[1],h[0],h[1],e)),o=[h[0],h[1]];break;case"C":{const[t,s,a,r,i,c]=h;n.push(...$(t,s,a,r,i,c,o,e)),o=[i,c];break}case"Z":n.push(...I(o[0],o[1],a[0],a[1],e)),o=[a[0],a[1]]}return{type:"path",ops:n}}(t,s))),this._d("path",n,s)}opsToPath(t,e){let s="";for(const n of t.ops){const t="number"==typeof e&&e>=0?n.data.map((t=>+t.toFixed(e))):n.data;switch(n.op){case"move":s+=`M${t[0]} ${t[1]} `;break;case"bcurveTo":s+=`C${t[0]} ${t[1]}, ${t[2]} ${t[3]}, ${t[4]} ${t[5]} `;break;case"lineTo":s+=`L${t[0]} ${t[1]} `}}return s.trim()}toPaths(t){const e=t.sets||[],s=t.options||this.defaultOptions,n=[];for(const t of e){let e=null;switch(t.type){case"path":e={d:this.opsToPath(t),stroke:s.stroke,strokeWidth:s.strokeWidth,fill:H};break;case"fillPath":e={d:this.opsToPath(t),stroke:H,strokeWidth:0,fill:s.fill||H};break;case"fillSketch":e=this.fillSketch(t,s)}e&&n.push(e)}return n}fillSketch(t,e){let s=e.fillWeight;return s<0&&(s=e.strokeWidth/2),{d:this.opsToPath(t),stroke:e.fill||H,strokeWidth:s,fill:H}}}class B{constructor(t,e){this.canvas=t,this.ctx=this.canvas.getContext("2d"),this.gen=new N(e)}draw(t){const e=t.sets||[],s=t.options||this.getDefaultOptions(),n=this.ctx,a=t.options.fixedDecimalPlaceDigits;for(const o of e)switch(o.type){case"path":n.save(),n.strokeStyle="none"===s.stroke?"transparent":s.stroke,n.lineWidth=s.strokeWidth,s.strokeLineDash&&n.setLineDash(s.strokeLineDash),s.strokeLineDashOffset&&(n.lineDashOffset=s.strokeLineDashOffset),this._drawToContext(n,o,a),n.restore();break;case"fillPath":{n.save(),n.fillStyle=s.fill||"";const e="curve"===t.shape||"polygon"===t.shape||"path"===t.shape?"evenodd":"nonzero";this._drawToContext(n,o,a,e),n.restore();break}case"fillSketch":this.fillSketch(n,o,s)}}fillSketch(t,e,s){let n=s.fillWeight;n<0&&(n=s.strokeWidth/2),t.save(),s.fillLineDash&&t.setLineDash(s.fillLineDash),s.fillLineDashOffset&&(t.lineDashOffset=s.fillLineDashOffset),t.strokeStyle=s.fill||"",t.lineWidth=n,this._drawToContext(t,e,s.fixedDecimalPlaceDigits),t.restore()}_drawToContext(t,e,s,n="nonzero"){t.beginPath();for(const n of e.ops){const e="number"==typeof s&&s>=0?n.data.map((t=>+t.toFixed(s))):n.data;switch(n.op){case"move":t.moveTo(e[0],e[1]);break;case"bcurveTo":t.bezierCurveTo(e[0],e[1],e[2],e[3],e[4],e[5]);break;case"lineTo":t.lineTo(e[0],e[1])}}"fillPath"===e.type?t.fill(n):t.stroke()}get generator(){return this.gen}getDefaultOptions(){return this.gen.defaultOptions}line(t,e,s,n,a){const o=this.gen.line(t,e,s,n,a);return this.draw(o),o}rectangle(t,e,s,n,a){const o=this.gen.rectangle(t,e,s,n,a);return this.draw(o),o}ellipse(t,e,s,n,a){const o=this.gen.ellipse(t,e,s,n,a);return this.draw(o),o}circle(t,e,s,n){const a=this.gen.circle(t,e,s,n);return this.draw(a),a}linearPath(t,e){const s=this.gen.linearPath(t,e);return this.draw(s),s}polygon(t,e){const s=this.gen.polygon(t,e);return this.draw(s),s}arc(t,e,s,n,a,o,h=!1,r){const i=this.gen.arc(t,e,s,n,a,o,h,r);return this.draw(i),i}curve(t,e){const s=this.gen.curve(t,e);return this.draw(s),s}path(t,e){const s=this.gen.path(t,e);return this.draw(s),s}}const J="http://www.w3.org/2000/svg";class K{constructor(t,e){this.svg=t,this.gen=new N(e)}draw(t){const e=t.sets||[],s=t.options||this.getDefaultOptions(),n=this.svg.ownerDocument||window.document,a=n.createElementNS(J,"g"),o=t.options.fixedDecimalPlaceDigits;for(const h of e){let e=null;switch(h.type){case"path":e=n.createElementNS(J,"path"),e.setAttribute("d",this.opsToPath(h,o)),e.setAttribute("stroke",s.stroke),e.setAttribute("stroke-width",s.strokeWidth+""),e.setAttribute("fill","none"),s.strokeLineDash&&e.setAttribute("stroke-dasharray",s.strokeLineDash.join(" ").trim()),s.strokeLineDashOffset&&e.setAttribute("stroke-dashoffset",`${s.strokeLineDashOffset}`);break;case"fillPath":e=n.createElementNS(J,"path"),e.setAttribute("d",this.opsToPath(h,o)),e.setAttribute("stroke","none"),e.setAttribute("stroke-width","0"),e.setAttribute("fill",s.fill||""),"curve"!==t.shape&&"polygon"!==t.shape||e.setAttribute("fill-rule","evenodd");break;case"fillSketch":e=this.fillSketch(n,h,s)}e&&a.appendChild(e)}return a}fillSketch(t,e,s){let n=s.fillWeight;n<0&&(n=s.strokeWidth/2);const a=t.createElementNS(J,"path");return a.setAttribute("d",this.opsToPath(e,s.fixedDecimalPlaceDigits)),a.setAttribute("stroke",s.fill||""),a.setAttribute("stroke-width",n+""),a.setAttribute("fill","none"),s.fillLineDash&&a.setAttribute("stroke-dasharray",s.fillLineDash.join(" ").trim()),s.fillLineDashOffset&&a.setAttribute("stroke-dashoffset",`${s.fillLineDashOffset}`),a}get generator(){return this.gen}getDefaultOptions(){return this.gen.defaultOptions}opsToPath(t,e){return this.gen.opsToPath(t,e)}line(t,e,s,n,a){const o=this.gen.line(t,e,s,n,a);return this.draw(o)}rectangle(t,e,s,n,a){const o=this.gen.rectangle(t,e,s,n,a);return this.draw(o)}ellipse(t,e,s,n,a){const o=this.gen.ellipse(t,e,s,n,a);return this.draw(o)}circle(t,e,s,n){const a=this.gen.circle(t,e,s,n);return this.draw(a)}linearPath(t,e){const s=this.gen.linearPath(t,e);return this.draw(s)}polygon(t,e){const s=this.gen.polygon(t,e);return this.draw(s)}arc(t,e,s,n,a,o,h=!1,r){const i=this.gen.arc(t,e,s,n,a,o,h,r);return this.draw(i)}curve(t,e){const s=this.gen.curve(t,e);return this.draw(s)}path(t,e){const s=this.gen.path(t,e);return this.draw(s)}}return{canvas:(t,e)=>new B(t,e),svg:(t,e)=>new K(t,e),generator:t=>new N(t),newSeed:()=>N.newSeed()}}();
2 |
--------------------------------------------------------------------------------
/tools.html:
--------------------------------------------------------------------------------
1 | # ArtDraw
2 | ## Available Design Tools
3 |
4 |
5 |
--------------------------------------------------------------------------------