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" />


我上传个文件,你下载来看下

参考技术A <html>
<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. 对游戏画面截图

  2. 识别图像,确定当前位置和目标点位置

  3. 根据距离计算出跳的时间

  4. 进行模拟操作

实现

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分,最后一次对目标盒子边缘识别错了,导致直接飞了出去。
代码中还有好多不足:

  1. 边缘识别偶尔会出错,参数还需要微调;

  2. opencv识别的图像次数多了之后有时轮廓识别混杂前几次的结果,原因不明,感觉不在js这儿;

  3. 文中提过,小人的位置计算并不精确;

  4. 如果需要把外挂做成自动连跳,则需要对下水道、超市、魔方含有彩蛋的方块进行识别;

  5. ...

养病去了,不优化了,写出来抛砖引玉。


以上是关于js怎么写一个时钟?每秒跳一次的那种的主要内容,如果未能解决你的问题,请参考以下文章

每秒上百万次的跨数据中心写操作?Uber是如何使用Mesos和Cassandra来处理的

C语言 用devc++编写一个模拟时钟,最简单那种就行,但要能在devc++上运行。

跳一跳c

Go 网络编程示例

如何设置在第一次设置通知后每秒钟触发一次的本地通知?

用Node.js写一个跳一跳外挂