前言
1.创作背景
前些天庆祝1024的时候,我用java写了一个《星运测试:1024特别版》桌面程序。大致功能是通过让用户回答几道测试题,来给出未来一年的运势预测。我本想把jar包打包成exe文件,发给一位特别的朋友,但是试了好几种方法,无果而终。
于是最近我就把这个程序复刻为网页版,《星运测试:万圣夜特别版》。成品是一个html文件,可以发给朋友,用浏览器打开。效果如上图。
2.阅读本文需要的编程基础
(1)基本的html和css语法
(2)基本的JavaScript语法(按钮单击事件、自定义函数、画布canvas的2d简单应用等)
3.我的编程环境
(1)64位win10系统,代码编辑器VS Code
(2)已经亲自测试通过的浏览器
①windows系统自带的Edge浏览器
②360安全浏览器(默认为极速模式打开,一切正常;手动切换为兼容模式(IE内核)时,汉字会显示乱码)
③手机浏览器(我没有做响应式布局,只做了电脑端网页,但是用我小米手机自带的浏览器可以正常打开。)
测试时间:2024年10月30日
ps.理论上来说,支持html5的浏览器(绝大多数现代浏览器)都可正常打开这个网页
目录
一、目标效果
1.功能
在页面上依次显示几道运势测试的题目,用户点击按钮进行选择,最后程序给出运势测试结果。
2.文件
前端静态网页,且只有一个html文件。没有其它文件,也不走服务器。
3.页面布局
采用最简单的流式布局。
①顶部一个横幅(banner),其中用画布(canvas)画一些万圣夜元素的图案;
②中间一个文本区域(textarea),用于显示测试题目及测试结果;
③底部四个按钮(button),显示测试题的选项。
ps.我没有做响应式布局,但是我自己的手机浏览器可以打开,只是“关闭页面”这个按钮无效。
二、实现方法
本文最后会给出完整的代码,这里只说一些关键性的部分。
1.定义全局变量
注:
这个网页做好之后,以后某个时候可能会回来修改文案。修改文案只需要修改以下5个全局变量即可。以下这些全局变量的声明,我都放在html的<head>部分的JS代码中。我在代码中做了标记,一打开代码,可以比较直观地看到可以自定义文案的区域,而其它区域的代码无需改动。这样,以后打开代码修改文案时比较方便,不容易误改代码。
①当前页面编号pageIndex
程序要依次显示多个页面,所以可声明一个pageIndex变量来存储当前显示的页面编号,这相当于程序的进度条。初始值为0。
②最后一个页面的编号pageLast
再用一个pageLast变量来存储最后一个页面的编号。在程序其它地方都只调用这个变量,而不使用具体的页面编号。这样,程序的扩展性比较好。之后如果要修改文案,比如要增减页面的个数,那么只要更改变量的初始值即可。
③存储问题及选项的数组questions[][]
测试的问题及对应的选项,用一个二维数组question[][]来存储。行数应该等于页面个数,列数应该是5(一个问题加上4个选项)。有些页面可能是导语(或者其它情况),不需要那么多选项,那么选项的内容就用“0”来表示。这是我自定义的,可以修改,但是不能没有。
④存储结语库的数组results[][]
测试的每一个选项对应的一句结语,用另一个二维数组results[][]来存储。在用户对每一个页面按下按钮后,程序都要根据用户按下的按钮的编号,来决定将数组中哪一句结语添加到最后要给用户生成的运势测试结果中。这里假定最后一个页面是用来呈现测试结果的,那这最后一个页面就没有结语需要存储了。所以这个数组的行数应该是页面个数-1,列数是4(即选项的个数)。
⑤存储用户个性化结语的数组yourResult[]
还要有一个一维数组yourResult[],用来存储用户选的选项所对应的结语。待用户回答完所有问题后,只需要将这个数组中所有元素串接起来,就是要给用户生成的测试结果了。同样地假定最后一个页面是用来呈现测试结果的,所以这个数组的长度应该是页面个数-1。
2.按钮点击事件
用户每次按下按钮之后,程序要做两件事:一是要根据用户的选择进行处理(把相应的一句结语添加到yourResult[]数组中,以便最后能为用户生成运势测试结果);二是要刷新页面,即显示下一个页面。
(1)根据选项添加对应结语
先来说第一件事。
这是四个选项都有的功能,所以我写了一个通用的函数。函数功能是,根据用户按下的按钮编号,到结语库数组results[][]中,查找对应的那句结语,存储到用户的个性化结语数组yourResult[]中。
然后要将进度条+1,为显示下一个页面做好准备。
代码如下。
// 定义一个函数来实现按钮单击时的通用功能
function clickGeneral(buttonIndex){ //处理当前非最后一个页面时的情况
//处理选项所对应的结语
yourResult[pageIndex] = results[pageIndex][buttonIndex]; //将当前选项相应结语添加到为用户生成的结语数组中
if(pageIndex == pageLast-1){ //如果当前已经是最后一道题的页面,接下来是结语页面
questions[pageLast][0] = yourResult.join("\n"); //将为用户生成的结语数组用换行符串接成一个字符串,存储到最后一个页面的题干文本中
}
//显示下一道题目
pageIndex++; //进度条变到下一个页面
displayQuestion(pageIndex); //显示下一个页面的文本
}
而在按钮的单击事件中,只要调用这个函数,并且将按钮的编号作为参数传递即可。
// 为按钮3添加点击事件监听器
button3.addEventListener('click', function() {
clickGeneral(2); //采用通用处理程序
});
(2)显示下一个页面
这里我写了一个通用的函数,用于显示指定页面编号的页面内容。这个函数的基本内容如下。
// 定义一个函数来显示指定编号的页面
function displayQuestion(index) { //index是题目序号,从0开始
// 获取题干和选项的文本
var question = questions[index][0];
var options = questions[index].slice(1);
//获取页面元素
var ta = document.getElementByI