Stopping an animated gif within 5 seconds - javascript

I have the following code to "freeze" a gif within 5 seconds, however the gif stops as soon as the window.onLoad event is fired:
[].slice.apply(document.images).filter(is_gif_image).map(freeze_gif);
function is_gif_image(i) {
return /^(?!data:).*\.gif/i.test(i.src);
}
function freeze_gif(i) {
var c = document.createElement('canvas');
var w = c.width = i.width;
var h = c.height = i.height;
c.getContext('2d').drawImage(i, 0, 0, w, h);
try {
i.src = c.toDataURL("image/gif");
} catch(e) {
for (var j = 0, a; a = i.attributes[j]; j++)
c.setAttribute(a.name, a.value);
i.parentNode.replaceChild(c, i);
}
}
window.onLoad = function(){
var gifs = freeze_gif(i);
setTimeout( function() {
gifs[n].click();
}, 5000);
}
Is it correct to include the setTimeout in window.onLoad? I have tried to include it in the freeze_gif(i), but the gif keeps stopping when the event is fired up. Can you help?
Thank you
EDIT 1:
As rightly recommended, I am including a working example of the current code:
https://jsfiddle.net/rqfdkkgz/

You are running this line at start:
[].slice.apply(document.images).filter(is_gif_image).map(freeze_gif);
And it freezing all of your images.
The problem with jsfiddle is that all the javascript code there is already inside window.load so you can't really use it twice, but here is the same inside snippet:
function is_gif_image(i) {
return /^(?!data:).*\.gif/i.test(i.src);
}
function freeze_gif(i) {
var c = document.createElement('canvas');
var w = c.width = i.width;
var h = c.height = i.height;
c.getContext('2d').drawImage(i, 0, 0, w, h);
try {
i.src = c.toDataURL("image/gif");
} catch(e) {
for (var j = 0, a; a = i.attributes[j]; j++)
c.setAttribute(a.name, a.value);
i.parentNode.replaceChild(c, i);
}
}
window.onload = function() {
setTimeout(function() {
[].slice.apply(document.images).filter(is_gif_image).map(freeze_gif);
}, 5000);
}
<img src="http://rubentd.com/img/banana.gif" alt="" >
I moved the first line (that cases the freeze of all the gif images) inside the setTimeout function.

Related

I can't access my javascript code because of infinite prompts [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed last year.
Improve this question
Help, I've been using this website called "codepen" to do some javascript coding. But I accidently made it send me infinite prompts, everytime I open the project. Now I can't access the code. I searched for some time for an answer but I found none. heres a link to the problem: https://codepen.io/Aibel-Roy/pen/zYPBeEW
//I can't post the code because of the infinite prompts. Sorry.
Here's your code:
//config
var tick = 50;
var fieldOfView = 25;
var Speed = 0.25;
var ZMulti = 4;
var ClearOnDraw = true;
// variables
var keymap = [];
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var meshA = [
"0,0,0",
"1,0,0",
"1,1,0",
"0,1,0",
"0,0,1",
"1,0,1",
"0,1,1",
"1,1,1"
];
var textures = [
"http://www.textures4photoshop.com/tex/thumbs/red-sofa-leather-seamless-texture-53.jpg"
];
var cameraData = [0, 0, 0];
//keymap
window.addEventListener(
"keydown",
(event) => {
var name = event.key;
keymap.push(name);
},
false
);
window.addEventListener(
"keyup",
(event) => {
var name = event.key;
if (keymap.includes(name)) {
keymap.splice(keymap.indexOf(name), 1);
}
},
false
);
//render img
function draw() {
if (ClearOnDraw) {
ctx.clearRect(0, 0, 10000, 1000);
}
var img = new Image(); // texturing
img.src = textures[0];
prompt(img.src);
img.onLoad = function () {
var pattern = context.createPattern(imageObj, "repeat");
ctx.fillStyle = pattern;
var prevVert;
for (let i = 0; i <= meshA.length; i++) {
//convert 3D vector to 2D
var vert = meshA[i];
if (i >= meshA.length) {
vert = meshA[0];
}
var vertPos = vert.split(",");
var zMag = (vertPos[2] - cameraData[2]) * (fieldOfView / ZMulti);
var vertPos2D = [
(vertPos[0] - cameraData[0]) * fieldOfView + zMag,
(vertPos[1] - cameraData[1]) * fieldOfView + zMag
];
ctx.beginPath();
ctx.moveTo(vertPos2D[0], vertPos2D[1]);
for (let i1 = 0; i1 < meshA.length; i1++) {
var prv = meshA[i1].split(",");
var PrevzMag = (prv[2] - cameraData[2]) * (fieldOfView / ZMulti);
var I1VertPos = [
(prv[0] - cameraData[0]) * fieldOfView + PrevzMag,
(prv[1] - cameraData[1]) * fieldOfView + PrevzMag
];
ctx.lineTo(I1VertPos[0], I1VertPos[1]);
ctx.stroke();
}
ctx.closePath();
ctx.fill();
prevVert = vertPos2D;
}
};
}
function Movement() {
if (keymap.includes("w")) {
cameraData[2] -= Speed * 2;
}
if (keymap.includes("s")) {
cameraData[2] += Speed * 2;
}
if (keymap.includes("d")) {
cameraData[0] -= Speed;
}
if (keymap.includes("a")) {
cameraData[0] += Speed;
}
}
draw();
setInterval(function main() {
draw();
Movement();
}, tick);
How to disable the prompt(if the browser doesn't suggest you to suppress it):
On that page, bring up dev tools(Command + Option + I, or F12 on Windows).
Choose the correct page on the dev tool, usually looks like CodePen (Hash ID)
Override the prompt function in the console by typing window.prompt = () => {}.
Change your code, save and refresh the page.
There are probably better ways to do it but disabling JavaScript makes the code section unusable.
In your function draw(), there is a prompt in here:
function draw() {
// Trimmed
prompt(img.src);
// Trimmed
}
You also have setInterval calling draw() at a particular interval defined in tick (where you have assigned 50ms as the value):
setInterval(function main() {
draw();
Movement();
}, tick);
As a result, draw() gets called every 50ms, where prompt(img.src) gets called, leading to infinite prompt.
You need to change whatever you are doing in setInterval().

how to make a video preview with canvas?

this is my first question here!
im trying to make a website that show videos that i make and i want my viewers can see a preview of video when they hover mouse on the a element or element .
i just do it but i have some problems and questions. lemme show you code example first and then i ask my questions.
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<div id="thumbs" style="width:216px;height:468px;border: 5px solid blue;background-color:red;"><canvas onmouseover="getid1(this);" onmouseout="getid2(this);" id="canvas1"></canvas></div>
<script>
var thumbsList = [];
var delay = 100;
var i = 0;
var video = document.createElement("video");
var a = 0;
var m = document.getElementById("canvas1");
var mtx = m.getContext("2d");
var generate = true;
var animstop = false;
var vidFrames = 64;
m.width = 216;
m.height = 468;
video.preload = "auto";
video.src = "aaaa.mp4";
function stranim(bb){
if(generate){
animstop = false;
video.currentTime = i;
generateVid();
generate = false;
}else{
animstop = false;
startAnim();
}
}
function stpanim(bb) {
clearTimeout();
animstop = true;
mtx.drawImage(thumbsList[0], 0, 0);
}
// if i replace this section with generateVid() the code is working
/*video.addEventListener('seeked', function() {
var d = (video.duration / vidFrames) * 2;
generateThumbnail();
i += video.duration / vidFrames;
if (i <= video.duration) {
video.currentTime = i;
generateVid()
if(d == i){
startAnim();
}
}
});*/
function generateVid() {
var d = (video.duration / vidFrames) * 2;
generateThumbnail();
i += video.duration / vidFrames;
if (i <= video.duration) {
video.currentTime = i;
generateVid();
if(d == i){
startAnim();
}
}
}
function generateFirstThumbnail() {
var c = document.createElement("canvas");
var ctx = c.getContext("2d");
c.width = 216;
c.height = 468;
ctx.drawImage(video, 0, 0, 216, 468);
thumbsList.push(c);
thumbs.appendChild(m);
mtx.drawImage(thumbsList[0], 0, 0);
i += video.duration / vidFrames;
}
function generateThumbnail() {
var c = document.createElement("canvas");
var ctx = c.getContext("2d");
c.width = 216;
c.height = 468;
ctx.drawImage(video, 0, 0, 216, 468);
thumbsList.push(c);
}
function startAnim() {
var currentFrame = 0;
function anim() {
if(currentFrame != (vidFrames - 1) && animstop == false){
currentFrame = (currentFrame + 1) % thumbsList.length;
mtx.drawImage(thumbsList[currentFrame], 0, 0);
setTimeout(anim, delay);
}
}
anim();
}
function getid1(obj) {
stranim(obj.id)
}
function getid2(obj) {
stpanim(obj.id)
}
window.onload = function(){
generateFirstThumbnail();
};
</script>
</body>
</html>
the questions are :
1- why my generatevid() function is not working? this function is just like that eventlistener.
2- i want to add this code on a class to use it on multiple videos but idk how and i think this cant be done with js classes.( i search so many sites for it)
3-i can use 2d arrays for saving my video previews but is it dont make my site lower on load speed or it dont fill the ram of user?
4-there is any way that i make this code better and easyer?(i dont want to use jquery for no reason).
For a pure js approach you can check this not mine btw: https://codepen.io/tepexic/pen/BazYgJe
html:
<input type="file" accept="video/*" id="input-tag"/>
<hr>
<video controls id="video-tag">
<source id="video-source" src="splashVideo">
Your browser does not support the video tag.
</video>
JS
const videoSrc = document.querySelector("#video-source");
const videoTag = document.querySelector("#video-tag");
const inputTag = document.querySelector("#input-tag");
inputTag.addEventListener('change', readVideo)
function readVideo(event) {
console.log(event.target.files)
if (event.target.files && event.target.files[0]) {
var reader = new FileReader();
reader.onload = function(e) {
console.log('loaded')
videoSrc.src = e.target.result
videoTag.load()
}.bind(this)
reader.readAsDataURL(event.target.files[0]);
}
}
But for other approach i would probably use http://ffmpeg.org/ library to generate a preview video (e.g 10 seconds video) and https://videojs.com library for video player so you have a control when user hover the player.
I just did some test on your code, your video is getting seeked only once. No event is raised after that, which means your thumbnail will remain same.
Here is how I was able to fix it
function generateVid() {
var d = (video.duration / vidFrames) * 2;
generateThumbnail();
i += video.duration / vidFrames;
if (i <= video.duration) {
video.currentTime = i;
console.log("starting seeking");
if(d == i){
startAnim();
}
}
}
video.onseeked = (event) => {
if (animstop == false)
{
setTimeout(generateVid, delay);
}
console.log("seeked");
};

html canvas element blinking and then bugging out

I'm trying to have asteroids moving across the screen for a game. The first few asteroids work and then each asteroid will start blinking and bugging out to the point where they won't move across the screen. The variables acx and acy are the x and y coordinates for the asteroids respectively.
setInterval(throwAsteroid1A, 5000);
function throwAsteroid1A() {
var asteroidCanvas = document.getElementById('asteroidCanvas');
var context = asteroidCanvas.getContext('2d');
var acx = Math.floor(Math.random() * 200);
var acy = Math.floor(Math.random() * 10);
setInterval( () => {
asteroid.onload = function() {
context.drawImage(asteroid, asx, asy, aswidth, asheight, acx, acy, 20, 20);
acx += 1;
acy += 1;
}
asteroid.src = 'https://i.imgur.com/WfQKE6T.png';
}, 10)
setInterval(asteroidPath, 50)
}
function asteroidPath() {
// let computedStyle = getComputedStyle(canvasDisplay)
var asteroidCanvas = document.getElementById('asteroidCanvas');
let ctx = asteroidCanvas.getContext("2d");
ctx.clearRect(acx,acy, canvasDisplay.width, canvasDisplay.height);
}
Well there's obviously something conceptually wrong with your approach. I think the blinking is caused by a timing issue in-between the numerous individual interval timers you set up. The callback function asteroidPath() clears a part of the canvas and this might happen at the same time a new Asteroid has been added to the screen - which will delete it either entirely or partly depending on it's screen position.
To work around it you should:
keep a list of all asteroid objects
clear the screen completely once
update all asteroid's at once - not each one with it's own timer
So an example based on your code might look a little something like this (just click 'Run code snippet'):
Asteroid = function() {
this.acx = Math.floor(Math.random() * 200);
this.acy = Math.floor(Math.random() * 10);
this.image = new Image();
this.image.onload = function(e) {
this.loaded = true;
this.aswidth = e.target.naturalWidth;
this.asheight = e.target.naturalHeight;
}
this.image.src = 'https://i.imgur.com/WfQKE6T.png';
}
var asteroidCanvas = document.getElementById('asteroidCanvas');
var context = asteroidCanvas.getContext('2d');
let asteroids = [];
function spawnAsteroid() {
asteroids.push(new Asteroid());
}
function updateCanvas() {
context.clearRect(0, 0, asteroidCanvas.width, asteroidCanvas.height);
let asteroid;
for (let a = 0; a < asteroids.length; a++) {
asteroid = asteroids[a];
if (asteroid.image.loaded) {
context.drawImage(asteroid.image, 0, 0, asteroid.image.aswidth, asteroid.image.asheight, asteroid.acx, asteroid.acy, 20, 20);
asteroid.acx += 1;
asteroid.acy += 1;
}
}
}
setInterval(spawnAsteroid, 2000);
setInterval(updateCanvas, 50);
spawnAsteroid();
<canvas id="asteroidCanvas"></canvas>

Give id to a canvas

I have it so that when you (the PaintBrush) hit the finish everything clears and a button appears. When the button is clicked it starts level two, here it creates a new canvas. I've added some code so that when the button is clicked the old canvas is deleted, then the new one is made. However, this requires the canvas to have an id. how do i get this code:
canvas: document.createElement("canvas"),
To also include an id for it? I cannot have it say var canvas = blah blah and then have
canvas.id = "canvas";
because of the way i have it set up.
P.S the remove code is this if you need to know:
Element.prototype.remove = function() {
this.parentElement.removeChild(this);
}
NodeList.prototype.remove = HTMLCollection.prototype.remove = function() {
for(var i = this.length - 1; i >= 0; i--) {
if(this[i] && this[i].parentElement) {
this[i].parentElement.removeChild(this[i]);
}
}
}
and in the button "click" function area i put this for the remove:
document.getElementById("canvas").remove();
Please help! Thanks in Advance!
EDIT: Here is some extra code to help, it is what occurs when the PaintBrush hits the finish:
else if (PaintBrush.crashWith(Finish)) {
PaintBrush.y = 50;
var button = document.createElement("button");
button.innerHTML = "Level 3";
button.id = "button-2"; // add the id to the button
document.body.appendChild(button); // append to body
GameArena2.clear();
GameArena2.stop();
button.addEventListener ("click", function() {
startGame2();
document.getElement("canvas").remove();
document.getElementById("button-2").remove();
});
EDIT 2: Game canvas code:
var GameArena2 = {
canvas: document.createElement("canvas"),
start: function() {
this.canvas.width = 1280;
this.canvas.height = 480;
this.context = this.canvas.getContext("2d");
document.body.insertBefore(this.canvas, document.body.childNodes[0]);
this.frameNo = 0;
this.interval = setInterval(updateGameArea2, 20);
},
clear: function() {
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
},
stop: function() {
clearInterval(this.interval);
},
drawGameOver: function() {
ctx2 = GameArena2.context;
ctx2.fillStyle = "rgba(0,0,0,"+fader +")";
ctx2.fillRect(0,0,GameArena2.width,GameArena2.height);
drawStatic(fader/2);
fader += .1 * 1/fps
ctx2.fillStyle = "rgba(255,255,255," + fader + ")";
ctx2.font = "72px sans-serif";
ctx2.fillText("GAME OVER",GameArena2.width/2 - 220,GameArena2.height/2);
}
}
function everyinterval(n) {
if ((GameArena.frameNo / n) % 1 == 0) {
return true;
}
else if ((GameArena.frameNo / n) % 1 == 0) {
return true;
}
return false;
}
I think the best way is to create a static function like this:
function createElementOnDom (type,id) {
var element=document.createElement(type);
element.id=id;
return element;
}
console.log(createElementOnDom('CANVAS','myId'));
So you can simply create the canvas adding it his specific id using a simple single row function call like you need.
I only know a way to do direcly this on jQuery, that you wouldn't like to use.
simply you need to do that:
function createElementOnDom (type,id) {
var element=document.createElement(type);
element.id=id;
return element;
}
var GameArena2 = {
canvas: createElementOnDom('CANVAS','myId'),
Simple! Just assign it immediately after the GameArena2 object is created.
var GameArena2 = {
canvas: document.createElement("canvas"),
start: function() {
...
...
}
// give id to a canvas
GameArena2.canvas.id = "GameArena2";
function everyinterval(n) {
if ((GameArena.frameNo / n) % 1 == 0) {
...
...
}

tick method in javascript for canvas

I'm trying to make a tick method for this code.
When I try to put a while loop or time interval it just goes blank.
I want the tick method to call this function without the canvas going blank.
How would i make that tick method
function setup(){
var canvas = document.getElementById('my_canvas');
var ctx = canvas.getContext('2d');
canvas.width = 800;
canvas.height = 600;
var gun = new Image();
var badguy = new Image();
var wall1 = 200;
var ground = new Image();
var back = new Image();
var back2 = new Image();
var back3 = new Image();
var wall = new Image();
var wall2 = new Image();
back.onload = function() {
ctx.drawImage(back, 0, 0, 800, 300);
};
back2.onload = function() {
ctx.drawImage(back2, mountainplace, 0, mtnsize1, 300);
};
back3.onload = function() {
ctx.drawImage(back3, mountainplace2, 0, mtnsize2, 300);
};
ground.onload = function() {
ctx.drawImage(ground, groundplace, 300, 1980, 200);
};
wall.onload = function() {
ctx.drawImage(wall, place2, 250, size2, 100);
};
wall2.onload = function() {
ctx.drawImage(wall2, place, 250, size, 100);
};
badguy.onload = function() {
ctx.drawImage(badguy, badguyplace, 250, 100, 100);
};
gun.onload = function() {
ctx.drawImage(gun, 0, 100, 400, 400);
};
back2.src = "moutain1.png";
back3.src = "moutain2.png";
back.src = "backing.png";
ground.src = "ground1.jpg";
wall.src = "wall.png";
wall2.src = "wall2.png";
badguy.src = "santa2.png";
gun.src = "gun1.png";
};
You need to clarify the question because I'm not sure what exactly you are trying to achieve.
I assume you put some code at the end of your setup() function that performs some operations on the images. But before you can do it you need to wait for the images to load.
BTW: another problem with your code is that the images will be drawn on the canvas in the order in which they load, which may be unpredictable. You probably want to avoid this too.
A solution to your problem (or at least to what I think your problem is) is to first start loading the images and then only perform further operations after they have all been loaded.
You can use the following code to do this:
function makeAllLoadedHandler(image_files_count, on_all_loaded) {
return function() {
--image_files_count;
if (image_files_count == 0) {
// All images loaded, call the function.
on_all_loaded();
}
}
}
function loadAllImages(image_files, on_all_loaded) {
var images = {};
var callback = makeAllLoadedHandler(image_files.length, function() { on_all_loaded(images); } );
for (var i = 0; i < image_files.length; ++i) {
var image = new Image;
image.src = image_files[i];
image.onload = callback;
images[image_files[i]] = image;
}
}
The loadAllImages() function takes an array of image file names and a function to call when all the images have been loaded.
You can use it like this in your code:
function setup() {
var image_files = [
"mountain1.png",
"mountain2.png",
"backing.png",
"ground1.jpg",
"wall.png",
"wall2.png",
"santa2.png",
"gun1.png" ];
loadAllImages(image_files, onAllImagesLoaded);
}
function onAllImagesLoaded(images) {
// Draw your images and perform all the other tasks on them.
// The 'images' object stores each of the Image object under a key that is
// its file name.
ctx.drawImage(images['backing.png'], 0, 0, 800, 300);
// ...
// Do other stuff with the images.
}
You just call the setup() function like you used to and then the onAllImagesLoaded function will be called some time later when all the images are available. You continue your processing in there.
I hope this helps. Although it's possible that your problem is completely different ;)

Categories

Resources