vectorizer.ai

vectorizer.ai free download

目前为 2024-06-08 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name vectorizer.ai
  3. // @version 0.0.1
  4. // @description vectorizer.ai free download
  5. // @icon https://d1j8j7mb8gx2ao.cloudfront.net/p/assets/logos/vectorizer-ai-logo_1c2b7a3ae82c1def79ab4c0e9cc83bcc.svg
  6.  
  7. // @author ml98
  8. // @namespace http://tampermonkey.net/
  9. // @license MIT
  10.  
  11. // @match https://vectorizer.ai/images/*
  12. // @grant none
  13. // @run-at document-start
  14. // ==/UserScript==
  15.  
  16. let state = 0;
  17. let data = { width: 1, height: 1, curves: [], style: {} };
  18.  
  19. function proxy_functions(object, apply = (f, _this, args) => f.apply(_this, args)) {
  20. const descriptors = Object.getOwnPropertyDescriptors(object);
  21. Object.keys(descriptors).filter(
  22. (name) => descriptors[name].value instanceof Function
  23. ).forEach((f) => {
  24. object[f] = new Proxy(object[f], { apply });
  25. });
  26. }
  27.  
  28. function path2svg(name, args) {
  29. switch (name) {
  30. case "moveTo": {
  31. let [x, y] = args;
  32. return `M${x} ${y}`;
  33. }
  34. case "lineTo": {
  35. let [x, y] = args;
  36. return `L${x} ${y}`;
  37. }
  38. case "ellipse": {
  39. let [cx, cy, rx, ry, rotation, theta1, theta2, ccw] = args;
  40. let dx = rx * Math.cos(theta2), dy = ry * Math.sin(theta2);
  41. let c = Math.cos(rotation), s = Math.sin(rotation);
  42. let ex= cx + c * dx - s * dy, ey = cy + s * dx + c * dy;
  43. let angle = rotation * (180 / Math.PI);
  44. let large_arc = (theta2 - theta1) % (2 * Math.PI) > Math.PI ? 1 : 0;
  45. let sweep = ccw ? 0 : 1;
  46. return `A${rx} ${ry} ${angle} ${large_arc} ${sweep} ${ex} ${ey}`;
  47. }
  48. case "bezierCurveTo": {
  49. let [cp1x, cp1y, cp2x, cp2y, x, y] = args;
  50. return `C${cp1x} ${cp1y} ${cp2x} ${cp2y} ${x} ${y}`;
  51. }
  52. case "quadraticCurveTo": {
  53. let [cpx, cpy, x, y] = args;
  54. return `Q${cpx} ${cpy} ${x} ${y}`;
  55. }
  56. case "closePath": {
  57. return `Z`;
  58. }
  59. default: {
  60. // throw new Error("unimplemented path", name);
  61. return ``;
  62. }
  63. }
  64. }
  65.  
  66. proxy_functions(Path2D.prototype, (f, _this, args) => {
  67. _this.s ??= "";
  68. // _this.s += `${f.name}[${args.toString()}] `;
  69. _this.s += path2svg(f.name, args);
  70. return f.apply(_this, args);
  71. });
  72.  
  73. proxy_functions(CanvasRenderingContext2D.prototype, (f, _this, args) => {
  74. if(_this.canvas.id) {
  75. // width, height
  76. }
  77. if(!_this.canvas.id) {
  78. switch(f.name) {
  79. case 'drawImage':
  80. if(state == 0) {
  81. data.width = args[3];
  82. data.height = args[4];
  83. state = 1;
  84. }
  85. break;
  86. case 'clip':
  87. if(state == 1) {
  88. // console.log(_this.lineWidth, _this.lineJoin);
  89. data.curves = [];
  90. data.style = { lineWidth: _this.lineWidth, lineJoin: _this.lineJoin };
  91. state = 2;
  92. }
  93. break;
  94. case 'fill':
  95. if(state == 2) {
  96. // console.log(f.name, _this.fillStyle, args[0].s);
  97. if(!args[0].s) {
  98. state = 1;
  99. }
  100. data.curves.push({fill: _this.fillStyle, d: args[0].s});
  101. }
  102. break;
  103. case 'stroke':
  104. if(state == 2) {
  105. // console.log(f.name, _this.strokeStyle, args[0].s);
  106. if(!args[0].s) {
  107. state = 1;
  108. }
  109. data.curves.push({stroke: _this.strokeStyle, d: args[0].s});
  110. }
  111. break;
  112. case 'restore':
  113. if(state == 2) {
  114. state = 3;
  115. console.log(data);
  116. create_download_button();
  117. }
  118. break;
  119. }
  120. }
  121. return f.apply(_this, args);
  122. });
  123.  
  124. function svg_element(tag, attributes) {
  125. const element = document.createElementNS('http://www.w3.org/2000/svg', tag);
  126. for (let attr in attributes) {
  127. element.setAttribute(attr, attributes[attr]);
  128. }
  129. return element;
  130. }
  131.  
  132. function create_svg() {
  133. const { width, height, curves, style } = data;
  134. const svg = svg_element('svg', {
  135. xmlns: 'http://www.w3.org/2000/svg',
  136. viewBox: `0 0 ${width} ${height}`,
  137. width,
  138. height,
  139. });
  140.  
  141. curves.forEach(({d, fill, stroke}) => {
  142. const path = fill ? {d, fill, stroke: fill} : {d, stroke};
  143. const element = svg_element('path', path);
  144. svg.appendChild(element);
  145. });
  146.  
  147. return svg;
  148. }
  149.  
  150. function create_download_button() {
  151. const svg = create_svg();
  152. const content = new XMLSerializer().serializeToString(svg);
  153. const type = 'image/svg+xml';
  154. const url = URL.createObjectURL(new Blob([content], {type}));
  155.  
  156. const button = document.querySelector('#App-DownloadLink');
  157. const a = button.cloneNode(true);
  158. button.before(a);
  159. a.style.borderRadius = 0;
  160. a.querySelector('.showPaid').style.display = 'none';
  161. a.querySelector('.showFree').style.display = 'inline';
  162. a.href = url;
  163. a.target = '_blank';
  164. a.download = 'result.svg';
  165. }