Javascript replay user input - javascript

I'm trying to capture user input (jquery event objects) in a captured array. I am tacking a t property on to the event, which is each event's elapsed time from the start of recording. Then I want to walk back through that array, using a setTimeout within a closure in a for loop in order to trigger those events with the same timing as user input.
I just don't understand why the animations won't play on the way back... !??!
Please, if anyone has insight into this... HELP!
$(function() {
var dancer = document.getElementById('dancer');
var $dancer = $(dancer);
var dancerContainer = document.querySelector('.dancer-container');
var $dancerContainer = $(dancerContainer);
var count = 3;
var captured = [];
var countInterval;
function replayDance(captured) {
for (i = 0; i < captured.length; i++) {
e = captured[i];
t = e.t;
setTimeout((function (e) {
return function () {
// $dancer.trigger(e.type);
// this should be
$dancer.trigger(e.originalEvent);
};
})(e), t);
}
}
function countdown() {
console.log(count);
--count;
if (count == 0) {
console.log('recording')
captureInput();
clearInterval(countInterval);
count = 3;
}
}
function captureInput() {
var mouseCapture = [];
var keyCapture = [];
var start = new Date().getTime();
$(document).on('mousemove.capture', function(event) {
event.t = new Date().getTime() - start;
captured.push(event);
});
$(document).on('keyup.capture', function(event) {
event.t = new Date().getTime() - start;
captured.push(event);
});
setTimeout(function() {
console.log('finished capturing');
$(document).off('.capture');
}, 3000);
}
function followMouse(event) {
var width = $(window).width();
var height = $(window).height();
var mouseX = event.pageX - (width * 0.25);
var mouseY = event.pageY - (height * 0.25);
var angleX = (mouseY / height) * 45;
var angleY = (mouseX / width) * 45;
dancer.style.webkitTransform = "rotateX(" + angleX + "deg) rotateY(" + angleY + "deg)";
console.log(dancer.style.webkitTransform);
}
function resize() {
var y = ($(window).height() - 250) * 0.5;
$("#box").css('margin-top', y + 'px');
}
function triggerAnimation(el, klassName) {
el.stop(true, false).addClass(klassName).one('webkitAnimationEnd', function() { el.removeClass(klassName) });
}
$(document).on('keyup', function(event) {
switch (event.which) {
case 49:
triggerAnimation($dancerContainer, 'shake');
break;
case 50:
triggerAnimation($dancerContainer, 'bounce');
break;
case 51:
triggerAnimation($dancerContainer, 'swing');
break;
case 52:
triggerAnimation($dancerContainer, 'wobble');
break;
}
});
$('#button-record').on('click', function(e) {
countInterval = setInterval(countdown, 1000);
});
$('#button-replay').on('click', function(e) {
if (captured.length) {
replayDance(captured);
} else {
console.log('nothing captured!');
}
})
$(window).on('resize', resize);
$(document).ready(resize);
$(document).on('mousemove', followMouse);
});

I needed to trigger the originalEvent attached to the Event object, rather than trying to trigger the e.type again. Corrected the offending line of code in my post.

Related

Variable is returning null in console

When I click on an anchor I pass the attribute ' data-target ' to my target var. In the scroll function I pass the target in the parameters and everything works well. My problem is that the console logs an error showing the target returning a null in this line:
var targetPosition = target.offsetTop;
Can anyone explain why this is happening?
var anchors = document.querySelectorAll('a[href^="#"]');
var headerHeight = document.querySelector('header').offsetHeight;
for (var i = 0; i < anchors.length; i++) {
anchors[i].addEventListener('click', function(event) {
event.preventDefault();
var anchor_location = this.getAttribute('data-target');
// Find the element with ID that matches data-target value.
var target = document.querySelector(anchor_location);
scroll(target, headerHeight);
})
}
function scroll(target, headerHeight) {
var start = null;
var duration = 1100; //d
var targetPosition = target.offsetTop;
var startPosition = window.pageYOffset; //b
var distance = targetPosition - startPosition - headerHeight; //c
console.log(distance);
window.requestAnimationFrame(step);
function step(timestamp) {
if (!start) start = timestamp;
var progress = timestamp - start; //t
// window.scrollTo(0, distance*(progress/duration) + startPosition);
window.scrollTo(0, quintic(progress, startPosition, distance, duration));
if (progress < duration) {
window.requestAnimationFrame(step);
}
}
}
// http://www.gizma.com/easing/ [easing equations]
function quintic (t, b, c, d) {
t /= d/2;
if (t < 1) return c/2*t*t*t*t*t + b;
t -= 2;
return c/2*(t*t*t*t*t + 2) + b;
};

is it possible keydown event will affect setInterval?

I made a simple snake game by javascript, I try to add a feature that when the
var trail = [];
var tail = 5;
var normal_speed = 1000 / 10
var speed = 1000 / 10;
var game_status = 0;
var my_game;
button.addEventListener("click", function () {
clearInterval(my_game);
my_game = setInterval(game, speed);
});
window.onload = function () {
canv = document.getElementById("gc");
context = canv.getContext("2d");
document.addEventListener("keydown", keyPush);
document.addEventListener("keyup", keyRelease);
}
function game() {
for (var i = 0; i < trail.length; i++) {
context.fillRect(trail[i].x * grid_size, trail[i].y * grid_size, grid_size - 2, grid_size - 2);
if (trail[i].x == player_x && trail[i].y == player_y) {
if (game_status == 0) {
tail = 5;
} else {
endGame();
return;
}
}
}
trail.push({
x: player_x,
y: player_y
});
while (trail.length > tail) {
trail.shift();
}
}
function keyPush(keyEvent) {
switch (keyEvent.keyCode) {
case 16:
clearInterval(my_game);
speed = normal_speed * 0.5;
my_game = setInterval(game, speed);
break;
}
}
function keyRelease(keyEvent) {
switch (keyEvent.keyCode) {
case 16:
clearInterval(my_game);
speed = normal_speed;
my_game = setInterval(game, speed);
break;
}
}
user holds the shift key, the snake will speed up. But right now when I hold shift for a short time it works fine, but if I hold it for a long time the game will pause (snake stop moving). Here is my code, please help me fix it.
Your question is not clear, hence I had some fun, enjoy :-D
onload = function () {
var ZOOM = 10;
var FPS = 24;
var LENGTH = 5;
var started = false;
var orientation = {
N: 1, S: 2, E: 3, W: 4
};
var frame = {
width: 20,
height: 15,
el: document.getElementById("frame")
};
var snake = function () {
var body = new Array(LENGTH);
for (let i = 0; i < LENGTH; i++) {
body[i] = { x: i + 1, y: 1 };
}
return {
orientation: orientation.E,
updated: null,
dead: false,
speed: 5, // steps/s
tail: 0,
head: LENGTH - 1,
body: body
};
}();
window.start = start;
frame.el.style.width = frame.width * ZOOM + "px";
frame.el.style.height = frame.height * ZOOM + "px";
refreshSnake();
function start () {
if (!started) {
started = true;
document.addEventListener("click", rotateSnake);
snake.updated = new Date().getTime();
setInterval(loop, 1000 / FPS);
}
}
function loop () {
var now = new Date().getTime();
var t = now - snake.updated;
var d = snake.speed * t / 1000;
if (d >= 1) {
updateSnake(Math.round(d));
snake.updated = now;
refreshSnake();
}
}
function rotateSnake () {
switch (snake.orientation) {
case orientation.N:
snake.orientation = orientation.E; break;
case orientation.E:
snake.orientation = orientation.S; break;
case orientation.S:
snake.orientation = orientation.W; break;
case orientation.W:
snake.orientation = orientation.N; break;
}
}
function updateSnake (steps) {
var tail, head;
var dead = snake.dead;
var length = snake.body.length;
for (let i = 0; !dead && i < steps; i++) {
tail = snake.body[snake.tail];
head = snake.body[snake.head];
snake.tail = (snake.tail + 1) % length;
snake.head = (snake.head + 1) % length;
tail.x = head.x;
tail.y = head.y;
head = tail;
switch (snake.orientation) {
case orientation.N: head.y -= 1; break;
case orientation.S: head.y += 1; break;
case orientation.E: head.x += 1; break;
case orientation.W: head.x -= 1; break;
}
if (snake.dead = (
head.y + 1 > frame.height
|| head.x + 1 > frame.width
|| head.y < 0
|| head.x < 0
)) break;
}
}
function refreshSnake (now) {
var bg = snake.dead ? "red" : "white";
frame.el.innerHTML = snake.body.map(function (bit) {
return "<div style=\""
+ "width:" + ZOOM + "px;"
+ "height:" + ZOOM + "px;"
+ "top:" + (bit.y * ZOOM) + "px;"
+ "left:" + (bit.x * ZOOM) + "px;"
+ "position:absolute;"
+ "background:" + bg + ";"
+ "\"></div>";
}).join("");
}
};
<p>Tap or click in the snippet viewer to turn right ! <button onclick="start(); event.stopPropagation();">Start</button></p>
<div id="frame" style="background:black;position:relative;"></div>
I'd suggest that there is some handling of 'Shift' somewhere else
try event.preventDefault()
http://api.jquery.com/event.preventDefault/

Combining two Javascript functions to one window.onload not working

I have two functions that I want to run on window.onload event but only the last function seems to work so far. One function is for an image slider and the other one retrieves data from a google spreadsheet cell.
function fun1() { //image slider
var ul;
var li_items;
var imageNumber;
var imageWidth;
var prev, next;
var currentPostion = 0;
var currentImage = 0;
function init() {
ul = document.getElementById('image_slider');
li_items = ul.children;
imageNumber = li_items.length;
imageWidth = li_items[0].children[0].clientWidth;
ul.style.width = parseInt(imageWidth * imageNumber) + 'px';
prev = document.getElementById("prev");
next = document.getElementById("next");
prev.onclick = function() {
onClickPrev();
};
next.onclick = function() {
onClickNext();
};
}
function animate(opts) {
var start = new Date;
var id = setInterval(function() {
var timePassed = new Date - start;
var progress = timePassed / opts.duration;
if (progress > 1) {
progress = 1;
}
var delta = opts.delta(progress);
opts.step(delta);
if (progress == 1) {
clearInterval(id);
opts.callback();
}
}, opts.delay || 17);
}
function slideTo(imageToGo) {
var direction;
var numOfImageToGo = Math.abs(imageToGo - currentImage);
direction = currentImage > imageToGo ? 1 : -1;
currentPostion = -1 * currentImage * imageWidth;
var opts = {
duration: 1000,
delta: function(p) {
return p;
},
step: function(delta) {
ul.style.left = parseInt(currentPostion + direction * delta * imageWidth * numOfImageToGo) + 'px';
},
callback: function() {
currentImage = imageToGo;
}
};
animate(opts);
}
function onClickPrev() {
if (currentImage == 0) {
slideTo(imageNumber - 1);
} else {
slideTo(currentImage - 1);
}
}
function onClickNext() {
if (currentImage == imageNumber - 1) {
slideTo(0);
} else {
slideTo(currentImage + 1);
}
}
}
function fun2() {
// Google spreadsheet js
google.load('visualization', '1', {
callback: function() {
var query = new google.visualization.Query('https://docs.google.com/spreadsheets/d/1sA7M5kG6Xo8YScD1Df38PIA_G0bvhGRdqoExXg0KJTs/gviz/tq?tqx=out:html&tq?gid=0&headers=0&range=A1:C');
query.send(displayData);
}
});
function displayData(response) {
numRows = response.getDataTable().getValue(0, 0);
document.getElementById('data').innerHTML = numRows;
}
}
var addFunctionOnWindowLoad = function(callback) {
if (window.addEventListener) {
window.addEventListener('load', callback, false);
} else {
window.attachEvent('onload', callback);
}
}
addFunctionOnWindowLoad(fun1);
addFunctionOnWindowLoad(fun2);
This is the answer I've tried link but I can't seem to figure out where I'm going wrong.
This is what I ended up doing, and now all the functions work.
var ul;
var li_items;
var imageNumber;
var imageWidth;
var prev, next;
var currentPostion = 0;
var currentImage = 0;
function init() {
ul = document.getElementById('image_slider');
li_items = ul.children;
imageNumber = li_items.length;
imageWidth = li_items[0].children[0].clientWidth;
ul.style.width = parseInt(imageWidth * imageNumber) + 'px';
prev = document.getElementById("prev");
next = document.getElementById("next");
prev.onclick = function() {
onClickPrev();
};
next.onclick = function() {
onClickNext();
};
}
function animate(opts) {
var start = (new Date());
var id = setInterval(function() {
var timePassed = (new Date()) - start;
var progress = timePassed / opts.duration;
if (progress > 1) {
progress = 1;
}
var delta = opts.delta(progress);
opts.step(delta);
if (progress == 1) {
clearInterval(id);
opts.callback();
}
}, opts.delay || 17);
//return id;
}
function slideTo(imageToGo) {
var direction;
var numOfImageToGo = Math.abs(imageToGo - currentImage);
// slide toward left
direction = currentImage > imageToGo ? 1 : -1;
currentPostion = -1 * currentImage * imageWidth;
var opts = {
duration: 1000,
delta: function(p) {
return p;
},
step: function(delta) {
ul.style.left = parseInt(currentPostion + direction * delta * imageWidth * numOfImageToGo) + 'px';
},
callback: function() {
currentImage = imageToGo;
}
};
animate(opts);
}
function onClickPrev() {
if (currentImage === 0) {
slideTo(imageNumber - 1);
} else {
slideTo(currentImage - 1);
}
}
function onClickNext() {
if (currentImage == imageNumber - 1) {
slideTo(0);
} else {
slideTo(currentImage + 1);
}
}
window.onload = init;
function addLoadEvent(func) {
var oldonload = window.onload;
if (typeof window.onload != 'function') {
window.onload = func;
} else {
window.onload = function() {
if (oldonload) {
oldonload();
}
func();
}
}
}
function fun2() {
// Google spreadsheet js
google.load('visualization', '1', {
callback: function() {
var query = new google.visualization.Query('https://docs.google.com/spreadsheets/d/1sA7M5kG6Xo8YScD1Df38PIA_G0bvhGRdqoExXg0KJTs/gviz/tq?tqx=out:html&tq?gid=0&headers=0&range=A1:C');
query.send(displayData);
}
});
function displayData(response) {
numRows = response.getDataTable().getValue(0, 0);
document.getElementById('data').innerHTML = numRows;
}
}
addLoadEvent(fun2);
addLoadEvent(function() {
});
I found this function a while ago and believe it or not, I still need to use it every so often. addEventLoad() Just call addEventLoad while passing the function to load.
"The way this works is relatively simple: if window.onload has not already been assigned a function, the function passed to addLoadEvent is simply assigned to window.onload. If window.onload has already been set, a brand new function is created which first calls the original onload handler, then calls the new handler afterwards."
This snippet will load 3 functions on window.onload
Snippet
function addLoadEvent(func) {
var oldonload = window.onload;
if (typeof window.onload != 'function') {
window.onload = func;
} else {
window.onload = function() {
if (oldonload) {
oldonload();
}
func();
}
}
}
function alert1() {
alert("First Function Loaded");
}
function alert2() {
alert("Second Function Loaded");
}
function alert3(str) {
alert("Third Function Loaded; Msg: " + str);
}
addLoadEvent(alert1);
addLoadEvent(alert2);
addLoadEvent(function() {
alert3("This works");
});
<script src="http://gh-canon.github.io/stack-snippet-console/console.min.js"></script>

disable scrolling while scrolling

I am writting a code , which animates scroll of 100% body.height. Everything works fine , but i am trying to disable the scrolling while the animation last to prevent further unwanted behavior.
i am using this code
function animate(x) {
var start = new Date();
var id = setInterval(function (e) {
var timepassed = new Date() - start;
var progress = timepassed / x.duration;
if (progress > 1) {
progress = 1;
}
var delta = x.delta(progress);
x.step(delta);
if (progress == 1) {
clearInterval(id);
}
}, x.delay);
}
function fak(e) {
e.preventDefault();
return false;
}
function move(e) {
e.preventDefault();
var wheel = e.wheelDelta;
wheel = (wheel == 120) ? "-1" : "1";
var body_height = document.body.offsetHeight;
var scrollIt = body_height * wheel;
var page = window.pageYOffset;
animate({
delay: 10,
duration: 700,
delta: function (p) {
return p;
},
step: function (delta) {
window.scrollTo(0, page + (delta * scrollIt));
}
});
return false;
}
document.body.addEventListener("mousewheel", move, false);
document.body.addEventListener("DOMMouseScroll", move, false);
I tried to assign function fak , on mousewheel , mousescroll in interval and then restoring original assigment to them at the end using
function animate(x) {
var start = new Date();
var id = setInterval(function (e) {
document.body.addEventListener("mousewheel", fak, false);
document.body.addEventListener("DOMMouseScroll", fak, false);
var timepassed = new Date() - start;
var progress = timepassed / x.duration;
if (progress > 1) {
progress = 1;
}
var delta = x.delta(progress);
x.step(delta);
if (progress == 1) {
clearInterval(id);
document.body.addEventListener("mousewheel", move, false);
document.body.addEventListener("DOMMouseScroll", move, false);
}
}, x.delay);
}
But didnt work either. Live demo : http://jsfiddle.net/Trolstover/o2pvo2t8/ Did i overlook something?
i changed a bit on your code.
http://jsfiddle.net/o2pvo2t8/2/
just set a flag "running" while scrolling (at start of animate() ), and clear it at the end.
and execute mov only when no scrolling appears.
hope it helps.
var running;
function animate(x) {
running = 1;
var start = new Date();
var id = setInterval(function (e) {
var timepassed = new Date() - start;
var progress = timepassed / x.duration;
if (progress > 1) {
progress = 1;
}
var delta = x.delta(progress);
x.step(delta);
if (progress == 1) {
clearInterval(id);
running = 0;
}
}, x.delay);
}
function fak(e) {
e.preventDefault();
return false;
}
function move(e) {
e.preventDefault();
if (running==1) return;
var wheel = e.wheelDelta;
console.log(wheel);
wheel = (wheel == 120) ? "-1" : "1";
var body_height = document.body.offsetHeight;
var scrollIt = body_height * wheel;
var page = window.pageYOffset;
animate({
delay: 10,
duration: 700,
delta: function (p) {
return p;
},
step: function (delta) {
window.scrollTo(0, page + (delta * scrollIt));
}
});
return false;
}
document.body.addEventListener("mousewheel", move, false);
document.body.addEventListener("DOMMouseScroll", move, false);

how to completely remove

please help to remove the new Bullet. jsfiddle
after the object it moves across the screen from the bottom up. coordinate with y <= 5px method works helper.deleteElement (), but the object is still there exists (see the console - console.log ('move') ;)
I need to to be removed completely
js:
Bullet = function(bulletId){
var self = this;
self.id = bulletId;
self.x = 100;
self.y = 500;
self.move = function(){
console.log('move');
var offsetY = -10,
newY = self.y + offsetY;
if(newY <= 5){
helper.deleteElement(self.id);
if(observerable.removeListener(this, "makeMoveBullet", "move")){
console.log('dont worked!');
}
}
self.y = newY;
self.render(self.x, newY);
return;
};
self.render = function(x, y){
$('#' +self.id).css({
'left': (self.x = x || self.x) + 'px',
'top': (self.y = y || self.y) + 'px'
}).appendTo('#wrap');
return;
};
self.init = function(playerX, playerY){
$('<div class="bullet" id="' + self.id + '" />').appendTo('#wrap');
self.x = playerX + 31;
self.y = playerY - 9;
self.render(self.x, self.y);
return;
};
};
// ------------------------------------------------------------------------------------ observer
var observerable = {
listeners: {},
addListener: function (object, evt, callback) {       
if (!this.listeners.hasOwnProperty(evt)) {           
this.listeners[evt] = [];    
}        
this.listeners[evt].push(object[callback]);       
},
removeListener: function (object, evt, callback) {       
if (this.listeners.hasOwnProperty(evt)) {      
var i, length;     
        
for (i = 0, length = this.listeners[evt].length; i < length; i += 1) {               
if (this.listeners[evt][i] === object[callback]) {                   
this.listeners[evt].splice(i, 1);        
}      
}    
}  
},
    
publisher: function (evt, args) {       
if (this.listeners.hasOwnProperty(evt)){                       
var i, length;       
                          
for (i = 0, length = this.listeners[evt].length; i < length; i += 1){                
this.listeners[evt][i](args);      
}            
}                            
}
};
// ------------------------------------------------------------------------------------ helper
function Helper(){
this.deleteElement = function(id){
$('#' + id).remove();
return;
};
};
// ------------------------------------------------------------------------------------ init
var helper = new Helper();
bullet = new Bullet('bullet_0');
bullet.init(500, 500);
observerable.addListener(bullet, "makeMoveBullet", "move");
setInterval(function(){
observerable.publisher("makeMoveBullet");
}, 100);
JavaScript uses a Garbage Collector to remove unused variables. I would say to do something like this:
delete this.x; delete this.y ; ... ; delete this;
When you want to remove the object (also remove it from any other external data structures). Remove all it's properties then the object itself. Then the GC should remove it.
setInterval returns an interval identifier. Clear the interval using clearInterval function when you don't want more executions of the interval.
var int = setInterval(...);
...
clearInterval(int);
removeListener: function (object, evt, callback) {
if (this.listeners.hasOwnProperty(evt)) {
var i, length;
for (i = 0, length = this.listeners[evt].length; i < length; i += 1) {
if (this.listeners[evt][i] === object[callback]) {
this.listeners[evt].splice(i, 1);
}
}
}
}
object[callback] is always undefined so this.listeners[evt].splice(i, 1); cannot be executed;

Categories

Resources