首页 > 代码库 > 杂谈-网页设计大赛的一些感想
杂谈-网页设计大赛的一些感想
又是一年科技节,鉴于去年参加一个比较没意思的比赛,拿了一个不该拿的奖。今年我想着去参加一个稍微有点意思的比赛,凭自己的努力拿个奖。(题外话,血亏的是同学参加ctf比赛,我一开始以为我个人能力不行没敢和他组队(主要是怕我太坑),结果我帮他们解决了两道前端的题目,他们得了个二等奖……)
说正事,接触html和css是很早以前的事情了,但是js方面还是刚刚入门,之前有用bootstrap搭过一个blog(还没有完成)。队友想的是所有的都自己来写,也当是给自己一个练手的机会。这正如一个学长说的,用模板就是前期简单,后面自己要修改起来就很难了 ,而自己写的,后面再修改起来就会省去很多的功夫。抱着尝试总是没有错的心态,我们开始写这个网页了。大赛的题目是帮学校的某个社团做一个主页,我们当时选的是一个新成立不久的社团——天文社。队友刚刚提出这个想法,我的脑海里就有了一个感觉上很不错的思路了,毕竟天文能让人联想到星星,而星星的背景应该是能够抓住人的眼球的绝好的东西。canvas是html5新的标签,我想着用canvas做出这个效果可能是再合适不过的了。
这个是第一个版本
第一个版本遇到的第一个问题,同样也是写js通常情况下遇到的问题,那就是兼容性问题。鼠标移动事件再不同的浏览器上是有不同的方法来表示的。由于是刚开始学,我先是模仿的是网上的写法,但是我的浏览器中并不能兼容他的代码,于是我有baidu,google了好久,最后又去找了官方的api还是没有找到;其实问题出在监控的对象上,我们设定的背景的z-index应该是最下的,而如果监控的对象选为canvas,鼠标移动并不能发生在canvas上,后来我随便改了一下,改为window终于得到了效果了。这个效果其实和我当初的设想差不多,我把我写的发给同学,让他评价一下,谁知道他当头一棒,就说这个动态很碍眼。我一下就不服气了,我辛辛苦苦弄了这么久,却被说成这样,一时实在是没法接受。不过后来我也越看越不怎么协调,就去掉了。
第二版,我的想法是既然移动的那么不好看,不如写个不动的,让星星自己闪。把这个想法和队友说,队友也没太大的意见,于是我又开始去折腾了。实现的方法就是先给每一个点设置一个初相位st,然后让他们不透明度从st->1然后再从[0,1]往返,然后就是我们能够看到的一闪一闪的效果。
这个是第二版的背景(图中红圈圈出的地方有明显的明暗变化)
如此一来,没了移动的效果,但是闪烁的效果也并没有想象中的好看。之前写js完全没去想性能上可能会有问题,这次,我突然发现一打开这个背景的页面,就cpu的占用就非常的高。我开始尝试分析我的代码,看看有没有什么能够优化的地方,由于是采用的是之前鼠标移动事件相似的方法,我使用了每次都删除整个画布的全部内容,然后再计算每个点的不透明度,然后再重新画这个点。
function twinkle() { run = function() { context_stars.clearRect(0, 0, canvas_stars.width, canvas_stars.height);//每次清除整个画布 for (var i = 0; i < starsnum; i++) { start[i] ++; starArr[i].opacity = Tween.Quart.easeInOut(start[i], flag[i], 1-2*flag[i], 100);//这里用到了一个缓动的库 drawCirle(context_stars, starArr[i].centerX, starArr[i].centerY, starArr[i].radius, starArr[i].opacity); if(start[i] == 100){ //当start == 100的时候完成两件事情,一个是start置零 另一个是flag方向交换,简单来讲就是从0->1变成1->0或者反之 start[i] = 0; flag[i] = 1-flag[i]; } } requestAnimationFrame(run); }; run(); }
整个思路是非常的清晰的,但是事实上每次清除并重新计算的cpu代价是非常的大的。研究了半天优化的方法,最后总结下来有两种:
(1)每次不清除,一层一层的覆盖,通过改变整体的不透明度来改变星星闪烁的效果
(2)每次清除一个点周围的一小块区域,而不是清除整个画布
第一种我倒是有尝试过,cpu的占用瞬间降下来了,可能是参数调节的时候的问题,最后的效果同样不能让我满意。至于第二种,由于画布给的api种只有清除某个矩形区域的内容,而星星采用的圆形的表示方法,一旦清除可能会给周围的点造成缺少一个角的问题,所有后来也就没有去实现。
在制作背景的过程当中,我交给我的队友去想,他给出我下面这个版本:
这个其实是改的人家的demo
不过星星数量太多,运动效果同样鬼畜,和文字显得实在不搭,最后我还是否决了这个想法。
最后,因为这个网页的设计我们想走的风格还是一种简约的路线,最后改成了一个不动的效果:
这个是最终版本,星星没有移动也没有闪烁
最后的版本我还加入了窗口resize的事件的处理,又对星星之间连线的判断做了优化,为了让星星之间的连线横向,纵向上分布的尽量均匀。这样的星星背景的效果,达到了理想效果的80%,但不失美观和简洁,也是评委看到感觉很满意的一项。导航栏上的图标去掉有两个原因,一个是为了美观,另一个是因为布局容易出问题。
说到导航栏,我做的第二部分就是导航栏,导航栏是有个变化的过程,从顶部往下,导航栏收缩,背景色从无色变为有颜色;从下面到顶部,导航栏从有颜色变为没有颜色。与之同时的还有个返回顶部的小火箭的变化,从顶部往下,小火箭有个从display none到dispaly block不透明度从0到1的变化;从下面到顶部反之。
当时纠结最久的并不在变化上面,因为只要写个css的animation效果就行了,虽然时间锁死最少一秒,不过效果已经很不错了;而在于滚轮事件的判定上面。众所周知,浏览器对于鼠标滚轮事件的判定有各种各样的办法,不知道是我的写的问题,还是队友写的问题,我试着console.log一下,发现我的chrome在返回顶部的过程中出现了两个scrollTop=0的点,这就非常神奇了。如果一个向上的过程中出现了两个scrollTop=0就意味着浏览器给了两个顶部(现在想想很有可能是css的问题),导航栏变化的过程会执行两次,而真正到达顶部的时候,它却并不能处在它应有的状态。单单这个事情就困扰了我好久,想了好久,既要能够精确的反应滚轮位置的变化,又要能够找不到不同浏览器的兼容性问题。最后我想到了一种比较能够两者兼顾的解决方法,分别订一个pre_wheel和cur_wheel分别记录上一个滚轮的位置和当前滚轮的位置,放入body的onscroll事件中。
var wheel = { pre_wheel: 0, //前一个滚轮位置 cur_wheel: 0, //当前滚轮位置 wheelup: false, //滚轮是否向上 wheeldown: false, //滚轮是否向下 on_top: false, //滚轮是否到顶 on_bottom: false //滚轮是否到底 } function scroll() { //滚动的时候判断滚轮的状态 wheel.cur_wheel = $(window).scrollTop(); if (wheel.cur_wheel < wheel.pre_wheel) { wheel.wheelup = true; wheel.wheeldown = false; } else if (wheel.cur_wheel > wheel.pre_wheel) { wheel.wheelup = false; wheel.wheeldown = true; } else if(wheel.cur_wheel == wheel.pre_wheel) { wheel.wheelup = wheel.wheeldown = false; } if ($(window).scrollTop() == 0) { wheel.on_top = true; } else { wheel.on_top = false; } if ($(window).scrollTop() + $(window).height() >= $(document).height()) { wheel.on_bottom = true; } else { wheel.on_bottom = false; } /*鼠标滚动函数接口*/ /*此处可以放入一些需要滚轮监控的事件*/ wheel.pre_wheel = wheel.cur_wheel; }
这样处理过后,用console调试后的效果果然非常好,甚至精确到了小数点后,感觉这个正是我想要的结果。细心的你一定能看出,如果滚动结束了以后,滚轮的wheelup和wheeldown应该都重置为false,但是用这种方法却没法做的;实际运用的过程中,两个变化的效果都完美实现了,各种地方测试都没有问题,于是我就选择性的无视了这个问题。
滚轮的事件处理总算“解决“了,接下来我们想到写个页面跳转的方法,这个同样并不难,加了一个缓动的库,我又对滚动的时间用距离差距做了一个简单的运算,使得每个页面跳转的时间大体相同,缓入还是缓出又还是缓入缓出,我们测试了好几种,最后敲定了四次方缓入缓出的方式。
代码如下:
var block_top = false; var block_jump = false; function to_top() { //跳转回顶部 if(block_top == false) { x = document.body.scrollTop; rocket = document.getElementById(‘rocket‘); if (x == 0) { return; } block_jump = true; block_top = true; start = 0, during = Math.floor(40 * x / document.documentElement.clientHeight); tween_to_top = function() { start++; document.body.scrollTop = Tween.Quart.easeInOut(start, x, -x, during); if (start < during) requestAnimationFrame(tween_to_top); if (start == during) { rocket.style.cssText = "display: none"; block_jump = false; block_top = false; } }; tween_to_top(); } } function jump(obj) { if(block_jump == false){ object = document.getElementById(obj); x = document.body.scrollTop; to = object.offsetTop; if(Math.abs(x - to) < 1) return; start = 0, during = Math.floor(40 * Math.abs(to - x) / document.documentElement.clientHeight); block_top = true; block_jump = true; cur_page = getindex(pages, obj); jump_to = function() { start++; document.body.scrollTop = Tween.Quart.easeInOut(start, x, to - x, during); if (start <= during) { requestAnimationFrame(jump_to); }else{ block_top = false; block_jump = false; } }; jump_to(); } }
这里分成了两个函数,一个是返回顶部的,一个是页面之间直接跳转的,这个是一开始为了避免一些不必要的冲突,(其实是没有必要的),另外这里有个处理的小技巧。js的本身特性使得同一个函数能在同一时间执行多次,这样会出现很多奇奇怪怪的bug,为此我加了两道block,保证同一时间,只能有一个jump函数或者to_top函数在运行,避免bug。
接下来我做的部分就是公告部分了。公告我们最一开始就想写一个简单的,大家都很常见的那种公告的方式,后来,因为社团那里发了很多的照片(虽然大多拍摄的不大好...),我就想到了可以弄一个时间轴的方式来做。假设有个时间轴,过去举行的活动就放在前面的点上,点击就会出现过去的活动的介绍和图片展示;通知相当于未来要发生的事情,所以就放在最后一个时间点上。这里在处理点和时间对其的上面,我们用到了table标签,table的td和tr标签以及自带的自动居中效果正好能够帮助我们构建这个时间轴。而我所需要控制的就是节点的数目以及内容,这个用了jquery来实现就是十分容易的一件事了。
$(function(){ let num = Events.length; for(var i = 0; i < num; i++){ $(‘.time‘).append("<td class=‘time_text‘>" + Events[i].date + "</td>"); $(‘.timepoint‘).append("<td class=‘time_point‘><img src=http://www.mamicode.com/‘img/circle.svg‘>"); } $(‘.time‘).append("<td class=‘time_text‘>接下来会发生什么呢...</td>"); $(‘.timepoint‘).append("<td class=‘time_point‘><img src=http://www.mamicode.com/‘img/circle_cur.svg‘>"); $(‘.time_line_notice‘).html("<div class=‘time_line_img‘></div>"+ "<div class=‘time_line_intro‘></div>"+ "<h3 style = ‘text-align:center;‘>" + "通告" + "</h3>"+ "<p style = ‘font-weight: normal;‘>" + notice + "</p>"); $(‘.time_line_intro‘).css("display", "none"); $(‘.time_line_img‘).css("display", "none"); $(‘.time_point img‘).click(function(){ var i = $(‘.time_point img‘).index(this); $(‘.time_point img‘).attr("src", "img/circle.svg"); $(‘.time_point img‘).eq(i).attr("src", "img/circle_cur.svg"); if (i == num) { $(‘.time_line_intro‘).css("display", "none"); $(‘.time_line_center‘).text(‘未来计划‘); $(‘.time_line_img‘).removeAttr("style"); $(‘.time_line_notice‘).html("<div class=‘time_line_img‘></div>"+ "<div class=‘time_line_intro‘></div>"+ "<h3 style = ‘text-align:center;‘>" + "通告" + "</h3>"+ "<p style = ‘font-weight: normal;‘>" + notice + "</p>"); $(‘.time_line_intro‘).css("display", "none"); $(‘.time_line_img‘).css("display", "none"); }else{ $(‘.time_line_intro‘).css("display", "block"); $(‘.time_line_img‘).css("display", "block"); $(‘.time_line_center‘).text(‘过往记忆‘); $(‘.time_line_intro‘).html("<b>" + Events[i].title + "</b>" + "<p>" + Events[i].date +" "+ Events[i].place + "</p>" + "<p>" + Events[i].context + "</p>"); $(‘.time_line_img‘).css("background-image", "url(" + Events[i].pic +")"); } }); });
下面是效果展示:
这其中当前时间点的变化是通过两个颜色不同的svg图片互相替换实现的,因为图片下面写文字的效果不一定好看,所以我们底下的介绍是用一个线性渐变做底,然后把文字放在上面实现的,也算是我们整洁美观的一种体现吧。这里还有很多的细节可以完善,不过由于时间的仓促,我们也没有余力去弄接下来的优化了。
整个网页设计的最后一个我做的部分其实是最后赶工阶段临时增加出来的一个需求。鉴于我们页面的配色不是很好,我们想做一个向下滚动,自动跳转到下一页的效果。由于之前写的滚动监测我感觉非常的完美,于是我首先就接下了这个锅,然而我当时并不知道,这个却成了我们最后最大的一个问题,最后都没有能够解决成功的问题。之前有提到,我写的滚动监测的bug,但是可能按照那个bug我的向下滚动应该是一直滚动到底部,或者滚动到顶部,停不下来的那种。事实却出乎我的意料,向上的滚动完全没有问题,向下的滚动出了很大的问题,他会先向下,然后在向上回弹,导致根本没法往下滚动,更可怕的是我之前写的认为非常好的点击跳转,在加上了这个效果以后都出现了类似的bug。这个在我们看来只是要注释这一个点的问题,但是对于用户来说这个简直是个灾难。这个bug的情况也是令人捉摸不透,我的windows下的chrome运行毫无问题,但是换到队友同样是windows下的chrome浏览器就出了问题;更更令人匪夷所思的是,我早晨写的没有问题,中午打开就出了问题。调试发现,我的浏览器显示的距离能够精确到小数点,然而他们的都不能精确到小数点,至此总算bug的原因是搞清楚了,然而却没有任何的解决思路,试着换成jquery,问题依旧在。眼看还有一两天就要交了,我的电脑依然是处在一会儿可以,一会儿不可以的状态,实在没有头绪,我尝试像是和跳转一样处理滚动加了锁之后,依旧还是有问题。最后我们无能为力,只能将有问题的部分注释掉了,交了上去,真是遗憾。
总结起来,网页设计比赛最后能够获得二等奖实属不易。网页设计比赛,其实重点突出一个设计,我们三个人没一个有设计的基础,单纯凭借着“嗯,这个厉害”,“这个好看”来做,确实有很多的问题,甚至最后临近提交5个小时,我还改了好多的图片和布局,最后的结果早已经和最先设想的南辕北辙了。其次,一个原因在于我们的基础太差,底子太薄,经验不足,一开始的框架搭的不够好,导致后面修修补补都能动相当大的部分,浪费了太多的时间,最后响应式也出了很多的问题,最后无奈删掉了。还有没能好好利用git,本想利用git提高工作的效率,结果却耽误了好多的时间,学长指导之后稍微好点,然而最后还是崩了...总之,还是一个在学习的过程,解决这一个个问题后,收获的也还是有很多的。
最后放一下github上的地址:
https://github.com/MZIchenjl/NUPT_Astronomy_Association
杂谈-网页设计大赛的一些感想