Using conditional statements from within an SVG

Twine Version: 2.3.15
Story Format: Sugarcube

I’m trying to make it so that a link in an svg file is only visible once the player has visited a certain passage more than once. I’ve tried $.wiki(’<<if visited(“Passage”) == 2>>’) method but it doesn’t seem to work… is there another work around for this?

(eventually I’ll get rid of the inkscape formatting and figure out how to make the link colour dynamic)

<div class="svg-container"><svg  version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg"  class="svg-content" viewBox="0 0 2000 1000"  
preserveAspectRatio="xMidYMin meet" xmlns:xlink="http://www.w3.org/1999/xlink">
<svg
   width="210mm"
   height="297mm"
   viewBox="0 0 210 297"
   version="1.1"
   id="svg5"
   inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20)"
   sodipodi:docname="drawing.svg"
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
   xmlns:xlink="http://www.w3.org/1999/xlink"
   xmlns="http://www.w3.org/2000/svg"
   xmlns:svg="http://www.w3.org/2000/svg">

  <g
     class="layer" display="inline">
	 
<path
       style="fill:none;fill-opacity:0.0294118;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0"
       d="m 12.169627,93.59226 c 8.437794,-13.447736 -0.626049,1.229484 14.401366,-25.293854 2.930239,-5.171864 5.324723,-10.722555 8.996695,-15.397073 9.351711,-11.904974 27.56698,-22.482815 42.405869,-26.07493 4.367067,-1.057157 7.046293,-1.297479 11.4579,-1.150572 4.457067,0.14842 5.478931,0.877104 9.961221,0.439649 1.603592,-0.156505 3.147962,-0.698286 4.739482,-0.949455 4.33292,-0.68381 6.54712,-0.629123 10.72619,-1.463938 3.73038,-0.745185 7.59478,-1.79184 11.14193,-3.171086 4.09074,-1.590609 8.25654,-2.864688 12.37254,-4.359074 1.13178,-0.410914 0.6144,-0.457768 1.28049,-0.509805"
       id="path7986" />
        <a id="svg_31"  onclick="$.wiki('<<goto [[Start]]>>')" > <text
       xml:space="preserve"
       style="font-style:normal;font-weight:normal;font-size:10.5833px;line-height:1.25;font-family:sans-serif;fill:#6688dd;fill-opacity:1;stroke:none;stroke-width:0.264583"
       id="text11554"><textPath
         xlink:href="#path7986"
         id="textPath15231"
         style="fill:#6688dd;fill-opacity:1">I belong</textPath></text></a>
		 
		 

		$.wiki('<<if visited("Concrete") == 2>>')
		 
    <path
       style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
       d="m 25.230581,17.661408 c 7.093897,1.659748 56.292546,0.71698 63.436893,2.162622 19.806236,4.007746 21.467416,10.742883 27.753646,16.580096 8.13987,7.558458 10.4304,24.237127 15.13835,34.241504 2.76235,5.870009 9.47772,9.023932 14.41747,12.975728 10.11649,8.093196 2.74618,3.04211 14.05704,10.452671 4.28868,2.809825 38.30561,0.720877 43.25242,0.720877"
       id="path35695"
       sodipodi:nodetypes="csssssc" />
     <a id="svg_31"  onclick="$.wiki('<<goto [[Start]]>>')" ><text
       xml:space="preserve"
       style="font-style:normal;font-weight:normal;font-size:10.5833px;line-height:1.25;font-family:sans-serif;fill:#6688dd;fill-opacity:1;stroke:none;stroke-width:0.264583"
       id="text37503"><textPath
         xlink:href="#path35695"
         id="textPath40468"><tspan
           id="tspan37501"
           style="fill:#6688dd;fill-opacity:1;stroke-width:0.264583">I learned a lot from this unpleasantness</tspan></textPath></text></a>
		   
		  $.wiki('<<endif>>') */<
  </g>
</svg>
</div>

Calling $.wiki("whatever") doesn’t cause it to be executed inline, it causes it to be executed in its own separate space. Worse, it wouldn’t work anyways, because you can’t just plop JavaScript code into a passage like that, you’d have to put it inside of a macro, like the <<run>> macro, if you want it to be run. Even worse still, SugarCube generally ignores any code (including attribute directives) inside of an SVG element.

To get around those problems and do what you’re attempting to do, a good solution would probably be to set up a class on any elements you may want to optionally hide within the SVG element and then also add a class to the <div> element whenever you want those other elements hidden. That way you can just use CSS to hide things when both of those classes are in use.

I fixed a few problems with the SVG code, removed the raw JavaScript, ran it through an SVG minifier, tweaked it a bit further to fix a problem with the text getting cut off, added classes to elements to do what I described above, and the result was this:

<<nobr>><div @class="'svg-container' + (visited('Concrete') == 2 ? '' : ' hidepart')">
	<svg width="210mm" height="297mm" version="1.1" viewBox="0 0 225 297" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
		<g class="layer">
			<path id="a" d="m12.17 93.592c8.4378-13.448-0.62605 1.2295 14.401-25.294 2.9302-5.1719 5.3247-10.723 8.9967-15.397 9.3517-11.905 27.567-22.483 42.406-26.075 4.3671-1.0572 7.0463-1.2975 11.458-1.1506 4.4571 0.14842 5.4789 0.8771 9.9612 0.43965 1.6036-0.1565 3.148-0.69829 4.7395-0.94946 4.3329-0.68381 6.5471-0.62912 10.726-1.4639 3.7304-0.74518 7.5948-1.7918 11.142-3.1711 4.0907-1.5906 8.2565-2.8647 12.373-4.3591 1.1318-0.41091 0.6144-0.45777 1.2805-0.5098" fill="none" stroke-opacity="0"/>
			<a onclick="$.wiki('<<goto [[Start]]>>')">
				<text fill="#6688dd" font-family="sans-serif" font-size="10.583px" stroke-width=".26458" style="line-height:1.25" xml:space="preserve">
					<textPath fill="#6688dd" xlink:href="#a">
						I belong
					</textPath>
				</text>
			</a>
			<path class="hideme" id="b" d="m25.231 17.661c7.0939 1.6597 56.293 0.71698 63.437 2.1626 19.806 4.0077 21.467 10.743 27.754 16.58 8.1399 7.5585 10.43 24.237 15.138 34.242 2.7624 5.87 9.4777 9.0239 14.417 12.976 10.116 8.0932 2.7462 3.0421 14.057 10.453 4.2887 2.8098 38.306 0.72088 63.252 0.72088" fill="none" stroke="#000" stroke-width=".26458px" />
			<a class="hideme" onclick="$.wiki('<<goto [[Start]]>>')">
				<text fill="#6688dd" font-family="sans-serif" font-size="10.583px" stroke-width=".26458" style="line-height:1.25" xml:space="preserve">
					<textPath xlink:href="#b">
						<tspan fill="#6688dd" stroke-width=".26458">
							I learned a lot from this unpleasantness
						</tspan>
					</textPath>
				</text>
			</a>
		</g>
	</svg>
</div><</nobr>>

and you’ll also need this CSS in your Stylesheet section:

.hidepart .hideme {
	display: none;
}

The important bit is this part of the above code:

<div @class="'svg-container' + (visited('Concrete') == 2 ? '' : ' hidepart')">

That uses a SugarCube attribute directive and a JavaScript conditional operator to determine whether to include the “hidepart” class on the <div> element. Essentially, that sets the <div>'s class to “svg-container hidepart” unless the player has visited the “Concrete” passage exactly twice, in which case it just sets it to “svg-container”. If the “hidepart” class is there, then, due to the above CSS code, any elements within the <div> which have the “hideme” class will be not be displayed. I added the “hideme” class to just the <path> and <a> elements which you were attempting to hide.

I should mention that you can also use CSS like that to dynamically change the link color in your SVG elements.

The <<nobr>> macro was added to prevent line breaks from being turned into <br> elements, so that the code remains readable while also preventing any line break elements from messing up the SVG code.

Please let me know if you have any questions on any of that.

Enjoy! :slight_smile:

P.S. I should also mention that <<endif>> is depreciated, so you should be using <</if>> instead to end your <<if>> macros.

1 Like

This is amazing, it worked perfectly! And I’m bookmarking that minimizer, thank you.

<a onclick="$.wiki('<<goto [[Start]]>>')">

???

Why not simply use the data-passage content attribute? E.g.,

<a data-passage="Start">
1 Like

It was just copied from the original. I meant to clean that bit up as well, but I forgot since there were a lot of other broken bits I had to figure out how to fix first.

But yeah, that’s a better way to do it.

1 Like