cubing / cubing.js

🛠 A library for displaying and working with twisty puzzles. Also currently home to the code for Twizzle.
https://js.cubing.net/cubing/
GNU General Public License v3.0
232 stars 42 forks source link

How to change TwistyPlayer render size? #320

Closed Wyverex42 closed 4 months ago

Wyverex42 commented 4 months ago

Goal

Sorry if this is a dumb question but I'm trying to control the rendered size of a TwistyPlayer and so far I haven't been able to.

My goal is to have a grid of rendered puzzles on a page representing different training cases. I first tried to generate screenshots using the experimentalScreenshot function. That lets me control the size but when I have more than one on a single page, only the last case is rendered into all of the images.

So now I tried appending the TwistyPlayers themselves, but the canvas always seems to have a fixed size and doesn't respect the fixed size of the div I'm appending it to. I think I tracked it down to this.contentWrapper.clientWidth; in Twisty3DVantage.ts but I'm not sure where the contentWrapper is getting its size from.

Am I missing something obvious?

Btw: If the TwistyPlayer itself is too heavyweight to render multiple instances of (I'd expect up to around 50 on a page), I'm happy to accept a different solution as well.

Thanks!

Possible solution

Maybe have an config option to specify the canvas size?

Alternatives

No response

Wyverex42 commented 4 months ago

Update:

I've tracked it down to https://github.com/cubing/cubing.js/blob/38d73c08c30e0697aa02c333395a860a47c3f522/src/cubing/twisty/views/TwistyPlayer.css.ts#L8 (and learned about shadow DOM along the way).

Seems the size is just fixed and can't be changed. I've hacked in a solution locally where I create that string with width and height parameters (and then use patch-package) which is good enough for my use case. Would be curious to know though what your plans are!

lgarron commented 4 months ago

Indeed, the reason there are no attributes or properties for size is that this is a job for CSS. Eventually we'll have some example/recipe pages, but right now it's undocumented because it's specifically not a feature. 😆

<twisty-player> comes with a default size, as you've found. You can override this with what you need, such as width: 100% and height: 100% if you need to fill a container.

Btw: If the TwistyPlayer itself is too heavyweight to render multiple instances of (I'd expect up to around 50 on a page), I'm happy to accept a different solution as well.

This should definitely not be the case; it's designed to have a lot of copies for rendering alg cases. If you see performance issues, please let us know!

Wyverex42 commented 4 months ago

You can override this with what you need, such as width: 100% and height: 100% if you need to fill a container.

What would be the approach for this though? As far as I understand, you can't influence a shadow DOM from the outside, except by setting adoptedStyleSheets on the shadow root. I tried doing that using twistyPlayer.shadow.adoptedStyleSheets.push(myStylesheet); (since the addCSS function is not exposed) where the stylesheet was a replacement of the :host class, but those changes were never applied. My thinking was that if I apply this after the default stylesheet, my changes should take precedence. I also made sure that the shadow root existed by awaiting one of the various promises on the player. I'm probably missing something very obvious.

I'd much rather control the CSS correctly from the outside than using my dirty hack.

it's designed to have a lot of copies for rendering alg cases

That's good to know!

lgarron commented 4 months ago

Yeah, trying to modify the internal CSS is unsupported and may break at any moment.

What would be the approach for this though?

Just regular ol' CSS. You can set it on the element directly:

<script src="https://cdn.cubing.net/js/cubing/twisty" type="module"></script>

<twisty-player
  alg="R U R' U R U2' R'"
  style="width: 100%;"
></twisty-player>

Or using a style sheet:

<script src="https://cdn.cubing.net/js/cubing/twisty" type="module"></script>

<twisty-player
  alg="R U R' U R U2' R'"
  class="full-size"
></twisty-player>

<style>
  .full-size {
    width: 100%;
    height: 100%;
  }
</style>
Wyverex42 commented 4 months ago

D'oh, I wasn't even considering this! Tbf, I'm creating the player in code and then appending it to a div, but still... Thanks!

On a potentially related note: Is there a way to disable the initial fade-in when the player is created?

lgarron commented 4 months ago

Glad we got that figured out!

On a potentially related note: Is there a way to disable the initial fade-in when the player is created?

No, that's not configurable at the moment. If this makes it hard to work for some use cases, please let us know in another issue with more details!