上上个礼拜公司的展销会活动需要一个展示在LED大屏幕的页面,顶部显示平台交易总金额,左右两边分别是厂家和买家实时交易记录,具体页面长下面这个样子

需求评审的时候产品说顶部的总金额要有一个数字滚动或者翻牌子的效果,我想着我有封装好的运动框架,加个效果应该不是问题,然后自告奋勇的跟我们技术老大说想做这个页面,结果就是没称好自己几斤几两掉进了自己挖的大坑!!!

第一个坑是分辨率问题,当时设计把页面给我的时候说的LED屏幕是9*5米,所以他设计图的比例也是9:5,我就照着设计图开发了,之前PC端的布局都是用px做单位,但是这个页面做的时候为了可以兼容多个屏幕,用rem做单位(我真不喜欢rem,虽然它确实做到了不同尺寸显示器的兼容)。等快上线的时候发现投到LED上的页面下面有一道还挺宽的白边。因为那边笔记本的分辨率是1024*768,我开发的笔记本的分辨率是1600*900,背景图我是整个切下来了一张大背景图,改了分辨率之后背景图和字都被压扁了,背景图上显示时间的框的位置也变了,只能再改css,勉强改的能看了,但是页面变得很丑很丑...

第二个坑是左右厂家和买家交易记录无缝滚动,之前只做过图片的无缝滚动,实现方式是克隆法(把要显示的元素内容复制一份,当显示到复制内容部分时再设置从头开始滚),但是因为数据是每隔10分钟从后台调取,其实也可以实现啦,不过总之后来用了裁剪法(ul滚完了就remove,同时后面再新生成一个ul追加),定义一个数据存放请求的数据,去重之后push进去,显示的时候呢就是根据每屏展示的条数轮循这个数组,实现数据滚动展示。

第三个坑是定时器,页面里左右滚动、定时请求数据、加上金额累计滚动特效,我用的全部都是setInterval,差不多开了七八个,哪个没清也搞晕了,结果换成setTimeout,递归调用自己,不用担心哪个定时器没有清了。

第四个坑是自己疏忽造成的bug,把差额(请求到的金额减去上一次的金额)分成60份,每一秒钟累计一次,然后又写了个setTimeout每分钟请求一次数据,结果导致这一次的金额还没累计完,请求到的新数据已经开始累计了,然后就出现了页面忘回跳的bug,改了之后就可以了。

总结一下这次的收获吧,这次最大的收获就是认识到自己技术还很烂!不像是有三年开发经验的人。

把这次开发的部分代码贴上来吧(很烂,自己读着都费劲)

总金额累计部分代码

请求数据

function getMoney(){
//请求数据
$.ajax({
url: Domain.webDomain+"/countTodayOrder/getOrderAmount",
type: "POST",
dataType: "jsonp",
jsonp: "callback",
success: function (rs) {
if (rs.success) {
var money = rs.data; //返回的金额
var cookieAmount = getCookie("totalAmount"); //获取cookie中上次请求的金额
if (!cookieAmount) {
cookieAmount = "0";
}
cookieAmount = parseInt(cookieAmount); if(money != "null"){ //不为空的情况下
if (money.lastIndexOf(".") > -1) {
money = parseInt(money.substring(0, money.lastIndexOf("."))); //把金额小数点及以后的数据清掉
} else {
money = parseInt(money);
}
moneyProcess(money, cookieAmount);
}else{
moneyProcess(cookieAmount, cookieAmount);
}
}
}
});
}

累计金额前的操作

function moneyProcess(money,cookieAmount){
var oldMoney = 0;
var balance = money - cookieAmount;
var newMoney = cookieAmount; if(balance > 0) { //请求到的金额一定要比上一次的金额大,否则视为异常
var avgMoney = parseInt(balance / 60); //一分钟请求一次,每分钟显示的钱数
if (avgMoney < 1) { //如果平均每分钟的金额少于1块钱,就按1块钱算
avgMoney = 1;
}
moneyChange();
function moneyChange(){
oldMoney = newMoney;
newMoney += avgMoney;
if (newMoney <= money) {
showMoney(newMoney.toString(), oldMoney.toString());
setTimeout(moneyChange,1000);
}else{
showMoney(money.toString(), money.toString());
setTimeout(function(){ //每隔一秒钟请求一次数据
getMoney();
},1000)
}
}
setCookie("totalAmount",money,1); //累计完成后把这次的总金额存到cookie
}else{
setTimeout(function(){
getMoney();
},60000);
showMoney(newMoney.toString(),newMoney.toString());
}
}

金额滚动效果

function showMoney(money,oldMoney){
var money2 = money.toString();
money = formatMoney(money.toString(),0);
oldMoney = formatMoney(oldMoney.toString(),0);
if(money.length > oldMoney.length){
oldMoney = money;
} var hid_comma_left = document.getElementById("hid-comma").offsetWidth || 61;
var hid_num_left = document.getElementById("hid-num").offsetWidth || 86;
var hid_sign_left = document.getElementById("hid-sign").offsetWidth || 130; var moneyBox = document.getElementById("money-box"); var l = 0;
moneyBox.innerHTML = "";
for (var i = 0; i < oldMoney.length; i++) {
var span = document.createElement("span");
if (oldMoney.charAt(i) == ",") {
span.className = "comma";
span.left = hid_comma_left;
span.style.bottom = 0;
} else if (oldMoney.charAt(i) == "¥") {
span.className = "sign";
span.left = hid_sign_left;
span.style.bottom = 0;
} else{
span.style.top = "0";
span.className ="num num" + oldMoney.charAt(i);
span.left = hid_num_left;
}
span.num = oldMoney.charAt(i);
span.style.left = l + "px";
l += span.left;
moneyBox.style.width = l + "px"; //动态设置moneyBox的宽度
moneyBox.appendChild(span);
}
var spanList = document.getElementsByClassName("num"); //旧金额显示之后,替换为新金额
var k = spanList.length - 1;
moneyReplace();
function moneyReplace(){
if (k < 0) {
return;
}
if(money != oldMoney) {
if(spanList[k]) {
if (money2.charAt(k) == spanList[k].num && money != oldMoney) {
spanList[k].style.top = "0px"
k--;
} else {
startMove(spanList[k], {top: "-183"}, 50, "easeOut", function () {
this.style.top = "183px";
this.className = "num" + money2.charAt(k);
startMove(this, {top: "0"}, 50, "easeOut");
k--;
});
}
}else{
k--;
}
}
setTimeout(moneyReplace,150);
}
}

左右厂家买家交易记录滚动代码

获取数据
//把请求的数据添加到数组
function getScrollData(typeId,dataArr){ var url = ""; if(typeId == 0) { //买家订单信息
url = Domain.webDomain+"/countTodayOrder/getBuyerAmount";
}else{
url =Domain.webDomain+"/countTodayOrder/getFactoryAmount";
}
$.ajax({
url:url,
dataType:"jsonp",
jsonp: "callback",
success:function(rs){
if(rs.success ){
var data = $.parseJSON(rs.data);
if(data.length > 0){
$.each(data,function(key,item){
var json = {};
if(typeId == 0){ //买家交易
json.key = item.userId.toString() + item.orderId.toString();
json.name = item.nickName;
json.amount = formatMoney(item.amount,0);
}else{
json.key = item.factoryId.toString() + item.orderId.toString();
json.name = item.factoryName;
json.amount = formatMoney(item.amount,0);
} //去重复数据
if(findInArr(dataArr,json.key)) { //重复订单不添加到数组
dataArr.push(json);
}
});
}
}
}
});
}
滚动代码
function scrollMove(id,arr){

    //获取滚动元素
var scrollObj = document.getElementById(id);
var parentNode = scrollObj.parentNode;
var speed = 1;
var t = 0;
var h = scrollObj.offsetHeight / 2 - 2; scrollObj.sub = 0;
scrollObj.scrollIndex = 0;
scrollObj.count = 0; time();
function time()
{
scroll();
setTimeout(time,30);
} function scroll(){
if(t >= parentNode.offsetHeight ){
//换数据
scrollDataGet(arr,scrollObj);
t = 0;
}
if(scrollObj.children.length < 2){
scrollDataGet(arr,scrollObj);
}
if( scrollObj.children.length>2 ){
scrollObj.removeChild(scrollObj.children[0]);
}
t += speed;
scrollObj.style.top = -t + 'px';
} }

循环数组
function scrollDataGet(dataArr,scrollObj){

    var arr = []; //定义一个数组存这一轮要显示的数据信息

    while(arr.length<scrollSize) {

        var startIndex = scrollObj.scrollIndex * scrollSize + scrollObj.sub ;  //本轮开始数据

        var endIndex = startIndex + scrollSize;  //每轮显示12条,结束数据为开始数据加显示条数

        scrollObj.sub = endIndex - dataArr.length;

        if(scrollObj.sub > 0){
endIndex = dataArr.length;
scrollObj.scrollIndex = 0; }else{
scrollObj.sub = 0;
scrollObj.scrollIndex ++;
} //把数据添加到显示数组里
for (var i = startIndex; i < endIndex; i++) {
arr.push(dataArr[i]);
}
if(arr.length < scrollSize) {
if (scrollObj.sub > 0) {
if (scrollObj.sub > dataArr.length) {
scrollObj.sub = dataArr.length;
}
for (var j = 0; j < scrollObj.sub; j++) { //补数据
arr.push(dataArr[j]);
}
scrollObj.sub = 0;
}
} }
scrollDataFill(arr,scrollObj);
}

填充数据
function scrollDataFill(arr,scrollObj){

    var className = "";

    var ul = document.createElement("ul");
ul.className = "info-list"; for(var i = 0; i < arr.length; i++ ){
if( i % 2 == 0){
className = "odd";
}else{
className = "even";
}
var str = '<li class="' + className + '" ><span class="info-name" style="width:3.2rem;">' + arr[i].name + '</span><span class="info-name" style="width: 1.64rem; text-align: center;">' + arr[i].amount + '</span></li>'; ul.innerHTML += str;
}
scrollObj.appendChild(ul);
}

开发LED屏幕页面遇到的问题的更多相关文章

  1. 使用 video.js 开发 HTML5 视频页面

    时间 2015-05-13 17:11:58 The GIS Guy 原文  http://thegisguy.tk/html5-video-using-video-js/ 主题 Video.js H ...

  2. ASP.NET Core 开发人员异常页面

    UseDeveloperExceptionPage 中间件 我们谈谈在 Startup 类的 Configure()方法中以下代码: public void Configure(IApplicatio ...

  3. chrome拓展开发实战:页面脚本的拦截注入

    原文请访问个人博客:chrome拓展开发实战:页面脚本的拦截注入 目前公司产品的无线站点已经实现了业务平台组件化,所有业务组件的转场都是通过路由来完成,而各个模块是通过requirejs进行统一管理, ...

  4. Android中使用ViewPager实现屏幕页面切换和页面切换效果

    之前关于如何实现屏幕页面切换,写过一篇博文<Android中使用ViewFlipper实现屏幕切换>,相比ViewFlipper,ViewPager更适用复杂的视图切换,而且Viewpag ...

  5. [课程设计]Scrum 3.2 多鱼点餐系统开发进度(页面优化&下单详细信息页面)

    Scrum 3.2 多鱼点餐系统开发进度(页面优化&下单详细信息页面)  1.团队名称:重案组 2.团队目标:长期经营,积累客户充分准备,伺机而行 3.团队口号:矢志不渝,追求完美 4.团队选 ...

  6. 实战使用Axure设计App,使用WebStorm开发(5) – 实现页面功能

    系列文章 实战使用Axure设计App,使用WebStorm开发(1) – 用Axure描述需求  实战使用Axure设计App,使用WebStorm开发(2) – 创建 Ionic 项目   实战使 ...

  7. 实战使用Axure设计App,使用WebStorm开发(4) – 实现页面UI

    系列文章 实战使用Axure设计App,使用WebStorm开发(1) – 用Axure描述需求  实战使用Axure设计App,使用WebStorm开发(2) – 创建 Ionic 项目   实战使 ...

  8. 实战使用Axure设计App,使用WebStorm开发(3) – 构建页面架构

    系列文章 实战使用Axure设计App,使用WebStorm开发(1) – 用Axure描述需求  实战使用Axure设计App,使用WebStorm开发(2) – 创建 Ionic 项目   实战使 ...

  9. Scrum 3.2 多鱼点餐系统开发进度(页面优化&下单详细信息页面)

    Scrum 3.2 多鱼点餐系统开发进度(页面优化&下单详细信息页面)  1.团队名称:重案组 2.团队目标:长期经营,积累客户充分准备,伺机而行 3.团队口号:矢志不渝,追求完美 4.团队选 ...

随机推荐

  1. 全然卸载oracle11g步骤

    iLife's 博客http://blog.csdn.net/fei1502816 全然卸载oracle11g步骤: 1. 開始->设置->控制面板->管理工具->服务 停止全 ...

  2. settimeout--原来定时器是有三个及以上参数的

    我平常使用的 settimeout 定时,只知道他有两个参数,一个是function异步成功后的回调函数,一个是delay延时毫秒,今天发现它还可以接着传餐,作为 执行回调函数的参数 语法:var t ...

  3. 通达信版F10检索工具下载

    通达信版的F10採用的是维赛特的F10资料. 维赛特的F10资料请前往:http://www.vsatsh.cn/xzzq.aspx  下载. 通达信版的F10检索工具下载地址:http://pan. ...

  4. MapReduce01

    ================== Hadoop内核 | MapReduce(分布式计算框架) ================== 源于Google的MapReduce论文 ----------& ...

  5. luogu2679 子串

    题目大意 有两个仅包含小写英文字母的字符串 A 和 B.现在要从字符串 A 中取出 k 个互不重叠的非空子串,然后把这 k 个子串按照其在字符串 A 中出现的顺序依次连接起来得到一 个新的字符串,请问 ...

  6. YES,IT IS

  7. cloudstack ---部署的架构

    cloudstack跟KVM一起部署的架构 下图是CloudStack跟kvm一起部署的架构: 在每个kvm的宿主机上都需要部署agent程序. cloudstack跟vsphere一起部署的架构 下 ...

  8. PCB genesis自制孔点 Font字体实现方法

    一.先看genesis原有Font字体 在PCB工程CAM加孔点字体要求时,通常我们直接用Geneis软件给我们提供了2种孔点字体canned_57与canned_67,但此字体可能不能满足各个工厂个 ...

  9. P2420 让我们异或吧(倍增)

    题目描述 异或是一种神奇的运算,大部分人把它总结成不进位加法. 在生活中…xor运算也很常见.比如,对于一个问题的回答,是为1,否为0.那么: (A是否是男生 )xor( B是否是男生)=A和B是否能 ...

  10. [Swift通天遁地]三、手势与图表-(13)制作美观简介的滚动图表:折线图表、面积图表、柱形图表、散点图表

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...