Need help using external JS

Hey everybody,

the other day I stumbled upon this formidable repository, which comes super-handy for my svg-heavy game. The instructions on github suggest this use:

<!-- script loading -->
<script src="https://unpkg.com/svg2roughjs/dist/svg2roughjs.umd.min.js"></script>
<script>
  const svgConverter = new svg2roughjs.Svg2Roughjs('#output-div')
  svgConverter.svg = document.getElementById('input-svg')
  svgConverter.sketch()
</script>

so I turned it into this in my StoryJS:

importScripts("https://unpkg.com/svg2roughjs/dist/svg2roughjs.umd.min.js");

const svgConverter = new svg2roughjs.Svg2Roughjs('#output-div')
  svgConverter.svg = document.getElementById('input-svg')
  svgConverter.sketch()

But I get the old “Error [tw-user-script-0]: svg2roughjs is not defined.”
Could you help me use this script?

The objective would be to parse every svg in the game through svg2roughjs. I figured calling a macro in passageDone which takes care of that.
Also, could some JS-magician help me how to assign the properties mentioned on github, for changing the style?

Thank you so much!

The 1st note in the importScripts() function’s documentation explains that the loading of the script(s) is done asynchronously. Which basically mean the web-browser handles the loading of the file(s) in a way that doesn’t halt the execution of other code, like that in the rest of your project’s Story > JavaScript area or that of the engine itself.

So like many things in life, your first issue is likely due to timing. As in you are trying to use the outcome of the file loading (eg. the svg2roughjs variable) before the file has finished being loaded.

To help overcome this issue the function returns a Promise object, which can be used to delay the execution of any code that relies on the successful loading of the file(s) being imported…

importScripts("https://unpkg.com/svg2roughjs/dist/svg2roughjs.umd.min.js")
	.then(function () {
		/* the script has successfully loaded, do stuff. */
		const svgConverter = new svg2roughjs.Svg2Roughjs('#output-div');
		svgConverter.svg = document.getElementById('input-svg');
		svgConverter.sketch();
	})
	.catch(function (err) {
		/* an error occurred while loading the script, log it. */
		console.log(err);
	});;

…which fixes the svg2roughjs variable related “not defined” error. However, there is now a “Could not find target in document” related error, which is also due to timing.

In your code example there are two function calls…

svg2roughjs.Svg2Roughjs('#output-div')
document.getElementById('input-svg')

…that search the Document Object Model (DOM) of the page to find specific HTML elements.
eg. one element with an id of output-div, and one element that has a type of input-svg.

However, unless you are creating those elements sometime earlier in your project’s Story > JavaScript area, then neither of those elements will exist because they aren’t part of the SugarCube HTML template.

So there is no point in calling the svg2roughjs related code in the then() method of the Promise. You will just need to delay the execution of those two functions until after the target elements have been added to the DOM.

The svg2rough.js project’s documentation becomes very vague at this point, and it expects you to:

  • read through the source code of its /sample-application/. (which isn’t trivial)
  • understand how svg2rough.js project makes use of the Rough.js project’s features.
  • [potentially] read parts of the Rough.js project’s API documentation.

So while I can explain why you are getting the error (and the follow on one) you had (will have), I found it difficult to provide a working example of using that library in a Twine based project.

Perhaps one of the more advanced/knowledgeable JavaScript users will be able to help you do that.

Thank you so much! That pushed me a great deal forward, I actually got it running on a passage. Here’s what I did:

  1. I changed your JS-part in the Story JavaScript to:
importScripts(https://unpkg.com/svg2roughjs/dist/svg2roughjs.umd.min.js)

                .then(function () {

                               /* the script has successfully loaded, do stuff. */

                               console.log("svg2roughjs loaded");

                })

                .catch(function (err) {

                               /* an error occurred while loading the script, log it. */

                               console.log(err);

                });;

(to overcome the issue with the at loadtime inexistent SVGs). Then I created a passage which looks like this:

<svg
   version="1.1"
   viewBox="0.00 0.00 672.00 384.00"
   id="room1"
....
> 

<div id="output-div"></div>

<<done>>
                <<script>>
    const svgConverter = new svg2roughjs.Svg2Roughjs('#output-div');
               svgConverter.svg = document.getElementById('room1');
    console.log("roughConfig: " );
                console.log(svgConverter.roughConfig);
               svgConverter.sketch();  
        <</script>>

<</done>>

This actually creates and displays the processed svg. What I couldn’t get running was the roughConfig object. It exists, but I can’t assign it to svgConverter as shown here:


{
  // Create an empty SVG element to which svg2rough.js can populate
  const el = html`<svg>`;

  const svgConverter = new svg2rough.Svg2Roughjs(el);
  svgConverter.backgroundColor = "white";
  svgConverter.pencilFilter = pencilFilter;
  svgConverter.randomize = randomize;
  svgConverter.svg = svgLogo;
  svgConverter.roughConfig = {
    bowing,
    roughness,
    fillStyle
  };
  svgConverter.sketch();

  return el;
}

I’ll keep on trying.