Harlowe 2.0.1: Making an image go from 100% to 0% opacity over time

Hey guys!

I’m trying to figure out if there a way to make an image in a passage go from 100% to 0% opacity over a timer that I set, and I can reset after pressing a ‘link-repeat’ button.

I’m pretty much a Twine newb so the more hand holdy the answers the better, thanks in advance for any advice!

Working with CSS in certain ways in Harlowe can be very complicated. The following example will do what you asked, but it might not be what you want.

(link-repeat: "Show Image") [

  (set: $imageOpacity to 1)

  (live: 0.5s)[
	  (css: "opacity: " + (text: $imageOpacity) )[<img src="https://twinery.org/homepage/img/logo.svg" width="200" height="200">]

	  (set: $imageOpacity to $imageOpacity - 0.10)

	  (if: $imageOpacity <= 0)[
		  (set: $imageOpacity to 1)
		  (stop:)
	  ]
  ]
  
]

First, (set: $imageOpacity to 1) is used to set $imageOpacity to 1. CSS opacity has a range from 0 to 1. Since you asked about moving from 100% to 0%, that’s the start: 1 (100%).

Next, the (live:) macro is used. This creates a looping structure based on time. It is given the argument “0.5s”, which means 0.5 seconds. Every 0.5 seconds, everything within the hook associated with the macro will run. (And will keep running until it encounters the (stop:) macro.)

Next, the (css:) macro is used. This applies the “styles” given to it on an associated hook. Inside of the macro is another, (text:). This converts a number into a string, a collection of letters and numbers enclosed in quotation marks. The full line, then, takes $imageOpacity, a number, converts it into a string, and then uses it as part of (css:) to apply the “opacity” rule to a hook.

In this example, the hook contains an image. As part of the question, this is where another image would go.

After that is another (set:) macro. This changes the value of $imageOpacity by 0.10 each loop. Since the movement is from 100% to 0%, this decreases the opacity each loop by 10%.

Next is the stopping condition. Since (live:) will contain to run forever, it needs some code to stop it at some point. The use of the (if:) macro tests to see if $imageOpacity is less than or equal to 0. If so, it runs its contents.

Within the (if:) macro is the value of $imageOpacity is reset to 1 and the (stop:) macro is finally used. This ends the loop.

Around all of this code is the use of the (link-repeat:) macro. Clicking its link text once will start the (live:) looping, which will, itself, end once enough loops happen to decrease the value of $imageOpacity below 0.

Why (link-repeat:) is probably not what you want

All that written, you probably don’t want to use (link-repeat:) for this. Why? Because, as per its documentation, it “appends”. This means that each re-run of the link adds an image, loops until the opacity is below 0, and then ends. Clicking the link again adds another image and starts the cycle over again. Perhaps this is what you want, but probably not.

1 Like

Thanks a lot for the in-depth breakdown! Really helpful!

You are right, I don’t want each re-run to add an image, in fact I want the image to already be on screen, and the timer start running as soon as the passage loads…

And you are probably correct that ‘link-repeat’ is not the best solution here, but I want the “show image” link to always stick around, even after clicking it, and I want each re-run to apply to the same image. Effectively running that 100%-0% opacity effect on the same image each time it clicked.

If you have any advice for that, that would be awesome, but i’m going to try and reverse engineer what you have written here and see if I can figure something out :slight_smile:

EDIT: Another thing to note is that even though this code is making the variable $imageOpacity decrease, it’s not literally decreasing the opacity of the image, the image is staying at 100% opacity :thinking:

EDIT 2: Turns out the opacity decrease wasn’t working correctly because of some CSS code I had in my Stylesheet, now it works perfectly! I’ve modified this to work exactly how I need it to work! Thank’s so much!

“I want the “show image” link to always stick around, even after clicking it, and I want each re-run to apply to the same image. Effectively running that 100%-0% opacity effect on the same image each time it clicked.”

Harlowe probably won’t really help you with that. If you are going to be combining more complex scripting with CSS styles, you really should move over to SugarCube or Snowman. They will allow you to more easily work with more advanced programming techniques and usages.

Not to write that you can’t do what you are proposing with Harlowe, but it does become more and more complex the more you move away from what Harlowe is designed to allow users to work with and design from within Twine.

I’m not sure if it helps, but there is a pure CSS solution which would allow you to make the image slowly fade to complete transparency, become opaque when clicked on, and then slowly fade to transparent again. Just add the “fade” class to an element and add this to your Stylesheet section:

.fade {
	opacity: 0;
	animation: fadeAnim linear 5s;
	transition: opacity 5s;
}
.fade:active {
	opacity: 1;
	transition: opacity 0s;
}
@keyframes fadeAnim {
	0%   { opacity: 1; }
	100% { opacity: 0; }
}

That will make it fade out over 5 seconds, become opaque when clicked on or the mouse is held down on it, and then fade out again.

Hope that helps! :slight_smile:

1 Like

Hi,

I’ve used your code and it works fine. But can you help with getting the fade to go in the opposite direction, from completely invisible to completely visible?

Thanks.