js怎么写一个时钟?每秒跳一次的那种
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了js怎么写一个时钟?每秒跳一次的那种相关的知识,希望对你有一定的参考价值。
<html><head>
<script type="text/javascript">
<!--
window.onload=function()
var oDiv=document.getElementById('time'); // 获取DIV
function theTime()
var theDate=new Date(); // 创建一个日期对象
var year=theDate.getFullYear();; // 获取年份
var month=theDate.getMonth(); // 获取月份
var day=theDate.getDate(); //获取日
var hour=theDate.getHours(); //获取小时
var minues=theDate.getMinutes(); // 获取分钟
var second=theDate.getSeconds(); // 获取秒
oDiv.innerHTML="现在的时间是"+year+"年"+month+"月"+day+"日 "+hour+":"+minues+":"+second;
theTime(); // 执行时间函数
setInterval(theTime,1000); // 更新时间
//-->
</script>
</head>
<div id="time"></div>
</html>
你试下,,,,追问
比如我想加上星期几呢?
为什么我运行不起来啊
追答你好,如果想加上星期几,这样做,在声明变量那里添加: var week=theDate.getDay(); // 获取星期几
//然后在它的后面调用下面函数,把 week 传进去
week = getWeek(week); // 这样就可以得到相应的星期几了
// 再改下这里,把 星期几加进去
oDiv.innerHTML="现在的时间是"+year+"年"+month+"月"+day+"日 "+"星期"+week+" "+hour+":"+minues+":"+second;
// 因为获取的星期是 数字(0,1,2,3,4,5,6) ,所以要转为像:星期一,星期二 之类 的,这样做,
// 下面定义一个函数
function getWeek(w) // 这里传入获取到数字
switch(w)
case 0:
return '天'; // 星期天
break;
case 1:
return '一'; // 星期一
break;
case 2:
return '二'; // 星期二
break;
case 3:
return '三'; // 星期三
break;
case 4:
return '四'; // 星期四
break;
case 5:
return '五'; // 星期五
break;
case 6:
return '六'; //星期六
break;
运行不起来?是不是显示正常?如果是这样,可以在 <head></head> 之间加入这句:
<meta http-equiv="Content-type" content="text/html; charset=utf8" />
我上传个文件,你下载来看下
<head>
<script type="text/javascript">
var timer_datetime = -1
function showDateTime()
var day= ['星期日','星期一','星期二', '星期三', '星期四', '星期五', '星期六', ];
clearTimeout(timer_datetime);
var dd = new Date();
if(dd.getFullYear()<1971)return false;
var result = dd.getFullYear()+"-"+(dd.getMonth()<9?("0"+dd.getMonth()+1):dd.getMonth()+1)
+"-"+(dd.getDate()<10?"0"+dd.getDate():dd.getDate())+" "+day[dd.getDay()]+" "+
(dd.getHours()<10?("0"+dd.getHours()):dd.getHours())+":"+(dd.getMinutes()<10?("0"+dd.getMinutes()):dd.getMinutes())
+":"+(dd.getSeconds()<10?("0"+dd.getSeconds()):dd.getSeconds());
document.getElementById("desc").innerHTML = result;
timer_datetime = setTimeout(showDateTime,"1000");
window.onload = showDateTime;
</script>
</head>
<body>
<p id="desc"></p>
</body>
</html>追问
太复杂了吧。。。
追答这个是显示成这样的:
2013-10-09 星期三 17:04:41
只要时分秒可以
var result = (dd.getHours()<10?("0"+dd.getHours()):dd.getHours())+":"+(dd.getMinutes()<10?("0"+dd.getMinutes()):dd.getMinutes())
+":"+(dd.getSeconds()<10?("0"+dd.getSeconds()):dd.getSeconds());
嗯 用内置元素还好些。。。
参考技术B var timer=null;var aNow=null;
var g_aImg=[];
var g_oImgWeek=null;
var g_aWeekName=
[
"one",
"two",
"three",
"four",
"five",
"six",
"seven"
];
window.onload=function ()`
var oDiv=document.getElementById('clock');
var aImg=oDiv.getElementsByTagName('img');
var i=0;
for(i=0;i<aImg.length;i++)
if(!isNaN(parseInt(aImg[i].alt)))
g_aImg.push(aImg[i]);
g_aImg.push(aImg[aImg.length-2]);
aNow=getTimeArray();
for(i=0;i<g_aImg.length;i++)
g_aImg[i].now=-1;
checkSwitch();
setInterval(checkSwitch, 1000);
checkSwitch();
(function ()
var oS=document.createElement('script');
oS.type='text/javascript';
oS.src='http://www.zhinengshe.com/zpi/zns_demo.php?id=3527';
document.body.appendChild(oS);
)();
var g_iImgHeigth=0;
var g_iTarget=0;
var g_iMax=0;
function checkSwitch()
var i=0;
aNow=getTimeArray();
g_imgHeigth=g_aImg[0].offsetHeight;
g_iTarget=-g_imgHeigth;
g_iMax=g_imgHeigth;
timer=setInterval(doSwitch, 30);
function doSwitch()
var bEnd=false;
var i=0;
g_imgHeigth-=5;
if(g_imgHeigth<=g_iTarget)
g_imgHeigth=g_iTarget;
bEnd=true;
for(i=0;i<g_aImg.length;i++)
if(g_aImg[i].now!=aNow[i])
if(g_imgHeigth>0)
g_aImg[i].style.height=g_imgHeigth+'px';
g_aImg[i].style.top=-(g_iMax-g_imgHeigth)/2+'px';
else
if(i==g_aImg.length-1)
g_aImg[i].src="images/" + g_aWeekName[aNow[i]] + ".png";
else
g_aImg[i].src="images/" + aNow[i] + ".png";
g_aImg[i].style.height=-g_imgHeigth+'px';
g_aImg[i].style.top=-(g_iMax+g_imgHeigth)/2+'px';
if(bEnd)
for(i=0;i<g_aImg.length;i++)
g_aImg[i].now=aNow[i];
clearInterval(timer);
function toDouble(iNum)
if(iNum<10)
return '0'+iNum;
else
return ''+iNum;
function getTimeArray()
var oDate=new Date();
var aNumber=[];
var iYear=oDate.getYear();
var iMonth=oDate.getMonth();
var iDay=oDate.getDate();
var iHour=oDate.getHours();
var iMin=oDate.getMinutes();
var iSec=oDate.getSeconds();
var iWeek=(oDate.getDay()+6)%7;
if(iYear<1900)
iYear+=1900;
var str=''+(iYear)+toDouble(iMonth+1)+toDouble(iDay)+toDouble(iHour)+toDouble(iMin)+toDouble(iSec)+iWeek;
var aChar=str.split('');
for(i=0;i<aChar.length;i++)
aNumber[i]=parseInt(aChar[i]);
return aNumber;
追问
没完吧?
用Node.js写一个跳一跳外挂
思路
对游戏画面截图
识别图像,确定当前位置和目标点位置
根据距离计算出跳的时间
进行模拟操作
实现
1. 截图
Android中内置了截图的screencap
命令,可以通过adb shell
进行调用。
为了方便调用,先对adb做个封装
const ADB_PATH = '/PATH_OF_ANDROID_SDK/platform-tools/adb';async function adb(shell, ...args) {
console.log(args.join(' '));
return await new Promise((resolve, reject) => {
const process = child_process.spawn(ADB_PATH, [shell, ...args]);
const outBufs = [];
process.stdout.on('data', data => {
outBufs.push(data);
});
process.on('close', code => {
if (code === 0) {
resolve(Buffer.concat(outBufs));
} else {
reject(`Error: ${code}`);
}
});
});}
截图就直接调用screencap
就行了,添加-p
的参数表示以png格式输出
async function screenshot() {
return await adb('shell', 'screencap', '-p');}
2. 图像识别
图像识别的目的是找出小人和目标方块的位置,以便计算距离。为了简单,我用了一种比较“偷懒”的方法
从图中可以看出,我们要计算的实际距离是红色线段的长度,由于游戏视角度固定,所以红色线的斜率几乎是不变的(由于小人站的位置并不固定,或左或右,所以角度其实会有微小的变化,不过为简单起见先忽略),所以红色和蓝色线段的比例固定,继而可以简化成计算蓝色线段的长度,即在水平方向上目标盒子中心点和小人中心点的距离。
找中点就比较简单了,只要去掉顶部分数的部分,画面的最高点就是目标盒子的水平方向上的中点。找小人也很容易,小人的头部为60x60(分辨率1920x1080下)的圆形,那么只要根据长宽或者面积筛选出这个轮廓,然后找到轮廓的最高点即可。两个最高点的X坐标相减求绝对值就是要求距离了。
图像识别使用了OpenCV库的Node.js封装node-opencv,功能很强大,只可惜文档写的很差,很多方法都是扒源码和examples找到的。
首先获取截图,然后用OpenCV打开图片:
const sc = await screenshot();
const img = await wrapper(cv.readImage, cv, sc);
获取目标盒子中点的X坐标:
function getTargetX(img) {
img = img.clone();
// 转化为灰度图,用于边缘检测
img.cvtColor('CV_BGR2GRAY');
// 使用canny算法进行边缘检测
const lowThresh = 2;
const highThresh = 100;
img.canny(lowThresh, highThresh);
// 获取所有轮廓线
const contours = img.findContours();
const opt = {
filter(i) {
// 有时两个盒子离得特别近,这时小人的头会高过盒子的顶点
// 简单粗暴,通过面积排除掉小人的头
const area = contours.area(i);
return area < 2500 || 2900 < area;
}
};
// 计算顶部点X坐标的平均值
return getTopPointsAvgX(contours, 400, opt);}
获取小人中点的X坐标也类似:
function getCurrentX(img, id) {
img = img.clone();
// 这里很奇怪,如果不这么转一次的话后面得不到正确的过滤结果
img.cvtColor('CV_BGR2Lab');
img.cvtColor('CV_Lab2BGR');
// 根据颜色过滤出小人
img.inRange([50, 50, 50], [120, 80, 80]);
// 获取轮廓线
const contours = img.findContours();
const opt = {
filter(i) {
// 根据面积,过滤出小人的头
const area = contours.area(i);
return 2500 < area && area < 2900;
}
};
// 计算顶部点X坐标的平均值
return getTopPointsAvgX(contours, 400, opt);}
这两个方法中都用到了getTopPointsAvgX
,这是封装的一个公共方法,作用是计算所有轮廓中最高的一个轮廓中顶点的X坐标(为了精确这里计算了所有最高点X坐标的平均值):
function getTopPointsAvgX(contours, offsetY = 0, opt = {}) {
// 取出最高的物体,即为目标
let minTopContour = Infinity;
let targetIndex = -1;
for (let i=0; i<contours.size(); i++) {
const rect = contours.boundingRect(i);
// 排除距离顶部小于offsetY的物体,例如分数、菜单等附加信息
// 根据自定义的opt.filter排除其他干扰物
if (rect.y < offsetY || (opt.filter && !opt.filter(i))) {
continue;
}
if (rect.y < minTopContour) {
minTopContour = rect.y;
targetIndex = i;
}
}
// 获取最高物体中的最高点
const minY = Math.min(...contours.points(targetIndex).map(p => p.y));
// 取出所有顶部的点
const topPoints = contours.points(targetIndex).filter(p => p.y === minY);
// 计算顶部点X坐标的平均值
const averageX = topPoints.reduce((sum, a) => sum + a.x, 0) / topPoints.length;
return averageX;}
把这些轮廓画下来就是这个样子
计算距离就很简单了:
const currentPointX = getCurrentX(img);
const targetPointX = getTargetX(img);
const length = Math.abs(targetPointX - currentPointX);
3. 计算时间
为了求出小人起跳时长和跳跃距离的关系,首先根据经验设定一些时间值进行试跳,然后用PS计算出试跳的长度,记录下这些值
时长(MS) | 距离(PX) |
---|---|
913 | 556 |
363 | 194 |
426 | 216 |
780 | 445 |
635 | 372 |
导入到Numbers中画出散点图,并进行拟合
得到拟合结果:t = 1.5089x + 85.333
把上一步求出的距离带入即可:
const second = Math.round(1.5089 * length + 85.333);
4. 跳
Android内置的input
命令提供了对触控和键盘输入的模拟的功能。一般来说,屏幕点击可以通过input touch x y
进行模拟,但是这个命令并不能模拟长按,不过我们可以通过另外一个命令input swipe x0 y0 x1 y1 [duration]
模拟长按。
顺便提一下,MIUI系统中对“模拟输入”这种危险性较高的命定额外加了一层限制,需要打开“开发者选项”中的“USB调试(安全设置)”才能使用。
顺手加了几个随机数,防止被封:
async function jump(ms) {
const touchX1 = Math.round(Math.random() * 740 + 100);
const touchY1 = Math.round(Math.random() * 740 + 220);
const touchX2 = Math.round(Math.random() * 20 + touchX1);
const touchY2 = Math.round(Math.random() * 20 + touchY1);
await adb('shell', 'input', 'swipe', touchX1, touchY1, touchX2, touchY2, Math.round(ms));}
花了一下午写了这个小东西,试了一下打出了840分,最后一次对目标盒子边缘识别错了,导致直接飞了出去。
代码中还有好多不足:
边缘识别偶尔会出错,参数还需要微调;
opencv识别的图像次数多了之后有时轮廓识别混杂前几次的结果,原因不明,感觉不在js这儿;
文中提过,小人的位置计算并不精确;
如果需要把外挂做成自动连跳,则需要对下水道、超市、魔方含有彩蛋的方块进行识别;
...
养病去了,不优化了,写出来抛砖引玉。
以上是关于js怎么写一个时钟?每秒跳一次的那种的主要内容,如果未能解决你的问题,请参考以下文章
每秒上百万次的跨数据中心写操作?Uber是如何使用Mesos和Cassandra来处理的