美文网首页
Libgdx实现圆形进度条

Libgdx实现圆形进度条

作者: 贼噶人 | 来源:发表于2021-01-11 14:43 被阅读0次
    image.png
    package com.mytian.mgarden.stages.other;
    
    import com.badlogic.gdx.graphics.Color;
    import com.badlogic.gdx.graphics.Texture;
    import com.badlogic.gdx.graphics.g2d.Batch;
    import com.badlogic.gdx.graphics.g2d.PolygonSpriteBatch;
    import com.badlogic.gdx.math.Vector2;
    import com.badlogic.gdx.scenes.scene2d.Group;
    import com.badlogic.gdx.scenes.scene2d.InputEvent;
    import com.badlogic.gdx.scenes.scene2d.Touchable;
    import com.badlogic.gdx.scenes.scene2d.ui.Image;
    import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
    
    public class CircularSeekBar extends Group {
        private Texture backgroundT;
        private Texture progressT;
        private float progress = 0;
        private float backgroundX;
        private float backgroundY;
        private float progressX;
        private float progressY;
        private float barX;
        private float barY;
        private float radius;
        private Image bar;
        private ISeekProgressUpdate iSeekProgressUpdate;
        public int duration;
        private float[] polygonVertices;
        private short[] polygonTriangles;
    
        public void setiSeekProgressUpdate(ISeekProgressUpdate iSeekProgressUpdate) {
            this.iSeekProgressUpdate = iSeekProgressUpdate;
        }
    
        public interface ISeekProgressUpdate {
            void OnSeekProgressUpdate(float progress);
        }
    
    
        public CircularSeekBar(final Texture backgroundT
                , final Texture progressT, final Texture barT) {
            this.backgroundT = backgroundT;
            this.progressT = progressT;
            backgroundT.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear);
            progressT.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear);
            barT.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear);
            setSize(Math.max(backgroundT.getWidth(), progressT.getWidth())
                            + barT.getWidth() / 2
                    , Math.max(backgroundT.getHeight(), progressT.getHeight())
                            + barT.getHeight() / 2);
            backgroundX = (getWidth() - backgroundT.getWidth()) / 2;
            backgroundY = (getHeight() - backgroundT.getHeight()) / 2;
            progressX = (getWidth() - progressT.getWidth()) / 2;
            progressY = (getHeight() - progressT.getHeight()) / 2;
            radius = progressT.getWidth() / 2;
            bar = new Image(barT);
            barY = (float) (getHeight() / 2 + (getHeight() / 2 - 8)
                    * Math.cos(Math.toRadians(360 * progress)));
            barX = (float) (getWidth() / 2 + (getWidth() / 2 - 8)
                    * Math.sin(Math.toRadians(360 * progress)));
            addActor(bar);
            bar.setPosition(barX - bar.getWidth() / 2
                    , barY - bar.getHeight() / 2);
            bar.setTouchable(Touchable.disabled);
            addListener(new ClickListener() {
                @Override
                public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
                    super.touchDown(event, x, y, pointer, button);
                    if (bar.getX() + bar.getWidth() > x && x > bar.getX() - bar.getWidth()
                            && bar.getY() + bar.getHeight() > y && y > bar.getY() - bar.getHeight()) {
                        return true;
                    }
                    return false;
                }
    
                @Override
                public void touchDragged(InputEvent event, float x, float y, int pointer) {
                    super.touchDragged(event, x, y, pointer);
                    final Vector2 vector21 = new Vector2(0, getHeight() / 2);
                    final Vector2 vector22 = new Vector2(x - getWidth() / 2
                            , y - getHeight() / 2);
                    float m =
                            (float) ((vector21.x * vector22.x + vector21.y * vector22.y) / (Math.sqrt(vector21.x * vector21.x + vector21.y * vector21.y)
                                    * Math.sqrt(vector22.x * vector22.x + vector22.y * vector22.y)));
                    float degrees = (float) Math.toDegrees(Math.acos(m));
                    if (x > getWidth() / 2) {
                        progress = degrees / 360;
                    } else {
                        progress = (360 - degrees) / 360;
                    }
                    barY = (float) (getHeight() / 2 + (getHeight() / 2 - 8)
                            * Math.cos(Math.toRadians(360 * progress)));
                    barX = (float) (getWidth() / 2 + (getWidth() / 2 - 8)
                            * Math.sin(Math.toRadians(360 * progress)));
                    bar.setPosition(barX - bar.getWidth() / 2
                            , barY - bar.getHeight() / 2);
                }
    
                @Override
                public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
                    super.touchUp(event, x, y, pointer, button);
                    if (null != iSeekProgressUpdate) {
                        iSeekProgressUpdate
                                .OnSeekProgressUpdate(progress);
                    }
                }
            });
        }
    
    
        public void setProgress(final float progress, final int duration) {
            this.progress = Math.min(1, progress);
            barY = (float) (getHeight() / 2 + (getHeight() / 2 - 8)
                    * Math.cos(Math.toRadians(360 * progress)));
            barX = (float) (getWidth() / 2 + (getWidth() / 2 - 8)
                    * Math.sin(Math.toRadians(360 * progress)));
            bar.setPosition(barX - bar.getWidth() / 2, barY - bar.getHeight() / 2);
            this.duration = duration;
        }
    
    
        static int SPLIT_NUMS = 180;
    
        @Override
        protected void positionChanged() {
            super.positionChanged();
            backgroundX += getX();
            backgroundY += getY();
            progressX += getX();
            progressY += getY();
            barY = (float) (getHeight() / 2 + (getHeight() / 2 - 8)
                    * Math.cos(Math.toRadians(360 * progress)));
            barX = (float) (getWidth() / 2 + (getWidth() / 2 - 8)
                    * Math.sin(Math.toRadians(360 * progress)));
            bar.setPosition(barX - bar.getWidth() / 2, barY - bar.getHeight() / 2);
            polygonVertices = new float[(SPLIT_NUMS + 1) * 5];
            float color = Color.WHITE.toFloatBits();
            polygonVertices[0] = radius + progressX;
            polygonVertices[1] = radius + progressY;
            polygonVertices[2] = color;
            polygonVertices[3] = 0.5f;
            polygonVertices[4] = 0.5f;
            for (int i = 0; i < SPLIT_NUMS; i++) {
                polygonVertices[5 * (i + 1)] =
                        (float) (radius + radius * Math.sin(2 * Math.PI / SPLIT_NUMS * i)) + progressX;
                polygonVertices[5 * (i + 1) + 1] =
                        (float) (radius + radius * Math.cos(2 * Math.PI / SPLIT_NUMS * i)) + progressY;
                polygonVertices[5 * (i + 1) + 2] = color;
                polygonVertices[5 * (i + 1) + 3] =
                        (float) (0.5f + 0.5f * Math.sin(2 * Math.PI / SPLIT_NUMS * i));
                polygonVertices[5 * (i + 1) + 4] =
                        (float) (0.5f + 0.5f * Math.cos(2 * Math.PI / SPLIT_NUMS * i));
            } // 三角形坐标点,颜色、U、V坐标
            polygonTriangles = new short[SPLIT_NUMS * 3];
            for (int i = 0; i < SPLIT_NUMS; i++) {
                polygonTriangles[3 * i] = 0;
                polygonTriangles[3 * i + 1] = (short) (i + 1);
                if (i == SPLIT_NUMS - 1) {
                    polygonTriangles[3 * i + 2] = 1;
                } else {
                    polygonTriangles[3 * i + 2] = (short) (i + 2);
                }
            } // 画三角形时的顶点索引坐标
        }
    
        @Override
        public void draw(final Batch batch, final float parentAlpha) {
            batch.draw(backgroundT, backgroundX, backgroundY);
            if (batch instanceof PolygonSpriteBatch) {
                final int nums = (int) (SPLIT_NUMS * progress);
                ((PolygonSpriteBatch) batch).draw(progressT, polygonVertices
                        , 0, Math.min((nums + 2) * 5, polygonVertices.length),
                        polygonTriangles, 0
                        , Math.min(nums * 3, polygonTriangles.length)); //画圆
            }
            super.draw(batch, parentAlpha);
        }
    }
    

    原理是根据OpenGL 画三角形,来生成圆,然后把纹理UV坐标映射到三角形。

    相关文章

      网友评论

          本文标题:Libgdx实现圆形进度条

          本文链接:https://www.haomeiwen.com/subject/qwrdaktx.html