本期我们给大家带来的是“画图”应用开发者Rick的分享,希望能给你的HarmonyOS开发之旅带来启发~
2021年的华为开发者大会(HDC2021)上,HarmonyOS 发布了新一代的声明式UI框架——方舟开发框架(ArkUI)。ArkUI框架引入了基于TS扩展的声明式开发范式,让开发变得更加简洁、高效!
已经有很多开发者在使用eTS(extended TypeScript)语言,基于声明式开发范式开发应用了。本期我们要介绍的就是eTS开发先行者Rick的分享——100行代码实现“画图”应用,带大家一起领略eTS语言的简洁之美~
100行代码实现的“画图”应用是怎样的?我们先来看看实现效果吧:

图1 实现效果
“画图”应用除了实现必须的画图功能外,还能够设置画笔的颜色和大小,且提供了撤销功能,可谓短小而精美了。你心动了吗?是否也想试试?赶紧跟随Rick的开发过程,也来尝试一下吧!
1. 安装DevEco Studio
eTS开发需安装DevEco Studio V3.0.0.601 Beta1或更高版本。
DevEco Studio下载地址:https://developer.harmonyos.com/cn/develop/deveco-studio/
2. 创建eTS工程
(1) 打开DevEco Studio,在菜单栏选择“File > New > New Project”。
(2) 选择工程模板“Empty Ability”,然后点击Next。

图2 选择工程模板
(3) 工程配置时,注意将“Language”配置为“eTS”。

图3 工程配置
(4) 最后点击Finish,DevEco Studio就会自动创建一个eTS工程。
3. 代码实现
工程创建完成后,可以看到文件目录结构如图4所示。其中,“ets”为代码实现目录,声明式UI实现的布局及逻辑代码都放在这个目录里面。

图4 文件目录结构
本次“画图”应用的代码都放在“entry/src/main/ets/default/pages/index.ets”文件中。
完整的实现代码可从华为开发者论坛获取:
下面为大家介绍两段关键代码:
(1) 画图功能实现代码
// 画布
@Builder Canvas() {
ForEach(this.pathInfoArray, (pathInfo) => OnePath({ pathInfo: pathInfo })) // 遍历构建所有画图路径
Stack() // 覆盖层,用于接收触摸事件,实现画图
.width('100%')
.height('100%')
.onTouch((event: TouchEvent) => {
switch (event.type) {
case TouchType.Down: // 按下时,新建一条画图路径
this.pathInfoArray.push(new PathInfo(`M${event.touches[0].x} ${event.touches[0].y}`, this.paintSize, this.paintColor))
break
case TouchType.Move: // 移动或抬起时,补充画图路径信息
case TouchType.Up:
this.pathInfoArray[this.pathInfoArray.length-1].commands += `L${event.touches[0].x} ${event.touches[0].y}`
break
}
})
}
以上代码通过Canvas组件定义画布,再通过onTouch组件监听触摸事件实现了画图功能。
(2) “设置画笔”的界面和功能实现代码
// 设置画笔组件
@Builder SetPaint() {
Panel(this.showSetPaint) {
Column({ space: 30 }) {
Row() {
Text('画图效果:')
Path()
.width(200)
.height(50)
.backgroundColor(Color.White)
.fillOpacity(0) // 不填充,只要stroke
.commands(`M${vp2px(10)} ${vp2px(10)} S${vp2px(100)} ${vp2px(70)} ${vp2px(190)} ${vp2px(10)}`) // stroke路径,弧线
.strokeWidth(this.paintSize) // stroke宽度
.stroke(this.paintColor) // stroke颜色
}
Row() {
Text('画笔大小:')
Slider({ value: this.paintSize, min: this.PAINT_SIZE_MIN, max: this.PAINT_SIZE_MAX })
.onChange((value) => this.paintSize = value) // 改变画笔大小
.width(200)
}
Row() {
Text('画笔颜色:')
ForEach(this.COLORS, color => {
Stack() {
Stack()
.width(color == this.paintColor ? 26 : 20) // 若是当前画笔颜色,则放大一点显示
.height(color == this.paintColor ? 26 : 20)
.backgroundColor(color)
.onClick(() => this.paintColor = color) // 点击改变画笔颜色
}
.width(32)
.height(32)
})
}
}.width('100%').margin({ top: 30 })
}.onChange((value: any) => {
if (value.mode == 'mini') { // 最小显示状态时隐藏,不隐藏会阻挡触摸事件
this.showSetPaint = false
}
})
}
以上代码通过Panel、Column和Row等容器组件实现了“设置画笔”界面的布局。
此界面包含三个部分:画笔颜色、画笔大小和画图效果。代码中,通过Stack组件展示画笔的颜色,通过Slider组件调整画笔大小,通过Path组件绘制弧线来展示画图效果。最终实现效果如图5所示。

图5 “设置画笔”界面
至此,“画图”应用就开发完成啦!感兴趣的小伙伴也可以去尝试开发哦~
使用eTS语言开发,仅用短短100行左右的代码就实现了“画图”应用的界面和功能。这正是eTS语言的魅力所在——简洁、高效!感兴趣的小伙伴也赶紧加入我们,开启你的eTS开发之旅吧~
我们为大家汇总了以下eTS开发的学习资源,强烈建议收藏哦!
声明式语法:
组件说明:
欢迎更多开发者与我们共享开发成果,分享技术解读与经验心得!

对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl
如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby
在rails源中:https://github.com/rails/rails/blob/master/activesupport/lib/active_support/lazy_load_hooks.rb可以看到以下内容@load_hooks=Hash.new{|h,k|h[k]=[]}在IRB中,它只是初始化一个空哈希。和做有什么区别@load_hooks=Hash.new 最佳答案 查看rubydocumentationforHashnew→new_hashclicktotogglesourcenew(obj)→new_has
我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当
我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此
我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r
刚入门rails,开始慢慢理解。有人可以解释或给我一些关于在application_controller中编码的好处或时间和原因的想法吗?有哪些用例。您如何为Rails应用程序使用应用程序Controller?我不想在那里放太多代码,因为据我了解,每个请求都会调用此Controller。这是真的? 最佳答案 ApplicationController实际上是您应用程序中的每个其他Controller都将从中继承的类(尽管这不是强制性的)。我同意不要用太多代码弄乱它并保持干净整洁的态度,尽管在某些情况下ApplicationContr
我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R
我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden
我已经在Sinatra上创建了应用程序,它代表了一个简单的API。我想在生产和开发上进行部署。我想在部署时选择,是开发还是生产,一些方法的逻辑应该改变,这取决于部署类型。是否有任何想法,如何完成以及解决此问题的一些示例。例子:我有代码get'/api/test'doreturn"Itisdev"end但是在部署到生产环境之后我想在运行/api/test之后看到ItisPROD如何实现? 最佳答案 根据SinatraDocumentation:EnvironmentscanbesetthroughtheRACK_ENVenvironm