Measure how many times iOS can draw per frame - javascript

I am trying to benchmark how many times iOS natively can draw between frame refresh compared to HTML5/JavaScript.
Using this JavaScript I get a number for how may times the browser can draw during the 33 ms (30 Hz):
var ctx = document.getElementById('canvas').getContext('2d');
var img = document.getElementById('img');
var draw = function(load) {
var angle = 0.01;
ctx.clearRect(0,0,400,400);
ctx.save();
ctx.translate(200,200);
for (var i=0; i<load; i++) {
ctx.rotate(angle);
ctx.drawImage(img, 0, 0);
}
ctx.restore();
};
var t, previousTime;
var drawLoad = 1;
var slowCount = 0;
var maxSlow = 10;
var requestAnimationFrame = window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame;
t = previousTime = Date.now();
var tick = function() {
var maximumFrameTime = 1000/30; // 30 FPS
t = Date.now();
var elapsed = t - previousTime;
previousTime = t;
if (elapsed < maximumFrameTime || slowCount < maxSlow) {
if (elapsed < maximumFrameTime) {
drawLoad+=10;
} else {
slowCount++;
}
draw(drawLoad);
requestAnimationFrame(tick);
} else {
// found maximum sustainable load at 30 FPS
document.getElementById('res').innerHTML = ("could draw "+(drawLoad)+" in " + maximumFrameTime + " ms");
}
};
requestAnimationFrame(tick);
See http://jsfiddle.net/tbhZs/117/ for complete code with HTML-markup.
I have fiddled around in objective-c without finding a fair way to get a comparable number. Is there a way to produce a comparable benchmark natively in iOS?

Try instruments tool. you can measure the frames per socond via the core animation instrument.

Related

requestAnimationFrame loop not correct FPS

I have a javascript function that my game loops through (hopefully) 60 times a second that controls input, drawing, etc.
The way it is currently coded it seems to be always be around 52, noticeably lower than 60 fps, and it even dips to 25-30 fps even when nothing else is happening
function loop() {
setTimeout(function () {
requestAnimationFrame(loop);
time += (1000 / 60);
if (time % 600 == 0) {
oldtick = tick;
tick += 1;
time = 0;
aiMovement();
combat();
}
context.clearRect(0, 0, c.width, c.height);
drawMap();
playerInput();
movePlayer();
drawEntities();
drawPopups();
var thisLoop = new Date;
var fps = 1000 / (thisLoop - lastLoop);
lastLoop = thisLoop;
context.drawImage(cursor, mouse.x, mouse.y, 16, 16);
context.fillStyle = "#ffff00";
context.fillText("FPS: " + Math.floor(fps) + " Time: " + Math.floor(time) + " tick: " + tick, 10, 450);
context.fillText("Gold: " + gold, 10, 460);
//requestAnimationFrame(loop);
}, 1000 / 60);
}
if I remove the setTimeout and the first requestAnimationFrame from the top and uncomment the reuqestAnimationFrame at the bottom and remove the other setTimeout things, the FPS improves to 58 but rapidly changes between 58 and 62, again, not statically 60. Does it have something to do with 1000/60 is not a whole number? How would people using requestAnimationFrame achieve 60 fps if this was true?
Don`t use setTimeout or setInterval for animation.
The problem is that you are calling a timer event from within the request animation event. Remove the timeout and just use requestAnimationFrame.
function loop(time){ // microsecond timer 1/1,000,000 accuracy in ms 1/1000th
// render code here
requestAnimationFrame(loop);
// or render code here makes no diff
}
requestAnimationFrame(loop); // to start
RequestAnimationFrame (rAF) is always in sync (unless the browser has vertical sync turned off). The next frame will be presented in 1/60th, 2/60th, 3/60th etc... of a second. You will not get 52frame per second using rAF, rather 60fps, 30fps, 15fps, etc...
The Demo below show the difference in use.
Because requestAnimationFrame uses some smarts to time the animation they can not both run at the same time so click on the canvas to start it.
You can also add a load to simulate rendering. There is a 14ms load and a 28 ms load. The 28ms load is design to mess up rAF as it will on many machines flick between 30 and 60 frames per second. The point is to show that rAF can only have 60, 30, 20,.. etc frames per second.
var ctx1 = can1.getContext("2d");
var ctx2 = can2.getContext("2d");
var ctx3 = can3.getContext("2d");
var lastTime1 = 0;
var lastTime2 = 0;
var lastTime3 = 0;
var frameFunction = frame1;
var frameText = "";
var drag = false;
var loadAmount = 14;
var stats = [{
data : [],
pos : 0,
add(val){
this.data[(this.pos ++) % 150] = val;
}
},{
data : [],
pos : 0,
add(val){
this.data[(this.pos ++) % 150] = val;
}
},{
data : [],
pos : 0,
add(val){
this.data[(this.pos ++) % 150] = val;
}
}
];
for(let i = 0; i < 150; i += 1){
stats[0].add(0);
stats[1].add(0);
stats[2].add(0);
}
setupContext(ctx1);
setupContext(ctx2);
setupContext(ctx3);
drawFrameTime(ctx1,0);
drawFrameTime(ctx2,0);
drawFrameTime(ctx3,0);
can1.addEventListener("click",()=>frameFunction = frame1);
can2.addEventListener("click",()=>frameFunction = frame2);
can3.addEventListener("click",()=>frameFunction = frame3);
load.addEventListener("click",()=>{
if(drag){
drag = false;
load.value = "Add load.";
}else{
drag = true;
load.value = "Remove load.";
}
});
loadPlus.addEventListener("click",()=>{
if(loadAmount === 14){
loadAmount = 28;
loadPlus.value = "28ms";
}else{
loadAmount = 14;
loadPlus.value = "14ms";
}
});
function CPULoad(){
if(drag){
var stopAt = performance.now() + loadAmount;
while(performance.now() < stopAt);
}
}
function setupContext(ctx){
ctx.font = "64px arial";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
}
function drawStats(ctx,stat){
ctx.setTransform(1,0,0,1,0,64);
ctx.strokeStyle = "red";
ctx.strokeRect(-1,16.666,152,0);
ctx.strokeStyle = "black";
ctx.beginPath();
var i = stat.pos + 149;
var x = 0;
ctx.moveTo(x,stat.data[(i++) % 150]);
while(x ++ < 150 && stat.data[i % 150] !== undefined) {
ctx.lineTo(x,stat.data[(i++) % 150]);
}
ctx.stroke();
}
function drawFrameTime(ctx,time){
ctx.fillStyle = "black";
ctx.setTransform(1,0,0,1,0,0);
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
if(time > 0){
ctx.fillStyle = drag ? "red" : "black";
ctx.setTransform(1,0,0,1,ctx.canvas.width / 2,ctx.canvas.height *0.25);
ctx.fillText(time,0,0);
ctx.setTransform(0.4,0,0,0.4,ctx.canvas.width / 2,ctx.canvas.height * 0.75);
ctx.fillText(Math.round(1000 / Number(time)) + "fps",0,0);
}else{
ctx.setTransform(0.4,0,0,0.4,ctx.canvas.width / 2,ctx.canvas.height * 0.75);
ctx.fillText("Click to Start.",0,0);
}
ctx.fillStyle = "black";
ctx.setTransform(0.2,0,0,0.2,ctx.canvas.width / 2,ctx.canvas.height * 0.9);
ctx.fillText(frameText,0,0);
if(drag){
ctx.fillStyle = "red";
ctx.setTransform(0.2,0,0,0.2,ctx.canvas.width / 2,ctx.canvas.height * 0.5);
ctx.fillText("Load " + loadAmount + "ms",0,0);
}
}
function frame1(time){
requestAnimationFrame(frameFunction);
frameText = "Using rAF.";
var frameTime = time - lastTime1;
lastTime1 = time;
stats[0].add(frameTime);
drawFrameTime(ctx1,frameTime.toFixed(2));
drawStats(ctx1,stats[0]);
CPULoad()
}
function frame2() {
setTimeout(function () {
frameText = "Using rAF & setTimeout.";
var time = performance.now();
var frameTime = time - lastTime2;
stats[1].add(frameTime);
lastTime2 = time;
drawFrameTime(ctx2, frameTime.toFixed(2));
drawStats(ctx2,stats[1]);
CPULoad();
requestAnimationFrame(frameFunction);
}, 1000 / 60);
}
function frame3() {
setTimeout(frameFunction,1000/60);
frameText = "SetTimeout by itself.";
var time = performance.now();
var frameTime = time - lastTime3;
stats[2].add(frameTime);
lastTime3 = time;
drawFrameTime(ctx3, frameTime.toFixed(2));
drawStats(ctx3,stats[2]);
CPULoad();
}
requestAnimationFrame(frameFunction);
body {
font-family : arial ;
}
canvas {
border : 1px solid black;
}
div {
text-align : center;
}
<div><h2>RequestAnimationFrame (rAF)</h2>
rAF V rAF & setTimeout V setTimeout<br>
<canvas id = can1 width = 150></canvas>
<canvas id = can2 width = 150></canvas>
<canvas id = can3 width = 150></canvas><br>
Click the frame to set the current test.<br>
The left frame is using rAF alone, the middle using setTimeout and rAf, and the rigth frame uses setTimeout alone.<br>
Click <input type="button" id=load value="add Load"></input> to simulate a rendering load of around <input type="button" id=loadPlus value="14ms" title="click to change CPU load between 14 and 28ms"></input> <br>
Try draging and selecting this text and see how it effects the different methods.<br>
rAF is by far the most stable of the 3.<br>
</div>
The functions purpose isnt to have 60 FPS, but to draw while a frame is beeing drawn and make the performance better. No computer will stay perfectly at 60 FPS.
Also, why is your requestAnimationFrame IN the timeout?

How to make a snow fall on web page text?

I have this JavaScript code for snow falling effect. It's working really nice,
but I decided to create a snow falling on web page text. I have tried, but not getting how to do it.
How to make snow fall on that "I love you" text? http://jsfiddle.net/DgrxX/22/
I have already seen in VB6 code where snow fall on text. If it is possible in Visual Basic 6 seven years ago, why not today in JavaScript or CSS3 or jQuery?
function vp(woh)
{
var viewportwidth;
var viewportheight;
if (typeof window.innerWidth != 'undefined')
{
viewportwidth = window.innerWidth,
viewportheight = window.innerHeight
}
else if (typeof document.documentElement != 'undefined'
&& typeof document.documentElement.clientWidth !=
'undefined' && document.documentElement.clientWidth != 0)
{
viewportwidth = document.documentElement.clientWidth,
viewportheight = document.documentElement.clientHeight
}
else
{
viewportwidth = document.getElementsByTagName('body')[0].clientWidth,
viewportheight = document.getElementsByTagName('body')[0].clientHeight
}
if (woh == 'w')
{
return viewportwidth;
}
else if (woh == 'h')
{
return viewportheight;
}
else
{
return false;
}
}
function snowflake()
{
this.x = Math.random() * canvas.width;
this.y = Math.random() * canvas.height;
this.radius = Math.random()*2;
this.color = "white";
var tobefallingSpeed = Math.random() * 100;
this.fallingSpeed = tobefallingSpeed + 30;
}
function render()
{
ctx.clearRect(0,0,canvas.width, canvas.height);
for (b=0;b<snowflakes;b++)
{
sf[b].y+=0.4;
if(sf[b].y> canvas.height){
sf[b].y = 0;
}
ctx.fillStyle = "#FFFFFF";
ctx.fillRect(sf[b].x,sf[b].y,sf[b].radius,sf[b].radius);
}
}
function main()
{
now = Date.now();
delta = now - then;
render();
then = now;
}
then = Date.now();
var int = self.setInterval(main,1);
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
canvas.width = vp('w');
canvas.height = vp('h');
document.body.appendChild(canvas);
var numberofSnowflakes = 100;
var sf = [];
for (i=0;i<numberofSnowflakes;i++)
{
sf[i] = new snowflake();
snowflakes = i;
}
Okay so I have seen a few answers but the asker wants the snow to be exclusively piling up on the text. Exact piling (according to the snow in background) would be really very difficult but I would like to suggest a (maybe complex) working method.
Make images.
A lots of them. With the text 'I love You' and contents of snow different in each. This maybe similar to creating picture frames from a video.
Define a div. Change your picture every x seconds, where x depends on number of images you have made.
You can use the following code for changing image:
function change_background( new_image_source ) {
var myimage = $( '#myimage' );
myimage.attr( 'src', new_image_source );
setTimeout( function () {
change_background( 'new image source here' );
}, 100);
}
This code will change the image after 0.1. This can hopefully give you the required effect but you will need to make a lot of pictures that differ slightly. I would make lots of pictures for my gf (if I had one).

Why doesn't this For loop work in Canvas?

I was trying to get the canvas to display the i in a loop - I want the i to be changing just like the counting t, from 1-9 non-stop. I just couldn't figure out what's wrong. The javascript looks like this:
window.requestAnimFrame = (function(){
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(callback){window.setTimeout(callback, 1000/60)};
})();
var cvs = document.getElementById("canvasId"),
c = cvs.getContext("2d"),
t = 0;
window.onload=function loop(){
window.requestAnimFrame(loop);
t++;
for(i=0;i<10;i++){
c.clearRect(0,0,cvs.width,cvs.height);
c.font = "bold 90px Arial";
c.fillText(i + " " + t, 100, 200);
}
};
http://jsfiddle.net/luxiyalu/9UZU5/
This is part of a mini game and I've been stuck in here for 2 days; if anyone could tell me what's wrong with it... Thanks a lot!
As you're iterating i from 0 to 9 in your drawing function, there is no time left between two drawings and the user can only see the last iteration value, that is 9.
I'm not sure of what you really want to achieve but it looks like you want this :
var cvs = document.getElementById("canvasId"),
c = cvs.getContext("2d"),
t = 0,
i = 0;
window.onload = function loop(){
window.requestAnimFrame(loop);
i++;
if (i==10) {
i = 0;
t++;
}
c.clearRect(0,0,cvs.width,cvs.height);
c.font = "bold 90px Arial";
c.fillText(i + " " + t, 100, 200);
};
Demonstration

Free memory on FPS system

I start on KineticJS (and on Canvas) and i'm creating a small game for learn...
Right now, I have just 2 layers :
First with a map composed by Kinetic.Image
Second with the last time who game as draw.
I want refresh display X time per second but after 20 or 30 times the game are really slow.. And it's the same when I flood event click ( who launch the draw function too)...
Moreover, i can see in the second layer : the old text are never clean, the new are added on top... :/
var stage;
var layers = {};
var CANEVAS_WIDTH = 800;
var CANEVAS_HEIGHT = 600;
var MAP_WIDTH = 10;
var MAP_HEIGHT = 10;
var MAPPING_WIDTH = 150;
var MAPPING_HEIGHT = 88;
var LEFT_X = 0;
var LEFT_Y = MAP_WIDTH*MAPPING_HEIGHT/2;
var TOP_X = MAP_WIDTH/2*MAPPING_WIDTH;
var TOP_Y = 0;
var VIEW_X = 0;
var VIEW_Y = 0;
var CURSOR_X = 6;
var CURSOR_Y = 0;
var images = {};
function loadImages(sources, callback)
{
var loadedImages = 0;
var numImages = 0;
// get num of sources
for (var src in sources)
numImages++;
for (var src in sources)
{
images[src] = new Image();
images[src].onload = function(){
if (++loadedImages >= numImages)
callback();
};
images[src].src = sources[src];
}
}
function getMouseInfo(mousePos)
{
var info = {screen_x : mousePos.x,
screen_y : mousePos.y,
mouse_x : mousePos.x+VIEW_X,
mouse_y : mousePos.y+VIEW_Y-LEFT_Y,
onMap : 0,
map_x : -1,
map_y : -1};
map_x = -(info.mouse_y - ((LEFT_Y * info.mouse_x) / TOP_X)) / MAPPING_HEIGHT;
map_y = -(-info.mouse_y - ((LEFT_Y * info.mouse_x) / TOP_X)) / MAPPING_HEIGHT;
if(map_x >= 0 && map_x < MAP_WIDTH && map_y >= 0 && map_y < MAP_HEIGHT)
{
info.map_y = parseInt(map_y);
info.map_x = parseInt(map_x);
info.onMap = 1;
}
return info;
}
function draw()
{
drawMap();
drawFPS();
stage.add(layers.mapLayer);
stage.add(layers.fpsLayer);
}
function drawFPS()
{
layers.fpsLayer.clear();
var fps = new Kinetic.Shape(function(){
var date = new Date();
var time = date.getTime();
var context = this.getContext();
context.beginPath();
context.font = "12pt Calibri";
context.fillStyle = "red";
context.fillText("FPS : "+time, 10, 20);
});
layers.fpsLayer.add(fps);
}
function drawMap()
{
var x=0,y=0;
layers.mapLayer.clear();
var s = new Kinetic.Shape(function(){
var context = this.getContext();
context.beginPath();
context.rect(0, 0, CANEVAS_WIDTH, CANEVAS_HEIGHT);
context.fillStyle = "#000";
context.fill();
context.closePath();
});
layers.mapLayer.add(s);
for(x=0; x<MAP_WIDTH; x++)
for(y=0;y<MAP_HEIGHT; y++)
{
var img = new Kinetic.Image({
image: ((x==CURSOR_X && y==CURSOR_Y)?images.testMapCursor:images.testMap)
});
img.x = x*MAPPING_WIDTH/2 + y*MAPPING_WIDTH/2 - VIEW_X;
img.y = (MAP_WIDTH-1)*MAPPING_HEIGHT/2 - x*MAPPING_HEIGHT/2 + y*MAPPING_HEIGHT/2 - VIEW_Y;
layers.mapLayer.add(img);
}
}
function changeCursorPosition(cursor_x, cursor_y)
{
CURSOR_X = cursor_x;
CURSOR_Y = cursor_y;
draw();
}
function initStage()
{
layers.mapLayer = new Kinetic.Layer();
layers.fpsLayer = new Kinetic.Layer();
draw();
}
/*
* INIT
*/
window.onload = function(){
stage = new Kinetic.Stage("container", <?=CANEVAS_WIDTH;?>, <?=CANEVAS_HEIGHT;?>);
stage.on("mousemove", function(){
var mouseInfo = getMouseInfo(stage.getMousePosition());
if(mouseInfo.onMap)
document.body.style.cursor = "pointer";
else
document.body.style.cursor = "default";
});
stage.on("mousedown", function(){
var mouseInfo = getMouseInfo(stage.getMousePosition());
if(mouseInfo.onMap)
changeCursorPosition(mouseInfo.map_x, mouseInfo.map_y);
});
var sources = {
testMap : "testMap.png",
testMapCursor : "testMapCursor.png"
};
loadImages(sources, initStage);
};
Sorry, my english are realy bad.
Thank all.
I know someone who is trying out KineticJS. I haven't used it myself, so I apologize that I cannot provide more specific help.
Unfortunately, it is very difficult to get good performance with canvas, and it depends greatly on the browser. Last I checked, Opera 12 and IE 9 performed significantly faster than other browsers, since their 2D rendering is 3D accelerated (using OpenGL and Direct3D, respectively)
I am not sure if this applies to KineticJS, but one technique you can use to improve performance with canvas is to use multiple canvas elements, and transform their positions rather than blitting on a single surface.
I've been pretty happy with the results I've gotten using Jeash, which is wired into NME's command-line tools. The development is similar to working with Flash, but it will create an HTML5 Canvas application using your code. The same application will also be able to publish to Windows, Mac, Linux, iOS, Android, webOS and Flash, as either native C++ and OpenGL, or as SWF bytecode. This gives you a lot of options for providing the best experience for each user.
http://www.haxenme.org

Track mouse speed with JS

What's the best way to track the mouse speed with plain JS/JQuery? I'd like to track how fast a user moves the mouse in all directions (up/down/left/right).
Sparklines has a nifty example of tracking mouse movement and graphing it. Their code is available in the source of their site starting at line 315.
Simple and effective.
Here is the code:
var mrefreshinterval = 500; // update display every 500ms
var lastmousex=-1;
var lastmousey=-1;
var lastmousetime;
var mousetravel = 0;
$('html').mousemove(function(e) {
var mousex = e.pageX;
var mousey = e.pageY;
if (lastmousex > -1)
mousetravel += Math.max( Math.abs(mousex-lastmousex), Math.abs(mousey-lastmousey) );
lastmousex = mousex;
lastmousey = mousey;
});
var timestamp = null;
var lastMouseX = null;
var lastMouseY = null;
document.body.addEventListener("mousemove", function(e) {
if (timestamp === null) {
timestamp = Date.now();
lastMouseX = e.screenX;
lastMouseY = e.screenY;
return;
}
var now = Date.now();
var dt = now - timestamp;
var dx = e.screenX - lastMouseX;
var dy = e.screenY - lastMouseY;
var speedX = Math.round(dx / dt * 100);
var speedY = Math.round(dy / dt * 100);
timestamp = now;
lastMouseX = e.screenX;
lastMouseY = e.screenY;
});
With current modern browser we can now use movementX or movementY to detect mouse's movement speed. Before you want to use it you should see the compatibility table because older browser will have a prefix like webkitMovementX.
document.addEventListener("mousemove", function(ev){
console.log(`Movement X: ${ev.movementX}, Y: ${ev.movementY}`);
}, false);
The result above is not an average speed like pixel/second but it's total movement between triggered mousemove event. If you need px/s then you can do it like below:
var totalX = 0;
var totalY = 0;
var moveX = 0;
var moveY = 0;
document.addEventListener("mousemove", function(ev){
totalX += Math.abs(ev.movementX);
totalY += Math.abs(ev.movementY);
moveX += ev.movementX;
moveY += ev.movementY;
}, false);
setInterval(function(){
console.log(`Speed X: ${totalX}px/s, Y: ${totalY}px/s`);
console.log(`Movement X: ${moveX}px/s, Y: ${moveY}px/s`);
moveX = moveY = totalX = totalY = 0;
}, 1000);
Negative number represent movement to the left or top, while positive represent movement to the bottom or right direction.
Same way you get speed for anything else:
speed = distance / time
acceleration = speed / time
And use:
$(document).mousemove(function(e){
var xcoord = e.pageX;
var ycoord = e.pageY;
});
To get the mouse coordinates whenever the mouse moves.
This is a method to counter the fact you could start tracking, pause and then move your finger or mouse very quickly (suppose a sudden flick on a touch screen).
var time = 200
var tracker = setInterval(function(){
historicTouchX = touchX;
}, time);
document.addEventListener("touchmove", function(){
speed = (historicTouchX - touchX) / time;
console.log(Math.abs(speed));
}, false);
I have done this with only the touchX in this example. The idea is to take a snapshot of the x position every 200 milliseconds, and then take that from the current position then divide by the 200 (speed = distance / time). This would keep a fresh update on the speed. The time is milliseconds and the output would be the number of pixels traveled per 200 milliseconds.
I also had a requirement to find the acceleration, speed, movement of the mouse. Below is the code which is implemented for the react application. Through this we were able to find the movement, speed, max speed, acceleration, maximum acceleration of the mouse.
let previousEvent, currentEvent;
let maxSpeed = 0, previousSpeed = 0, speed = 0, maxPositiveAcc = 0, maxNegativeAcc = 0;
componentDidMount() {
document.addEventListener('mousemove', (event) => {
currentEvent = event
});
setInterval(function () {
if (currentEvent && previousEvent) {
let movementX = Math.abs(currentEvent.pageX - previousEvent.pageX);
let movementY = Math.abs(currentEvent.pageY - previousEvent.pageY);
let movement = Math.sqrt(movementX * movementX + movementY * movementY);
//Dividing by 100 since the setInterval function is called every 100ms
speed = 10 * movement;
maxSpeed = Math.round(speed > maxSpeed ? (maxSpeed = speed) : maxSpeed);
let acceleration = 10 * (speed - previousSpeed);
if (acceleration > 0) {
maxPositiveAcceleration = Math.round(acceleration > maxPositiveAcc ? (maxPositiveAcc = acceleration) : maxPositiveAcc);
} else {
maxNegativeAcceleration = Math.round(acceleration < maxNegativeAcc ? (maxNegativeAcc = acceleration) : maxNegativeAcc);
}
}
previousEvent = currentEvent
previousSpeed = speed;
}, 100);
}
I'm looking for a way to track mouse speed as well. I found this video on Youtube https://www.youtube.com/watch?v=Lrfmu9V_foE. You can see how to track mouse speed with mousemove event once has defined previous mouse event and current mouse event.
Anyways, I want to store the speed as a value to use elsewhere but don't know how to.

Categories

Resources