从零开发HarmonyOS(鸿蒙)运动手表小游戏——数字华容道

原创
2020/11/22 20:29
阅读数 1.4W

 

 

前言

此次博客是深鸿会博主(Zzt_01-23)学习完HarmonyOS(鸿蒙)后,自行开发的第二个鸿蒙demo——数字华容道,详细讲述了数字华容道的开发思路,适合刚入门小白,使读者能自行从零开发一个小游戏APP——数字华容道,文末附有整个demo的源代码,有兴趣的读者也可以前往观看我的第一个游戏开发学习:黑白翻棋,较第一个而言,此次只是多了滑动事件和计时器,其他组件和第一个游戏一样,建议先观看完第一个再学习第二个。

概述

本个demo将从零基础开始完成鸿蒙小游戏APP在可穿戴设备上的编译,此处以运动手表为例,在项目中我们所使用到的软件为DevEco Studio,下载地址为:DevEco Studio下载DevEco Studio安装教程,在项目中我们要实现的内容为数字华容道APP的开发。

  1. 在初始界面中显示4*4的方阵,方阵中分布有随意打乱的1至15的数字和一个空白方格,方阵上方增加一个计时器,显示游戏进行的时间,单位为秒,方阵下方显示一个“重新开始”的按钮,为用户提供重新开始游戏的机会。
    在这里插入图片描述

  2. 向上、下、左、右任一方向滑动,空白方格周围对应位置的方格便会随之向对应的方向移动一格,计时器也会显示游戏开始到当前的时间。
    在这里插入图片描述

  3. 经过若干次移动后,当所有的数字按顺序排列后,则会弹出游戏成功的界面,再滑动也不会有任何变化,此时方阵上方的计时器停止计时,点击“重新开始”的按钮后则会重新返回步骤1界面所示。
    在这里插入图片描述

正文

创建项目

DevEco Studio下载安装成功后,打开DevEco Studio,点击左上角的File,点击New,再选择New Project,选择Lite Wearable选项,选择默认的模板,然后选择保存路径,将文件命名为Game1(文件名不能出现中文或者特殊字符,否则将无法成功创建项目文件),最后点击Finish。
在这里插入图片描述
主要编写的文件为index.css、index.hml和index.js,打开路径如图所示,index.hml用于描述页面中包含哪些组件,index.css用于描述页面中的组件都长什么样,index.js用于描述页面中的组件是如何进行交互的。
在这里插入图片描述

实现开始界面的布局

首先,我们要先画出一个4*4的方阵,方阵中按照顺序显示1至15的数字,方阵上方显示“当前秒数:0”,方阵下方有一个“重新开始”的按钮。
在这里插入图片描述
1.在index.hml中添加相应的页面组件:
首先创建一个基础容器div类名为container,用于盛装所有的其他组件

<div class="container" >
</div>

然后在此基础容器中添加一个文字组件text类名为seconds,且注明显示的固定部分“当前秒数:”,为动态变换部分赋予一个名为currentSteps的变量,用于动态显示游戏进行的秒数

<text class="seconds">
        当前秒数:{
   {
   currentSeconds}}
</text>

再添加一个画布组件canvas类名为canvas,增加一个引用属性ref,用来指定指向子元素或子组件的引用信息,该引用将注册到父组件的$refs 属性对象上,以便在此画布上画出4*4的方阵

<canvas class="canvas" ref="canvas" >
</canvas>

最后添加一个普通按钮组件,类名为bit,并赋值“重新开始”,用于重新开始游戏

<input type="button" value="重新开始" class="bit"/>

至此,index.hml文件已经全部编写完毕

<div class="container" >
    <text class="seconds">
        当前秒数:{
   {
   currentSeconds}}
    </text>
    <canvas class="canvas" ref="canvas" ></canvas>
    <input type="button" value="重新开始" class="bit"/>
</div>

2.在index.css中描述刚才添加的页面组件的样式:
首先编写container的样式,flex-direction为容器主轴方向,选择column(垂直方向从上到下),justify-content为容器当前行的主轴对齐格式,选择center(项目位于容器的中心),align-items为容器当前行的交叉轴对齐格式,选择center(元素在交叉轴居中),width、height分别为容器以像素为单位的宽度和高度,都设定为450px

.container {
   
    flex-direction: column;
    justify-content: center;
    align-items: center;
    width:450px;
    height:450px;
}

然后编写seconds的样式,font-size为设置文本的尺寸,设定为18px,text-align为设置文本的文本对齐方式,选择center(文本居中对齐),width、height分别设定为300px和20px,letter-spacing为设置文本的字符间距,设定为0px,margin-top为设置上外边距,设定为10px

.seconds{
   
    font-size: 18px;
    text-align:center;
    width:300px;
    height:20px;
    letter-spacing:0px;
    margin-top:10px;
}

再编写canvas的样式,width、height都设定为320px,background-color为设置背景颜色,设定为#FFFFFF

.canvas{
   
    width:305px;
    height:305px;
    background-color: #FFFFFF;
}

最后编写bit的样式,width、height分别设定为150px和30px,background-color设定为#AD9D8F,font-size设定为24px,margin-top设定为10px

.bit{
   
    width:150px;
    height:30px;
    background-color:#AD9D8F;
    font-size:24px;
    margin-top:10px;
}

至此,index.css文件已经全部编写完毕
3.在index.js中描述页面中的组件交互情况:
首先在data中为当前秒数currentSeconds赋值为0

data: {
   
        currentSeconds:0,
    }

然后在文件开头定义一个全局变量context,定义一个全局变量的二维数组grids,其中的值为1至15和0,定义全局常量方格的边长SIDELEN为70,方格的间距MARGIN为5,创建一个onReady()函数,用于定义2d绘画工具

var grids=[[1, 2, 3, 4],
           [5, 6, 7, 8],
           [9, 10, 11, 12],
           [13, 14, 15, 0]];
var context;

const SIDELEN = 70;
const MARGIN = 5;

onReady(){
   
        context=this.$refs.canvas.getContext('2d');
    }

再创建drawGrids()函数,先将grids的值利用toString()函数全部转化为字符串,fillStyle为画图工具context的方格的颜色,方格的背景颜色定义为#BBADA0,数字的颜色定义为#000000,fillRect为画图工具context的画图矩形的大小,其中有四个参数,第一个参数指定矩形左上角的x坐标,第二个参数指定矩形左上角的y坐标,第三个参数指定矩形的高度,第四个参数指定矩形的宽度。font为为画图工具context的字体大小,定义为30px HYQiHei-65S,因为要出现一个空白的方格,所以需要添加一个判断语句,当数字为0时不显示数字。fillText为画图工具context的文本字体大小,其中有三个参数,第一个参数为绘制的文本,第二个参数指定文本左上角的x坐标,第三个参数指定文本左上角的y坐标,最后创建onShow()函数,用于调用drawGrids()函数

onShow() {
   
        this.drawGrids();
    },
    drawGrids() {
   
        for (let row = 0; row < 4; row++) {
   
            for (let column = 0; column < 4; column++) {
   
                let gridStr = grids[row][column].toString();

                context.fillStyle = "#BBADA0";
                let leftTopX = column * (MARGIN + SIDELEN) + MARGIN;
                let leftTopY = row * (MARGIN + SIDELEN) + MARGIN;
                context.fillRect(leftTopX, leftTopY, SIDELEN, SIDELEN);

                context.font = "30px HYQiHei-65S";
                if (gridStr != "0") {
   
                    context.fillStyle = "#000000";
                    let offsetX = (4 - gridStr.length) * (SIDELEN / 8);
                    let offsetY = (SIDELEN - 30) / 2;
                    context.fillText(gridStr, leftTopX + offsetX, leftTopY + offsetY);
                }
            }
        }
    }

至此,index.jd文件已经全部编写完毕,运行即可得出上述界面布局了

var grids=[[1, 2, 3, 4],
           [5, 6, 7, 8],
           [9, 10, 11, 12],
           [13, 14, 15, 0]];
var context;

const SIDELEN = 70;
const MARGIN = 5;

export default {
   
    data: {
   
        currentSeconds:0,
    },
    onReady() {
   
        context = this.$refs.canvas.getContext('2d');
    },
    onShow() {
   
        this.drawGrids();
    },
    drawGrids() {
   
        for (let row = 0; row < 4; row++) {
   
            for (let column = 0; column < 4; column++) {
   
                let gridStr = grids[row][column].toString();

                context.fillStyle = "#BBADA0";
                let leftTopX = column * (MARGIN + SIDELEN) + MARGIN;
                let leftTopY = row * (MARGIN + SIDELEN) + MARGIN;
                context.fillRect(leftTopX, leftTopY, SIDELEN, SIDELEN);

                context.font = "30px HYQiHei-65S";
                if (gridStr != "0") {
   
                    context.fillStyle = "#000000";
                    let offsetX = (4 - gridStr.length) * (SIDELEN / 8);
                    let offsetY = (SIDELEN - 30) / 2;
                    context.fillText(gridStr, leftTopX + offsetX, leftTopY + offsetY);
                }
            }
        }
    },
}

实现数字的随机打乱和方格的移动

其次我们要在屏幕上随机生成一个数字被随意打乱的4*4的方阵,并且向任意方向滑动屏幕,空白方格周围对应位置的方格便会随之向对应的方向移动一格
在这里插入图片描述
在这里插入图片描述
1.在index.hml中添加相应的页面组件:
我们需要在画布中添加一个swipe属性,用于响应滑动事件,赋予一个所自动调用的函数swipeGrids

<canvas class="canvas" ref="canvas" onswipe="swipeGrids"></canvas>

至此,index.hml文件已经全部编写完毕
2.在index.css中描述刚才添加的页面组件的样式:
这一部分不需要添加或修改页面组件的样式
3. 在index.js中描述页面中的组件交互情况:
首先我们得先实现方格的移动,创建一个函数changeGrids(direction),接受一个参数direction指示滑动的方向,先找出空白方格所在位置对应的二维数组下标,接着判断参数direction为’left’、‘right’、‘up’ 或’down’时,当isShow为false时,对应的方格和空白方格对应的二维数组的数值对调,创建响应滑动事件所自动调用的函数swipeGrids(event),参数为滑动事件,调用函数changeGrids(direction),并传入滑动的方向,最后调用函数drawGrids()

swipeGrids(event) {

        this.changeGrids(event.direction);
        this.drawGrids();
    },
    changeGrids(direction) {
        let x;
        let y;
        for (let row = 0; row < 4; row++) {
            for (let column = 0; column < 4; column++) {
                if (grids[row][column] == 0) {
                    x = row;
                    y = column;
                    break;
                }
            }
        }
        let temp;
        if(this.isShow==false){
            if (direction == 'left' && (y + 1) < 4) {
                temp = grids[x][y + 1];
                grids[x][y + 1] = grids[x][y];
                grids[x][y] = temp;
            } else if (direction == 'right' && (y - 1) > -1) {
                temp = grids[x][y - 1];
                grids[x][y - 1] = grids[x][y];
                grids[x][y] = temp;
            } else if (direction == 'up' && (x + 1) < 4) {
                temp = grids[x + 1][y];
                grids[x + 1][y] = grids[x][y];
                grids[x][y] = temp;
            } else if (direction == 'down' && (x - 1) > -1) {
                temp = grids[x - 1][y];
                grids[x - 1][y] = grids[x][y];
                grids[x][y] = temp;
            }
        }

然后添加一个函数initGrids(),用于随机打乱排列规则的数字,先创建一个一维数组变量array,赋值为上下左右四个方向"left",“up”,“right”,“down”,Math.random()函数是随机[0,1)内的小数,Math.random() * 4是随机[0,4)内的小数,Math.floor(x)为得出小于或等于x的最大整数,随机生成一个数字,读取数组array对应的值,调用函数this.changeGrids(direction)并将刚才的array对应的值传入,便能移动一次方格,循环此步骤若干次便可随机打乱排列规则的数字,生成一个数字被随意打乱的4*4的方阵

initGrids(){
   
        let array=["left","up","right","down"];

        for (let i = 0; i < 100; i++){
   
            let randomIndex = Math.floor(Math.random() * 4);
            let direction = array[randomIndex];
            this.changeGrids(direction);
        }
    }

最后在函数onShow()中调用函数initGrids()

onShow() {
   
        this.initGrids();
        this.drawGrids();
    }

至此,index.jd文件已经全部编写完毕,运行即可得出上述界面布局了

实现计时器、重新开始和游戏成功

最后我们要在方阵上方动态显示游戏开始到当前的时间,并且当数字按顺序排列后弹出“游戏成功”界面,点击“重新开始”按钮能够重新随机生成一个数字被随意打乱的4*4的方阵,当前秒数置为0 ,且能够重新开始计时
在这里插入图片描述
在这里插入图片描述
1.在index.hml中添加相应的页面组件:
为了使数字按顺序排列后才显示“游戏成功”界面,需要添加一个栈stack类名设定为stack,使画布先进栈,“游戏成功”后进栈,这样就能达到“游戏成功”界面显示在画布上方了

<stack class="stack">
</stack>

在栈stack组件中增加一个游戏成功的容器div类名为subcontainer,以isShow控制该容器是否进栈,当isShow为true时才进栈,增加文本组件text,类名gameover,并赋值“游戏成功”

<div class="subcontainer" show="{
   {isShow}}">
            <text class="gameover">
                游戏成功
            </text>
        </div>

最后为“重新开始”按钮增加一个点击事件click,所调用的函数为restartGame

<input type="button" value="重新开始" class="bit" onclick="restartGame"/>

至此,index.hml文件已经全部编写完毕

<div class="container" >
    <text class="seconds">
        当前秒数:{
   {
   currentSeconds}}
    </text>
    <stack class="stack">
        <canvas class="canvas" ref="canvas" onswipe="swipeGrids"></canvas>
        <div class="subcontainer" show="{
   {isShow}}">
            <text class="gameover">
                游戏成功
            </text>
        </div>
    </stack>
    <input type="button" value="重新开始" class="bit" onclick="restartGame"/>
</div>

2.在index.css中描述刚才添加的页面组件的样式:
首先编写stack的样式,width、height都设定为320px,margin-top设定为10px

.stack{
   
    width: 305px;
    height: 305px;
    margin-top: 10px;
}

然后编写subcontainer的样式,left为指示距边界框左上角的以像素为单位的水平坐标,top为指示距边界框左上角的以像素为单位的垂直坐标,width、height分别设定为220px和130px,justify-content选择center,align-items选择center, background-color设定为#E9C2A6

.subcontainer {
   
    left:50px;
    top:95px;
    width: 220px;
    height: 130px;
    justify-content: center;
    align-items: center;
    background-color: #E9C2A6;
}

最后编写gameover的样式,font-size设定为38px,color设定为black

.gameover {
   
    font-size: 38px;
    color: black;
}

至此,index.css文件已经全部编写完毕
3.在index.js中描述页面中的组件交互情况:
首先在data函数中给isShow赋值为false,将开头的全局变量grids赋值删除,增加一个函数onInit()给grids赋值,并调用函数initGrids()和this.drawGrids()

var grids;

data: {
   
        currentSeconds:0,
        isShow: false
    },
    onInit() {
   
        grids=[[1, 2, 3, 4],
               [5, 6, 7, 8],
               [9, 10, 11, 12],
               [13, 14, 15, 0]];

        this.initGrids();
        this.drawGrids();
    }

然后在开头定义一个全局变量timer赋值为null,在函数onShow()中增加一个计时器setInterval(),其中有两个参数,第一个参数为调用的函数,第二个参数为每隔多长时间调用一次函数,单位为毫秒,再定义调用的函数run(),用于每次currentSeconds加0.1,parseFloat是使字符串转换为单精度浮点数,至此计时器便完成了

var timer = null;

onShow() {
        this.initGrids();
        this.drawGrids();

        timer = setInterval(this.run, 100);
    }
 
run(){
        this.currentSeconds = (Math.floor(parseFloat(this.currentSeconds) * 10+ 1) / 10).toString();
        if(parseFloat(this.currentSeconds) % 1 == 0){
            this.currentSeconds = this.currentSeconds + ".0";
        }
    }

创建一个函数gameover()判断数字是否有顺序地排列好即判断游戏是否成功,循环判断当前二维数组的数值是否等于有顺序排列好的二维数组的数值即可判断游戏是否成功,当游戏成功时返回true,否则返回false,在函数中swipeGrids(event)调用函数gameover(),当返回值为true时将isShow赋值为true,使游戏成功界面显示在最上方,并且调用函数clearInterval停止计时

swipeGrids(event) {
        this.changeGrids(event.direction);
        this.drawGrids();

        if(this.gameover()){
            clearInterval(timer);
            this.isShow = true;
        }
    },
    gameover(){
        let originalgrids=[[1, 2, 3, 4],
                           [5, 6, 7, 8],
                           [9, 10, 11, 12],
                           [13, 14, 15, 0]];
        for (let row = 0; row < 4; row++) {
            for (let column = 0; column < 4; column++) {
                if (grids[row][column] != originalgrids[row][column]){
                    return false;
                }
            }
        }
        return true;
    }

最后创建点击“重新开始”按钮所自动调用的函数restartGame(),调用函数onInit(),重新随机生成一个数字被随意打乱的4*4的方阵,将isShow赋值为false,使“游戏成功”界面隐藏,将currentSeconds置为0,将time赋值为null,调用函数onShow()重新开始计时

restartGame(){

        this.currentSeconds = "0.0";
        this.isShow = false;

        this.onShow();
    }

至此,index.jd文件已经全部编写完毕,整个demo也全部完成了

心得体会

本个demo整体难度不高,涉及的组件或样式都是很常见的,需要掌握栈、按钮、画布、计时器、滑动等组件即可完成编写,组件交互采用二维数组串连整个项目,十分适合刚入门的读者编写与学习,其中组件学习可以前往官方文档查看更详细的介绍:官方文档,较之第一个游戏黑白翻棋,组件虽多了一种,但算法更简单了,代码更优化,可读性更加强,建议读者在学习时可以与第一个游戏黑白翻棋对照一起学习:黑白翻棋

结语

本次项目为博主学习了鸿蒙一些基础后自行编写完成的,感兴趣的读者可以自行跟着本博客编写,相信你们也能够完成的。如果有遇到什么问题,或者查找出其中的错误之处,欢迎留言,本博主也欢迎与各位感兴趣的读者一起学习HarmonyOS(鸿蒙)开发。

源代码

index.hml如下:

<div class="container" >
    <text class="seconds">
        当前秒数:{{currentSeconds}}
    </text>
    <stack class="stack">
        <canvas class="canvas" ref="canvas" onswipe="swipeGrids"></canvas>
        <div class="subcontainer" show="{{isShow}}">
            <text class="gameover">
                游戏成功
            </text>
        </div>
    </stack>
    <input type="button" value="重新开始" class="bit" onclick="restartGame"/>
</div>

index.css如下:

.container {
    flex-direction: column;
    justify-content: center;
    align-items: center;
    width:450px;
    height:450px;
}
.seconds{
    font-size: 18px;
    text-align:center;
    width:300px;
    height:20px;
    letter-spacing:0px;
    margin-top:10px;
}
.canvas{
    width:305px;
    height:305px;
    background-color: #FFFFFF;
}
.bit{
    width:150px;
    height:30px;
    background-color:#AD9D8F;
    font-size:24px;
    margin-top:10px;
}
.stack{
    width: 305px;
    height: 305px;
    margin-top: 10px;
}
.subcontainer {
    left:50px;
    top:95px;
    width: 220px;
    height: 130px;
    justify-content: center;
    align-items: center;
    background-color: #E9C2A6;
}
.gameover {
    font-size: 38px;
    color: black;
}

index.js如下:

var grids;
var context;
var timer;

const SIDELEN = 70;
const MARGIN = 5;

export default {
    data: {
        currentSeconds: '0.0',
        isShow: false
    },
    onInit() {
        grids=[[1, 2, 3, 4],
               [5, 6, 7, 8],
               [9, 10, 11, 12],
               [13, 14, 15, 0]];

        this.initGrids();
        this.drawGrids();
    },
    initGrids(){
        let array=["left","up","right","down"];

        for (let i = 0; i < 100; i++){
            let randomIndex = Math.floor(Math.random() * 4);
            let direction = array[randomIndex];
            this.changeGrids(direction);
        }
    },
    onReady() {
        context = this.$refs.canvas.getContext('2d');
    },
    onShow() {
        this.initGrids();
        this.drawGrids();

        timer = setInterval(this.run, 100);
    },
    drawGrids() {
        for (let row = 0; row < 4; row++) {
            for (let column = 0; column < 4; column++) {
                let gridStr = grids[row][column].toString();

                context.fillStyle = "#BBADA0";
                let leftTopX = column * (MARGIN + SIDELEN) + MARGIN;
                let leftTopY = row * (MARGIN + SIDELEN) + MARGIN;
                context.fillRect(leftTopX, leftTopY, SIDELEN, SIDELEN);

                context.font = "30px HYQiHei-65S";
                if (gridStr != "0") {
                    context.fillStyle = "#000000";
                    let offsetX = (4 - gridStr.length) * (SIDELEN / 8);
                    let offsetY = (SIDELEN - 30) / 2;
                    context.fillText(gridStr, leftTopX + offsetX, leftTopY + offsetY);
                }
            }
        }
    },
    run(){
        this.currentSeconds = (Math.floor(parseFloat(this.currentSeconds) * 10+ 1) / 10).toString();
        if(parseFloat(this.currentSeconds) % 1 == 0){
            this.currentSeconds = this.currentSeconds + ".0";
        }
    },
    swipeGrids(event) {
        this.changeGrids(event.direction);
        this.drawGrids();

        if(this.gameover()){
            clearInterval(timer);
            this.isShow = true;
        }
    },
    gameover(){
        let originalgrids=[[1, 2, 3, 4],
                           [5, 6, 7, 8],
                           [9, 10, 11, 12],
                           [13, 14, 15, 0]];
        for (let row = 0; row < 4; row++) {
            for (let column = 0; column < 4; column++) {
                if (grids[row][column] != originalgrids[row][column]){
                    return false;
                }
            }
        }
        return true;
    },
    changeGrids(direction) {
        let x;
        let y;
        for (let row = 0; row < 4; row++) {
            for (let column = 0; column < 4; column++) {
                if (grids[row][column] == 0) {
                    x = row;
                    y = column;
                    break;
                }
            }
        }
        let temp;
       if(this.isShow==false){
            if (direction == 'left' && (y + 1) < 4) {
                temp = grids[x][y + 1];
                grids[x][y + 1] = grids[x][y];
                grids[x][y] = temp;
            } else if (direction == 'right' && (y - 1) > -1) {
                temp = grids[x][y - 1];
                grids[x][y - 1] = grids[x][y];
                grids[x][y] = temp;
            } else if (direction == 'up' && (x + 1) < 4) {
                temp = grids[x + 1][y];
                grids[x + 1][y] = grids[x][y];
                grids[x][y] = temp;
            } else if (direction == 'down' && (x - 1) > -1) {
                temp = grids[x - 1][y];
                grids[x - 1][y] = grids[x][y];
                grids[x][y] = temp;
            }
        }
    },
    restartGame(){
        this.currentSeconds = "0.0";
        this.isShow = false;

        this.onShow();
    }
}
展开阅读全文
打赏
4
1 收藏
分享
加载中
作者你好,您的两篇文章的程序我都导入了,发现一个关于画布组件canvas的问题,调查后发现,目前,官方还没有正式release组件canvas,因此在其下方会显示一个红色的波浪线,请问您是如何使用这个组件且不报错成功运行项目的呢?望指点,谢谢!
2020/11/24 13:31
回复
举报
鲸云夕陌博主
你好,因为目前官方还没有正式release组件canvas,因此在其下方会显示一个红色的波浪线,但是,这并不影响代码的成功运行,仍然是可以正常运行在预览器或模拟器中的,只是无法正常运行在鸿蒙手表Watch GT2 Pro中,所以我两个程序都是使用这个组件会报错但是能够运行项目,目前没有办法使用这个组件且不报错成功运行项目的。
2020/11/24 14:24
回复
举报
你好,我是在Tools下的HVD Manager中的wearable模拟器运行的。首先在创建项目的时候选择Lite Wearable运行会报出一个(此设备类型与项目配置文件不匹配。部署HAP时出错。)这样的错误,然而当我重新创建Wearable工程正常运行,但手表的页面会直接黑屏。而更改配置文件也无法解决,我想到内置默认的模拟器Huawei Lite Wearable Simulator运行后成功打开页面,项目为数字华容道。但爆出一个错误,消息为:(Jerry Launcher: [JS Exception]: TypeError: Cannot set property 'fillStyle' of undefined)。画面显示为当前秒数这一行显示上半部分,计时功能可能异常,盘面上游戏成功的棕色背景框始终保持在页面上。望定位错误,帮助解决,谢谢作者!
2020/11/24 15:51
回复
举报
鲸云夕陌博主
你尝试一下重新按照教程创建项目,敲写代码,然后点击菜单栏的View,再选择Tool Windows,最后点击Previewer预览模式运行项目,或者只点击右上角工具栏的三角形图标,选择Huawei Lite Wearable Simulator,点击OK运行项目看看
2020/11/24 18:20
回复
举报
1.关于Tool Windows中的Huawei Lite Wearable Simulator,我在上文已陈述正在使用。 2.关于Previewer预览模式,与1.展示效果相同。 3.Jerry Launcher: [JS Exception]: TypeError: Cannot set property 'fillStyle' of undefined ,,,这是唯一运行报错,在index.js文件中,全局变量context已经var出,但仍爆出undefined,可能是因为onReady()中未获取到画布对象?但什么原因呢?如何解决?求解求解! onReady() { context = this.$refs.canvas.getContext('2d'); },
2020/11/25 13:09
回复
举报
鲸云夕陌博主
var context = this.$refs.canvas.getContext('2d');把这行代码放在onShow()中
2020/11/25 13:56
回复
举报
回复 @鲸云夕陌 : 经尝试,依然不好使。Jerry Launcher: [JS Exception]: TypeError: Cannot set property 'fillStyle' of undefined
2020/11/25 14:19
回复
举报
鲸云夕陌博主
回复 @言逍 : wx372798663你加一下这个微信询问一下老师吧
2020/11/25 14:50
回复
举报
控制台输出如下,我看不懂,希望能帮到您找到解决方案。 15:51:59: Executing task 'compileDebugJsWithNodeJs -Pjs_watch_mode=true'... Executing tasks: [compileDebugJsWithNodeJs] > Task :entry:preBuild > Task :entry:validateDebugSigning > Task :entry:collectDebugDependencies > Task :entry:mergeDebugResources > Task :entry:mergeDebugProfile UP-TO-DATE > Task :entry:compileDebugResources UP-TO-DATE > Task :entry:generateDebugJsManifest UP-TO-DATE webpack is watching the files… > Task :entry:compileDebugJsWithNodeJs Deprecated Gradle features were used in this build, making it incompatible with Gradle 7.0. Use '--warning-mode all' to show the individual deprecation warnings. See https://docs.gradle.org/6.3/userguide/command_line_interface.html#sec:command_line_warnings BUILD SUCCESSFUL in 2s 8 actionable tasks: 5 executed, 3 up-to-date 15:52:02: Task execution finished 'compileDebugJsWithNodeJs -Pjs_watch_mode=true'.
2020/11/24 15:54
回复
举报
鲸云夕陌博主
你尝试一下重新按照教程创建项目,敲写代码,然后点击菜单栏的View,再选择Tool Windows,最后点击Previewer预览模式运行项目,或者只点击右上角工具栏的三角形图标,选择Huawei Lite Wearable Simulator,点击OK然后运行项目看看
2020/11/24 18:50
回复
举报
鲸云夕陌博主
代码可能要做一些小修改才能使它更完美 onShow()函数和 run()函数修改成如下,这样就能实现计时器精确到0.1秒计时了,就不像原来那个是精确到1秒的,精确度不高,而且看起来感觉计时有些迟钝
onShow() {
this.initGrids();
this.drawGrids();

timer = setInterval(this.run, 100);
}

run(){
this.currentSeconds = Math.floor(this.currentSeconds * 10 + 1) / 10;
}
如果是修改成如下会有一个显示格式的问题,感兴趣的读者可以自行尝试,这里就不过多叙述了
onShow() {
this.initGrids();
this.drawGrids();

timer = setInterval(this.run, 100);
}

run(){
this.currentSeconds += 0.1;
}
如果想计时器精确到0.01秒时,用类似的方法就不行了,原因在于Math.floor函数精确的问题,会使currentSeconds到达一个值后不再发生变化的了,也无法完成后面的计时了,感兴趣的读者可以自行尝试
onShow() {
this.initGrids();
this.drawGrids();

timer = setInterval(this.run, 10);
}

run(){
this.currentSeconds = Math.floor(this.currentSeconds * 100 + 1) / 100;
}
2020/11/23 16:37
回复
举报
优秀的文章!
2020/11/23 11:26
回复
举报
更多评论
打赏
12 评论
1 收藏
4
分享
返回顶部
顶部