I created a prototype for a horizontal scroller which will select a winner in an animated fashion. I am looking to improve this by programmatically highlighting the selected image under the indicator. I have figured out how to get it to scroll where I want, but I cannot figure out how to programmatically select the image after it's won.
Currently using:
HTML
CSS
jQuery
GSAP TimeLineMax
Working Example: http://codepen.io/ByteKnight13/pen/950a1a0d277fc0204d1827120bdcc090/
Current Code:
if (!String.prototype.format) {
String.prototype.format = function () {
var args = arguments;
return this.replace(/{(\d+)}/g, function (match, number) {
return typeof args[number] != 'undefined'
? args[number]
: match;
});
};
}
$(window).load(function () {
console.log('Window loaded!');
var $roulette = $('#roulette-images-list');
$roulette.html(generateRouletteImages(200));
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function getPositionOfWinner(winner) {
var widthOfImg = $('#roulette-img0').width();
var minDistanceToEdgeAllowed = 4;
var desiredImg = $('#roulette-img' + winner.toString());
var minPos = desiredImg.position().left + minDistanceToEdgeAllowed;
var maxPos = desiredImg.position().left + widthOfImg - minDistanceToEdgeAllowed;
console.log('Position.Left: {0} | Offset().left: {1}'.format(desiredImg.position().left, desiredImg.offset().left));
return getRandomInt(minPos, maxPos);
}
function printLeftOfRouletteSpinner() {
var pos = $('#roulette-images-list').position().left;
if (pos % 100 == 0) console.log(pos);
}
function rouletteSpin(destImg) {
if (!destImg) destImg = 40;
var tl = new TimelineMax({onUpdate: printLeftOfRouletteSpinner}),
rouletteImages = $('#roulette-images-list'),
startLeft = rouletteImages.position().left;
tl//.to(rouletteImages, 0, {x: 5000})
.to(rouletteImages, 10, {x: getPositionOfWinner(destImg) * -1, ease:Power4.easeOut})
.to(rouletteImages, 0, {x: 0}, 11);
}
$('#spin').click(function () {
var winner = $('#winner-text').val();
//if (isNaN(winner) || winner > 49) alert('Enter 0 through 49');
rouletteSpin(winner);
});
function getRandomColor() {
return ((1 << 24) * Math.random() | 0).toString(16)
}
function generateRouletteImages(howMany) {
var imgTemplate = '<img src="{0}" class="{1}" id="roulette-img{2}">';
var imgClass = 'roulette-img';
var imgSrcTemplate = 'http://placehold.it/{0}/{1}?text={2}';
var completedRouletteImages = [];
for (var i = 0; i < howMany; i++) {
var color = getRandomColor();
var imgSrc = imgSrcTemplate.format('80', color, i);
var completedTemplate = imgTemplate.format(imgSrc, imgClass, i);
completedRouletteImages.push('<li>' + completedTemplate + '</li>');
}
return completedRouletteImages;
}
});
There is an onComplete parameter on TimelineMax. Combining that with the onCompleteParams parameter, you can pass the winner image reference to the onComplete callback.
new TimelineMax({
onComplete: timelineFinished,
onCompleteParams: [ destImg ]
})
function timelineFinished(destImg){
// this is where you highlight your winner
$('#roulette-img' + destImg).css({
border: '3px solid red'
});
}
Also, the roulette was resetting after to completed the spin, so I removed the last: .to(rouletteImages, 0, {x: 0}, 11)
Its a pretty rough selection, but you can clean it up with some CSS or whatever you are trying to achieve.
Working Example:
http://codepen.io/kingkode/pen/EyKwJW
Related
I'm trying to replicate the Monty Hall Problem, if you've heard of it, and I need to add in a system that will change one of two Math.floor random numbers when they are equal. My question is how do I change a variable that is random into another if it is equal to a second random variable. If you look into the Monty Hall Problem, the wrong variable would be an incorrect choice and door is correct, I set both to be random, but obviously, they cannot both be equal. This is what I have so far.
setInterval(gr, 1000)
function gr() {
if (wrong === door) {
door = Math.floor((Math.random() * 3) + 1);
}
}
var door1 = 0;
var door2 = 0;
var door3 = 0;
var door;
var wrong;
var attempt = 0;
var d1 = document.getElementById('door1');
var d2 = document.getElementById('door2');
var d3 = document.getElementById('door3');
setInterval(gr, 1000)
function gr() {
if (wrong === door) {
door = Math.floor((Math.random() * 3) + 1);
}
}
function dr1() {
document.getElementById('door1').style.pointerEvents = 'none';
document.getElementById('door2').style.pointerEvents = 'none';
document.getElementById('door3').style.pointerEvents = 'none';
document.getElementById('door1').style.backgroundColor = "green";
door1 = 1;
if (door2 === 1) {
document.getElementById('door2').style.backgroundColor = "black";
door2 = 0;
} else if (door3 === 1) {
document.getElementById('door3').style.backgroundColor = "black";
door3 = 0;
}
if (attempt === 0) {
wrong = Math.floor((Math.random() * 2) + 1);
door = Math.floor((Math.random() * 3) + 1);
if (wrong === 1) {
document.getElementById('door2').style.backgroundColor = "white";
change1a();
} else if (wrong === 2) {
document.getElementById('door3').style.backgroundColor = "white";
change1b();
}
}
attempt = 1;
}
function dr2() {
document.getElementById('door1').style.pointerEvents = 'none';
document.getElementById('door3').style.pointerEvents = 'none';
document.getElementById('door2').style.backgroundColor = "green";
door2 = 1;
if (door1 === 1) {
document.getElementById('door1').style.backgroundColor = "black";
door1 = 0;
} else if (door3 === 1) {
document.getElementById('door3').style.backgroundColor = "black";
door3 = 0;
}
if (attempt === 0) {
wrong = Math.floor((Math.random() * 2) + 1);
door = Math.floor((Math.random() * 3) + 1);
if (wrong === 1) {
document.getElementById('door1').style.backgroundColor = "white";
change2a();
} else if (wrong === 2) {
document.getElementById('door3').style.backgroundColor = "white";
change2b();
}
}
attempt = 1;
}
function dr3() {
document.getElementById('door1').style.pointerEvents = 'none';
document.getElementById('door2').style.pointerEvents = 'none';
document.getElementById('door3').style.backgroundColor = "green";
door3 = 1;
if (door1 === 1) {
document.getElementById('door1').style.backgroundColor = "black";
door1 = 0;
} else if (door2 === 1) {
document.getElementById('door2').style.backgroundColor = "black";
door2 = 0;
}
if (attempt === 0) {
wrong = Math.floor((Math.random() * 2) + 1);
door = Math.floor((Math.random() * 3) + 1);
if (wrong === 1) {
document.getElementById('door1').style.backgroundColor = "white";
change3a();
} else if (wrong === 2) {
document.getElementById('door2').style.backgroundColor = "white";
change3b();
}
}
attempt = 1;
}
function change1a() {
document.getElementById('door3').style.pointerEvents = "all";
}
function change1b() {
document.getElementById('door2').style.pointerEvents = "all";
}
function change2a() {
document.getElementById('door3').style.pointerEvents = "all";
}
function change2b() {
document.getElementById('door1').style.pointerEvents = "all";
}
}
I tried adapting your code, but it looked too messy for me to understand everything you wanted to do. So, instead, I decided to create my own, just for fun. You can get some inspiration in there.
To answer your specific question, this is the way I choose the door:
var selectedDoor = 1,
correctDoor = 2,
losingDoor = getLosingDoor();
function getLosingDoor() {
var losingDoor;
do {
losingDoor = Math.floor((Math.random() * 3) + 1);
} while ([correctDoor, selectedDoor].indexOf(losingDoor) > -1);
return losingDoor;
}
Full demo
// Create a MontyHall instance in the #app div
var myMontyHall = MontyHall(document.getElementById('app'));
function MontyHall(container) {
var self = {
// Will hold DOM references
refs: null,
// Will hold the MontyHall instance's state
state: null,
/*
* Creates the doors in the DOM and in the state
*/
init: function() {
self.state = {
attempts: 0,
doorCount: 3,
correctDoor: self.getRandomInt(0, 3)
};
self.refs = {
container: container,
instructions: document.createElement('p'),
doorsWrapper: document.createElement('div'),
doors: []
};
// Reset container
self.refs.container.innerHTML = '';
// Setup a container for the doors
self.refs.doorsWrapper.className = 'doors-wrapper';
self.refs.container.appendChild(self.refs.doorsWrapper);
// Setup a container for instructions
self.say('Please select a door.');
self.refs.container.appendChild(self.refs.instructions);
// For each door
for (var i=0; i<self.state.doorCount; i++) {
// Create a div
var el = document.createElement('div');
// Give it a class
el.className = 'door';
// Add click event listener
(function(index) {
el.addEventListener('click', function(){
self.clickOnDoor(index);
});
})(i);
// Append it to the doors container
self.refs.doorsWrapper.append(el);
// Store a reference to it
self.refs.doors.push(el);
}
return self;
},
/*
* Called when a door is clicked
*/
clickOnDoor: function(index) {
self.state.selectedDoor = index;
// If this is the first attempt
if (self.state.attempts === 0) {
// Show it is selected
self.refs.doors[self.state.selectedDoor].classList.add('selected');
// Find a non selected losing door
self.state.losingDoor = self.getLosingDoor();
// Open it
self.refs.doors[self.state.losingDoor].classList.add('disabled', 'loser');
// Update instructions
self.say(
'You selected door #' + (index + 1) + '.<br>'
+ 'I opened door #' + (self.state.losingDoor + 1) + ', '
+ 'it contains a sheep.<br>'
+ 'You can now keep your choice, or change your mind.'
);
self.state.attempts++;
} else {
// For each door
self.refs.doors.forEach(function(el, i) {
// Disable it
el.classList.add('disabled');
// Show it as a winner or a loser
el.classList.add(i === self.state.correctDoor ? 'winner' : 'loser');
// Show it as selected or not
el.classList.toggle('selected', i === index);
});
// Update instructions
self.say(
(
self.state.correctDoor === index ?
'<span class="green">Congratulations, you won!</span>' :
'<span class="red">Sorry, you lost...</span>'
)
+ '<br>'
+ 'The gold was behind door #' + (self.state.correctDoor + 1) + '.<br>'
+ '<button class="restart">Play again</button>'
);
// Enable restart button
self.refs.instructions.querySelector('.restart')
.addEventListener('click', self.init);
}
},
/*
* Returns the index of a losing door, which is not selected
*/
getLosingDoor: function() {
var losingDoor;
do {
losingDoor = self.getRandomInt(0, self.state.doorCount);
} while ([
self.state.correctDoor,
self.state.selectedDoor
].indexOf(losingDoor) > -1);
return losingDoor;
},
/*
* Sets the instructions innerHTML
*/
say: function(html) {
self.refs.instructions.innerHTML = html;
},
/*
* Returns an integer between min and max
*/
getRandomInt: function(min, max) {
return Math.floor((Math.random() * (max-min)) + min);
}
};
return self.init();
}
/* I minified the CSS to avoid cluttering my answer. Full version in link below */body{font-family:Arial,Helvetica,sans-serif;text-align:center}p{margin-top:.2em}button{margin-top:.5em}.door{display:inline-block;width:3em;height:5em;border:1px solid #000;margin:.5em;background-image:url(https://image.ibb.co/c7mssS/doors.jpg);background-size:300% 100%;background-position:center;cursor:pointer;box-shadow:0 0 5px 1px #1070ff;transition:all .3s ease}.door:not(.disabled):hover{opacity:.9}.door.selected{box-shadow:0 0 5px 3px #b910ff}.door.loser{background-position:right}.door.winner{background-position:left}.door.disabled{pointer-events:none}.door.disabled:not(.selected){box-shadow:none}span{font-weight:700}.green{color:#42e25d}.red{color:#ff2f00}
<div id="app"></div>
JSFiddle demo
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/
// videogame.js
// don't forget to validate at jslint.com
/*jslint devel: true, browser: true */
/*global $*/
$(function () {
"use strict";
// global functions
function boundaryCheck(element_selector) {
var element = $(element_selector);
var universe = $("#universe");
var p = element.position();
if (p.left < 0) {
element.css("left", "0px");
}
if (p.top < 0) {
element.css("top", "0px");
}
if (p.left + element.width() > universe.width()) {
element.css("left", (universe.width() - element.width()) + "px");
}
if (p.top + element.height() > universe.height()) {
element.css("top", (universe.height() - element.height()) + "px");
}
}
function getRandomInt(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min)) + min;
}
// Constructor for Player Ship object
function PlayerShip() {
var my = {};
$("#universe").append($("<div>").attr("id", "player"));
my.navigate = function (keys) {
var RIGHTARROW_KEYCODE = 39;
var LEFTARROW_KEYCODE = 37;
var UPARROW_KEYCODE = 38;
var DOWNARROW_KEYCODE = 40;
if (keys === RIGHTARROW_KEYCODE) {
$("#player").css("left", "+=10px");
}
if (keys === LEFTARROW_KEYCODE) {
$("#player").css("left", "-=10px");
}
if (keys === UPARROW_KEYCODE) {
$("#player").css("top", "-=10px");
}
if (keys === DOWNARROW_KEYCODE) {
$("#player").css("top", "+=10px");
}
boundaryCheck("#player");
};
return my;
}
// Constructor for Enemy Ship object
function EnemyShip() {
var my = {};
$("#universe").append($("<div>").attr("id", "enemy"));
my.move = function (paused) {
if (!paused) {
var left = Boolean(getRandomInt(0, 2));
var top = Boolean(getRandomInt(0, 2));
if (left) {
$("#enemy").css("left", "-=" + getRandomInt(1, 10) + "px");
} else {
$("#enemy").css("left", "+=" + getRandomInt(1, 10) + "px");
}
if (top) {
$("#enemy").css("top", "-=" + getRandomInt(1, 10) + "px");
} else {
$("#enemy").css("top", "+=" + getRandomInt(1, 10) + "px");
}
boundaryCheck("#enemy");
}
};
return my;
}
// this might make an asteroid happen, maybe. I don't know if it will work.
function Asteroid() {
var my = {};
$("#universe").append($("<div>").attr("id", "asteroid"));
my.move = function (paused) {
if (!paused) {
var left = Boolean(getRandomInt(0, 2));
var top = Boolean(getRandomInt(0, 2));
if (left) {
$("#asteroid").css("left", "-=" + getRandomInt(1, 10) + "px");
} else {
$("#asteroid").css("left", "+=" + getRandomInt(1, 10) + "px");
}
if (top) {
$("#asteroid").css("top", "-=" + getRandomInt(1, 10) + "px");
} else {
$("#asteroid").css("top", "+=" + getRandomInt(1, 10) + "px");
}
boundaryCheck("#asteroid");
}
};
return my;
}
// Constructor for Game object
function Game() {
// total points
var _health = 1000;
var _time = 0;
// is the game paused?
var _game_paused = false;
// speed of background animation in ms (larger = slower)
var _background_speed = 100;
// player ship
var _player_ship = new PlayerShip();
// enemy ship
var _enemy_ship = new EnemyShip();
var _asteroid = new Asteroid(); //make this an actual thing
var my = {
health: _health,
time: _time,
game_paused: _game_paused,
background_speed: _background_speed,
player_ship: _player_ship,
enemy_ship: _enemy_ship,
asteroid: _asteroid
};
$("#universe").append($("<div>").attr("id", "results"));
$("#results").append($("<h1>"));
$("#universe").append($("<div>").attr("id", "results2"));
$("#results2").append($("<h1>"));
my.health = function (value) {
if (value === undefined) {
return _health;
}
_health = value;
return my;
};
my.time = function (value) {
if (value === undefined) {
return _time;
}
_time = value;
return my;
};
my.game_paused = function (value) {
if (value === undefined) {
return _game_paused;
}
_game_paused = value;
return my;
};
my.background_speed = function (value) {
if (value === undefined) {
return _background_speed;
}
_background_speed = value;
return my;
};
my.player_ship = function (value) {
if (value === undefined) {
return _player_ship;
}
_player_ship = value;
return my;
};
function runtimer() {
_time++;
};
my.enemy_ship = function (value) {
if (value === undefined) {
return _enemy_ship;
}
_enemy_ship = value;
return my;
};
my.asteroid = function (value) {
if (value === undefined) {
return _asteroid;
}
_asteroid = value;
return my;
};
// METHODS
// display total points
my.displayHealth = function () {
$("#results h1").html("Health: " + _health);
};
my.increaseTime = function () {
setInterval(function(){ runTimer() }, 1000)
}
my.displayTimer = function () {
$("#results2 h1").html("Time: "+ _time);
};
my.moveBackground = function () {
if (!_game_paused) {
var background_position = $("#universe")
.css("backgroundPosition")
.split(" ");
var current_x = parseInt(background_position[0], 10);
var current_y = parseInt(background_position[1], 10);
var new_x = current_x - 1;
var new_y = current_y;
$("#universe").css({
"background-position": new_x + "px " + new_y + "px"
});
}
};
my.checkKeys = function () {
var ESCAPE_KEYCODE = 27;
$(document).keydown(function (key_event) {
if (key_event.which === ESCAPE_KEYCODE) {
if (_game_paused) {
_game_paused = false;
$("#pause").remove();
} else {
_game_paused = true;
var pause = $("<div>", {id: "pause"});
$("body").prepend(pause);
}
} else {
_player_ship.navigate(key_event.which);
}
});
};
my.checkCollisions = function (paused) {
var p = $("#player");
var e = $("#enemy");
var ppos = p.position();
var epos = e.position();
if (!paused) {
if (
(
(ppos.left + p.width() < epos.left) ||
(ppos.left > epos.left + e.width())
) ||
(
(ppos.top + p.height() < epos.top) ||
(ppos.top > epos.top + e.height())
)
) {
return false;
} else {
return true;
}
}
};
my.checkAsteroid = function (paused) {
var p = $("#player");
var a = $("#asteroid");
var ppos = p.position();
var apos = a.position();
if (!paused) {
if (
(
(ppos.left + p.width() < apos.left) ||
(ppos.left > apos.left + a.width())
) ||
(
(ppos.top + p.height() < apos.top) ||
(ppos.top > apos.top + a.height())
)
) {
return false;
} else {
return true;
}
}
};
my.play = function () {
_enemy_ship.move(_game_paused);
_asteroid.move(_game_paused);
if (my.checkCollisions(_game_paused)) {
_health --;
my.displayHealth();
} else if (
my.checkAsteroid(_game_paused)) {
_health --;
my.displayHealth();
}
};
return my;
}
var game = new Game();
game.checkKeys();
game.displayHealth();
game.displayTimer();
game.increaseTime();
setInterval(game.moveBackground, game.background_speed);
setInterval(game.play, game.background_speed);
});
I'm relatively new to programming. I took a class in high school, which was very mediocre. I'm now taking some starter courses in college, and my assignment is to improve a generic space game (which I have already started doing). I have a div for the timer, but for some reason, I can't get any functions to increase the _time variable. It's almost as though they're not allowed to access it. I have a function called "runTimer", which is supposed to increase "_time" by one every time it is run. I have another function called "increaseTime", which is supposed to run "runTimer" every 1000 milliseconds. The variable never seems to increase though. This hasn't been my first spaghetti code implementation of a timer, since I've tried various things over the past few hours. I just can't understand why the variable won't increase.
This is a big hunk of code. As RobG pointed out, try to work on paring back your question to the minimal, complete, and verifiable example you can.
That said, at a glance, it would appear that your timer probably is updating. At least _time is.
The problem is likely you are never re-drawing your div, so it isn't showing the updated value. You need to call game.displayTimer() every time _time updates.
Probably the easiest place to add it would be in your setInterval() in increaseTime():
my.increaseTime = function () {
setInterval(function(){
runTimer();
my.displayTime();
}, 1000)
}
I have a lazy-load code block here:
(function($){
var items = [];
function winPos(win) {
return { x: 0, y: 0, x2: win.width() - 1, y2: win.height() - 1 };
}
function pos(win, el) {
var p = el.offset();
var x = p.left - win.scrollLeft();
var y = p.top - win.scrollTop();
return { x: x, y: y, x2: x + el.width() -1, y2: y + el.height() - 1 };
}
function intersects(a, b) {
return !(a.x2 < b.x || a.x > b.x2 || a.y2 < b.y || a.y > b.y2);
}
function check(win, w, item) {
var p = pos(win, $(item.el));
var s = intersects(w, p);
if (s != item.shown) {
item.shown = s;
(s ? item.show : item.hide).call(item.el);
}
}
$.fn.visible = function(show, hide){
var win = $(window), w = winPos(win);
return this.each(function(i, el){
var item = { el: el, show: show, hide: hide, shown: false };
items.push(item);
check(win, w, item);
});
};
$(window).on('scroll resize', function(e){
var win = $(window), w = winPos(win);
for (var i = 0; i < items.length; i++) {
check(win, w, items[i]);
}
});
})(jQuery);
// Lazy loading images plugin
(function($){
$.fn.lazyImage = function(){
return this.visible(function(){
$(this).append($('<img>', {'src': $(this).data('src') }).css('opacity', 0).load(function(){
$(this).animate({ opacity: 1 });
}));
}, function(){
$(this).empty();
});
};
})(jQuery);
// Usage
$('div').lazyImage();
https://jsfiddle.net/Guffa/u7bcms27/
I want to lazy load each iframe div.
*
Here's my code, that gets links and titles from the Reddit API, and loads the videos into Iframes.
fetch('https://www.reddit.com/r/cleanupearth.json')
.then(res=>res.json())
.then(res=>res.data.children)
.then(res=>res.map(post=>({
// author: post.data.author,
link: post.data.url,
img: post.data.thumbnail,
title: post.data.title
})))
.then(res=>res.map(render))
.then(res=>console.log(res))
const app = document.querySelector('#app');
const render = post => {
const node = document.createElement('div');
node.innerHTML= `${post.title}`;
node.className= 'clip-title';
app.appendChild(node);
//node.style.fontSize = "50px";
var regExp = /^.*(youtu\.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/;
var url = post.link;
// var url = "https://www.youtube.com/watch?v=MPmKEi4xXMg";
var match = url.match(regExp);
var strippedURL = match[2];
//alert("strippedURL is " + strippedURL);
if (match && match[2].length == 11) {
console.log(match[2]);
} else {
//error
console.log('error');
}
var a = document.createElement('iframe');
// iframe.id = 'appiframe';
a.className = "clip-content"
a.src = "https://www.youtube.com/embed/" + strippedURL; //add your iframe path here
a.width = "100%";
a.height = "100%";
a.padding = "500px";
app.style.textAlign = "center";
document.querySelector('#app').appendChild(a);
}
*
Here's an fiddle of the two snippets together.
https://jsfiddle.net/p5tL6jvr/
The original snippet creates an empty array called items:
var items = [];
and loads images into an append function;
$(this).append($('<img>', {'src': $(this).data('src') }).css('opacity', 0).load(function()
I could load the entire id=#app div into the items array, and swap the img line for a line that creates iframes. What is the best way to approach this?
BTW, if anyone knows of a succinct way to do this in pure Javascript, instead of JQuery, that would be interesting to read.
Hey I am using a Spawn function I found for a javascript game I am creating to randomy generate enemies to click on. But it is very slow and I would like it to be able to generate faster and faster.. is it possible to modify this code in that way? the spawn function is at the end of the code.
function Gem(Class, Value, MaxTTL) {
this.Class = Class;
this.Value = Value;
this.MaxTTL = MaxTTL;
};
var gems = new Array();
gems[0] = new Gem('green', 10, 0.5);
gems[1] = new Gem('blue', 20, 0.4);
gems[2] = new Gem('red', 50, 0.6);
function Click(event)
{
if(event.preventDefault) event.preventDefault();
if (event.stopPropagation) event.stopPropagation();
else event.cancelBubble = true;
var target = event.target || event.srcElement;
if(target.className.indexOf('gem') > -1){
var value = parseInt(target.getAttribute('data-value'));
var current = parseInt( score.innerHTML );
var audio = new Audio('music/blaster.mp3');
audio.play();
score.innerHTML = current + value;
target.parentNode.removeChild(target);
if (target.className.indexOf('red') > 0){
var audio = new Audio('music/scream.mp3');
audio.play();
endGame("You lose");
}
}
return false;
}
function Remove(id) {
var gem = game.querySelector("#" + id);
if(typeof(gem) != 'undefined')
gem.parentNode.removeChild(gem);
}
function Spawn() {
var index = Math.floor( ( Math.random() * 3 ) );
var gem = gems[index];
var id = Math.floor( ( Math.random() * 1000 ) + 1 );
var ttl = Math.floor( ( Math.random() * parseInt(gem.MaxTTL) * 1000 ) + 1000 ); //between 1s and MaxTTL
var x = Math.floor( ( Math.random() * ( game.offsetWidth - 40 ) ) );
var y = Math.floor( ( Math.random() * ( game.offsetHeight - 44 ) ) );
var fragment = document.createElement('span');
fragment.id = "gem-" + id;
fragment.setAttribute('class', "gem " + gem.Class);
fragment.setAttribute('data-value', gem.Value);
game.appendChild(fragment);
fragment.style.left = x + "px";
fragment.style.top = y + "px";
setTimeout( function(){
Remove(fragment.id);
}, ttl)
}
function Stop(interval) {
clearInterval(interval);
}
function endGame( msg ) {
count = 0;
Stop(interval);
Stop(counter);
var left = document.querySelectorAll("section#game .gem");
for (var i = 0; i < left.length; i++) {
if(left[i] && left[i].parentNode) {
left[i].parentNode.removeChild(left[i]);
}
}
time.innerHTML = msg || "Game Over!";
start.style.display = "block";
UpdateScore();
}
this.Start = function() {
score.innerHTML = "0";
start.style.display = "none";
interval = setInterval(Spawn, 750);
count = 4000;
counter = null;
function timer()
{
count = count-1;
if (count <= 0)
{
endGame();
return;
} else {
time.innerHTML = count + "s left";
}
}
counter = setInterval(timer, 1000);
setTimeout( function(){
Stop(interval);
}, count * 1000)
};
addEvent(game, 'click', Click);
addEvent(start, 'click', this.Start);
HighScores();
}
JS/HTML Performance tips:
1) var gems = new Array(); change to new Array(3);
2) cache all new Audio('...');
3) use getElementById it faster then querySelector('#')
4) prepare var fragment = document.createElement('span'); and cache it, use cloneNode to insert it.
5) fragment.style.left & top change to CSS3 transform: translate(). CSS3 transform use your video card GPU, style.left use CPU...
6) Use only single setInterval and run on all list of fragments.
7) You can make a pool of "fragments" and just show\hide, it will increase performance dramatically.
Basically it works slow due to many page redraws, every time you add new elements to page browser must to redraw whole screen, do not add elements, just show\hide them.