日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

html时钟自动刷新抖音,抖音上炫酷的网红文字时钟

發布時間:2023/12/10 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 html时钟自动刷新抖音,抖音上炫酷的网红文字时钟 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

原標題:抖音上炫酷的網紅文字時鐘

本文作者

作者:二娃_

https://juejin.im/post/5cb53e93e51d456e55623b07

1

起源

源碼地址

https://github.com/drawf/SourceSet/blob/master/app/src/main/java/me/erwa/sourceset/view/TextClockView.kt

周末在家刷抖音的時候看到了這款網紅時鐘,都是Android平臺的,想來何不自己實現一把。看抖音里大家發的視頻,這款時鐘基本分兩類,一類是展示在「壁紙」上,一類是展示在「鎖屏」上。

展示到「壁紙」通過LiveWallPaper相關API可以做到,這也是本專題要實現的方式。

展示到「鎖屏」目測是使用各ROM廠商的相關API,開發鎖屏主題可以做到。

然而實現兩者的基礎便是拿起Canvas Paint等把它繪制出來,所以「上篇」我先用自定View的方式把時鐘畫出來,在Activity中展示效果。「下篇」的時候再把該View結合LiveWallPaper設置到壁紙。

2

思考分析

這是我當時截圖下來的參考,先分析下涉及到的元素及樣式表現:

「圓中信息」圓中心的數字時間+數字日期+文字星期幾,始終為白色

「時圈」一圈文字小時,一點、二點..十二點,當前點數為白色,其它為白色+透明度,如圖中十點就是白色。

「分圈」一圈文字分鐘,一分、二分..五十九分,六十分顯示為空,同理,當前分鐘為白色,其它白色+透明度。

「秒圈」一圈文字秒,一秒、二秒..五十九秒,六十秒顯示為空,也是同理。

然后分析下動畫效果:

每秒鐘「秒圈」走一下,這一下的旋轉角度為360°/60=6°,并且走這一下的時候有個線性旋轉過去的動畫效果。

每分鐘「分圈」走一下,旋轉角度和動畫效果跟「秒圈」相同。

每小時「時圈」走一下,旋轉角度為360°/12=30°,動畫效果同上。

3

繪制靜態圖

1. 畫布準備

基本是將畫布背景填充黑色,然后將畫布的原點移動到View大小的中心,這樣方便思維理解與繪制。

//在onLayout方法中計算View去除padding后的寬高

overridefunonLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int){

super.onLayout(changed, left, top, right, bottom)

mWidth = (measuredWidth - paddingLeft - paddingRight).toFloat

mHeight = (measuredHeight - paddingTop - paddingBottom).toFloat

//后文會涉及到

//統一用View寬度*系數來處理大小,這樣可以聯動適配樣式

mHourR = mWidth * 0.143f

mMinuteR = mWidth * 0.35f

mSecondR = mWidth * 0.35f

}

//在onDraw方法將畫布原點平移到中心位置

overridefunonDraw(canvas: Canvas?){

super.onDraw(canvas)

if(canvas == null) return

canvas.drawColor(Color.BLACK) //填充背景

canvas.save

canvas.translate(mWidth / 2, mHeight / 2) //原點移動到中心

//繪制各元件,后文會涉及到

drawCenterInfo(canvas)

drawHour(canvas, mHourDeg)

drawMinute(canvas, mMinuteDeg)

drawSecond(canvas, mSecondDeg)

//從原點處向右畫一條輔助線,之后要處理文字與x軸的對齊問題,稍后再說

canvas.drawLine( 0f, 0f, mWidth, 0f, mHelperPaint)

canvas.restore

}

2. 畫「圓中信息」

經過第一步,可以在AS的Xml Preview中看到一屏黑色+一條從屏幕中心到右邊界的紅線。(一眼望去,還是挺美的)

/**

* 繪制圓中信息

*/

privatefundrawCenterInfo(canvas: Canvas){

Calendar.getInstance.run {

//繪制數字時間

valhour = get(Calendar.HOUR_OF_DAY)

valminute = get(Calendar.MINUTE)

mPaint.textSize = mHourR * 0.4f //字體大小根據「時圈」半徑來計算

mPaint.alpha = 255

mPaint.textAlign = Paint.Align.CENTER

canvas.drawText( "$hour:$minute", 0f, mPaint.getBottomedY, mPaint)

//繪制月份、星期

valmonth = ( this. get(Calendar.MONTH) + 1).let {

if(it < 10) "0$it"else"$it"

}

valday = this. get(Calendar.DAY_OF_MONTH)

valdayOfWeek = ( get(Calendar.DAY_OF_WEEK) - 1).toText //私有的擴展方法,將Int數字轉換為 一、十一、二十等,后文繪制三個文字圈都會用該方法

mPaint.textSize = mHourR * 0.16f //字體大小根據「時圈」半徑來計算

mPaint.alpha = 255

mPaint.textAlign = Paint.Align.CENTER

canvas.drawText( "$month.$day星期$dayOfWeek", 0f, mPaint.getTopedY, mPaint)

}

}

/**

* 擴展獲取繪制文字時在x軸上 垂直居中的y坐標

*/

privatefunPaint.getCenteredY: Float{

returnthis.fontSpacing / 2- this.fontMetrics.bottom

}

/**

* 擴展獲取繪制文字時在x軸上 貼緊x軸的上邊緣的y坐標

*/

privatefunPaint.getBottomedY: Float{

return- this.fontMetrics.bottom

}

/**

* 擴展獲取繪制文字時在x軸上 貼近x軸的下邊緣的y坐標

*/

privatefunPaint.getToppedY: Float{

return- this.fontMetrics.ascent

}

其中要說一下mPaint.getBottomedY mPaint.getToppedY,這是兩個擴展到Paint畫筆上的兩個kotlin方法。

他們的作用是為了處理繪制文字時與x軸的對齊關系。canvas.drawText方法的第三個參數是y坐標,但這個指的是文字的Baseline的y坐標,所以寫了工具方法來得到矯正后的y坐標。(這里就只拋出這個點吧,具體實現原理可先查閱Paint類的相關API就會明白,文末會貼出我拜讀的文章鏈接)

拿繪制數字時間舉例,展示下不同效果:

把mPaint.getBottomedY替換成0f(y坐標為0,就是文字的Baseline坐標為0),文字使用15:67 abc jqk,可以看到兩者區別。(紅線就是前文畫的那條好美的輔助線)

canvas.drawText("15 :67測試文字 abcjqk", 0 f, 0 f, mPaint)

canvas.drawText("15 :67測試文字 abcjqk", 0 f, mPaint.getBottomedY, mPaint)

ok,「圓中信息」繪制后長這個樣子:

3. 畫「時圈」「分圈」「秒圈」

繪制思路就是for循環12次,每次將畫布旋轉30°乘以i,然后在指定位置繪制文字,12次后剛好一個圓圈。

該方法接收一個degrees: Float參數,是控制「時圈」整體的旋轉的,后文就是不斷改變該值,而產生動畫效果的。并且因為三個圈的動畫方向都是逆時針,所以這個degrees是個始終會是個負數。

/**

* 繪制小時

*/

privatefundrawHour(canvas: Canvas, degrees: Float){

mPaint.textSize = mHourR * 0.16f

//處理整體旋轉

canvas.save

canvas.rotate(degrees)

for(i in0until 12) {

canvas.save

//從x軸開始旋轉,每30°繪制一下「幾點」,12次就畫完了「時圈」

valiDeg = 360/ 12f * i

canvas.rotate(iDeg)

//這里處理當前時間點的透明度,因為degrees控制整體逆時針旋轉

//iDeg控制繪制時順時針,所以兩者和為0時,剛好在x正半軸上,也就是起始繪制位置。

mPaint.alpha = if(iDeg + degrees == 0f) 255else( 0.6f * 255).toInt

mPaint.textAlign = Paint.Align.LEFT

canvas.drawText( "${(i + 1).toText}點", mHourR, mPaint.getCenteredY, mPaint)

canvas.restore

}

canvas.restore

}

同理繪制「分圈」「秒圈」

/**

* 繪制分鐘

*/

privatefundrawMinute(canvas: Canvas, degrees: Float){

mPaint.textSize = mHourR * 0.16f

//處理整體旋轉

canvas.save

canvas.rotate(degrees)

for(i in0until 60) {

canvas.save

valiDeg = 360/ 60f * i

canvas.rotate(iDeg)

mPaint.alpha = if(iDeg + degrees == 0f) 255else( 0.6f * 255).toInt

mPaint.textAlign = Paint.Align.RIGHT

if(i < 59) {

canvas.drawText( "${(i + 1).toText}分", mMinuteR, mPaint.getCenteredY, mPaint)

}

canvas.restore

}

canvas.restore

}

/**

* 繪制秒

*/

privatefundrawSecond(canvas: Canvas, degrees: Float){

mPaint.textSize = mHourR * 0.16f

//處理整體旋轉

canvas.save

canvas.rotate(degrees)

for(i in0until 60) {

canvas.save

valiDeg = 360/ 60f * i

canvas.rotate(iDeg)

mPaint.alpha = if(iDeg + degrees == 0f) 255else( 0.6f * 255).toInt

mPaint.textAlign = Paint.Align.LEFT

if(i < 59) {

canvas.drawText( "${(i + 1).toText}秒", mSecondR, mPaint.getCenteredY, mPaint)

}

canvas.restore

}

canvas.restore

}

DuangDuang!!效果出來啦~

4. 讓時鐘轉起來

那么如何可以讓時鐘轉起來呢?我們再看一下onDraw中的代碼,繪制三個圈的方法都會接收一個相應的degrees: Float參數,這個是控制一個圈的整體旋轉的,而且要逆時針轉,所以始終得是負數。

這樣一來就好說了,只要控制這三個角度變化,就能讓時鐘動起來。

overridefunonDraw(canvas: Canvas?){

super.onDraw(canvas)

... //省略

//繪制各元件,后文會涉及到

drawCenterInfo(canvas)

drawHour(canvas, mHourDeg)

drawMinute(canvas, mMinuteDeg)

drawSecond(canvas, mSecondDeg)

... //省略

}

那么首先定義三個角度的全局變量,并把他們與實際的時間關聯起來,然后每隔一秒觸發一次View的重繪即可。

//定義三個角度的全局變量

privatevarmHourDeg: FloatbyDelegates.notNull

privatevarmMinuteDeg: FloatbyDelegates.notNull

privatevarmSecondDeg: FloatbyDelegates.notNull

/**

* 繪制方法

*/

fundoInvalidate{

Calendar.getInstance.run {

valhour = get(Calendar.HOUR)

valminute = get(Calendar.MINUTE)

valsecond = get(Calendar.SECOND)

//這里將三個角度與實際時間關聯起來,當前幾點幾分幾秒,就把相應的圈逆時針旋轉多少

mHourDeg = -360/ 12f * (hour - 1)

mMinuteDeg = -360/ 60f * (minute - 1)

mSecondDeg = -360/ 60f * (second - 1)

invalidate

}

}

然后只需在Activity中使用timer每秒鐘刷新一次View即可。效果如下圖,會發現轉是轉起來的,但是卻每秒一跳。再看一下咱們當時的分析:

每秒鐘「秒圈」走一下,這一下的旋轉角度為360°/60=6°,并且走這一下的時候有個線性旋轉過去的動畫效果。

所以是還差一個線性旋轉的效果。

//Activity中的代碼

privatevarmTimer: Timer? = null

privatefuncaseTextClock{

setContentView(R.layout.activity_stage_text_clock)

mTimer = timer(period = 1000) {

runOnUiThread {

stage_textClock.doInvalidate

}

}

}

overridefunonDestroy{

super.onDestroy

mTimer?.cancel

}

5. 讓時鐘轉的優雅點

基于我們已經知道了,時鐘動起來的本質就是在一段時間內(比如150ms)不斷的改變參數degrees: Float的值并觸發重繪方法,這樣就產生了人眼看到的動畫效果。

所以,我們想讓「秒圈」(三個圈的代表)轉的更線性更優雅一點,就可以在要開始繪制新的一秒的時候,在前150ms線性的旋轉6°。

init {

//處理動畫,聲明全局的處理器

mAnimator = ValueAnimator.ofFloat( 6f, 0f) //由6降到1

mAnimator.duration = 150

mAnimator.interpolator = LinearInterpolator //插值器設為線性

doInvalidate

}

/**

* 開始繪制

*/

fundoInvalidate{

Calendar.getInstance.run {

valhour = get(Calendar.HOUR)

valminute = get(Calendar.MINUTE)

valsecond = get(Calendar.SECOND)

mHourDeg = -360/ 12f * (hour - 1)

mMinuteDeg = -360/ 60f * (minute - 1)

mSecondDeg = -360/ 60f * (second - 1)

//記錄當前角度,然后讓秒圈線性的旋轉6°

valhd = mHourDeg

valmd = mMinuteDeg

valsd = mSecondDeg

//處理動畫

mAnimator.removeAllUpdateListeners //需要移除先前的監聽

mAnimator.addUpdateListener {

valav = (it.animatedValue asFloat)

if(minute == 0&& second == 0) {

mHourDeg = hd + av * 5//時圈旋轉角度是分秒的5倍,線性的旋轉30°

}

if(second == 0) {

mMinuteDeg = md + av //線性的旋轉6°

}

mSecondDeg = sd + av //線性的旋轉6°

invalidate

}

mAnimator.start

}

}

就用這美麗優雅的時鐘結尾吧~

文末

個人能力有限,如有不正之處歡迎大家批評指出,我會虛心接受并第一時間修改,以不誤導大家。

https://github.com/drawf/SourceSet/blob/master/app/src/main/java/me/erwa/sourceset/view/TextClockView.kt返回搜狐,查看更多

責任編輯:

總結

以上是生活随笔為你收集整理的html时钟自动刷新抖音,抖音上炫酷的网红文字时钟的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。