HarmonyOS实战开发-如何实现一个自定义抽奖圆形转盘

介绍

本篇Codelab是基于画布组件、显式动画,实现的一个自定义抽奖圆形转盘。包含如下功能:

  1. 通过画布组件Canvas,画出抽奖圆形转盘。
  2. 通过显式动画启动抽奖功能。
  3. 通过自定义弹窗弹出抽中的奖品。

相关概念

  • Stack组件:堆叠容器,子组件按照顺序依次入栈,后一个子组件覆盖前一个子组件。
  • Canvas:画布组件,用于自定义绘制图形。
  • CanvasRenderingContext2D对象:使用RenderingContext在Canvas组件上进行绘制,绘制对象可以是矩形、文本、图片等。
  • 显式动画:提供全局animateTo显式动画接口来指定由于闭包代码导致的状态变化插入过渡动效。
  • 自定义弹窗: 通过CustomDialogController类显示自定义弹窗。

环境搭建

软件要求

  • DevEco Studio版本:DevEco Studio 3.1 Release。
  • OpenHarmony SDK版本:API version 9。

硬件要求

  • 开发板类型:润和RK3568开发板。
  • OpenHarmony系统:3.2 Release。

环境搭建

完成本篇Codelab我们首先要完成开发环境的搭建,本示例以RK3568开发板为例,参照以下步骤进行:

  1. 获取OpenHarmony系统版本:标准系统解决方案(二进制)。以3.2 Release版本为例:

2.搭建烧录环境。

  1. 完成DevEco Device Tool的安装
  2. 完成RK3568开发板的烧录

3.搭建开发环境。

  1. 开始前请参考工具准备,完成DevEco Studio的安装和开发环境配置。
  2. 开发环境配置完成后,请参考使用工程向导创建工程(模板选择“Empty Ability”)。
  3. 工程创建完成后,选择使用真机进行调测。

代码结构解读

本篇Codelab只对核心代码进行讲解。

├──entry/src/main/ets	            // 代码区
│  ├──common
│  │  ├──constants
│  │  │  ├──ColorConstants.ets      // 颜色常量类
│  │  │  ├──CommonConstants.ets     // 公共常量类 
│  │  │  └──StyleConstants.ets      // 样式常量类 
│  │  └──utils
│  │     ├──CheckEmptyUtils.ets     // 数据判空工具类
│  │     └──Logger.ets              // 日志打印类
│  ├──entryability
│  │  └──EntryAbility.ts            // 程序入口类
│  ├──pages
│  │  └──CanvasPage.ets             // 主界面	
│  ├──view
│  │  └──PrizeDialog.ets            // 中奖信息弹窗类
│  └──viewmodel
│     ├──DrawModel.ets              // 画布相关方法类
│     ├──FillArcData.ets            // 绘制圆弧数据实体类
│     └──PrizeData.ets              // 中奖信息实体类
└──entry/src/main/resources         // 资源文件目录

构建主界面

在这个章节中,我们将完成示例主界面的开发,效果如图所示:

在绘制抽奖圆形转盘前,首先需要在CanvasPage.ets的aboutToAppear()方法中获取屏幕的宽高。

// CanvasPage.ets
// 获取context
let context = getContext(this);aboutToAppear() {// 获取屏幕的宽高window.getLastWindow(context).then((windowClass) => {let windowProperties = windowClass.getWindowProperties();this.screenWidth = px2vp(windowProperties.windowRect.width);this.screenHeight = px2vp(windowProperties.windowRect.height);}).catch((error: Error) => {Logger.error('Failed to obtain the window size. Cause: ' + JSON.stringify(error));})
}

在CanvasPage.ets布局界面中添加Canvas组件,在onReady()方法中进行绘制。

// CanvasPage.ets
private settings: RenderingContextSettings = new RenderingContextSettings(true);
private canvasContext: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings);Stack({ alignContent: Alignment.Center }) {Canvas(this.canvasContext)....onReady(() => {// 通过draw方法进行绘制this.drawModel.draw(this.canvasContext, this.screenWidth, this.screenHeight);})// 开始抽奖图片Image($r('app.media.ic_center'))...
}
...

在DrawModel.ets中,通过draw()方法逐步进行自定义圆形抽奖转盘的绘制。

// DrawModel.ets
// 画抽奖圆形转盘
draw(canvasContext: CanvasRenderingContext2D, screenWidth: number, screenHeight: number) {if (CheckEmptyUtils.isEmptyObj(canvasContext)) {Logger.error('[DrawModel][draw] canvasContext is empty.');return;}this.canvasContext= canvasContext;this.screenWidth = screenWidth;this.canvasContext.clearRect(0, 0, this.screenWidth, screenHeight);// 将画布沿X、Y轴平移指定距离this.canvasContext.translate(this.screenWidth / CommonConstants.TWO,screenHeight / CommonConstants.TWO);// 画外部圆盘的花瓣this.drawFlower();// 画外部圆盘、小圈圈this.drawOutCircle();// 画内部圆盘this.drawInnerCircle();// 画内部扇形抽奖区域this.drawInnerArc();// 画内部扇形区域文字this.drawArcText();// 画内部扇形区域奖品对应的图片this.drawImage();this.canvasContext.translate(-this.screenWidth / CommonConstants.TWO,-screenHeight / CommonConstants.TWO);
}

画外部圆盘

画外部圆盘的花瓣:通过调用rotate()方法,将画布旋转指定角度。再通过调用save()和restore()方法,使画布保存最新的绘制状态。根据想要绘制的花瓣个数,改变旋转角度,循环画出花瓣效果。

// DrawModel.ets
// 画外部圆盘的花瓣
drawFlower() {let beginAngle = this.startAngle + this.avgAngle;const pointY = this.screenWidth * CommonConstants.FLOWER_POINT_Y_RATIOS;const radius = this.screenWidth * CommonConstants.FLOWER_RADIUS_RATIOS;const innerRadius = this.screenWidth * CommonConstants.FLOWER_INNER_RATIOS;for (let i = 0; i < CommonConstants.COUNT; i++) {this.canvasContext?.save();this.canvasContext?.rotate(beginAngle * Math.PI / CommonConstants.HALF_CIRCLE);this.fillArc(new FillArcData(0, -pointY, radius, 0, Math.PI * CommonConstants.TWO),ColorConstants.FLOWER_OUT_COLOR);this.fillArc(new FillArcData(0, -pointY, innerRadius, 0, Math.PI * CommonConstants.TWO),ColorConstants.FLOWER_INNER_COLOR);beginAngle += this.avgAngle;this.canvasContext?.restore();}
}// 画弧线方法
fillArc(fillArcData: FillArcData, fillColor: string) {if (CheckEmptyUtils.isEmptyObj(fillArcData) || CheckEmptyUtils.isEmptyStr(fillColor)) {Logger.error('[DrawModel][fillArc] fillArcData or fillColor is empty.');return;}if (this.canvasContext !== undefined) {this.canvasContext.beginPath();this.canvasContext.fillStyle = fillColor;this.canvasContext.arc(fillArcData.x, fillArcData.y, fillArcData.radius,fillArcData.startAngle, fillArcData.endAngle);this.canvasContext.fill();}
}

画外部圆盘、圆盘边上的小圈圈:在指定的X、Y(0, 0)坐标处,画一个半径为this.screenWidth * CommonConstants.OUT_CIRCLE_RATIOS的圆形。接下来通过一个for循环,且角度每次递增CommonConstants.CIRCLE / CommonConstants.SMALL_CIRCLE_COUNT,来绘制圆环上的小圈圈。

// DrawModel.ets
drawOutCircle() {// 画外部圆盘this.fillArc(new FillArcData(0, 0, this.screenWidth * CommonConstants.OUT_CIRCLE_RATIOS, 0,Math.PI * CommonConstants.TWO), ColorConstants.OUT_CIRCLE_COLOR);let beginAngle = this.startAngle;// 画小圆圈for (let i = 0; i < CommonConstants.SMALL_CIRCLE_COUNT; i++) {this.canvasContext?.save();this.canvasContext?.rotate(beginAngle * Math.PI / CommonConstants.HALF_CIRCLE);this.fillArc(new FillArcData(this.screenWidth * CommonConstants.SMALL_CIRCLE_RATIOS, 0,CommonConstants.SMALL_CIRCLE_RADIUS, 0, Math.PI * CommonConstants.TWO),ColorConstants.WHITE_COLOR);beginAngle = beginAngle + CommonConstants.CIRCLE / CommonConstants.SMALL_CIRCLE_COUNT;this.canvasContext?.restore();}
}

画内部扇形抽奖区域

画内部圆盘、内部扇形抽奖区域:使用fillArc()方法绘制内部圆盘。通过一个for循环,角度每次递增this.avgAngle。然后不断更改弧线的起始弧度this.startAngle * Math.PI / CommonConstants.HALF_CIRCLE和弧线的终止弧度(this.startAngle + this.avgAngle) * Math.PI / CommonConstants.HALF_CIRCLE。最后用fill()方法对路径进行填充。

// DrawModel.ets
// 画内部圆盘
drawInnerCircle() {this.fillArc(new FillArcData(0, 0, this.screenWidth * CommonConstants.INNER_CIRCLE_RATIOS, 0,Math.PI * CommonConstants.TWO), ColorConstants.INNER_CIRCLE_COLOR);this.fillArc(new FillArcData(0, 0, this.screenWidth * CommonConstants.INNER_WHITE_CIRCLE_RATIOS, 0,Math.PI * CommonConstants.TWO), ColorConstants.WHITE_COLOR);
}// 画内部扇形抽奖区域
drawInnerArc() {// 颜色集合let colors = [ColorConstants.ARC_PINK_COLOR, ColorConstants.ARC_YELLOW_COLOR,ColorConstants.ARC_GREEN_COLOR, ColorConstants.ARC_PINK_COLOR,ColorConstants.ARC_YELLOW_COLOR, ColorConstants.ARC_GREEN_COLOR];let radius = this.screenWidth * CommonConstants.INNER_ARC_RATIOS;for (let i = 0; i < CommonConstants.COUNT; i++) {this.fillArc(new FillArcData(0, 0, radius, this.startAngle * Math.PI / CommonConstants.HALF_CIRCLE,(this.startAngle + this.avgAngle) * Math.PI / CommonConstants.HALF_CIRCLE), colors[i]);this.canvasContext?.lineTo(0, 0);this.canvasContext?.fill();this.startAngle += this.avgAngle;}
}

画内部抽奖区域文字:用for循环,通过drawCircularText()方法绘制每组文字。drawCircularText()方法接收三个参数,分别是字符串,起始弧度和终止弧度。绘制文本前需要设置每个字母占的弧度angleDecrement,然后设置水平和垂直的偏移量。垂直偏移量circleText.y - Math.sin(angle) * radius就是朝着圆心移动的距离;水平偏移circleText.x + Math.cos(angle) * radius,是为了让文字在当前弧范围文字居中。最后使用fillText()方法绘制文本。

// DrawModel.ets
// 画内部扇形区域文字
drawArcText() {if (this.canvasContext !== undefined) {this.canvasContext.textAlign = CommonConstants.TEXT_ALIGN;this.canvasContext.textBaseline = CommonConstants.TEXT_BASE_LINE;this.canvasContext.fillStyle = ColorConstants.TEXT_COLOR;this.canvasContext.font = StyleConstants.ARC_TEXT_SIZE + CommonConstants.CANVAS_FONT;}// 需要绘制的文本数组集合let textArrays = [$r('app.string.text_smile'),$r('app.string.text_hamburger'),$r('app.string.text_cake'),$r('app.string.text_smile'),$r('app.string.text_beer'),$r('app.string.text_watermelon')];let arcTextStartAngle = CommonConstants.ARC_START_ANGLE;let arcTextEndAngle = CommonConstants.ARC_END_ANGLE;for (let i = 0; i < CommonConstants.COUNT; i++) {this.drawCircularText(this.getResourceString(textArrays[i]),(this.startAngle + arcTextStartAngle) * Math.PI / CommonConstants.HALF_CIRCLE,(this.startAngle + arcTextEndAngle) * Math.PI / CommonConstants.HALF_CIRCLE);this.startAngle += this.avgAngle;}
}// 绘制圆弧文本
drawCircularText(textString: string, startAngle: number, endAngle: number) {if (CheckEmptyUtils.isEmptyStr(textString)) {Logger.error('[DrawModel][drawCircularText] textString is empty.');return;}class CircleText {x: number = 0;y: number = 0;radius: number = 0;}let circleText: CircleText = {x: 0,y: 0,radius: this.screenWidth * CommonConstants.INNER_ARC_RATIOS};// 圆的半径let radius = circleText.radius - circleText.radius / CommonConstants.COUNT;// 每个字母占的弧度let angleDecrement = (startAngle - endAngle) / (textString.length - 1);let angle = startAngle;let index = 0;let character: string;while (index < textString.length) {character = textString.charAt(index);this.canvasContext?.save();this.canvasContext?.beginPath();this.canvasContext?.translate(circleText.x + Math.cos(angle) * radius,circleText.y - Math.sin(angle) * radius);this.canvasContext?.rotate(Math.PI / CommonConstants.TWO - angle);this.canvasContext?.fillText(character, 0, 0);angle -= angleDecrement;index++;this.canvasContext?.restore();}
}

画内部抽奖区域文字对应图片:使用drawImage()方法绘制抽奖区域文字对应图片,该方法接收五个参数,分别是图片资源、绘制区域左上角的X和Y轴坐标、绘制区域的宽度和高度。

// DrawModel.ets
// 画内部扇形区域文字对应的图片
drawImage() {let beginAngle = this.startAngle;let imageSrc = [CommonConstants.WATERMELON_IMAGE_URL, CommonConstants.BEER_IMAGE_URL,CommonConstants.SMILE_IMAGE_URL, CommonConstants.CAKE_IMAGE_URL,CommonConstants.HAMBURG_IMAGE_URL, CommonConstants.SMILE_IMAGE_URL];for (let i = 0; i < CommonConstants.COUNT; i++) {let image = new ImageBitmap(imageSrc[i]);this.canvasContext?.save();this.canvasContext?.rotate(beginAngle * Math.PI / CommonConstants.HALF_CIRCLE);this.canvasContext?.drawImage(image, this.screenWidth * CommonConstants.IMAGE_DX_RATIOS,this.screenWidth * CommonConstants.IMAGE_DY_RATIOS, CommonConstants.IMAGE_SIZE,CommonConstants.IMAGE_SIZE);beginAngle += this.avgAngle;this.canvasContext?.restore();}
}

实现抽奖功能

在CanvasPage.ets的Canvas组件中添加rotate属性,在Image组件中添加点击事件onClick。点击“开始抽奖”图片,圆形转盘开始转动抽奖。

// CanvasPage.ets
Stack({ alignContent: Alignment.Center }) {Canvas(this.canvasContext)....onReady(() => {this.drawModel.draw(this.canvasContext, this.screenWidth, this.screenHeight);}).rotate({x: 0,y: 0,z: 1,angle: this.rotateDegree,centerX: this.screenWidth / CommonConstants.TWO,centerY: this.screenHeight / CommonConstants.TWO})// 开始抽奖图片Image($r('app.media.ic_center'))....enabled(this.enableFlag).onClick(() => {this.enableFlag = !this.enableFlag;// 开始抽奖this.startAnimator();})
}
...

圆形转盘开始转动抽奖:给转盘指定一个随机的转动角度randomAngle,保证每次转动的角度是随机的,即每次抽到的奖品也是随机的。动画结束后,转盘停止转动,抽奖结束,弹出抽中的奖品信息。

// CanvasPage.ets
dialogController: CustomDialogController = new CustomDialogController({builder: PrizeDialog({prizeData: $prizeData,enableFlag: $enableFlag}),autoCancel: false
});// CanvasPage.ets
// 开始抽奖
startAnimator() {let randomAngle = Math.round(Math.random() * CommonConstants.CIRCLE);// 获取中奖信息this.prizeData = this.drawModel.showPrizeData(randomAngle);animateTo({duration: CommonConstants.DURATION,curve: Curve.Ease,delay: 0,iterations: 1,playMode: PlayMode.Normal,onFinish: () => {this.rotateDegree = CommonConstants.ANGLE - randomAngle;// 打开自定义弹窗,弹出抽奖信息this.dialogController.open();}}, () => {this.rotateDegree = CommonConstants.CIRCLE * CommonConstants.FIVE +CommonConstants.ANGLE - randomAngle;})
}

弹出抽中的奖品信息:抽奖结束后,弹出抽中的文本和图片信息,通过自定义弹窗实现。

// PrizeDialog.ets
@CustomDialog
export default struct PrizeDialog {@Link prizeData: PrizeData;@Link enableFlag: boolean;private controller?: CustomDialogController;build() {Column() {Image(this.prizeData.imageSrc)...Text(this.prizeData.message)...Text($r('app.string.text_confirm'))....onClick(() => {// 关闭自定义弹窗		this.controller?.close();this.enableFlag = !this.enableFlag;})}...}
}

总结

您已经完成了本次Codelab的学习,并了解到以下知识点:

  1. 使用画布组件Canvas,画出抽奖圆形转盘。
  2. 使用显式动画启动抽奖功能。
  3. 使用自定义弹窗弹出抽中的奖品。

为了帮助大家更深入有效的学习到鸿蒙开发知识点,小编特意给大家准备了一份全套最新版的HarmonyOS NEXT学习资源,获取完整版方式请点击→《HarmonyOS教学视频

HarmonyOS教学视频:语法ArkTS、TypeScript、ArkUI等.....视频教程

鸿蒙生态应用开发白皮书V2.0PDF:

获取完整版白皮书方式请点击→《鸿蒙生态应用开发白皮书V2.0PDF》

鸿蒙 (Harmony OS)开发学习手册

一、入门必看

  1. 应用开发导读(ArkTS)
  2. ……

二、HarmonyOS 概念

  1. 系统定义
  2. 技术架构
  3. 技术特性
  4. 系统安全
  5. ........

三、如何快速入门?《做鸿蒙应用开发到底学习些啥?》

  1. 基本概念
  2. 构建第一个ArkTS应用
  3. ……

四、开发基础知识

  1. 应用基础知识
  2. 配置文件
  3. 应用数据管理
  4. 应用安全管理
  5. 应用隐私保护
  6. 三方应用调用管控机制
  7. 资源分类与访问
  8. 学习ArkTS语言
  9. ……

五、基于ArkTS 开发

  1. Ability开发
  2. UI开发
  3. 公共事件与通知
  4. 窗口管理
  5. 媒体
  6. 安全
  7. 网络与链接
  8. 电话服务
  9. 数据管理
  10. 后台任务(Background Task)管理
  11. 设备管理
  12. 设备使用信息统计
  13. DFX
  14. 国际化开发
  15. 折叠屏系列
  16. ……

更多了解更多鸿蒙开发的相关知识可以参考:《鸿蒙 (Harmony OS)开发学习手册》

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/2906647.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

详解TCP的三次握手和四次挥手

文章目录 1. TCP报文的头部结构2. 三次握手的原理与过程三次握手连接建立过程解析 3. 四次挥手的原理与过程四次挥手连接关闭过程的解析 4. 常见面试题 深入理解TCP连接&#xff1a;三次握手和四次挥手 在网络通信中&#xff0c;TCP&#xff08;传输控制协议&#xff09;扮演着…

人才推荐 | 材料化学博士,热衷于创新且可扩展的电池技术开发

编辑 / 木子 审核 / 朝阳 伟骅英才 伟骅英才致力于以大数据、区块链、AI人工智能等前沿技术打造开放的人力资本生态&#xff0c;用科技解决职业领域问题&#xff0c;提升行业数字化服务水平&#xff0c;提供创新型的产业与人才一体化服务的人力资源解决方案和示范平台&#x…

java多线程——概述,创建方式及常用方法

前言&#xff1a; 学习到多线程了&#xff0c;整理下笔记&#xff0c;daydayup!!! 多线程 什么是线程 线程&#xff08;Thread&#xff09;是一个程序内部的一条执行流程。若程序只有一条执行流程&#xff0c;那这个程序就是单线程的程序。 什么是多线程 多线程是指从软硬件上…

【AIGC】如何在Windows/Linux上部署stable diffusion

文章目录 整体安装步骤windows10安装stable diffusion环境要求安装步骤注意事项参考博客其他事项安装显卡驱动安装cuda卸载cuda安装对应版本pytorch安装git上的python包Q&A linux安装stable diffusion安装anaconda安装cudagit 加速配置虚拟环境挂载oss&#xff08;optional…

传播力研究期刊投稿发表

《传播力研究》杂志是经国家新闻出版总署批准&#xff0c;黑龙江日报报业集团主管主办&#xff0c;面向全国公开发行的学术刊物。本刊为新闻、传媒、传播学类专业院校师生、文化传播理论研究者和从业人员及爱好者&#xff0c;开展学术交流与研讨&#xff0c;汲取当今业界新鲜的…

RGB,深度图,点云和体素的相互转换记录

目录 1.RGBD2Point 1.2 步骤 2.Point2Voxel-Voxelization 2.1 原理 2.2 代码 3.Voxel2Point 4.Point2RGB 5.Voxel2RGB 1.RGBD2Point input&#xff1a;RGB D 内外惨 output&#xff1a;points cloud def depth2pcd(depth_img):"""深度图转点云数据图…

翻译 《The Old New Thing》 - Why is a registry file called a “hive“?

Why is a registry file called a “hive“?https://devblogs.microsoft.com/oldnewthing/20030808-00/?p42943 为什么注册表文件被称为‘蜂巢’&#xff1f; Raymond Chen 2003年8月8日 分享一个没用的知识&#xff1a; 话说有一位 Windows NT 的开发者十分讨厌蜜蜂。于是&a…

FLV流媒体封装格式

1、FLV 简介 FLV(Flash Video) 是 Adobe 公司推出的一种流媒体格式&#xff0c;由于其封装后的音视频文件体积小、封装简单等特点&#xff0c;非常适合于互联网上使用。目前主流的视频网站基本都支持FLV。采用 FLV 格式封装的文件后缀为.flv。直播场景下拉流比较常见的是 http-…

计算机网络:现代通信的基石

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

小白了解Pinia第2集 · 三大核心状态Getters、Actions以及Plugins 插件

三大核心状态 state 第1集有详细讲解&#xff1a;https://blog.csdn.net/qq_51463650/article/details/137137080?spm1001.2014.3001.5501 getters Getter 完全等同于 Store 状态的 计算值。 它们可以用 defineStore() 中的 getters 属性定义。 他们接收“状态”作为第一个…

Elastic 8.13:Elastic AI 助手中 Amazon Bedrock 的正式发布 (GA) 用于可观测性

作者&#xff1a;来自 Elastic Brian Bergholm 今天&#xff0c;我们很高兴地宣布 Elastic 8.13 的正式发布。 有什么新特性&#xff1f; 8.13 版本的三个最重要的组件包括 Elastic AI 助手中 Amazon Bedrock 支持的正式发布 (general availability - GA)&#xff0c;新的向量…

汽车电子行业知识:什么是智能驾驶辅助系统(ADAS)

文章目录 1. 什么是智能驾驶辅助系统&#xff08;ADAS&#xff09;1.1 ADAS的功能1.2 ADAS的优势1.3 未来发展趋势 2. ADAS等级2.1. 0级驾驶辅助2.2. 1级驾驶辅助2.3. 2级驾驶辅助2.4. 3级驾驶辅助2.5. 4级和5级驾驶辅助 3. 智能车4. ADAS供应商 1. 什么是智能驾驶辅助系统&…

文章分享:协和文章《病原宏基因组高通量测序性能确认方案》

摘要&#xff1a;宏基因组学利用新一代高通量测序技术&#xff0c;以特定环境下病原体基因组为研究对象&#xff0c;在分析病原体多样性、种群结构、进化关系的基础上&#xff0c;进一步探究病原体的群体功能活性、相互作用及其与环境之间的关系&#xff0c;发掘潜在的生物学意…

STM32之HAL开发——串口配置(CubeMX)

串口引脚初始化&#xff08;CubeMX&#xff09; 选择RCC时钟来源 选择时钟频率&#xff0c;配置为最高频率72MHZ 将单片机调试模式打开 SW模式 选择窗口一配置为异步通信模式 点击IO口设置页面&#xff0c;可以看到当前使用的串口一的引脚。如果想使用复用功能&#xff0c;只需…

每天五分钟深度学习:使用神经网络完成人脸的特征点检测

本文重点 我们上一节课程中学习了如何利用神经网络对图片中的对象进行定位,也就是通过输出四个参数值bx、by、bℎ和bw给出图片中对象的边界框。 本节课程我们学习特征点的检测,神经网络可以通过输出图片中对象的特征点的(x,y)坐标来实现对目标特征的识别,我们看几个例子。…

前端发版上线出现白屏问题

目录 路由配置问题资源缓存问题首屏加载过慢 &#xff1a;喂&#xff0c;你的页面白啦&#xff01; 出现上线白屏的问题有很多&#xff0c;如&#xff1a;配置错误、缓存问题、浏览器兼容问题&#xff0c;根据不同情况去解决。 路由配置问题 问题描述&#xff1a; 在vue开发…

C语言中的联合体和枚举

联合体 联合体的创建 联合体的关键字是union union S {char a;int i; };除了关键字和结构体不一样之外&#xff0c;联合体的创建语法形式和结构体的很相似&#xff0c;如果不熟悉结构体的创建&#xff0c;可以看一下我上一篇的博客关于结构体知识的详解。 联合体的特点 联合…

HarmonyOS 应用开发之进程模型

系统的进程模型如下图所示。 应用中&#xff08;同一Bundle名称&#xff09;的所有UIAbility、ServiceExtensionAbility和DataShareExtensionAbility均是运行在同一个独立进程&#xff08;主进程&#xff09;中&#xff0c;如下图中绿色部分的“Main Process”。应用中&#x…

matlab及其在数字信号处理中的应用001:软件下载及安装

目录 一&#xff0c;matlab的概述 matlab是什么 matlab适用于的问题 matlab的易扩展性 二&#xff0c;matlab的安装 1&#xff0c;解压所有压缩文件 2&#xff0c;解压镜像压缩文件 3&#xff0c;运行setup.exe 4&#xff0c;开始安装 5&#xff0c;不要运行软件…

Python环境下基于深度学习的旋转机械故障诊断及其权重可视化

随着神经网络所要完成的任务越来越智能化&#xff0c;其内部的结构也变得越来越复杂&#xff0c;神经网络学到的解题方法也越来越难以被人类所理解。神经网络的内部单元就好比一个“黑箱”&#xff0c;虽然这种处理方法能够在某种程度上达到非常不错的效果&#xff0c;但其原因…