https://harmonyos.51cto.com
先看看效果
一.实现思路
冰墩墩作为近段时间以来的国际顶流,非常火热。网络上Python、three.js等各种版本冰墩墩层出不穷,我们本次也来使用ArkUI制作一个冰墩墩。
制作最主要的就是要很好地使用绘制组件。本人使用到的主要绘制组件有:Shape、Path、Circle三个ArkUI中的绘制组件。
二.组件介绍
1.Shape组件
接口:Shape(value:{target?: PixelMap})
关键属性:fill(形状填充颜色)、stroke(形状边框颜色)、strokeWidth(边框宽度)、antiAlias(是否抗锯齿,默认‘是’)
使用实例:
@Entry
@Component
struct ShapeExample {
build() {
Column({ space: 5 }) {
Shape() {
//shape子元素
Path().width(300).height(60).commands('M0 0 L400 0 L400 200 Z')
}
//形状视口
.viewPort({ x: -80, y: -5, width: 310, height: 100 })
//填充色
.fill(0x317Af7).stroke(0xEE8443).strokeWidth(10)
//边框拐角样式
.strokeLineJoin(LineJoinStyle.Miter).strokeMiterLimit(5)
}.width('100%').margin({ top: 15 }) //常规属性
}
}
2.Path组件
属性:width(路径所在矩形的宽度)、height(路径所在矩形的高度)、commands(路径绘制的命令字符串)
使用实例:
.
// 先后执行MoveTo(150, 0), LineTo(300, 300), LineTo(0, 300), ClosePath()
Path().width(100).height(100).commands('M150 0 L300 300 L0 300 Z')
// 先后执行MoveTo(0, 0), HorizontalLineto(300), VerticalLineto(300), HorizontalLineto(0), ClosePath()
Path().width(100).height(100).commands('M0 0 H300 V300 H0 Z')
// 先后执行MoveTo(150, 0), LineTo(0, 150), LineTo(60, 300), LineTo(240, 300), LineTo(300, 150), ClosePath()
Path().width(100).height(100).commands('M150 0 L0 150 L60 300 L240 300 L300 150 Z')
}.width('100%')
.
更多详细信息可参考:Path组件文档
3.Circle组件
接口:Circle(options?: {width: Length, height: Length})
参数:width(圆形的宽度)、height(圆形的高度)
使用实例:
@Entry
@Component
struct CircleExample {
build() {
Flex({ justifyContent: FlexAlign.SpaceAround }) {
// 绘制一个直径为150的圆
Circle({ width: 150, height: 150 })
// 绘制一个直径为150的圆
Circle().width(150).height(150)
}.width('100%').margin({ top: 5 }) //常规参数
}
}
4.画冰墩墩关键Path参数
如下为冰墩墩左耳形状绘制主要参数
//左耳
Path()
.commands("M950 480 S740 350 800 600 M800 600 S850 520 950 480")
M950 480:
像python-turtle库一样,我们都需要一只“画笔”。
M(moveto)代表 画笔的“落笔点”,后面的两个数据可理解为坐标系中的某个坐标点,如M950 480,即 设备屏幕左上角作为直角坐标系的(0,0)点,我们的落笔点为(横坐标,纵坐标)=>(950,480)
S740 350:
S(smooth curveto)代表 拐点坐标,通俗讲就是拐弯处坐标。
M600 500 L800 500:
L(lineto)代表 直线终点坐标,上面这行参数表示:画一条从(600,500)到(800,500)的直线。
示例效果
三.源代码
@Entry
@Component
struct DwenDwen {
build() {
Flex({ alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
Shape() {
//左耳+脸轮廓
Path()
.width('100%')
.height('100%')
.commands("M1000 450 S700 270 750 650 M750 650 S675 800 650 1100")
.stroke(Color.Gray)
.strokeWidth(3)
.fill(Color.White)
//左耳
Path()
.width('100%')
.height('100%')
.commands("M950 480 S740 350 800 600 M800 600 S850 520 950 480")
//右耳+脸轮廓
Path()
.width('100%')
.height('100%')
.commands("M1000 450 S1200 430 1450 450 M1450 450 S1750 270 1700 650 M1700 650 S1775 800 1775 900")
.stroke(Color.Gray)
.strokeWidth(3)
.fill(Color.White)
//右耳
Path()
.width('100%')
.height('100%')
.commands("M1500 480 S1700 360 1650 610 M1650 610 S1620 520 1500 480")
//左手轮廓
Path()
.width('100%')
.height('100%')
.commands("M650 1100 S500 1250 400 1500 M400 1500 S400 1700 650 1600 M650 1600 S660 1580 670 1560 M670 1560 S660 1550 720 1400")
.stroke(Color.Gray)
.strokeWidth(3)
.fill(Color.White)
//左手
Path()
.width('100%')
.height('100%')
.commands("M660 1150 S520 1250 440 1450 S670 1580 650 1540 S680 1450 700 1400 S640 1300 660 1150")
.fill(Color.Black)
//右手轮廓
Path()
.width('100%')
.height('100%')
.commands("M1775 900 S1795 800 1790 750 M1790 750 S1780 680 1830 620 M1830 620 S1940 580 2050 680 M2050 680 S2055 685 2050 720 M2050 720 S2000 1000 1850 1200")
.stroke(Color.Gray)
.strokeWidth(3)
.fill(Color.White)
//右手
Path()
.width('100%')
.height('100%')
.commands("M1850 670 S1980 600 2010 720 S1860 1100 1840 1180 S1750 1100 1760 980 S1750 940 1790 900 S1810 890 1830 820 S1800 800 1850 670")
.fill(Color.Black)
//腿轮廓
Path()
.width('100%')
.height('100%') //弯度20弯度高50 +0,+50 //腿长200
.commands("M720 1400 S740 1600 800 1700 M800 1700 S820 1750 820 1800 M820 1800 L820 2000 M820 2000 S820 2080 860 2100 M860 2100 L1100 2100 M1100 2100 S1140 2080 1140 2000 M1140 2000 S1240 1950 1340 2000 M1340 2000 S1340 2080 1380 2100 M1380 2100 L1620 2100 M1620 2100 S1660 2080 1660 2000 M1660 2000 L1660 1800 M1660 1800 S1660 1750 1680 1700 M1680 1700 S1800 1550 1850 1200")
.stroke(Color.Gray)
.strokeWidth(3)
.fill(Color.White)
//左腿
Path()
.width('100%')
.height('100%')
.commands("M820 1700 S920 1700 1100 1840 S970 1990 1100 1925 S1100 1960 1100 2075 L870 2075 S840 2050 850 1800")
.fill(Color.Black)
//右腿
Path()
.width('100%')
.height('100%')
.commands("M1650 1700 S1550 1700 1370 1840 S1500 1990 1370 1925 S1370 1960 1390 2075 L1610 2070 S1640 2070 1630 1800")
.fill(Color.Black)
//浅蓝环
Path()
.width('100%')
.height('100%')
.commands("M750 1000 S800 600 1250 600 M1250 600 S1700 600 1750 1000 M1750 1000 S1700 1400 1250 1400 M1250 1400 S800 1400 750 1000")
.fill(Color.White)
.strokeWidth(4)
.stroke("#66C2FF")
.antiAlias(true)
//蓝环
Path()
.width('100%')
.height('100%')
.commands("M770 1000 S820 620 1250 620 M1250 620 S1680 620 1730 1000 M1730 1000 S1680 1380 1250 1380 M1250 1380 S820 1380 770 1000")
.fill(Color.White)
.strokeWidth(4)
.stroke(Color.Blue)
.antiAlias(true)
//红环
Path()
.width('100%')
.height('100%')
.commands("M785 1000 S835 635 1250 635 M1250 635 S1665 635 1715 1000 M1715 1000 S1665 1365 1250 1365 M1250 1365 S835 1365 785 1000")
.fill(Color.White)
.strokeWidth(4)
.stroke(Color.Red)
.antiAlias(true)
//黄环
Path()
.width('100%')
.height('100%')
.commands("M800 1000 S850 650 1250 650 M1250 650 S1650 650 1700 1000 M1700 1000 S1650 1350 1250 1350 M1250 1350 S850 1350 800 1000")
.fill(Color.White)
.strokeWidth(4)
.stroke(Color.Yellow)
.antiAlias(true)
//绿环
Path()
.width('100%')
.height('100%')
.commands("M815 1000 S865 665 1250 665 M1250 665 S1665 665 1685 1000 M1685 1000 S1635 1335 1250 1335 M1250 1335 S865 1335 815 1000")
.fill(Color.White)
.strokeWidth(4)
.stroke("#39D839")
.antiAlias(true)
//左眼
Path()
.width('100%')
.height('100%')
.commands("M1000 800 S920 780 860 940 S860 1050 840 1050 S900 1300 1100 920 S600 990 1100 800")
.fill(Color.Black)
.antiAlias(true)
Circle({ width: 45, height: 45 })
.fill(Color.White)
.offset({ x: 282, y: 258 })
Circle({ width: 35, height: 35 })
.fill("#aaccff")
.offset({ x: 288, y: 263 })
Circle({ width: 20, height: 20 })
.fill(Color.Black)
.offset({ x: 297, y: 270 })
//右眼
Path()
.width('100%')
.height('100%')
.commands("M1400 800 S1520 650 1630 940 S1440 1150 1440 1050 S1460 1200 1400 920 S1650 990 1399 850")
.fill(Color.Black)
.antiAlias(true)
//右眼珠
Circle({ width: 45, height: 45 })
.fill(Color.White)
.offset({ x: 442, y: 258 })
Circle({ width: 35, height: 35 })
.fill("#aaccff")
.offset({ x: 448, y: 263 })
Circle({ width: 20, height: 20 })
.fill(Color.Black)
.offset({ x: 455, y: 270 })
//鼻子
Path()
.width('100%')
.height('100%')
.commands("M1200 950 S1250 940 1300 950 S1230 1100 1200 950")
.fill(Color.Black)
.strokeWidth(3)
.stroke(Color.Black)
.antiAlias(true)
//嘴
Path()
.width('100%')
.height('100%')
.commands("M1100 1050 S1250 1300 1400 1050 M1400 1050 S1250 1200 1100 1050")
.fill(Color.Black)
.antiAlias(true)
//logo
Text('BEIJING 2022').fontSize(20).fontStyle(FontStyle.Italic).offset({ x: 315, y: 470 })
//五环
Circle({ width: 25, height: 25 })
.fill(Color.White)
.stroke(Color.Blue)
.strokeWidth(3)
.offset({ x: 335, y: 498 })
Circle({ width: 25, height: 25 })
.fill(Color.White)
.stroke(Color.Black)
.strokeWidth(3)
.offset({ x: 365, y: 498 })
Circle({ width: 25, height: 25 })
.fill(Color.White)
.stroke(Color.Red)
.strokeWidth(3)
.offset({ x: 395, y: 498 })
Circle({ width: 25, height: 25 })
.fill(Color.White)
.opacity(0.4)
.stroke(Color.Yellow)
.strokeWidth(3)
.offset({ x: 350, y: 515 })
Circle({ width: 25, height: 25 })
.fill(Color.White)
.opacity(0.4)
.stroke(Color.Green)
.strokeWidth(3)
.offset({ x: 380, y: 515 })
//爱心
Image($r("app.media.love_icon")).width(30).height(30).offset({ x: 570, y: 220 })
}
}
.width('100%')
}
}