HarmonyOS自定义JS组件—元宵猜灯谜

原创
系统 OpenHarmony
东风夜放花千树,宝马雕车香满路。逛花市,猜灯谜作为传统节目,经久不衰,今天给大家带来一款猜灯谜的鸿蒙小游戏。

​想了解更多内容,请访问:​

​51CTO和华为官方合作共建的鸿蒙技术社区​

​https://harmonyos.51cto.com​

前言

东风夜放花千树,宝马雕车香满路。逛花市,猜灯谜作为传统节目,经久不衰,今天给大家带来一款猜灯谜的鸿蒙小游戏。

效果图

实现思路

首先我们来拆分下区域,如效果图所示,游戏区域分为:头部面板、谜语、谜字、控制按钮、提示、谜底面板(隐藏)

  • 记分面板:左边是一个得分text,右边是一个音乐播放按钮,可以用video实现
  • 谜语:主要是文本,使用text实现
  • 谜字:有一堆text组成,通过for来配置。每次放置的位置、旋转角度通过随机函数设置,不至于沉闷。
  • 控制按钮:查看谜底用来显示谜底面板。上一题,下一题则是改变题库的指针pointer来更改谜语,谜字。
  • 提示:一个简单的text
  • 谜底面板:这里用到了panel,起到弹起收拢的效果。

具体实现

头部面板

  <stack class="music">
<video show="false" id='videoId' src='/common/Homey.mp3' muted='false'
autoplay='true' poster='/common/images/music_symbol.png'
controls="true"
loop='true'>
</video>
<image src="/common/images/music_symbol.png" style="object-fit: contain;"></image>
</stack>

复制如上,音乐的播放我们使用video来实现,设置show为false不显示,loop为true表示不断轮播。video是负责后台播放,前台旋转音乐图片使用image实现,旋转动画我们选择CSS动画配置

.music {
width: 50;
height: 50;
position: absolute;
right: 5%;
top: 1.5%;
animation-name: musicrotation;
animation-duration: 4s;
animation-delay: 0s;
animation-fill-mode: forwards;
animation-iteration-count: -1;
animation-timing-function: linear
}

@keyframes musicrotation {
from {
transform: rotate(0deg);
}

to {
transform: rotate(360deg)
}
}

谜语

<text class="riddle">{{ riddle }}</text>

谜字

<stack id="content"
style="background-color : yellow; width : 100%; height : 30%;
margin-start : 7%;
margin-end : 7%;
margin-top : 2%;
margin-bottom : 2%"
>
<text for="{{ (i, v) in selection }}"
style="top : {{ selection_property[i].top }};
left : {{ selection_property[i].left }};
transform : rotate({{ selection_property[i].rotate }});
color : {{ [i].color }};
font-size : 30fp;
" onclick="onTextClick(i)">{{ v }}</text>
</stack>

谜字通过一个for循环动态生成text,这里的selection表示谜字的文本,selection_property表示每个文本的位置、选择,颜色等属性

生成selection_property的代码如下:

//配置selection_property
let selection_property = []
const degree_unit = 360 / len
const degree2Rad = Math.PI / 180
for (let i = 0;i < len; i++) {
let d = degree_unit * (i + (Math.random() * 0.3 + 0.3)) * degree2Rad
let r = (Math.random() * 0.1 + 0.6) * 50
let left = 50 + r * Math.cos(d) - 5 + '%'
let top = 50 + r * Math.sin(d) - 10 + '%'
let rotate = (Math.random() * 2 - 1) * 45 + '%'
selection_property.push({
top: top,
left: left,
rotate: rotate,
color: 'black'
})
}

通过更改selection_property中top,left,rotate,color这几个属性更改text的显示位置,为了生动使用了Math.Random()

判断是否答对

迷字开始是黑色,点击一次变成红色,我们通过遍历selection_property可以查看用户选择了那几个迷字,当迷字和我们的谜底相同时,表示答对

具体代码如下:

 //个数和词都能对上才算答对
checkIsCorrect() {
let count1 = 0, count2 = 0;
for (let i = 0;i < this.selection_property.length; i++) {
if (this.selection_property[i].color != 'black') {
count1++
if (this.answer.includes(this.selection[i])) {
count2++;
}
}
}
return count2 == this.answer.length && count1 == count2;
},

判断是否通关

当当前谜语的pointer指向最后一个了,当用户答对时,我们认为通关了

onTextClick(i) {
console.log('i-->' + i)
this.selection_property[i].color = this.selection_property[i].color == 'red' ? 'black' : 'red'
if (this.checkIsCorrect()) {
this.score += 10;
if (this.pointer == riddles.length - 1) {
prompt.showToast({
message: "恭喜通关,你的总得分是:" + this.score
})
} else {
prompt.showToast({
message: "恭喜答对了"
})
this.nextStage();
}
}
},

控制面板

   <div style="width : 100%; justify-content : center; flex-direction : row; margin-start : 5%; margin-end : 5%;">
<button type="capsule" @click="showAnswer">查看谜底</button>
<button type="capsule" style="margin-start : 10%;" @click="prevStage">上一题</button>
<button type="capsule" style="margin-start : 10%;" @click="nextStage">下一题</button>
</div>

查看谜底的click方法是用来显示谜底panel,当然这里是否显示谜底,需要在提示次数和积分够的情况下才行。

showAnswer() {
if (this.tipCount <= 0 && this.score < 20) {
prompt.showToast({
message: "提示次数已用完,得分高于20分才能看谜底额"
})
return
}
if (this.tipCount > 0) {
prompt.showToast({
message: "剩余提示次数:" + this.tipCount
})
this.tipCount -= 1;
setTimeout(() => {
this.$element('answer').show()
}, 1000)
} else {
this.score -= 20
this.$element('answer').show()
}
},

提示

提示:点击文字选择词语或者取消

<text style="font-size : 15px; color : white; bottom : 2%; margin-start : 5%; position : absolute;">提示:点击文字选择词语或者取消
</text>

谜底面板

<panel id="answer" type="minibar" mode="half" onsizechange="changeMode" miniheight="200px">
<div class="panel-div">
<div class="inner-btn">
<button style="background-color : blue;" type="capsule" value="Close" onclick="closeAnswer"></button>
</div>
<div class="inner-txt" onclick="closeAnswer">
<text class="txt">{{ answer }}</text>
</div>

</div>
</panel>

这里用到了panel,我们通过设置model为half来显示半屏。内部的txt用来显示谜底

​想了解更多内容,请访问:​

​51CTO和华为官方合作共建的鸿蒙技术社区​

​https://harmonyos.51cto.com​

责任编辑:jianghua 来源: 鸿蒙社区
相关推荐

2021-11-01 10:21:36

鸿蒙HarmonyOS应用

2022-02-21 15:16:30

HarmonyOS鸿蒙操作系统

2021-09-15 10:19:15

鸿蒙HarmonyOS应用

2022-07-06 20:24:08

ArkUI计时组件

2022-02-16 15:25:31

JS代码Canvas鸿蒙

2022-04-24 15:17:56

鸿蒙操作系统

2022-05-20 14:34:20

list组件鸿蒙操作系统

2023-02-20 15:20:43

启动页组件鸿蒙

2021-11-24 10:02:53

鸿蒙HarmonyOS应用

2022-06-20 15:43:45

switch开关鸿蒙

2021-12-21 15:22:22

鸿蒙HarmonyOS应用

2022-06-30 14:02:07

鸿蒙开发消息弹窗组件

2022-07-15 16:45:35

slider滑块组件鸿蒙

2022-07-12 16:56:48

自定义组件鸿蒙

2022-06-23 07:23:34

自定义组件计时器

2022-05-23 10:53:54

canvas柱状图鸿蒙

2021-12-24 15:46:23

鸿蒙HarmonyOS应用

2021-11-22 10:00:33

鸿蒙HarmonyOS应用

2022-10-25 15:12:24

自定义组件鸿蒙

2022-10-26 15:54:46

canvas组件鸿蒙
点赞
收藏

51CTO技术栈公众号