当前位置:网站首页>Cool 3D sphere text cloud effect!

Cool 3D sphere text cloud effect!

2022-06-23 21:15:00 User 9239674

cause

I saw one on the Internet a few days ago h5 It's more dazzling 3D Sphere text effect , I think it's interesting , Just ready to Android Side to side reproduction , Don't talk nonsense , Let's take a look at the effect (gif Looks like some cards , Actually not )

The core principle

Text coordinates

The first thing to do is to determine a coordinate for each text ,Android It's a left-handed coordinate system , And our effect is a sphere , So I use the spherical coordinate system to calculate the coordinates of each text .

y = radius * cos(Math.toRadians(this.upDegree))
z = -radius * sin(Math.toRadians(this.upDegree)) * sin(Math.toRadians(this.bottomDegree))
x = radius * sin(Math.toRadians(this.upDegree)) * cos(Math.toRadians(this.bottomDegree))

among radius Is the length of the line from the center of the circle to the sphere , That's the radius of the sphere ,upDegree For connecting with y The angle in the positive direction of the axis , The scope is [0,180],bottomDegree For connection at xz The projection on the plane determined by the axis and x The angle in the positive direction of the axis , The scope is [0,360].

Text color and size

When the text goes to and x The included angle in the positive direction of the shaft is 90 When , At this time, the text is the largest , The darkest color ,270 Minimum in degrees , Lightest color ,270 C to 360 Degree is the inverse of the above process . To do this, we define a variable factor Used to describe the change degree of text color and size , The scope is 【minFactor,1】minFactor Can be passed in through external variables .

According to the previous description , We can be sure factor The function of is

 factor = minFactor.coerceAtLeast(
            when (bottomDegree) {
                in 0.0..90.0 -> {
                    1.0 / Math.PI * Math.toRadians(bottomDegree) + 0.5
                }
                in 270.0..360.0 -> {
                    1.0 / Math.PI * Math.toRadians(bottomDegree) - 1.5
                }
                else -> {
                    -1.0 / Math.PI * Math.toRadians(bottomDegree) + 1.5
                }
            }
        )

By constructing three piecewise linear functions from different angles .

Calculate the text coordinates

Defining classes WordItem Used to represent each text , Coordinates and their corresponding factor, stay onMeasure Calculate the corresponding coordinates for all text when , And stored in wordItemList In the member variable .

class WordItem(
    var text: String,
    var upDegree: Double = 0.0,
    var bottomDegree: Double = 0.0,
    var x: Double = 0.0,
    var y: Double = 0.0,
    var z: Double = 0.0,
    var factor: Double = 0.0
) {

    fun cal(radius: Double, upDegree: Double, bottomDegree: Double, minFactor: Double) {
        this.upDegree = upDegree % 180
        this.bottomDegree = bottomDegree % 360
        y = radius * cos(Math.toRadians(this.upDegree))
        z = -radius * sin(Math.toRadians(this.upDegree)) * sin(Math.toRadians(this.bottomDegree))
        x = radius * sin(Math.toRadians(this.upDegree)) * cos(Math.toRadians(this.bottomDegree))
        factor = minFactor.coerceAtLeast(
            when (bottomDegree) {
                in 0.0..90.0 -> {
                    1.0 / Math.PI * Math.toRadians(bottomDegree) + 0.5
                }
                in 270.0..360.0 -> {
                    1.0 / Math.PI * Math.toRadians(bottomDegree) - 1.5
                }
                else -> {
                    -1.0 / Math.PI * Math.toRadians(bottomDegree) + 1.5
                }
            }
        )
    }

    fun move(radius: Double, upOffset: Double, bottomOffset: Double, minFactor: Double) {
        cal(radius, upDegree + upOffset, bottomDegree + bottomOffset, minFactor)
    }
}
private fun genWordItemList(): MutableList<WordItem>? {
        wordList?.let { list ->
            val wordItemList = mutableListOf<WordItem>()
            var upDegree = 0.0
            for (row in 0 until circleRowNum) {
                upDegree += upDegreeGap
                upDegree %= 180.0
                var bottomDegree = 0.0
                for (col in 0 until perNumInCircle) {
                    val index = row * perNumInCircle + col
                    if (index < wordList?.size ?: 0) {
                        bottomDegree += bottomDegreeGap
                        bottomDegree %= 360.0
                        val wordItem = WordItem(list[index])
                        wordItem.cal(radius, upDegree, bottomDegree, minFactor)
                        wordItemList.add(wordItem)
                    }
                }
            }
            return wordItemList
        }
        return null
    }

Draw text

First of all, according to the factor Set the size of the brush text and the corresponding alpha value , Then calculate the corresponding position according to the text size , Drawing , And it's growing bottomDegreeOffset, Modify the coordinates of each text , Achieve rotation .

canvas?.let { canvas ->
            wordItemList?.forEach { wordItem ->
                wordItem.move(radius, 0.0, 1.0, minFactor)
                paint.textSize = (wordItem.factor * maxTextSize).toFloat()
                paint.alpha = 30.coerceAtLeast((wordItem.factor * 255).toInt())
                textRect.setEmpty()
                paint.getTextBounds(wordItem.text, 0, wordItem.text.length, textRect)
                canvas.drawText(
                    wordItem.text,
                    ((width - paddingLeft - paddingRight) / 2 + wordItem.x - textRect.width() / 2).toFloat(),
                    ((height - paddingTop - paddingBottom) / 2 + wordItem.y - textRect.height() / 2).toFloat(),
                    paint
                )
            }
            postInvalidate()
        }

Android Advanced development system notes 、 The latest interview review notes PDF, my GitHub

At the end of the article What's your opinion on the article , Or any technical problems , Welcome to leave a message and discuss in the comment area !

原网站

版权声明
本文为[User 9239674]所创,转载请带上原文链接,感谢
https://yzsam.com/2021/12/202112251540125561.html