4
3

Modifier.graphicsLayerでPCの開閉を再現してみた

Last updated at Posted at 2023-12-21

Android Jetpack composeのModifier.graphicsLayerの紹介

graphicsLayerを使うと,物体の位置や,回転,縮小などを指定することができます.

指定可能な主な引数

graphicsLayer(
    scaleX: Float,
    scaleY: Float,
    alpha: Float,
    translationX: Float,
    translationY: Float,
    shadowElevation: Float,
    rotationX: Float,
    rotationY: Float,
    rotationZ: Float,
    cameraDistance: Float,
    transformOrigin: TransformOrigin,
)

各引数を簡単に説明します.
具体例はこのサイトで物凄く分かりやすくまとめられてます.

scaleX/Y

X軸Y軸で大きさを変化

Text("a", modifier=Modifier.graphicsLayer(scaleX=1.5f))

alpha

透明度の変化

translationX/Y

X軸Y軸方向の横移動

shadowElevation

影の距離

rotationX/Y/Z

X軸Y軸Z軸に対して回転
回転の基準点は,transformOriginで指定

cameraDistance

回転時にどれだけ遠近感をつけるか.小さいほどこちらに向かって大きく拡大する

実装例

回転角によって表示する画像を切り替えることで,下記のようなコトが出来ます.
(rotationXが90以上の場合で切り替えています.)

trimmed.gif

@Composable
fun PC(
    rotateX: Float,
    width: Dp,
    height: Dp,
    cameraDistance: Float,
){
    val isOpen = (abs(rotateX) % 360) > 90f
    Box {
        Box(
            modifier = Modifier
                .width(width)
                .height(height)
                .clip(RoundedCornerShape(8))
        ){
            Image(painterResource(R.drawable.keyboard),
                "キーボード画像",
                contentScale = ContentScale.FillBounds,)
        }
        if(isOpen){
            Box(
                modifier = Modifier
                    .graphicsLayer(
                        rotationX = rotateX,
                        transformOrigin = TransformOrigin(0.5f, 0f),
                        cameraDistance = cameraDistance
                    )
                    .width(width)
                    .height(height)
                    .clip(RoundedCornerShape(8))
            ){
                Image(painterResource(R.drawable.screen),
                    "スクリーン画像",
                    contentScale = ContentScale.FillBounds,)
            }
        }else{
            Box(
                modifier = Modifier
                    .graphicsLayer(
                        rotationX = rotateX,
                        transformOrigin = TransformOrigin(0.5f, 0f),
                        cameraDistance = cameraDistance
                    )
                    .width(width)
                    .height(height)
                    .clip(RoundedCornerShape(8))
            ){
                Image(painterResource(R.drawable.top),
                    "PC上面画像",
                    contentScale = ContentScale.FillBounds,)
            }
        }
    }
}
@Composable
fun PcOpenAndClose(){
    var open by remember{ mutableStateOf(false) }
    val alpha: Float by animateFloatAsState(
        if (open) 0f else 130f,
        animationSpec = tween(
            durationMillis = 800,
            delayMillis = 50,
            easing = LinearOutSlowInEasing
        ), label = ""
    )

    Column(
        horizontalAlignment = Alignment.CenterHorizontally
    ){
        PC(rotateX = alpha, width = 230.dp, height = 130.dp, cameraDistance = 11.0f)
        Spacer(Modifier.height(20.dp))
        Button(onClick = { open = !open }) {
            Text(text = "ぽちぽち")
        }
    }
}
4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3