#过年不停更# HarmonyOS自定义JS组件——元宵猜灯谜 原创 精华
深开鸿
发布于 2022-2-15 20:48
浏览
5收藏
作者:包月东
前言
又到了一年一度的元宵佳节,首先祝大家元宵节快乐!东风夜放花千树,宝马雕车香满路。逛花市,猜灯谜作为传统节目,经久不衰,今天给大家带来一款猜灯谜的鸿蒙小游戏。
效果图
实现思路
首先我们来拆分下区域,如效果图所示,游戏区域分为:头部面板、谜语、谜字、控制按钮、提示、谜底面板(隐藏)
- 记分面板:左边是一个得分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用来显示谜底
源码路径
参考
更多原创内容请关注:深开鸿技术团队
入门到精通、技巧到案例,系统化分享HarmonyOS开发技术,欢迎投稿和订阅,让我们一起携手前行共建鸿蒙生态。
©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
已于2022-2-25 10:00:28修改
赞
6
收藏 5
回复
相关推荐
元宵节能和家人一起以这种形式猜灯谜也是一种乐事。
666