【HarmonyOS之旅】基于ArkTS开发(二) -> UI开发三
目录
1 -> 绘制图形
1.1 -> 绘制基本几何图形
1.2 -> 绘制自定义几何图形
2 -> 添加动画效果
2.1 -> animateTo实现闪屏动画
2.2 -> 页面转场动画
3 -> 常见组件说明

1 -> 绘制图形
绘制能力主要是通过框架提供的绘制组件来支撑,支持svg标准绘制命令。
1.1 -> 绘制基本几何图形
绘制组件封装了一些常见的基本几何图形,比如矩形Rect、圆形Circle、椭圆形Ellipse等,为开发者省去了路线计算的过程。
FoodDetail页面的食物成分表里,给每一项成分名称前都加上一个圆形的图标作为成分标签。
1. 创建Circle组件,在每一项含量成分前增加一个圆形图标作为标签。设置Circle的直径为 6vp。修改FoodDetail页面的ContentTable组件里的IngredientItem方法,在成分名称前添加Circle。
// FoodDetail.ets
@Component
struct ContentTable {private foodItem: FoodData@Builder IngredientItem(title:string, colorValue: string, name: string, value: string) {Flex() {Text(title).fontSize(17.4).fontWeight(FontWeight.Bold).layoutWeight(1)Flex({ alignItems: ItemAlign.Center }) {Circle({width: 6, height: 6}).margin({right: 12}).fill(colorValue)Text(name).fontSize(17.4).flexGrow(1)Text(value).fontSize(17.4)}.layoutWeight(2)}}build() {......}
}
2. 每个成分的标签颜色不一样,所以我们在build方法中,调用IngredientItem,给每个Circle填充不一样的颜色。
// FoodDetail.ets
@Component
struct ContentTable {private foodItem: FoodData@Builder IngredientItem(title:string, colorValue: string, name: string, value: string) {Flex() {Text(title).fontSize(17.4).fontWeight(FontWeight.Bold).layoutWeight(1)Flex({ alignItems: ItemAlign.Center }) {Circle({width: 6, height: 6}).margin({right: 12}).fill(colorValue)Text(name).fontSize(17.4).flexGrow(1)Text(value).fontSize(17.4)}.layoutWeight(2)}}build() {Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Start }) {this.IngredientItem('Calories', '#FFf54040', 'Calories', this.foodItem.calories + 'kcal')this.IngredientItem('Nutrition', '#FFcccccc', 'Protein', this.foodItem.protein + 'g')this.IngredientItem(' ', '#FFf5d640', 'Fat', this.foodItem.fat + 'g')this.IngredientItem(' ', '#FF9e9eff', 'Carbohydrates', this.foodItem.carbohydrates + 'g')this.IngredientItem(' ', '#FF53f540', 'VitaminC', this.foodItem.vitaminC + 'mg')}.height(280).padding({ top: 30, right: 30, left: 30 })}
}

1.2 -> 绘制自定义几何图形
除绘制基础几何图形,开发者还可以使用Path组件来绘制自定义的路线,下面进行绘制应用的Logo图案。
1. 在pages文件夹下创建新的页面Logo.ets。

2. Logo.ets中删掉模板代码,创建Logo Component。
@Entry
@Component
struct Logo {build() {}
}
3. 创建Flex组件为根节点,宽高设置为100%,设置其在主轴方向和交叉轴方向的对齐方式都为Center,创建Shape组件为Flex子组件。
Shape组件是所有绘制组件的父组件。如果需要组合多个绘制组件成为一个整体,需要创建Shape作为其父组件。
我们要绘制的Logo的大小630px * 630px。声明式UI范式支持多种长度单位的设置,在前面的章节中,我们直接使用number作为参数,即采用了默认长度单位vp,虚拟像素单位。vp和设备分辨率以及屏幕密度有关。比如设备分辨率为1176 * 2400,屏幕基准密度(resolution)为3,vp = px / resolution,则该设备屏幕宽度是392vp。
但是绘制组件采用svg标准,默认采取px为单位的,为方便统一,在这绘制Logo这一部分,统一采取px为单位。声明式UI框架同样也支持px单位,入参类型为string,设置宽度为630px,即210vp,设置方式为width('630px')或者width(210)。
@Entry
@Component
struct Logo {build() {Flex({ alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {Shape() {}.height('630px').width('630px')}.width('100%').height('100%')}
}
4. 给页面填充渐变色。设置为线性渐变,偏移角度为180deg,三段渐变 #BDE895 -->95DE7F --> #7AB967,其区间分别为[0, 0.1], (0.1, 0.6], (0.6, 1]。
.linearGradient({angle: 180,colors: [['#BDE895', 0.1], ["#95DE7F", 0.6], ["#7AB967", 1]]
})

@Entry
@Component
struct Logo {build() {Flex({ alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {Shape() {}.height('630px').width('630px')}.width('100%').height('100%').linearGradient({angle: 180,colors: [['#BDE895', 0.1], ["#95DE7F", 0.6], ["#7AB967", 1]]})}
}

5. 绘制第一条路线Path,设置其绘制命令。
Path().commands('M162 128.7 a222 222 0 0 1 100.8 374.4 H198 a36 36 0 0 3 -36 -36')
Path的绘制命令采用svg标准,上述命令可分解为:
M162 128.7
将笔触移动到(Moveto)坐标点(162, 128.7)。
a222 222 0 0 1 100.8 374.4
画圆弧线(elliptical arc)半径rx,ry为222,x轴旋转角度x-axis-rotation为0,角度大小large-arc-flag为0,即小弧度角,弧线方向(sweep-flag)为1,即逆时针画弧线,小写a为相对位置,即终点坐标为(162 + 100.8 = 262.8, 128.7 + 374.4 = 503.1)。
H198
画水平线(horizontal lineto)到198,即画(262.8, 503.1)到(198, 503.1)的水平线。
a36 36 0 0 3 -36 -36
画圆弧线(elliptical arc),含义同上,结束点为(198 - 36 = 162, 503.1 - 36 = 467.1)。
V128.7
画垂直线(vertical lineto)到128.7,即画(162, 467.1)到(162, 128.7)的垂直线。
z
关闭路径(closepath)。

填充颜色为白色。
.fill(Color.White)
@Entry
@Component
struct Logo {build() {Flex({ alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {Shape() {Path().commands('M162 128.7 a222 222 0 0 1 100.8 374.4 H198 a36 36 0 0 3 -36 -36').fill(Color.White)}.height('630px').width('630px')}.width('100%').height('100%').linearGradient({angle: 180,colors: [['#BDE895', 0.1], ["#95DE7F", 0.6], ["#7AB967", 1]]})}
}

6. 在Shape组件内绘制第二个Path。第二条Path的背景色为渐变色,但是渐变色的填充是其整体的box,所以需要clip将其裁剪,入参为Shape,即按照Shape的形状进行裁剪。
Path().commands('M319.5 128.1 c103.5 0 187.5 84 187.5 187.5 v15 a172.5 172.5 0 0 3 -172.5 172.5 H198 a36 36 0 0 3 -13.8 -1 207 207 0 0 0 87 -372 h48.3 z').fill('none').linearGradient({angle: 30,colors: [["#C4FFA0", 0], ["#ffffff", 1]]}).clip(new Path().commands('M319.5 128.1 c103.5 0 187.5 84 187.5 187.5 v15 a172.5 172.5 0 0 3 -172.5 172.5 H198 a36 36 0 0 3 -13.8 -1 207 207 0 0 0 87 -372 h48.3 z'))
Path的绘制命令比较长,可以将其作为组件的成员变量,通过this调用。
@Entry
@Component
struct Logo {private pathCommands1:string = 'M319.5 128.1 c103.5 0 187.5 84 187.5 187.5 v15 a172.5 172.5 0 0 3 -172.5 172.5 H198 a36 36 0 0 3 -13.8 -1 207 207 0 0 0 87 -372 h48.3 z'build() {......Path().commands(this.pathCommands1).fill('none').linearGradient({angle: 30,colors: [["#C4FFA0", 0], ["#ffffff", 1]]}).clip(new Path().commands(this.pathCommands1))......}
}

7. 在Shape组件内绘制第二个Path。
@Entry
@Component
struct Logo {private pathCommands1:string = 'M319.5 128.1 c103.5 0 187.5 84 187.5 187.5 v15 a172.5 172.5 0 0 3 -172.5 172.5 H198 a36 36 0 0 3 -13.8 -1 207 207 0 0 0 87 -372 h48.3 z'private pathCommands2:string = 'M270.6 128.1 h48.6 c51.6 0 98.4 21 132.3 54.6 a411 411 0 0 3 -45.6 123 c-25.2 45.6 -56.4 84 -87.6 110.4 a206.1 206.1 0 0 0 -47.7 -288 z'build() {Flex({ alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {Shape() {Path().commands('M162 128.7 a222 222 0 0 1 100.8 374.4 H198 a36 36 0 0 3 -36 -36').fill(Color.White)Path().commands(this.pathCommands1).fill('none').linearGradient({angle: 30,colors: [["#C4FFA0", 0], ["#ffffff", 1]]}).clip(new Path().commands(this.pathCommands1))Path().commands(this.pathCommands2).fill('none').linearGradient({angle: 50,colors: [['#8CC36A', 0.1], ["#B3EB90", 0.4], ["#ffffff", 0.7]]}).clip(new Path().commands(this.pathCommands2))}.height('630px').width('630px')}.width('100%').height('100%').linearGradient({angle: 180,colors: [['#BDE895', 0.1], ["#95DE7F", 0.6], ["#7AB967", 1]]})}
}

完成应用Logo的绘制。Shape组合了三个Path组件,通过svg命令绘制出一个艺术的叶子,寓意绿色健康饮食方式。
8. 添加应用的标题和slogan。
@Entry
@Component
struct Logo {private pathCommands1:string = 'M319.5 128.1 c103.5 0 187.5 84 187.5 187.5 v15 a172.5 172.5 0 0 3 -172.5 172.5 H198 a36 36 0 0 3 -13.8 -1 207 207 0 0 0 87 -372 h48.3 z'private pathCommands2:string = 'M270.6 128.1 h48.6 c51.6 0 98.4 21 132.3 54.6 a411 411 0 0 3 -45.6 123 c-25.2 45.6 -56.4 84 -87.6 110.4 a206.1 206.1 0 0 0 -47.7 -288 z'build() {Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {Shape() {Path().commands('M162 128.7 a222 222 0 0 1 100.8 374.4 H198 a36 36 0 0 3 -36 -36').fill(Color.White)Path().commands(this.pathCommands1).fill('none').linearGradient({angle: 30,colors: [["#C4FFA0", 0], ["#ffffff", 1]]}).clip(new Path().commands(this.pathCommands1))Path().commands(this.pathCommands2).fill('none').linearGradient({angle: 50,colors: [['#8CC36A', 0.1], ["#B3EB90", 0.4], ["#ffffff", 0.7]]}).clip(new Path().commands(this.pathCommands2))}.height('630px').width('630px')Text('Healthy Diet').fontSize(26).fontColor(Color.White).margin({ top:300 })Text('Healthy life comes from a balanced diet').fontSize(17).fontColor(Color.White).margin({ top:4 })}.width('100%').height('100%').linearGradient({angle: 180,colors: [['#BDE895', 0.1], ["#95DE7F", 0.6], ["#7AB967", 1]]})}
}

2 -> 添加动画效果
2.1 -> animateTo实现闪屏动画
声明式UI范式组件动画包括属性动画和animateTo显式动画:
- 属性动画:设置组件通用属性变化的动画效果。
- 显式动画:可以设置组件从状态A到状态B的变化动画效果,包括样式、位置信息和节点的增加删除等,开发者无需关注变化过程,只需指定起点和终点的状态。animateTo还提供播放状态的回调接口,是对属性动画的增强与封装。
闪屏页面的动画效果是Logo图标的渐出和放大效果的动画,动画结束后跳转到食物分类列表页面。接下来,我们就使用animateTo来实现启动页动画的闪屏效果。
1. 动画效果自动播放。闪屏动画的预期效果是,进入Logo页面后,animateTo动画效果自动开始播放,可以借助于组件显隐事件的回调接口来实现。调用Shape的onAppear方法,设置其显式动画。
Shape() {...
}
.onAppear(() => {animateTo()
})
2. 创建opacity和scale数值的成员变量,用装饰器@State修饰。表示其为有状态的数据,即改变会触发页面的刷新。
@Entry
@Component
struct Logo {@State private opacityValue: number = 0@State private scaleValue: number = 0build() {Shape() {...}.scale({ x: this.scaleValue, y: this.scaleValue }).opacity(this.opacityValue).onAppear(() => {animateTo()})}
}
3. 设置animateTo的动画曲线curve。Logo的加速曲线为先慢后快,使用贝塞尔曲线cubicBezier,cubicBezier(0.4, 0, 1, 1)。
需要使用动画能力接口中的插值计算,首先要导入curves模块。
import Curves from '@ohos.curves'
@ohos.curves模块提供了线性Curve. Linear、阶梯step、三阶贝塞尔(cubicBezier)和弹簧(spring)插值曲线的初始化函数,可以根据入参创建一个插值曲线对象。
@Entry
@Component
struct Logo {@State private opacityValue: number = 0@State private scaleValue: number = 0private curve1 = Curves.cubicBezier(0.4, 0, 1, 1)build() {Shape() {...}.scale({ x: this.scaleValue, y: this.scaleValue }).opacity(this.opacityValue).onAppear(() => {animateTo({curve: this.curve1})})}
}
4. 设置动画时长为1s,延时0.1s开始播放,设置显示动效event的闭包函数,即起点状态到终点状态为透明度opacityValue和大小scaleValue从0到1,实现Logo的渐出和放大效果。
@Entry
@Component
struct Logo {@State private opacityValue: number = 0@State private scaleValue: number = 0private curve1 = Curves.cubicBezier(0.4, 0, 1, 1)build() {Shape() {...}.scale({ x: this.scaleValue, y: this.scaleValue }).opacity(this.opacityValue).onAppear(() => {animateTo({duration: 1000, curve: this.curve1, delay: 100, }, () => {this.opacityValue = 1this.scaleValue = 1})})}
}
5. 闪屏动画播放结束后定格1s,进入FoodCategoryList页面。设置animateTo的onFinish回调接口,调用定时器Timer的setTimeout接口延时1s后,调用router.replace,显示FoodCategoryList页面。
import router from '@ohos.router'@Entry
@Component
struct Logo {@State private opacityValue: number = 0@State private scaleValue: number = 0private curve1 = Curves.cubicBezier(0.4, 0, 1, 1)build() {Shape() {...}.scale({ x: this.scaleValue, y: this.scaleValue }).opacity(this.opacityValue).onAppear(() => {animateTo({duration: 1000,curve: this.curve1, delay: 100, onFinish: () => {setTimeout(() => {router.replace({ url: "pages/FoodCategoryList" })}, 1000);}}, () => {this.opacityValue = 1this.scaleValue = 1})})}
}
整体代码如下。
import Curves from '@ohos.curves'
import router from '@ohos.router'@Entry
@Component
struct Logo {@State private opacityValue: number = 0@State private scaleValue: number = 0private curve1 = Curves.cubicBezier(0.4, 0, 1, 1)private pathCommands1: string = 'M319.5 128.1 c103.5 0 187.5 84 187.5 187.5 v15 a172.5 172.5 0 0 3 -172.5 172.5 H198 a36 36 0 0 3 -13.8 -1 207 207 0 0 0 87 -372 h48.3 z'private pathCommands2: string = 'M270.6 128.1 h48.6 c51.6 0 98.4 21 132.3 54.6 a411 411 0 0 3 -45.6 123 c-25.2 45.6 -56.4 84 -87.6 110.4 a206.1 206.1 0 0 0 -47.7 -288 z'build() {Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {Shape() {Path().commands('M162 128.7 a222 222 0 0 1 100.8 374.4 H198 a36 36 0 0 3 -36 -36').fill(Color.White)Path().commands(this.pathCommands1).fill('none').linearGradient({angle: 30,colors: [["#C4FFA0", 0], ["#ffffff", 1]]}).clip(new Path().commands(this.pathCommands1))Path().commands(this.pathCommands2).fill('none').linearGradient({angle: 50,colors: [['#8CC36A', 0.1], ["#B3EB90", 0.4], ["#ffffff", 0.7]]}).clip(new Path().commands(this.pathCommands2))}.height('630px').width('630px').scale({ x: this.scaleValue, y: this.scaleValue }).opacity(this.opacityValue).onAppear(() => {animateTo({duration: 1000,curve: this.curve1,delay: 100,onFinish: () => {setTimeout(() => {router.replace({ url: "pages/FoodCategoryList" })}, 1000);}}, () => {this.opacityValue = 1this.scaleValue = 1})})Text('Healthy Diet').fontSize(26).fontColor(Color.White).margin({ top: 300 })Text('Healthy life comes from a balanced diet').fontSize(17).fontColor(Color.White).margin({ top: 4 })}.width('100%').height('100%').linearGradient({angle: 180,colors: [['#BDE895', 0.1], ["#95DE7F", 0.6], ["#7AB967", 1]]})}
}
2.2 -> 页面转场动画
食物分类列表页和食物详情页之间的共享元素转场,即点击FoodListItem/FoodGridItem后,食物缩略图会放大,随着页面跳转,到食物详情页的大图。
1. 设置FoodListItem和FoodGridItem的Image组件的共享元素转场方法(sharedTransition)。转场id为foodItem.id,转场动画时长为1s,延时0.1s播放,变化曲线为贝塞尔曲线Curves.cubicBezier(0.2, 0.2, 0.1, 1.0) ,需引入curves模块。
共享转场时会携带当前元素的被设置的属性,所以创建Row组件,使其作为Image的父组件,设置背景颜色在Row上。
在FoodListItem的Image组件上设置autoResize为false,因为image组件默认会根据最终展示的区域,去调整图源的大小,以优化图片渲染性能。在转场动画中,图片在放大的过程中会被重新加载,所以为了转场动画的流畅,autoResize设置为false。
// FoodList.ets
import Curves from '@ohos.curves'@Component
struct FoodListItem {private foodItem: FoodDatabuild() {Navigator({ target: 'pages/FoodDetail' }) {Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) {Row() {Image(this.foodItem.image).objectFit(ImageFit.Contain).autoResize(false).height(40).width(40).sharedTransition(this.foodItem.id, { duration: 1000, curve: Curves.cubicBezier(0.2, 0.2, 0.1, 1.0), delay: 100 })}.margin({ right: 16 })Text(this.foodItem.name).fontSize(14).flexGrow(1)Text(this.foodItem.calories + ' kcal').fontSize(14)}.height(64)}.params({ foodData: this.foodItem }).margin({ right: 24, left:32 })}
}@Component
struct FoodGridItem {private foodItem: FoodDatabuild() {Column() {Row() {Image(this.foodItem.image).objectFit(ImageFit.Contain).autoResize(false).height(152).width('100%').sharedTransition(this.foodItem.id, { duration: 1000, curve: Curves.cubicBezier(0.2, 0.2, 0.1, 1.0), delay: 100 })}Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) {Text(this.foodItem.name).fontSize(14).flexGrow(1).padding({ left: 8 })Text(this.foodItem.calories + 'kcal').fontSize(14).margin({ right: 6 })}.height(32).width('100%').backgroundColor('#FFe5e5e5')}.height(184).width('100%').onClick(() => {router.push({ url: 'pages/FoodDetail', params: { foodId: this.foodItem } })})}
}
2. 设置FoodDetail页面的FoodImageDisplay的Image组件的共享元素转场方法(sharedTransition)。设置方法同上。
import Curves from '@ohos.curves'@Component
struct FoodImageDisplay {private foodItem: FoodDatabuild() {Stack({ alignContent: Alignment.BottomStart }) {Image(this.foodItem.image).objectFit(ImageFit.Contain).sharedTransition(this.foodItem.id, { duration: 1000, curve: Curves.cubicBezier(0.2, 0.2, 0.1, 1.0), delay: 100 })Text(this.foodItem.name).fontSize(26).fontWeight(500).margin({ left: 26, bottom: 17.4 })}.height(357) }
}
3 -> 常见组件说明
组件是构建页面的核心,每个组件通过对数据和方法的简单封装,实现独立的可视、可交互功能单元。组件之间相互独立,随取随用,也可以在需求相同的地方重复使用。
声明式开发范式目前可供选择的组件如下表所示。
| 组件类型 | |
| 基础组件 | Blank、Button、Checkbox、CheckboxGroup、DataPanel、DatePicker、Divider、Gauge、Image、ImageAnimator、LoadingProgress、Marquee、Navigation、Progress、QRCode、Radio、Rating、RichText、ScrollBar、Search、Select、Slider、Span、Stepper、StepperItem、Text、TextArea、TextClock、TextInput、TextPicker、TextTimer、TimePicker、Toggle、Web、XComponent |
| 容器组件 | AlphabetIndexer、Badge、Column、ColumnSplit、Counter、Flex、GridContainer、Grid、GridItem、List、ListItem、Navigator、Panel、Refresh、Row、RowSplit、Scroll、SideBarContainer、Stack、Swiper、Tabs、TabContent |
| 媒体组件 | Video |
| 绘制组件 | Circle、Ellipse、Line、Polyline、Polygon、Path、Rect、Shape |
| 画布组件 | Canvas |
感谢各位大佬支持!!!
互三啦!!!
相关文章:
【HarmonyOS之旅】基于ArkTS开发(二) -> UI开发三
目录 1 -> 绘制图形 1.1 -> 绘制基本几何图形 1.2 -> 绘制自定义几何图形 2 -> 添加动画效果 2.1 -> animateTo实现闪屏动画 2.2 -> 页面转场动画 3 -> 常见组件说明 1 -> 绘制图形 绘制能力主要是通过框架提供的绘制组件来支撑,支…...
如何选择Spring AOP的动态代理?JDK与CGLIB的适用场景?
在Spring AOP中,选择JDK动态代理还是CGLIB动态代理取决于目标对象的特性以及具体需求。以下是两种代理方式的适用场景和特点: JDK动态代理 • 适用场景: • 目标对象实现了接口:JDK动态代理要求目标对象必须实现至少一个接口&a…...
手机连接WIFI可以上网,笔记本电脑连接WIFI却不能上网? 解决方法?
原因:DNS受污染了 解决办法 step 1:清空域名解析记录(清空DNS) ipconfig /flushdns (Windows cmd命令行输入) step 2:重新从DHCP 获取IP ipconfig /release(释放当前IP地址) ipconfig /renew &…...
MySQL不适合创建索引的11种情况
文章目录 前言1. **数据量小的表**2. **频繁更新的列**3. **低选择性的列**4. **频繁插入和删除的表**5. **查询中很少使用的列**6. **大文本或BLOB列**7. **复合索引中未使用的前导列**8. **频繁进行批量插入的表**9. **查询返回大部分数据的表**10. **临时表**11. **列值频繁…...
树莓派pico入坑笔记,故障解决:请求 USB 设备描述符失败,故障码(43)
今天心血来潮,拿出吃灰的pico把玩一下,打开thonny,上电,然后...... 上电识别不到端口,windows报错,请求 USB 设备描述符失败,故障码(43) 一开始以为是坏了(磕…...
GRE阅读双线阅读 --青山学堂GRE全程班 包括 阅读、数学、写作、填空、背单词
新版GRE考试整体结构 section题量时间写作1篇issue30min语文S112道题(7道填空5道阅读)18min数学S112道题21min语文S215道题(7道填空8道阅读)23min数学S215道题26min Tips: 写作结束后,语文和数学的顺序不固定,2中可能: issue -> V ->…...
98,【6】 buuctf web [ISITDTU 2019]EasyPHP
进入靶场 代码 <?php // 高亮显示当前 PHP 文件的源代码,通常用于调试或展示代码,方便用户查看代码逻辑 highlight_file(__FILE__);// 从 GET 请求中获取名为 _ 的参数值,并赋值给变量 $_ // 符号用于抑制可能出现的错误信息ÿ…...
Kamailio、MySQL、Redis、Gin后端、Vue.js前端等基于容器化部署
基于容器化的部署方案,通常会将每个核心服务(如Kamailio、MySQL、Redis、Gin后端、Vue.js前端等)独立运行在不同的容器中,通过Docker或Kubernetes统一管理。以下是具体实现方式和关键原因: 1. 容器化部署的核心思路 每…...
知识管理系统助力企业信息共享与创新思维的全面提升研究
内容概要 知识管理系统的引入极大地改变了企业内部的信息流程与创新机制。通过有效整合与管理组织内的知识资源,这些系统不仅降低了信息孤岛的现象,还提升了员工之间的协作能力。企业在信息共享方面,通过知识管理系统构建了一个透明、高效的…...
Leetcode 131 分割回文串(纯DFS)
131. 分割回文串https://leetcode.cn/problems/palindrome-partitioning/https://leetcode.cn/problems/palindrome-partitioning/ 给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是 回文串 。返回 s 所有可能的分割方案。 示例 1:…...
结构体DMA串口接收比特错位
发送: 显示: uint16_t接收时候会比特错位。...
用FormLinker实现自动调整数据格式,批量导入微软表单
每天早上打开Excel时,你是否也经历过这样的噩梦? 熬夜调整好的问卷格式,导入微软表单后全乱套 客户发来的PDF反馈表,手动录入3小时才完成10% 200道题库要转为在线测试,复制粘贴到手指抽筋 微软官方数据显示…...
技术架构师成长路线(2025版)
目录 通用知识 计算机原理(1 - 2 个月) 数据结构(2 - 3 个月) 网络编程(1 - 2 个月) 软件工程(1 个月) 基础知识 Java 编程语言基础(2 - 3 个月) JVM&…...
独立开发者的技术栈
文章目录 设计IDE&工具链前端后端移动端用户管理支付数据部署运维AI工具箱🔥避坑指南参考链接 一个人就是一家公司的时代已经到来 设计 FigmaPixso是国产设计工具,可作为Figma的替代版使用Sketch IDE&工具链 VscodeESLint & Prettier: &a…...
wordpress每隔24小时 随机推荐一个指定分类下的置顶内容。
在WordPress中实现每隔24小时随机推荐一个指定分类下的置顶内容,可以通过以下步骤实现: 1. 创建自定义函数 在主题的functions.php文件中添加以下代码,用于创建一个定时任务,每隔24小时随机选择一个置顶文章并存储到选项中&…...
Android13源码下载和编译过程详解
前言 作为Android开发者人人都应该有一份自己Android源码,这样我们就可以随时对自己有疑惑的地方通过亲手调试来加强理解 一 源码下载 1.1 配置要求 官方推荐配置请参考:AOSP使用入门文档,重点有如下几项: 1.1.1 硬件配置要求 至少需要…...
C++底层学习预备:模板初阶
文章目录 1.编程范式2.函数模板2.1 函数模板概念2.2 函数模板原理2.3 函数模板实例化2.3.1 隐式实例化2.3.2 显式实例化 2.4 模板参数的匹配原则 3.类模板希望读者们多多三连支持小编会继续更新你们的鼓励就是我前进的动力! 进入STL库学习之前我们要先了解有关模板的…...
使用mybatisPlus插件生成代码步骤及注意事项
使用mybatisPlus插件可以很方便的生成与数据库对应的PO对象,以及对应的controller、service、ImplService、mapper代码,生成这种代码的方式有很多,包括mybatis-plus提供的代码生成器,以及idea提供的代码生成器,无论哪一…...
扩散模型(二)
相关阅读:扩散模型(一) Parameterization of L t L_t Lt for Training Loss 回想一下,我们需要训练一个神经网络来近似反向扩散过程中的条件概率分布,即, p θ ( x t − 1 ∣ x t ) N ( x t − 1 ; μ θ ( x t…...
java异常处理——try catch finally
单个异常处理 1.当try里的代码发生了catch里指定类型的异常之后,才会执行catch里的代码,程序正常执行到结尾 2.如果try里的代码发生了非catch指定类型的异常,则会强制停止程序,报错 3.finally修饰的代码一定会执行,除…...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...
Docker 离线安装指南
参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性,不同版本的Docker对内核版本有不同要求。例如,Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本,Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...
day52 ResNet18 CBAM
在深度学习的旅程中,我们不断探索如何提升模型的性能。今天,我将分享我在 ResNet18 模型中插入 CBAM(Convolutional Block Attention Module)模块,并采用分阶段微调策略的实践过程。通过这个过程,我不仅提升…...
【Java学习笔记】Arrays类
Arrays 类 1. 导入包:import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序(自然排序和定制排序)Arrays.binarySearch()通过二分搜索法进行查找(前提:数组是…...
WordPress插件:AI多语言写作与智能配图、免费AI模型、SEO文章生成
厌倦手动写WordPress文章?AI自动生成,效率提升10倍! 支持多语言、自动配图、定时发布,让内容创作更轻松! AI内容生成 → 不想每天写文章?AI一键生成高质量内容!多语言支持 → 跨境电商必备&am…...
sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!
简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求,并检查收到的响应。它以以下模式之一…...
Selenium常用函数介绍
目录 一,元素定位 1.1 cssSeector 1.2 xpath 二,操作测试对象 三,窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四,弹窗 五,等待 六,导航 七,文件上传 …...
Ubuntu Cursor升级成v1.0
0. 当前版本低 使用当前 Cursor v0.50时 GitHub Copilot Chat 打不开,快捷键也不好用,当看到 Cursor 升级后,还是蛮高兴的 1. 下载 Cursor 下载地址:https://www.cursor.com/cn/downloads 点击下载 Linux (x64) ,…...
渗透实战PortSwigger靶场:lab13存储型DOM XSS详解
进来是需要留言的,先用做简单的 html 标签测试 发现面的</h1>不见了 数据包中找到了一个loadCommentsWithVulnerableEscapeHtml.js 他是把用户输入的<>进行 html 编码,输入的<>当成字符串处理回显到页面中,看来只是把用户输…...
LLaMA-Factory 微调 Qwen2-VL 进行人脸情感识别(二)
在上一篇文章中,我们详细介绍了如何使用LLaMA-Factory框架对Qwen2-VL大模型进行微调,以实现人脸情感识别的功能。本篇文章将聚焦于微调完成后,如何调用这个模型进行人脸情感识别的具体代码实现,包括详细的步骤和注释。 模型调用步骤 环境准备:确保安装了必要的Python库。…...
