浏览代码

使用canvas绘制渐变文本,闪动动画

XUYangWei 2 月之前
父节点
当前提交
e3d8da6cf9

+ 1 - 0
commons/basic/Index.ets

@@ -71,6 +71,7 @@ export {YTAddressSelectorDialog,DateOption} from './src/main/ets//datepicker/YTD
 
 export {YTDateUtil,DateFormat} from './src/main/ets/utils/YTDateUtil'
 
+export {DrawText} from './src/main/ets/components/animation/draw/DrawText'
 export * from '@mumu/crop'
 
 export * from './src/main/ets/models'

+ 95 - 0
commons/basic/src/main/ets/components/animation/draw/Draw.ets

@@ -0,0 +1,95 @@
+/**
+ * 专注画各种图形
+ */
+
+@Component
+export struct Draw{
+  private settings: RenderingContextSettings = new RenderingContextSettings(true)
+  private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)
+
+  /**
+   * 画的范围
+   */
+  @Prop drawWidth:number=100
+  @Prop drawHeight:number=100
+
+  startWidth:number=0
+  startHeight:number=0
+
+  /**
+   * 定点数组,
+   * 比如想画一个三角形
+   */
+  @Prop drawArr:number[][]=[[50,0],[100,100],[0,100]]
+  // @Prop drawArrX:number[]=[]
+  // @Prop drawArrY:number[]=[]
+  private drawCircleWithCustomRadii() {
+    // this.context.clearRect(0,0,0,0)
+    this.context.clearRect(0, 0, this.drawWidth, this.drawHeight); // 清空Canvas的内容
+
+    this.drawArr.forEach((item:number[],index:number)=>{
+        this.context.beginPath()
+        this.context.moveTo(this.drawArr[index][0], this.drawArr[index][1])
+      if(index!=this.drawArr.length-1) {
+        this.context.lineTo(this.drawArr[index+1][0], this.drawArr[index+1][1])
+      }else{
+        this.context.moveTo(this.drawArr[0][0], this.drawArr[0][1])
+      }
+        this.context.strokeStyle = '#efd4f9' // 红色半径线
+        this.context.lineWidth = 1.5
+        this.context.stroke()
+    })
+
+
+    // const radius = 125  // 圆半径
+    // 根据自定义角度数组绘制半径线
+    // this.cells.forEach(angle => {
+    //   // 将角度转换为弧度(Canvas使用弧度制)
+    //   const radians = (angle.angleEnd-90) * Math.PI / 180
+    //
+    //   // 计算半径线终点坐标
+    //   const endX = centerX + radius * Math.cos(radians)
+    //   const endY = centerY + radius * Math.sin(radians)
+    //
+    //   // 绘制半径线
+    //   this.context.beginPath()
+    //   this.context.moveTo(centerX, centerY)
+    //   this.context.lineTo(endX, endY)
+    //   this.context.strokeStyle = '#efd4f9' // 红色半径线
+    //   this.context.lineWidth = 1.5
+    //   this.context.stroke()
+    //
+    //   // // 标注角度值(修正后的文本绘制方式)
+    //   // this.context.font = '12px sans-serif'
+    //   // this.context.fillStyle = '#000000'
+    //   // this.context.textAlign = 'center'
+    //   // this.context.textBaseline = 'middle'
+    //
+    //   // // 文本位置稍微向外偏移
+    //   // const textRadius = radius + 15
+    //   // const textX = centerX + textRadius * Math.cos(radians)
+    //   // const textY = centerY + textRadius * Math.sin(radians)
+    //
+    //   // 使用fillText绘制文本
+    //   // this.context.fillText(`${angle}°`, textX, textY)
+    // })
+
+  }
+
+  aboutToAppear(): void {
+    // this.drawCircleWithCustomRadii()
+  }
+  build() {
+    Column(){
+      Canvas(this.context)
+        .width(this.drawWidth)
+        .height(this.drawHeight)
+        .backgroundColor(Color.Transparent)
+        .onReady(() => {
+          this.drawCircleWithCustomRadii()
+        })
+    }.width(this.drawWidth)
+    .height(this.drawHeight)
+
+  }
+}

+ 92 - 0
commons/basic/src/main/ets/components/animation/draw/DrawText.ets

@@ -0,0 +1,92 @@
+import { DrawTextAlign } from "."
+
+/**
+ * 传入文本,图案,可以画出对应的文字
+ */
+
+@Component
+export struct DrawText{
+  private settings: RenderingContextSettings = new RenderingContextSettings(true)
+  private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)
+
+  /**
+   * 画的范围
+   */
+  @Prop drawWidth:number=100
+  @Prop drawHeight:number=100
+  @Prop draw_FontSize:number=16
+  @Prop draw_TextStyle:string="sans-serif"
+  @Prop bgc:ResourceColor=Color.Black
+
+  @Prop draw_Position:CanvasTextAlign='center'
+  // @Prop textAlign:
+  @Prop text:string="你好你好你好"
+
+  @Prop underline:string='bottom'
+  @Prop colors:string[][]=[['0','#ff0000'],['0.5','#ffffff'],['1','#00ff00']]
+  @State opacityValue:number=1
+
+  startWidth:number=0
+  startHeight:number=0
+
+  // this.grad=this.context.createLinearGradient(0, 0, this.drawWidth, this.drawHeight)
+  // grad.addColorStop(0.0, '#ff0000')
+  // grad.addColorStop(0.5, '#ffffff')
+  // grad.addColorStop(1.0, '#00ff00')
+  /**
+   * 如果有自定义的文字样式
+   * // 加载rawfile目录下的自定义字体文件HarmonyOS_Sans_Thin_Italic.ttf
+   let fontCollection = text.FontCollection.getGlobalInstance();
+   fontCollection.loadFontSync('HarmonyOS_Sans_Thin_Italic', $rawfile("HarmonyOS_Sans_Thin_Italic.ttf"))
+   // 加粗,字体大小为30vp,字体系列为HarmonyOS_Sans_Thin_Italic
+   this.context.font = "bold 30vp HarmonyOS_Sans_Thin_Italic"
+   */
+
+  grad:CanvasGradient=this.context.createLinearGradient(0, 0, this.drawWidth, this.drawHeight)
+
+  aboutToAppear(): void {
+    // this.drawCircleWithCustomRadii()
+    this.grad=this.context.createLinearGradient(0, 0, this.drawWidth, this.drawHeight)
+    this.colors.forEach((item)=>{
+      this.grad?.addColorStop(Number(item[0]),item[1])
+    })
+
+  }
+  private drawCircleWithCustomRadii() {
+    // this.context.clearRect(0,0,0,0)
+    this.context.clearRect(0, 0, this.drawWidth, this.drawHeight); // 清空Canvas的内容
+    this.context.textAlign =this.draw_Position
+    //有很多值
+    // this.context.textBaseline = 'middle'
+    // this.context.fillStyle = '#333333'
+    this.context.fillStyle =this.grad
+    this.context.font = `${this.draw_FontSize}vp ${this.draw_TextStyle}`
+    this.context.fillText(this.text,this.drawWidth/2,this.drawHeight/2)
+    this.context.restore()
+  }
+
+  build() {
+    // Column(){
+      Canvas(this.context)
+        .width(this.drawWidth)
+        .height(this.drawHeight)
+        .opacity(this.opacityValue)
+        .animation({
+          duration: 500,
+          playMode: PlayMode.Alternate,
+          iterations: -1,
+          curve: Curve.EaseInOut
+        })
+        .onAppear(() => {
+          this.opacityValue = 0.8  //文本闪烁效果
+        })
+        .backgroundColor(Color.Transparent)
+        .onReady(() => {
+          this.drawCircleWithCustomRadii()
+        })
+    // }.width(this.drawWidth)
+    // .height(this.drawHeight)
+    // .backgroundColor(this.bgc)
+
+  }
+}

+ 14 - 0
commons/basic/src/main/ets/components/animation/draw/index.ets

@@ -0,0 +1,14 @@
+export enum DrawTextAlign{
+  Center="center",
+  End='end',
+  Left='left',
+  Right='right',
+  Start='start'
+}
+// export enum DrawUnderline{
+//   CenterLine="center",
+//   End='end',
+//   Left='left',
+//   Right='right',
+//   Start='start'
+// }

+ 21 - 1
features/feature/src/main/ets/view/MainView.ets

@@ -1,4 +1,4 @@
-import { BackgroundPageModifier, DateOption, YTAddressSelectorDialog, YTDateUtil } from 'basic'
+import { BackgroundPageModifier, DateOption, DrawText, YTAddressSelectorDialog, YTDateUtil } from 'basic'
 import { UnitType } from 'basic/src/main/ets/datepicker/DatePickerEnums'
 import { promptAction } from '@kit.ArkUI'
 
@@ -40,6 +40,26 @@ export struct MainView {
       Image('https://hm-static.ytpm.net/upload/20250821/处暑-1755757002591.jpg')
         .width('100%')
         .height(300)
+
+
+
+      DrawText({
+        drawWidth:100, //画板大小
+        drawHeight:100,
+        text:"彩色文本",
+        draw_FontSize:20,
+        draw_Position:'center',
+        bgc:Color.Black, //画板背景颜色
+        colors:[  //
+          ['0','#64b816'],
+          ['0.2','#1086ce'],
+          ['0.3','#1a3b68'],
+          ['0.5','#ff8080'],
+          ['0.8','#ffd76a'],
+          ['1','#f7f8f9']
+        ]
+
+      })
     }
     .attributeModifier(new BackgroundPageModifier(true))