开发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屏幕页面遇到的问题的更多相关文章
- 使用 video.js 开发 HTML5 视频页面
时间 2015-05-13 17:11:58 The GIS Guy 原文 http://thegisguy.tk/html5-video-using-video-js/ 主题 Video.js H ...
- ASP.NET Core 开发人员异常页面
UseDeveloperExceptionPage 中间件 我们谈谈在 Startup 类的 Configure()方法中以下代码: public void Configure(IApplicatio ...
- chrome拓展开发实战:页面脚本的拦截注入
原文请访问个人博客:chrome拓展开发实战:页面脚本的拦截注入 目前公司产品的无线站点已经实现了业务平台组件化,所有业务组件的转场都是通过路由来完成,而各个模块是通过requirejs进行统一管理, ...
- Android中使用ViewPager实现屏幕页面切换和页面切换效果
之前关于如何实现屏幕页面切换,写过一篇博文<Android中使用ViewFlipper实现屏幕切换>,相比ViewFlipper,ViewPager更适用复杂的视图切换,而且Viewpag ...
- [课程设计]Scrum 3.2 多鱼点餐系统开发进度(页面优化&下单详细信息页面)
Scrum 3.2 多鱼点餐系统开发进度(页面优化&下单详细信息页面) 1.团队名称:重案组 2.团队目标:长期经营,积累客户充分准备,伺机而行 3.团队口号:矢志不渝,追求完美 4.团队选 ...
- 实战使用Axure设计App,使用WebStorm开发(5) – 实现页面功能
系列文章 实战使用Axure设计App,使用WebStorm开发(1) – 用Axure描述需求 实战使用Axure设计App,使用WebStorm开发(2) – 创建 Ionic 项目 实战使 ...
- 实战使用Axure设计App,使用WebStorm开发(4) – 实现页面UI
系列文章 实战使用Axure设计App,使用WebStorm开发(1) – 用Axure描述需求 实战使用Axure设计App,使用WebStorm开发(2) – 创建 Ionic 项目 实战使 ...
- 实战使用Axure设计App,使用WebStorm开发(3) – 构建页面架构
系列文章 实战使用Axure设计App,使用WebStorm开发(1) – 用Axure描述需求 实战使用Axure设计App,使用WebStorm开发(2) – 创建 Ionic 项目 实战使 ...
- Scrum 3.2 多鱼点餐系统开发进度(页面优化&下单详细信息页面)
Scrum 3.2 多鱼点餐系统开发进度(页面优化&下单详细信息页面) 1.团队名称:重案组 2.团队目标:长期经营,积累客户充分准备,伺机而行 3.团队口号:矢志不渝,追求完美 4.团队选 ...
随机推荐
- 【原创】分布式之缓存击穿 【原创】自己动手实现静态资源服务器 【原创】自己动手实现JDK动态代理
[原创]分布式之缓存击穿 什么是缓存击穿 在谈论缓存击穿之前,我们先来回忆下从缓存中加载数据的逻辑,如下图所示 因此,如果黑客每次故意查询一个在缓存内必然不存在的数据,导致每次请求都要去存储层去查 ...
- TensorFlow 官方文档中文版
http://wiki.jikexueyuan.com/list/deep-learning/ TensorFlow 官方文档中文版 你正在阅读的项目可能会比 Android 系统更加深远地影响着世界 ...
- Nodejs创建HTTPS服务器
Nodejs创建HTTPS服务器 从零开始nodejs系列文章,将介绍如何利Javascript做为服务端脚本,通过Nodejs框架web开发.Nodejs框架是基于V8的引擎,是目前速度最快的Jav ...
- myeclipse中Servlet出错
在myeclipse中Servlet总是出错,执行的时候一直提示找不到出现404错误, 然后把代码拷贝到eclipse ee中就没有问题,一直不理解怎么回事. 然后发了好长时间试了好些方法,结果把my ...
- SpringBoot之Web开发——webjars&静态资源映射规则
在webjars中找到需要引入的Maven依赖,添加到pom.xml中,即可自动导入相关依赖.
- 通达信版F10检索工具下载
通达信版的F10採用的是维赛特的F10资料. 维赛特的F10资料请前往:http://www.vsatsh.cn/xzzq.aspx 下载. 通达信版的F10检索工具下载地址:http://pan. ...
- sql server的版本检查
https://support.microsoft.com/en-ph/help/321185/how-to-determine-the-version-edition-and-update-leve ...
- CodeForces - 557D Vitaly and Cycle(二分图)
Vitaly and Cycle time limit per test 1 second memory limit per test 256 megabytes input standard inp ...
- 【WIP】Bootstrap modal
创建: 2017/09/28 更新: 2017/10/14 标题加上[WIP]
- VUE element-ui下拉列表获取label值
有这样一个场景,当我们往后台数据传的是id时,我们却想在前台获取列表显示的值,这时候可以用下面的方法来获取你想要的label值 let obj = {}; obj = this.arr.find((i ...