一、导入





!




private settings: RenderingContextSettings = new RenderingContextSettings(true)
private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)
Canvas(this.context)
.width('100%')
.height(70)
.onReady(() => {
this.context.lineWidth = 2 // 设置线宽
this.context.fillStyle = '#ffffff' // 设置填充颜色为白色
this.context.strokeStyle = '#ffffff' // 设置描边颜色为白色
})
1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.
Canvas(this.context)
.width('100%')
.height(70)
.onReady(() => {
this.context.lineWidth = 2 // 设置线宽
this.context.fillStyle = '#ffffff' // 设置填充颜色为白色
this.context.strokeStyle = '#ffffff' // 设置描边颜色为白色
let total_width = Math.sqrt(3) * 36 * 2 // 计算总宽度
let radios: number = 36 // 圆的半径
// 圆心1
let p1: Point = {x: (this.screen_width - total_width) / 2, y: radios + this.padding_top}
// 圆心2
let p2: Point = {x: this.screen_width / 2, y: 0 + this.padding_top}
// 圆心3
let p3: Point = {x: (this.screen_width - total_width) / 2 + total_width, y: 36 + this.padding_top}
this.context.moveTo(0, this.padding_top) // 移动到起始点
// 画到圆心1的顶点
this.context.lineTo((this.screen_width - total_width) / 2, 0 + this.padding_top)
// 画第一个圆弧
this.context.arc(p1.x, p1.y, radios, 3.14 + 3.14 / 2, 3.14 + 3.14 / 2 + 3.14 / 3, false)
// 画第二个圆弧
this.context.arc(p2.x, p2.y, radios, 3.14 - 3.14 / 6, 3.14 / 6, true)
// 画第三个圆弧
this.context.arc(p3.x, p3.y, radios, 3.14 + 3.14 / 6, 3.14 + 3.14 / 2, false)
// 右侧直线到达右边界
this.context.lineTo(this.screen_width, 0 + this.padding_top)
// 画从右侧向下的直线
this.context.lineTo(this.screen_width, 64 + this.padding_top)
// 画到底部并连接到左边
this.context.lineTo(0, 64 + this.padding_top)
this.context.lineTo(0, 0 + this.padding_top)
// 设置阴影效果
this.context.shadowOffsetY = 0
this.context.shadowColor = '#949494' // 阴影颜色
this.context.shadowBlur = 12 // 阴影模糊度
this.context.stroke(); // 描边
this.context.fill(); // 填充
})
1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28.29.30.31.32.33.34.35.36.37.38.39.40.41.42.43.44.45.46.47.48.49.50.51.52.


import { TabItem } from "./NormalClass" // 导入 TabItem 类型
import { Rectangle } from "./Rectangle" // 导入 Rectangle 组件
import { display } from "@kit.ArkUI" // 导入显示相关功能
@Component
export struct Tabbar {
@Prop tabItems: TabItem[] // 定义 tabItems,传入的 TabItem 数组
@Link currentIndex: number // 当前选中的索引,链接到外部状态
@State fontColor: string = '#949494' // 默认字体颜色
@State selectedFontColor: string = 'rgb(61,141,255)' // 选中时字体颜色
@State screen_width: number = px2vp(display.getDefaultDisplaySync().width) // 计算屏幕宽度
build() {
Stack() { // 创建一个 Stack 组件
Rectangle() // 绘制一个矩形背景
Row() { // 创建一个行布局
// 检查 tabItems 数组的长度,确保是偶数且大于等于2
if (this.tabItems.length % 2 == 0 && this.tabItems.length >= 2) {
// 遍历 tabItems
ForEach(this.tabItems, (item: TabItem, index) => {
// 判断当前索引是否为中间索引
if (index == this.tabItems.length / 2) {
Image($r('app.media.middle')) // 中间图像
.width(60) // 设置宽度
.height(60) // 设置高度
.borderRadius(30) // 设置圆角
.offset({ y: -30 }) // 垂直偏移
.borderWidth(4) // 边框宽度
.borderColor(Color.White) // 边框颜色
.borderStyle(BorderStyle.Solid) // 边框样式
.shadow({ // 添加阴影效果
radius: 20,
color: Color.Gray,
offsetX: 0,
offsetY: 0
})
.onClick(() => {
this.currentIndex = -1 // 点击时重置 currentIndex
})
}
Column() { // 创建垂直布局
Image(this.currentIndex == index ? item.selectImage : item.image) // 根据当前索引选择图像
.width(22) // 设置图像宽度
.height(22) // 设置图像高度
.objectFit(ImageFit.Contain) // 设置图像适配方式
Text(item.title) // 显示文本
.fontSize(13) // 设置字体大小
.fontColor(this.currentIndex == index ? this.selectedFontColor : this.fontColor) // 根据选择状态设置字体颜色
}
.width((this.screen_width - 60) / this.tabItems.length) // 设置列宽度
.alignItems(HorizontalAlign.Center) // 设置对齐方式
.onClick(() => {
this.currentIndex = index // 点击时更新 currentIndex
})
})
}
}
.width('100%') // 设置行的总宽度
.height('100%') // 设置行的总高度
.justifyContent(FlexAlign.SpaceAround) // 设置对齐方式
}
.width(px2vp(display.getDefaultDisplaySync().width)) // 设置 Stack 的宽度
.height(64) // 设置 Stack 的高度
}
}