我编写了一个Java小程序来记录用户鼠标的位置,并计算每个时间步的速度和加速度。我想将其转换为Javascript。这可能吗?
编辑2:我现在公开发布了代码并编写了一个关于如何实现它的简短教程。
http://math.bu.edu/people/jackwalt/qualtrics-mousetracking/
随意使用和分享!
编辑1:以下是Javascript代码:
<input type="hidden" id="xPos" name="ED~xPos" value="" />
<input type="hidden" id="yPos" name="ED~yPos" value="" />
<input type="hidden" id="time" name="ED~time" value="" />
<script type="text/javascript">
var initTime = new Date().getTime();
document.onmousemove = getMousePosition;
function getMousePosition(mp) {
var divPos = getPosition(document.getElementById("mousearea"));
var event = [mp.pageX - divPos[0], mp.pageY - divPos[1], new Date().getTime() - initTime];
document.getElementById("xPos").value += event[0] + ", ";
document.getElementById("yPos").value += event[1] + ", ";
document.getElementById("time").value += event[2] + ", ";
return true;
}
function getPosition(obj){
var topValue= 0,leftValue= 0;
while(obj){
leftValue+= obj.offsetLeft;
topValue+= obj.offsetTop;
obj= obj.offsetParent;
}
return [leftValue, topValue];
}
</script>
这是Java代码:
主类:
package com.jackson.allgood;
import java.applet.Applet;
import java.awt.Graphics;
import java.awt.MouseInfo;
import java.awt.Point;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* This is a simple applet to record the position, velocity, and acceleration of a
* mouse pointer as it moves relative to names positioned in the window. Metadata is
* written to a text file and raw data to a .csv file.
*
* @author Jackson Walters
*
*/
public class Main extends Applet {
private static final long serialVersionUID = 1L;
private List<Data> dataList;
private MouseListenerThread testThread;
private long startTime;
private long endTime;
private static long DT = 10L;
private static final String[] NAMES = {"Name 1","Name 2","Name 3","Name 4"};
private static final String METADATA_FILENAME = "metadata";
private static final String DATA_FILENAME = "data";
/**
* Initializes the applet by creating an ArrayList to hold the data
* and starts a thread to begin collecting data.
*/
public void init() {
dataList = new ArrayList<Data>();
testThread = new MouseListenerThread();
testThread.start();
}
/**
* Stops the applet. Asks the thread to stop and waits until it does, then prints
* the metadata and data.
*/
public void stop(){
testThread.requestStop();
try {
testThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
printData();
printMetaData();
}
public void paint(Graphics g)
{
g.drawString(NAMES[0],getSize().width/2,20);
g.drawString(NAMES[1],getSize().width/2,getSize().height-20);
g.drawString(NAMES[2],10,getSize().height/2);
g.drawString(NAMES[3],getSize().width-100,getSize().height/2);
}
/**
* Thread that records the time and position of the mouse, calculates velocity and acceleration,
* then stores the data into the data list. Sleeps for the time interval specified by DT. Able to
* be stopped by setting a flag then waiting one time interval for the loop to exit.
*
*/
private class MouseListenerThread extends Thread{
private boolean running = true;
@Override
public void run(){
//initialize time and first data point
startTime = System.currentTimeMillis();
dataList.add(new Data(
0L,
MouseInfo.getPointerInfo().getLocation().getX(),
MouseInfo.getPointerInfo().getLocation().getY(),
0.,0.,0.,0.)
);
while(running){
long currentTime = System.currentTimeMillis()-startTime;
Point mousePos = MouseInfo.getPointerInfo().getLocation();
double xPos = mousePos.getX();
double yPos = mousePos.getY();
double xVel = (xPos-dataList.get(dataList.size()-1).getXPos())/DT;
double yVel = (yPos-dataList.get(dataList.size()-1).getYPos())/DT;
double xAcc = (xVel-dataList.get(dataList.size()-1).getXVel())/DT;
double yAcc = (yVel-dataList.get(dataList.size()-1).getYVel())/DT;
dataList.add(new Data(currentTime, xPos, yPos, xVel, yVel, xAcc, yAcc));
try {
sleep(DT);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
endTime = System.currentTimeMillis();
}
public void requestStop(){
running = false;
}
}
/**
* Prints the raw data generated by the program to a .csv file.
*/
private void printData(){
try {
BufferedWriter out = new BufferedWriter(new FileWriter(DATA_FILENAME + ".csv"));
out.write(Data.DATA_HEADER_STRING);
for(Data data : dataList){
out.write(data.toString());
}
out.close();
} catch (Exception e){
System.err.println("Error: " + e.getMessage());
}
}
/**
* Prints general information about what the program did to a text file.
*/
private void printMetaData(){
try {
BufferedWriter out = new BufferedWriter(new FileWriter(METADATA_FILENAME + ".txt"));
out.write("Start time: " + DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG).format(new Date(startTime))); out.newLine();
out.write("End time: " + DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG).format(new Date(endTime))); out.newLine();
out.write("Elapsed time: " + formatElapsedTime(endTime-startTime)); out.newLine();
out.write("Number of measurments: " + dataList.size()); out.newLine();
out.write("Measurement interval: " + DT + "ms"); out.newLine(); out.newLine();
out.write("Names:"); out.newLine();
for(String name : NAMES){
out.write(name); out.newLine();
} out.newLine(); out.newLine();
out.close();
} catch (Exception e){
System.err.println("Error: " + e.getMessage());
}
}
/**
* Converts milliseconds in the format min:sec.
* @param ms
* @return Time as min:sec.
*/
private static String formatElapsedTime(long ms){
int seconds = (int) (ms/1000.);
int minutes = seconds/60;
seconds %= 60;
if(seconds < 10) return minutes + ":0" + seconds;
else return minutes + ":" + seconds;
}
}
实用程序类:
package com.jackson.allgood;
/**
* Simple class to store data such as time, position, velocity, and acceleration.
* @author Jackson Walters
*
*/
public class Data {
protected static final String DATA_HEADER_STRING = "Time, " +
"x position, " +
"y position, " +
"x velocity, " +
"y velocity, " +
"x acceleration, " +
"y acceleration" +
"\n";
private long time;
private double xPos;
private double yPos;
private double xVel;
private double yVel;
private double xAcc;
private double yAcc;
public Data(){}
public Data(long time, double xPos, double yPos, double xVel, double yVel, double xAcc, double yAcc){
this.time = time;
this.xPos = xPos;
this.yPos = yPos;
this.xVel = xVel;
this.yVel = yVel;
this.xAcc = xAcc;
this.yAcc = yAcc;
}
//getters and setters for time, pos, vel, and acc
public long getTime(){return time;}
public void setTime(long time){this.time = time;}
public double getXPos(){return xPos;}
public void setXPos(double xPos){this.xPos = xPos;}
public double getYPos(){return yPos;}
public void setYPos(double yPos){this.yPos = yPos;}
public double getXVel(){return xVel;}
public void setXVel(double xVel){this.xVel = xVel;}
public double getYVel(){return yVel;}
public void setYVel(double yVel){this.yVel = yVel;}
public double getXAcc(){return xAcc;}
public void setXAcc(double xAcc){this.xAcc = xAcc;}
public double getYAcc(){return yAcc;}
public void setYAcc(double yAcc){this.yAcc = yAcc;}
/**
* Formats the data as a string of comma separated values.
*/
@Override
public String toString(){
String toReturn = "";
toReturn += time + ", ";
toReturn += xPos + ", ";
toReturn += yPos + ", ";
toReturn += xVel + ", ";
toReturn += yVel + ", ";
toReturn += xAcc + ", ";
toReturn += yAcc + ", ";
toReturn += "\n";
return toReturn;
}
}