Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Word wrapping makes the last word of a text line jumps into the next line as it gets longer during text advancement #116

Open
FiveYellowMice opened this issue Jul 19, 2020 · 13 comments

Comments

@FiveYellowMice
Copy link

FiveYellowMice commented Jul 19, 2020

I've noticed that on narrow screens, due to the nature of browser's word wrapping, if the last word of a particular text line is long, it may apear at the end of the line first, when not all of its characters have been shown yet:

mi1

Then, when the word is long enough that can't fit anymore, it "jumps" into the next line.

mi2

This probably isn't a good user experience and I don't seem to have noticed on other visual novel engines. It's not so bad on desktops, where the text box is so long that it doesn't happen very often, but on mobile devices this is kind of distracting in my opinion.

As for a fix, I think perhaps one way is to put all of the dialog piece inside of the text box element at once, but with opacity: 0, and then progressively changes the opacity of each character to 100%. This way the browser knows how long each word is at once and don't have to re-layout.

@Hyuchia
Copy link
Member

Hyuchia commented Jul 22, 2020

@FiveYellowMice Hi! Thanks for reporting this, I agree this is not an ideal behaviour, right now Monogatari uses a fork of Typed.js for the typewrite animation. Solving this will require some work since we would either have to solve it in that library or, create our own.

Doing the opacity change is a good solution but would need each character to be in it's own HTML element so we still need to figure out what's the best option to solve this.

@LoganTann
Copy link
Contributor

A possible way to get rid of this behavior is to use the css trick I have explained in Discord to show the text word by word. Unfortunately, this is definitely not the good solution.


I added this in the main.css

[data-toAfter]:after {
  content: attr(data-toAfter);
}

and replaced yourWord by<span data-toAfter="yourWord"></span>

An example that mixes both characters by characters and word by word

shin all of it emitting <span data-toAfter="noise"></span> {pause:100}  <span data-toAfter="noise"></span> {pause:100}  <span data-toAfter="noise"></span>

gif screenshot

This is possible to create a custom action that converts every word into a <span data-toAfter=""> element.

@ComedyTomedy
Copy link

Just discovered Monogatari and found the same thing jarring.

If the text never contains HTML, i.e. there will never be bold or italics, characters could be simply moved over from one span to another.

<p>
  <span class="visible">The future is</span>
  <span class="hidden"> yet to be decided</span>
</p>

But presumably text will want to contain other elements sometimes, so I think the only answer is to walk the text's DOM and wrap characters in individual elements, then later step through them with setInterval or a recursive setTimeout.

DOM performance should be okay, because they're never large texts.

CSS { visibility: [hidden|visible] } rather than opacity would make most sense as the property to animate.

@FiveYellowMice
Copy link
Author

FiveYellowMice commented Sep 9, 2021

Having a <span> for every single character definetely sound like it could be a good idea, if DOM performance really isn't bad (I have never tested it).

Also, thanks for reviving the issue. I was planning to make a PoC at the start, but then just got busy and forgot. (Still don't have time for a PR though)

@ComedyTomedy
Copy link

Hello again @FiveYellowMice and @Hyuchia ☺ I've made a small library to do wrapped typing. It's been a learning journey! It's the first thing I've ever put on Github.

https://github.com/ComedyTomedy/typewrapper

It's very basic, and has no fancy controls. It's pretty much what I said in my previous comment, but doesn't wrap characters in individual elements.

@FiveYellowMice
Copy link
Author

Neat!

@LoganTann
Copy link
Contributor

Hello again @FiveYellowMice and @Hyuchia ☺ I've made a small library to do wrapped typing. It's been a learning journey! It's the first thing I've ever put on Github.

https://github.com/ComedyTomedy/typewrapper

It's very basic, and has no fancy controls. It's pretty much what I said in my previous comment, but doesn't wrap characters in individual elements.

Oh, the way you've created this is quite clever, awesome work !
I'm looking forward for compatibility with monogatari 👀

@ComedyTomedy
Copy link

Merci bcp! I've just looked at Monogatari's Dialog.js, and it's quite a big job to make a drop-in replacement.

Perhaps there's a central "engine" in typed.js, and we can fork & replace. I may try at some point soon ☺ but right now I'm both (1) too busy, and (2) underskilled, since I'm not a developer, and don't know Typescript, OOP, etc.

On the other hand I imagine it's fairly easy to hack Monogatari to accept my thingy, albeit with fewer options. It should probably announce when it's finished typing; that would be a good change.

@frameDoubt
Copy link

So I'm not sure if you've tried a couple CSS properties on the [data-component="text-box"] selector in main.css:

hyphens: auto;
word-break: break-all;

They can both do interesting thing with word-wrapping.

@FiveYellowMice
Copy link
Author

FiveYellowMice commented Mar 28, 2022

[data-component="text-box"]

It doesn't seem that an element matching this selector exists, I assume you are referring to [data-ui="text"] ?

word-break: break-all;

This would indeed stop the characters from jumping to the next line, but it would also break words into halves. It's not ideal, although it can be a viable compromise.

@frameDoubt
Copy link

[data-component="text-box"]

It doesn't seem that an element matching this selector exists, I assume you are referring to [data-ui="text"] ?

this selector is used to add styles to the src/components/text-box/index.js component, which components are you trying to style?

@FiveYellowMice
Copy link
Author

Screenshot_20220329_090728

I don't know what component it is since it doesn't have a data-component attribute, but this is the element I was trying to style. It's from the demo.

It looks like text-box only became a thing in v2, but the demo still uses v1, so that's why I can't find it. Anyway, they seem to be counterparts of each other, so I think we are on the same page as far as the effects of hyphens and work-break go.

@frameDoubt
Copy link

Oh, ha. Ok, I'll see if I can look into that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants