开发LED屏幕页面遇到的问题
Posted 九玖啾
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了开发LED屏幕页面遇到的问题相关的知识,希望对你有一定的参考价值。
上上个礼拜公司的展销会活动需要一个展示在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屏幕页面遇到的问题的主要内容,如果未能解决你的问题,请参考以下文章
Wagtail - 在页面上呈现带有相关片段和标签的数据时遇到问题
ESP 保姆级教程 疯狂点灯篇 —— 案例:ESP8266 + LED + 按键 + Web页面控制(Web页面控制开关LED灯)
ESP 保姆级教程 疯狂点灯篇 —— 案例:ESP8266 + LED + 按键 + PWM调整亮度 + Web页面控制(Web页面控制开关LED灯亮度)