diff --git a/docs/0.bootstrap.js b/docs/0.bootstrap.js index cc91e5e..7496600 100644 --- a/docs/0.bootstrap.js +++ b/docs/0.bootstrap.js @@ -43,7 +43,7 @@ eval("\"use strict\";\n// Instantiate WebAssembly module\nvar wasmExports = __we /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var vtracer__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vtracer */ \"../pkg/vtracer_webapp.js\");\n\n\nlet runner;\nconst canvas = document.getElementById('frame');\nconst ctx = canvas.getContext('2d');\nconst svg = document.getElementById('svg');\nconst img = new Image();\nconst progress = document.getElementById('progressbar');\nconst progressregion = document.getElementById('progressregion');\nlet mode = 'spline', clustering_mode = 'color';\n\n// Hide canas and svg on load\ncanvas.style.display = 'none';\nsvg.style.display = 'none';\n\n// Paste from clipboard\ndocument.addEventListener('paste', function (e) {\n\tif (e.clipboardData) {\n\t\tvar items = e.clipboardData.items;\n\t\tif (!items) return;\n\n\t\t//access data directly\n\t\tfor (var i = 0; i < items.length; i++) {\n\t\t\tif (items[i].type.indexOf(\"image\") !== -1) {\n\t\t\t\t//image\n\t\t\t\tvar blob = items[i].getAsFile();\n\t\t\t\tvar URLObj = window.URL || window.webkitURL;\n\t\t\t\tvar source = URLObj.createObjectURL(blob);\n\t\t\t\tsetSourceAndRestart(source);\n\t\t\t}\n\t\t}\n\t\te.preventDefault();\n\t}\n});\n\n// Download as SVG\ndocument.getElementById('export').addEventListener('click', function (e) {\n const blob = new Blob([new XMLSerializer().serializeToString(svg)], {type: 'octet/stream'}),\n url = window.URL.createObjectURL(blob);\n\n this.href = url;\n this.target = '_blank';\n\n this.download = 'export-' + new Date().toISOString().slice(0, 19).replace(/:/g, '').replace('T', ' ') + '.svg';\n});\n\n// Store template config\nvar presetConfigs = [\n {\n src: 'assets/samples/K1_drawing.jpg',\n clustering_mode: 'binary',\n filter_speckle: 4,\n color_precision: 6,\n layer_difference: 16,\n mode: 'spline',\n corner_threshold: 60,\n length_threshold: 4,\n splice_threshold: 45,\n source: 'https://commons.wikimedia.org/wiki/File:K1_drawing.jpg',\n credit: 'Wikimedia',\n },\n {\n src: 'assets/samples/Cityscape Sunset_DFM3-01.jpg',\n clustering_mode: 'color',\n filter_speckle: 4,\n color_precision: 8,\n layer_difference: 25,\n mode: 'spline',\n corner_threshold: 60,\n length_threshold: 4,\n splice_threshold: 45,\n source: 'https://www.vecteezy.com/vector-art/227400-beautiful-cityscape-at-sunset',\n credit: 'Building Vectors by Vecteezy',\n },\n {\n src: 'assets/samples/Gum Tree Vector.jpg',\n clustering_mode: 'color',\n filter_speckle: 4,\n color_precision: 8,\n layer_difference: 28,\n mode: 'spline',\n corner_threshold: 60,\n length_threshold: 4,\n splice_threshold: 45,\n source: 'https://www.vecteezy.com/vector-art/172177-gum-tree-vector',\n credit: 'Nature Vectors by Vecteezy',\n },\n {\n src: 'assets/samples/vectorstock_31191940.png',\n clustering_mode: 'color',\n filter_speckle: 8,\n color_precision: 7,\n layer_difference: 64,\n mode: 'spline',\n corner_threshold: 60,\n length_threshold: 4,\n splice_threshold: 45,\n source: 'https://www.vectorstock.com/royalty-free-vector/dessert-poster-design-with-chocolate-cake-mousses-vector-31191940',\n credit: 'Vector image by VectorStock / vectorstock',\n },\n {\n src: 'assets/samples/angel-luciano-LATYeZyw88c-unsplash-s.jpg',\n clustering_mode: 'color',\n filter_speckle: 10,\n color_precision: 8,\n layer_difference: 48,\n mode: 'spline',\n corner_threshold: 180,\n length_threshold: 4,\n splice_threshold: 45,\n source: 'https://unsplash.com/photos/LATYeZyw88c',\n credit: 'Photo by Angel Luciano on Unsplash',\n },\n {\n src: 'assets/samples/spaceships.png',\n clustering_mode: 'color',\n filter_speckle: 0,\n color_precision: 8,\n layer_difference: 0,\n mode: 'none',\n corner_threshold: 180,\n length_threshold: 4,\n splice_threshold: 45,\n source: 'https://opengameart.org/content/spaceships-1',\n credit: 'Photo by wuhu on opengameart.org',\n },\n];\n\n// Insert gallery items dynamically\nfor (let i = 0; i < presetConfigs.length; i++) {\n\tdocument.getElementById('galleryslider').innerHTML += \n\t`
  • \n\t
    \n\t\t\n\t\t\t\n\t\t\n\t
    \n\t
  • `;\n document.getElementById('credits-modal-content').innerHTML += \n `

    ${presetConfigs[i].credit}

    `;\n}\n\n// Function to load a given config WITHOUT restarting\nfunction loadConfig(config) {\n\tmode = config.mode;\n\tclustering_mode = config.clustering_mode;\n\n\tglobalcorner = config.corner_threshold;\n\tdocument.getElementById('cornervalue').innerHTML = globalcorner;\n\tdocument.getElementById('corner').value = globalcorner;\n\t\n\tgloballength = config.length_threshold;\n\tdocument.getElementById('lengthvalue').innerHTML = globallength;\n\tdocument.getElementById('length').value = globallength;\n\t\n\tglobalsplice = config.splice_threshold;\n\tdocument.getElementById('splicevalue').innerHTML = globalsplice;\n\tdocument.getElementById('splice').value = globalsplice;\n\n\tglobalfilterspeckle = config.filter_speckle;\n\tdocument.getElementById('filterspecklevalue').innerHTML = globalfilterspeckle;\n\tdocument.getElementById('filterspeckle').value = globalfilterspeckle;\n\n\tglobalcolorprecision = config.color_precision;\n\tdocument.getElementById('colorprecisionvalue').innerHTML = globalcolorprecision;\n\tdocument.getElementById('colorprecision').value = globalcolorprecision;\n\n\tgloballayerdifference = config.layer_difference;\n\tdocument.getElementById('layerdifferencevalue').innerHTML = globallayerdifference;\n\tdocument.getElementById('layerdifference').value = globallayerdifference;\n\n}\n\n// Choose template from gallery\nlet chooseGalleryButtons = document.querySelectorAll('.galleryitem a');\nchooseGalleryButtons.forEach(item => {\n\titem.addEventListener('click', function (e) {\n\t\t// Load preset template config\n\t\tlet i = Array.prototype.indexOf.call(chooseGalleryButtons, item);\n\t\tif (presetConfigs.length > i) {\n\t\t\tloadConfig(presetConfigs[i]);\n\t\t}\n\n\t\t// Set source as specified\n\t\tsetSourceAndRestart(this.firstElementChild.src);\n\t});\n});\n\n// Upload button\nvar imageSelect = document.getElementById('imageSelect'),\nimageInput = document.getElementById('imageInput'); \nimageSelect.addEventListener('click', function (e) {\n imageInput.click();\n e.preventDefault();\n});\n\nimageInput.addEventListener('change', function (e) {\n setSourceAndRestart(this.files[0]);\n});\n\n// Drag-n-Drop\nvar drop = document.getElementById('drop');\nvar droptext = document.getElementById('droptext');\ndrop.addEventListener('dragenter', function (e) {\n if (e.preventDefault) e.preventDefault();\n e.dataTransfer.dropEffect = 'copy';\n droptext.classList.add('hovering');\n return false;\n});\n\ndrop.addEventListener('dragleave', function (e) {\n if (e.preventDefault) e.preventDefault();\n e.dataTransfer.dropEffect = 'copy';\n droptext.classList.remove('hovering');\n return false;\n});\n\ndrop.addEventListener('dragover', function (e) {\n if (e.preventDefault) e.preventDefault();\n e.dataTransfer.dropEffect = 'copy';\n droptext.classList.add('hovering');\n return false;\n});\n\ndrop.addEventListener('drop', function (e) {\n if (e.preventDefault) e.preventDefault();\n droptext.classList.remove('hovering');\n setSourceAndRestart(e.dataTransfer.files[0]);\n return false;\n});\n\n// Get Input from UI controls\nvar globalcorner = parseInt(document.getElementById('corner').value),\n globallength = parseFloat(document.getElementById('length').value),\n globalsplice = parseInt(document.getElementById('splice').value),\n globalfilterspeckle = parseInt(document.getElementById('filterspeckle').value),\n globalcolorprecision = parseInt(document.getElementById('colorprecision').value),\n globallayerdifference = parseInt(document.getElementById('layerdifference').value);\n\n// Load past inputs from localStorage\n/*\nif (localStorage.VSsettings) {\n var settings = JSON.parse(localStorage.VSsettings);\n document.getElementById('cornervalue').innerHTML = document.getElementById('corner').value = globalcorner = settings.globalcorner;\n document.getElementById('lengthvalue').innerHTML = document.getElementById('length').value = globallength = settings.globallength;\n document.getElementById('splicevalue').innerHTML = document.getElementById('splice').value = globalsplice = settings.globalsplice;\n}\n*/\n\ndocument.getElementById('none').addEventListener('click', function (e) {\n mode = 'none';\n restart();\n}, false);\n\ndocument.getElementById('polygon').addEventListener('click', function (e) {\n mode = 'polygon';\n restart();\n}, false);\n\ndocument.getElementById('spline').addEventListener('click', function (e) {\n mode = 'spline';\n restart();\n}, false);\n\ndocument.getElementById('clustering-binary').addEventListener('click', function (e) {\n clustering_mode = 'binary';\n restart();\n}, false);\n\ndocument.getElementById('clustering-color').addEventListener('click', function (e) {\n clustering_mode = 'color';\n restart();\n}, false);\n\ndocument.getElementById('filterspeckle').addEventListener('change', function (e) {\n globalfilterspeckle = parseInt(this.value);\n document.getElementById('filterspecklevalue').innerHTML = this.value;\n restart();\n});\n\ndocument.getElementById('colorprecision').addEventListener('change', function (e) {\n globalcolorprecision = parseInt(this.value);\n document.getElementById('colorprecisionvalue').innerHTML = this.value;\n restart();\n});\n\ndocument.getElementById('layerdifference').addEventListener('change', function (e) {\n globallayerdifference = parseInt(this.value);\n document.getElementById('layerdifferencevalue').innerHTML = this.value;\n restart();\n});\n\ndocument.getElementById('corner').addEventListener('change', function (e) {\n globalcorner = parseInt(this.value);\n document.getElementById('cornervalue').innerHTML = this.value;\n restart();\n});\n\ndocument.getElementById('length').addEventListener('change', function (e) {\n globallength = parseFloat(this.value);\n document.getElementById('lengthvalue').innerHTML = this.value;\n restart();\n});\n\ndocument.getElementById('splice').addEventListener('change', function (e) {\n globalsplice = parseInt(this.value);\n document.getElementById('splicevalue').innerHTML = this.value;\n restart();\n});\n\n// Save inputs before unloading\n/*\nwindow.addEventListener('beforeunload', function () {\n localStorage.VSsettings = JSON.stringify({\n globalcorner: globalcorner,\n globallength: globallength,\n globalsplice: globalsplice,\n });\n});\n*/\n\nfunction setSourceAndRestart(source) {\n img.src = source instanceof File ? URL.createObjectURL(source) : source;\n img.onload = function () {\n svg.setAttribute('viewBox', `0 0 ${img.naturalWidth} ${img.naturalHeight}`);\n canvas.width = img.naturalWidth;\n canvas.height = img.naturalHeight;\n restart();\n }\n // Show display\n canvas.style.display = 'block';\n svg.style.display = 'block';\n // Hide upload text\n droptext.style.display = 'none';\n}\n\nfunction restart() {\n document.getElementById('clustering-binary').classList.remove('selected');\n document.getElementById('clustering-color').classList.remove('selected');\n document.getElementById('clustering-' + clustering_mode).classList.add('selected');\n Array.from(document.getElementsByClassName('clustering-color-options')).forEach((el) => {\n el.style.display = clustering_mode == 'color' ? '' : 'none';\n });\n\n document.getElementById('none').classList.remove('selected');\n document.getElementById('polygon').classList.remove('selected');\n document.getElementById('spline').classList.remove('selected');\n document.getElementById(mode).classList.add('selected');\n Array.from(document.getElementsByClassName('spline-options')).forEach((el) => {\n el.style.display = mode == 'spline' ? '' : 'none';\n });\n\n if (!img.src) {\n return;\n }\n while (svg.firstChild) {\n svg.removeChild(svg.firstChild);\n }\n ctx.clearRect(0, 0, canvas.width, canvas.height);\n ctx.drawImage(img, 0, 0);\n let converter_params = JSON.stringify({\n 'canvas_id': canvas.id,\n 'svg_id': svg.id,\n 'mode': mode,\n 'clustering_mode': clustering_mode,\n 'corner_threshold': deg2rad(globalcorner),\n 'length_threshold': globallength,\n 'max_iterations': 10,\n 'splice_threshold': deg2rad(globalsplice),\n 'filter_speckle': globalfilterspeckle*globalfilterspeckle,\n 'color_precision': 8-globalcolorprecision,\n 'layer_difference': globallayerdifference,\n });\n if (runner) {\n runner.stop();\n }\n runner = new ConverterRunner(converter_params);\n progress.value = 0;\n progressregion.style.display = 'block';\n runner.run();\n}\n\nfunction deg2rad(deg) {\n return deg/180*3.141592654;\n}\n\nclass ConverterRunner {\n constructor (converter_params) {\n this.converter =\n clustering_mode == 'color' ?\n vtracer__WEBPACK_IMPORTED_MODULE_0__[\"ColorImageConverter\"].new_with_string(converter_params):\n vtracer__WEBPACK_IMPORTED_MODULE_0__[\"BinaryImageConverter\"].new_with_string(converter_params);\n this.converter.init();\n this.stopped = false;\n if (clustering_mode == 'binary') {\n svg.style.background = '#000';\n canvas.style.display = 'none';\n } else {\n svg.style.background = '';\n canvas.style.display = '';\n }\n canvas.style.opacity = '';\n }\n\n run () {\n const This = this;\n setTimeout(function tick () {\n if (!This.stopped) {\n let done = false;\n const startTick = performance.now();\n while (!(done = This.converter.tick()) &&\n performance.now() - startTick < 25) {\n }\n progress.value = This.converter.progress();\n if (progress.value >= 50) {\n canvas.style.display = 'none';\n } else {\n canvas.style.opacity = (50 - progress.value) / 25;\n }\n if (progress.value >= progress.max) {\n progressregion.style.display = 'none';\n progress.value = 0;\n }\n if (!done) {\n setTimeout(tick, 1);\n }\n }\n }, 1);\n }\n\n stop () {\n this.stopped = true;\n this.converter.free();\n }\n}\n\n//# sourceURL=webpack:///./index.js?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var vtracer__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vtracer */ \"../pkg/vtracer_webapp.js\");\n\n\nlet runner;\nconst canvas = document.getElementById('frame');\nconst ctx = canvas.getContext('2d');\nconst svg = document.getElementById('svg');\nconst img = new Image();\nconst progress = document.getElementById('progressbar');\nconst progressregion = document.getElementById('progressregion');\nlet mode = 'spline', clustering_mode = 'color';\n\n// Hide canas and svg on load\ncanvas.style.display = 'none';\nsvg.style.display = 'none';\n\n// Paste from clipboard\ndocument.addEventListener('paste', function (e) {\n\tif (e.clipboardData) {\n\t\tvar items = e.clipboardData.items;\n\t\tif (!items) return;\n\n\t\t//access data directly\n\t\tfor (var i = 0; i < items.length; i++) {\n\t\t\tif (items[i].type.indexOf(\"image\") !== -1) {\n\t\t\t\t//image\n\t\t\t\tvar blob = items[i].getAsFile();\n\t\t\t\tvar URLObj = window.URL || window.webkitURL;\n\t\t\t\tvar source = URLObj.createObjectURL(blob);\n\t\t\t\tsetSourceAndRestart(source);\n\t\t\t}\n\t\t}\n\t\te.preventDefault();\n\t}\n});\n\n// Download as SVG\ndocument.getElementById('export').addEventListener('click', function (e) {\n const blob = new Blob([new XMLSerializer().serializeToString(svg)], {type: 'octet/stream'}),\n url = window.URL.createObjectURL(blob);\n\n this.href = url;\n this.target = '_blank';\n\n this.download = 'export-' + new Date().toISOString().slice(0, 19).replace(/:/g, '').replace('T', ' ') + '.svg';\n});\n\n// Store template config\nvar presetConfigs = [\n {\n src: 'assets/samples/K1_drawing.jpg',\n clustering_mode: 'binary',\n filter_speckle: 4,\n color_precision: 6,\n layer_difference: 16,\n mode: 'spline',\n corner_threshold: 60,\n length_threshold: 4,\n splice_threshold: 45,\n source: 'https://commons.wikimedia.org/wiki/File:K1_drawing.jpg',\n credit: 'Wikimedia',\n },\n {\n src: 'assets/samples/Cityscape Sunset_DFM3-01.jpg',\n clustering_mode: 'color',\n filter_speckle: 4,\n color_precision: 8,\n layer_difference: 25,\n mode: 'spline',\n corner_threshold: 60,\n length_threshold: 4,\n splice_threshold: 45,\n source: 'https://www.vecteezy.com/vector-art/227400-beautiful-cityscape-at-sunset',\n credit: 'Building Vectors by Vecteezy',\n },\n {\n src: 'assets/samples/Gum Tree Vector.jpg',\n clustering_mode: 'color',\n filter_speckle: 4,\n color_precision: 8,\n layer_difference: 28,\n mode: 'spline',\n corner_threshold: 60,\n length_threshold: 4,\n splice_threshold: 45,\n source: 'https://www.vecteezy.com/vector-art/172177-gum-tree-vector',\n credit: 'Nature Vectors by Vecteezy',\n },\n {\n src: 'assets/samples/vectorstock_31191940.png',\n clustering_mode: 'color',\n filter_speckle: 8,\n color_precision: 7,\n layer_difference: 64,\n mode: 'spline',\n corner_threshold: 60,\n length_threshold: 4,\n splice_threshold: 45,\n source: 'https://www.vectorstock.com/royalty-free-vector/dessert-poster-design-with-chocolate-cake-mousses-vector-31191940',\n credit: 'Vector image by VectorStock / vectorstock',\n },\n {\n src: 'assets/samples/angel-luciano-LATYeZyw88c-unsplash-s.jpg',\n clustering_mode: 'color',\n filter_speckle: 10,\n color_precision: 8,\n layer_difference: 48,\n mode: 'spline',\n corner_threshold: 180,\n length_threshold: 4,\n splice_threshold: 45,\n source: 'https://unsplash.com/photos/LATYeZyw88c',\n credit: 'Photo by Angel Luciano on Unsplash',\n },\n {\n src: 'assets/samples/tank-unit-preview.png',\n clustering_mode: 'color',\n filter_speckle: 0,\n color_precision: 8,\n layer_difference: 0,\n mode: 'none',\n corner_threshold: 180,\n length_threshold: 4,\n splice_threshold: 45,\n source: 'https://opengameart.org/content/sideview-sci-fi-patreon-collection',\n credit: 'Artwork by Luis Zuno on opengameart.org',\n },\n];\n\n// Insert gallery items dynamically\nfor (let i = 0; i < presetConfigs.length; i++) {\n\tdocument.getElementById('galleryslider').innerHTML += \n\t`
  • \n\t
    \n\t\t\n\t\t\t\n\t\t\n\t
    \n\t
  • `;\n document.getElementById('credits-modal-content').innerHTML += \n `

    ${presetConfigs[i].credit}

    `;\n}\n\n// Function to load a given config WITHOUT restarting\nfunction loadConfig(config) {\n\tmode = config.mode;\n\tclustering_mode = config.clustering_mode;\n\n\tglobalcorner = config.corner_threshold;\n\tdocument.getElementById('cornervalue').innerHTML = globalcorner;\n\tdocument.getElementById('corner').value = globalcorner;\n\t\n\tgloballength = config.length_threshold;\n\tdocument.getElementById('lengthvalue').innerHTML = globallength;\n\tdocument.getElementById('length').value = globallength;\n\t\n\tglobalsplice = config.splice_threshold;\n\tdocument.getElementById('splicevalue').innerHTML = globalsplice;\n\tdocument.getElementById('splice').value = globalsplice;\n\n\tglobalfilterspeckle = config.filter_speckle;\n\tdocument.getElementById('filterspecklevalue').innerHTML = globalfilterspeckle;\n\tdocument.getElementById('filterspeckle').value = globalfilterspeckle;\n\n\tglobalcolorprecision = config.color_precision;\n\tdocument.getElementById('colorprecisionvalue').innerHTML = globalcolorprecision;\n\tdocument.getElementById('colorprecision').value = globalcolorprecision;\n\n\tgloballayerdifference = config.layer_difference;\n\tdocument.getElementById('layerdifferencevalue').innerHTML = globallayerdifference;\n\tdocument.getElementById('layerdifference').value = globallayerdifference;\n\n}\n\n// Choose template from gallery\nlet chooseGalleryButtons = document.querySelectorAll('.galleryitem a');\nchooseGalleryButtons.forEach(item => {\n\titem.addEventListener('click', function (e) {\n\t\t// Load preset template config\n\t\tlet i = Array.prototype.indexOf.call(chooseGalleryButtons, item);\n\t\tif (presetConfigs.length > i) {\n\t\t\tloadConfig(presetConfigs[i]);\n\t\t}\n\n\t\t// Set source as specified\n\t\tsetSourceAndRestart(this.firstElementChild.src);\n\t});\n});\n\n// Upload button\nvar imageSelect = document.getElementById('imageSelect'),\nimageInput = document.getElementById('imageInput'); \nimageSelect.addEventListener('click', function (e) {\n imageInput.click();\n e.preventDefault();\n});\n\nimageInput.addEventListener('change', function (e) {\n setSourceAndRestart(this.files[0]);\n});\n\n// Drag-n-Drop\nvar drop = document.getElementById('drop');\nvar droptext = document.getElementById('droptext');\ndrop.addEventListener('dragenter', function (e) {\n if (e.preventDefault) e.preventDefault();\n e.dataTransfer.dropEffect = 'copy';\n droptext.classList.add('hovering');\n return false;\n});\n\ndrop.addEventListener('dragleave', function (e) {\n if (e.preventDefault) e.preventDefault();\n e.dataTransfer.dropEffect = 'copy';\n droptext.classList.remove('hovering');\n return false;\n});\n\ndrop.addEventListener('dragover', function (e) {\n if (e.preventDefault) e.preventDefault();\n e.dataTransfer.dropEffect = 'copy';\n droptext.classList.add('hovering');\n return false;\n});\n\ndrop.addEventListener('drop', function (e) {\n if (e.preventDefault) e.preventDefault();\n droptext.classList.remove('hovering');\n setSourceAndRestart(e.dataTransfer.files[0]);\n return false;\n});\n\n// Get Input from UI controls\nvar globalcorner = parseInt(document.getElementById('corner').value),\n globallength = parseFloat(document.getElementById('length').value),\n globalsplice = parseInt(document.getElementById('splice').value),\n globalfilterspeckle = parseInt(document.getElementById('filterspeckle').value),\n globalcolorprecision = parseInt(document.getElementById('colorprecision').value),\n globallayerdifference = parseInt(document.getElementById('layerdifference').value);\n\n// Load past inputs from localStorage\n/*\nif (localStorage.VSsettings) {\n var settings = JSON.parse(localStorage.VSsettings);\n document.getElementById('cornervalue').innerHTML = document.getElementById('corner').value = globalcorner = settings.globalcorner;\n document.getElementById('lengthvalue').innerHTML = document.getElementById('length').value = globallength = settings.globallength;\n document.getElementById('splicevalue').innerHTML = document.getElementById('splice').value = globalsplice = settings.globalsplice;\n}\n*/\n\ndocument.getElementById('none').addEventListener('click', function (e) {\n mode = 'none';\n restart();\n}, false);\n\ndocument.getElementById('polygon').addEventListener('click', function (e) {\n mode = 'polygon';\n restart();\n}, false);\n\ndocument.getElementById('spline').addEventListener('click', function (e) {\n mode = 'spline';\n restart();\n}, false);\n\ndocument.getElementById('clustering-binary').addEventListener('click', function (e) {\n clustering_mode = 'binary';\n restart();\n}, false);\n\ndocument.getElementById('clustering-color').addEventListener('click', function (e) {\n clustering_mode = 'color';\n restart();\n}, false);\n\ndocument.getElementById('filterspeckle').addEventListener('change', function (e) {\n globalfilterspeckle = parseInt(this.value);\n document.getElementById('filterspecklevalue').innerHTML = this.value;\n restart();\n});\n\ndocument.getElementById('colorprecision').addEventListener('change', function (e) {\n globalcolorprecision = parseInt(this.value);\n document.getElementById('colorprecisionvalue').innerHTML = this.value;\n restart();\n});\n\ndocument.getElementById('layerdifference').addEventListener('change', function (e) {\n globallayerdifference = parseInt(this.value);\n document.getElementById('layerdifferencevalue').innerHTML = this.value;\n restart();\n});\n\ndocument.getElementById('corner').addEventListener('change', function (e) {\n globalcorner = parseInt(this.value);\n document.getElementById('cornervalue').innerHTML = this.value;\n restart();\n});\n\ndocument.getElementById('length').addEventListener('change', function (e) {\n globallength = parseFloat(this.value);\n document.getElementById('lengthvalue').innerHTML = this.value;\n restart();\n});\n\ndocument.getElementById('splice').addEventListener('change', function (e) {\n globalsplice = parseInt(this.value);\n document.getElementById('splicevalue').innerHTML = this.value;\n restart();\n});\n\n// Save inputs before unloading\n/*\nwindow.addEventListener('beforeunload', function () {\n localStorage.VSsettings = JSON.stringify({\n globalcorner: globalcorner,\n globallength: globallength,\n globalsplice: globalsplice,\n });\n});\n*/\n\nfunction setSourceAndRestart(source) {\n img.src = source instanceof File ? URL.createObjectURL(source) : source;\n img.onload = function () {\n svg.setAttribute('viewBox', `0 0 ${img.naturalWidth} ${img.naturalHeight}`);\n canvas.width = img.naturalWidth;\n canvas.height = img.naturalHeight;\n restart();\n }\n // Show display\n canvas.style.display = 'block';\n svg.style.display = 'block';\n // Hide upload text\n droptext.style.display = 'none';\n}\n\nfunction restart() {\n document.getElementById('clustering-binary').classList.remove('selected');\n document.getElementById('clustering-color').classList.remove('selected');\n document.getElementById('clustering-' + clustering_mode).classList.add('selected');\n Array.from(document.getElementsByClassName('clustering-color-options')).forEach((el) => {\n el.style.display = clustering_mode == 'color' ? '' : 'none';\n });\n\n document.getElementById('none').classList.remove('selected');\n document.getElementById('polygon').classList.remove('selected');\n document.getElementById('spline').classList.remove('selected');\n document.getElementById(mode).classList.add('selected');\n Array.from(document.getElementsByClassName('spline-options')).forEach((el) => {\n el.style.display = mode == 'spline' ? '' : 'none';\n });\n\n if (!img.src) {\n return;\n }\n while (svg.firstChild) {\n svg.removeChild(svg.firstChild);\n }\n ctx.clearRect(0, 0, canvas.width, canvas.height);\n ctx.drawImage(img, 0, 0);\n let converter_params = JSON.stringify({\n 'canvas_id': canvas.id,\n 'svg_id': svg.id,\n 'mode': mode,\n 'clustering_mode': clustering_mode,\n 'corner_threshold': deg2rad(globalcorner),\n 'length_threshold': globallength,\n 'max_iterations': 10,\n 'splice_threshold': deg2rad(globalsplice),\n 'filter_speckle': globalfilterspeckle*globalfilterspeckle,\n 'color_precision': 8-globalcolorprecision,\n 'layer_difference': globallayerdifference,\n });\n if (runner) {\n runner.stop();\n }\n runner = new ConverterRunner(converter_params);\n progress.value = 0;\n progressregion.style.display = 'block';\n runner.run();\n}\n\nfunction deg2rad(deg) {\n return deg/180*3.141592654;\n}\n\nclass ConverterRunner {\n constructor (converter_params) {\n this.converter =\n clustering_mode == 'color' ?\n vtracer__WEBPACK_IMPORTED_MODULE_0__[\"ColorImageConverter\"].new_with_string(converter_params):\n vtracer__WEBPACK_IMPORTED_MODULE_0__[\"BinaryImageConverter\"].new_with_string(converter_params);\n this.converter.init();\n this.stopped = false;\n if (clustering_mode == 'binary') {\n svg.style.background = '#000';\n canvas.style.display = 'none';\n } else {\n svg.style.background = '';\n canvas.style.display = '';\n }\n canvas.style.opacity = '';\n }\n\n run () {\n const This = this;\n setTimeout(function tick () {\n if (!This.stopped) {\n let done = false;\n const startTick = performance.now();\n while (!(done = This.converter.tick()) &&\n performance.now() - startTick < 25) {\n }\n progress.value = This.converter.progress();\n if (progress.value >= 50) {\n canvas.style.display = 'none';\n } else {\n canvas.style.opacity = (50 - progress.value) / 25;\n }\n if (progress.value >= progress.max) {\n progressregion.style.display = 'none';\n progress.value = 0;\n }\n if (!done) {\n setTimeout(tick, 1);\n }\n }\n }, 1);\n }\n\n stop () {\n this.stopped = true;\n this.converter.free();\n }\n}\n\n//# sourceURL=webpack:///./index.js?"); /***/ }), diff --git a/docs/assets/samples/attributions.txt b/docs/assets/samples/attributions.txt deleted file mode 100644 index 0a84553..0000000 --- a/docs/assets/samples/attributions.txt +++ /dev/null @@ -1,22 +0,0 @@ -K1_drawing -B/W 4 -https://commons.wikimedia.org/wiki/File:K1_drawing.jpg - -Cityscape Sunset_DFM3-01 -Color 4,8,32 -Building Vectors by Vecteezy - -Gum Tree Vector -Color 4,8,32 -Nature Vectors by Vecteezy - -vectorstock_31191940 -Color 8,7,64 -Vector image by VectorStock / vectorstock - -angel-luciano-LATYeZyw88c-unsplash -Color 10,8,48 180 -Photo by Angel Luciano on Unsplash - -spaceships.png -https://opengameart.org/content/spaceships-1 \ No newline at end of file diff --git a/docs/assets/samples/spaceships.png b/docs/assets/samples/spaceships.png deleted file mode 100644 index d98f085..0000000 Binary files a/docs/assets/samples/spaceships.png and /dev/null differ diff --git a/docs/assets/samples/tank-unit-preview.png b/docs/assets/samples/tank-unit-preview.png new file mode 100644 index 0000000..fc9dca7 Binary files /dev/null and b/docs/assets/samples/tank-unit-preview.png differ