• Runtimes
  • How to make the size of Root as the size of the canvas

You would need a way of knowing which attachment is that background. Then you can get the attachment and inspect it to determine its size and position.

You could use the first slot found on the root bone, but there may be multiple. The order of slots is not controlled on the bone, it is done in the draw order. I think it would be easier to use a name, like bg. It should still be under the root bone though, so you don't need to compute the world position.

If you use a region attachment, it has x, y, width, and height properties. Note the X and Y are the center of the region attachment.

It looks like you are using a clipping attachment. If you name that bg and put it in a bg slot, then you can easily find it. Loop through the vertices and take the min and max values for X and Y out of all the vertices. minX and minY are your viewport X and Y. maxX - minX and maxY - minY are the viewport width and height.

Make sure the clipping attachment is not weighted to bones, otherwise the vertices are in a more complex format. They shouldn't be animating the clipping attachment vertices for the viewport anyway.

    Related Discussions
    ...

    Nate Sounds complex for a newbie to Spine, It seems that I should do the calculation in the frame or update callback?

    You need to set the viewport once in the beginning. Start by getting the example to run:
    https://github.com/EsotericSoftware/spine-runtimes/tree/4.1/spine-ts/spine-player/example

    Eg, install Python 3 if you don't have it, change to the spine-ts/spine-player folder, then:

    python -m http.server

    Then open a browser to:
    http://localhost:8000/example/example.html

    Look at the callbacks available:
    https://github.com/EsotericSoftware/spine-runtimes/blob/4.1/spine-ts/spine-player/src/Player.ts#L145-L162

    Use the success callback so your code runs after the skeleton is loaded. See docs here:
    https://esotericsoftware.com/spine-player#Advanced-playback

    Figure out how to get an attachment by name:
    http://esotericsoftware.com/spine-api-reference#Skeleton-getAttachment2
    The API is generic and applies to all languages. Check the spine-ts code to be sure of the method you want to call:
    https://github.com/EsotericSoftware/spine-runtimes/blob/4.1/spine-ts/spine-core/src/Skeleton.ts#L515

    Now you can modify the example:

    new spine.SpinePlayer("container", {
    	skelUrl: "assets/spineboy-pro.skel",
    	atlasUrl: "assets/spineboy-pma.atlas",
    	premultipliedAlpha: true,
    	backgroundColor: "#cccccc",
    	viewport: {
    		debugRender: true,
    	},
    	showControls: false,
    	success: function (player) {
    		var vertices = player.skeleton.getAttachmentByName("head-bb", "head").vertices;
    		var minX = 99999, minY = 99999, maxX = -99999, maxY = -99999;
    		for (var i = 0, n = vertices.length; i < n; i += 2) {
    			var x = vertices[i], y = vertices[i + 1];
    			minX = Math.min(minX, x);
    			minY = Math.min(minY, y);
    			maxX = Math.max(maxX, x);
    			maxY = Math.max(maxY, y);
    		}
    		player.config.viewport.x = minX;
    		player.config.viewport.y = minY;
    		player.config.viewport.width = maxX - minX;
    		player.config.viewport.height = maxX - minX;
    
    		// Needed to show skeleton when no animation is specified (bug fixed in 4.2):
    		player.skeleton.updateWorldTransform();
    	}
    });

    For that to work you'll have to move the spineboy head-bb slot to the root (here spineboy-pro.skel), then you get:

      Nate I did find the Background Attachment, But I didn't find the vertices properties, I use code below

            success(player) {
              player.paused = false
              const bg = player.skeleton?.getAttachmentByName('Background', 'Background')
              player.config.viewport.x = bg.x
              player.config.viewport.y = bg.y
              player.config.viewport.width = bg.width
              player.config.viewport.height = bg.height
              player.skeleton.updateWorldTransform()
      
              const animation = player.skeleton?.data?.animations?.[0]?.name
              player.setAnimation(animation)
      }

      It turns out

      You don't get a vertices array, because your attachment is a region, not a mesh. Set viewport.x to bg.x - bg.width / 2 and viewport.y to bg.y - bg.height / 2.

      Yep, or use the clipping attachment, not the background.

        Nate designer did give me a clipping attachment
        using player.skeleton?.getAttachmentByName('Background', 'Background') can get an Attachment, but getAttachmentByName('Background'2, 'Background') can not, it throw an error says: Can't find slot with name Background2

        Likely your export doesn't match the project file. Also to get the clipping attachment, use it's name eg 'Background2', 'Background2'.

          Nate It' works well, but it still has some black area in the top and bottom, how can I cut them off

          You'll need to adjust the size of your canvas to match the attachment width and height. Note that you'll need to set both canvas.width/.height and canvas.style.width/height.

            Mario My canvas' size is equal to the screen of the user's phone. Is it possible to adjust the size of viewport to match the canvas's size

            Your problem is that your background aspect ratio doesn't match your canvas size. There are only 3 solutions:

            1. You could stretch your Spine skeleton to fill the canvas.
            2. You could zoom in so the height fills the canvas, but that will cut off some of the Spine skeleton on the left and right edges.
            3. You could live with the "black bars".

            I suggest option 2. To do it you need to calculate the viewport size and position based on 1) your background size, as we've already computed above, and 2) the aspect ratio of the user's screen. To do that you can look at the functions provided here:
            https://github.com/libgdx/libgdx/blob/master/gdx/src/com/badlogic/gdx/utils/Scaling.java
            Each function is a different way of fitting a source width/height (your background size) to a target width/height (the user's screen size). The result is the width height you want to use for your viewport, which you should center using this x, y, width, height:

            -width / 2, height / 2 - bgHeight / 2, width, height

            Which scaling function you choose from my link is up to you. To fill the screen, choose fill.

            I also suggest that you get rid of that clipping attachment. Clipping uses a lot of CPU, based on how many triangles you are clipping. See here:
            http://esotericsoftware.com/spine-clipping#Performance
            When you are clipping your ENTIRE skeleton, like you are doing, it can use a lot of CPU. That may be acceptable, especially if your app isn't doing much else. However, if it is not needed, then it is wasteful. With option 2, any content off screen can't be seen anyway, so clipping is not needed.