简体   繁体   English

在没有任何库的情况下从多个图像在 Javascript 中制作 GIF

[英]Make GIF in Javascript from multiple images without any library

Is there any way to make GIFs in Javascript without any library?有没有办法在没有任何库的情况下在 Javascript 中制作 GIF? I've searched half the internet and found nothing.我在互联网上搜索了一半,一无所获。

Note to potential downvoters请注意潜在的反对者

I know that this is a low-quality question.我知道这是一个低质量的问题。 However, I believe that the usual reasons for not answering have been invalidated.但是,我认为通常不回答的原因已失效。 Seeing as it has been almost a month since it was asked, I doubt I'll be doing their homework as it would probably be past due for weeks at this point.自从被问到已经快一个月了,我怀疑我是否会做他们的功课,因为此时可能会过期数周。 And as for them not taking the time to research this myself, I'm fixing the problem at its source by teaching them how to research it.至于他们自己没有花时间研究这个问题,我正在通过教他们如何研究来解决问题的根源。

Answer回答

Note that I'm answering this assuming that you know some Javascript, but not all of it, and that you want to learn how to write code that you might not yet know how to do .请注意,我在回答这个问题时假设您知道一些 Javascript,但不是全部,并且您想学习如何编写您可能还不知道该怎么做的代码 If you're just looking for the solution, then feel free to copy-paste it or whatever.如果您只是在寻找解决方案,请随意复制粘贴或其他方式。 But reading through this and understanding the process I used to tackle this problem, like how to think through it and look things up, will help you in the future.但是通读一遍并理解我用来解决这个问题的过程,比如如何思考和查找问题,将对你未来有所帮助。 If you learn how to learn, you'll be a lot better off.如果你学会如何学习,你会过得更好。

Now, first of all, we need a way to display images.现在,首先,我们需要一种显示图像的方法。 I know from experience that there are two main methods to do this.我从经验中知道有两种主要方法可以做到这一点。 One involves using the canvas element to draw the image;一种是使用canvas 元素来绘制图像; this is the more complicated method.这是更复杂的方法。 Method 2 uses the image tag , <img> .方法 2 使用图像标签<img> I assume this is the method you want.我假设这是你想要的方法。 If you didn't know how to draw an image using HTML and Javascript, a simple google search ( here's another ) can clear that up.如果您不知道如何使用 HTML 和 Javascript 绘制图像,一个简单的谷歌搜索这是另一个)可以解决这个问题。 (Actually, the second one mostly returns the canvas method-- but you probably knew about the image tag already anyways.) (实际上,第二个主要返回 canvas 方法——但无论如何你可能已经知道图像标签。)

Next we need a way to change what image is displayed.接下来,我们需要一种方法来更改显示的图像。 Well, that should be as simple as changing the thing that tells the image what to display in the first place.嗯,这应该就像更改告诉图像首先要显示的内容一样简单。 The top result from the first example search is a nice documentation page -- perfect.第一个示例搜索的最高结果是一个不错的文档页面——完美。 Reading through, I get to this part:通读一遍,我进入了这一部分:

HTML Images Syntax HTML 图像语法

In HTML, images are defined with the tag.在 HTML 中,图像是用标签定义的。

The tag is empty, it contains attributes only, and does not have a closing tag.标签是空的,它只包含属性,没有结束标签。

The src attribute specifies the URL (web address) of the image: src 属性指定图像的 URL(网址):

<img src="url">

Well that looks like it's what controls what the image is.嗯,看起来它是控制图像的东西。 So we simply have to make a Javascript script that changes this property regularly.所以我们只需要制作一个 Javascript 脚本来定期更改此属性。 To do this right, we need a JS method that will wait for a specified amount of time.为了做到这一点,我们需要一个 JS 方法来等待指定的时间。 Searching "javascript wait" in Google, I see the second result is from the same source webpage that told me about images, so I'll go with that one.在 Google 中搜索“javascript wait” ,我看到第二个结果来自告诉我有关图像的同一个源网页,所以我会选择那个。 In the docs, I see this:在文档中,我看到了这个:

The setInterval() Method setInterval() 方法

The setInterval() method repeats a given function at every given time-interval. setInterval() 方法在每个给定的时间间隔重复给定的函数。

window.setInterval(function, milliseconds);

The window.setInterval() method can be written without the window prefix. window.setInterval() 方法可以在没有窗口前缀的情况下编写。

The first parameter is the function to be executed.第一个参数是要执行的函数。

The second parameter indicates the length of the time-interval between each execution.第二个参数表示每次执行之间的时间间隔长度。

(It even gives an example!) (它甚至给出了一个例子!)

This seems to be what we want.这似乎是我们想要的。 Using this method, I can make a simple code to change between two images every second (explanatory comments to the right, scroll to see them better):使用这种方法,我可以编写一个简单的代码来每秒在两个图像之间切换(右侧的解释性注释,滚动以更好地查看它们):

 function changePicture(){ //Make the function that will change the pictures var picture = document.getElementById('picture1'); //Get the picture element from the HTML if(picture.src == "https://vignette.wikia.nocookie.net/starpolar/images/9/96/Paul_blart.jpg/revision/latest?cb=20150419171412"){ //If it's the Paul Blart picture then: picture.src = "https://i.ytimg.com/vi/A5KWYdrOXDk/movieposter.jpg"; //Set it to the Bee Movie } else { //If it's not Paul Blart (and is therefore probably the Bee Movie image): picture.src = "https://vignette.wikia.nocookie.net/starpolar/images/9/96/Paul_blart.jpg/revision/latest?cb=20150419171412"; //Set it to Paul Blart } } setInterval(changePicture, 1000); //Use the new method we learned about to schedule our picture-changing function to happen once every second
 <!--This is the image that we will change.--> <img id="picture1" src="https://vignette.wikia.nocookie.net/starpolar/images/9/96/Paul_blart.jpg/revision/latest?cb=20150419171412"/>

Now, that's a good start-- we can change between 2 different totally definitely random images.现在,这是一个好的开始——我们可以在 2 个不同的完全随机的图像之间切换。

But we need more.但我们需要更多。 We don't want to code in every new image manually;我们不想在每个新图像中手动编码; what we need is an array .我们需要的是一个数组 It's hard to know that through a search, but if you've taken a primer course or learned some JS on your own you should be pretty familiar with arrays and would probably realize that they are a good option here.通过搜索很难知道这一点,但是如果您参加过入门课程或自学了一些 JS,您应该对数组非常熟悉,并且可能会意识到它们在这里是一个不错的选择。 So we set up the array with all the images we want it to change between (scroll to the right to see it all):因此,我们设置了包含我们希望它在之间更改的所有图像的数组(向右滚动以查看所有内容):

var gifImages = ["https://vignette.wikia.nocookie.net/starpolar/images/9/96/Paul_blart.jpg/revision/latest?cb=20150419171412","https://i.ytimg.com/vi/A5KWYdrOXDk/movieposter.jpg","http://content.tv3.ie/content/images/0647/1_165781.jpg","https://upload.wikimedia.org/wikipedia/en/thumb/4/47/Spongebob-squarepants.svg/1200px-Spongebob-squarepants.svg.png","http://i0.kym-cdn.com/entries/icons/mobile/000/016/958/Dankkkk.jpg"];

Then we need to change our original function.然后我们需要改变我们原来的功能。 It should cycle through this array of images;它应该循环浏览这组图像; to do this, we'll need to make a variable to hold the position in the array.为此,我们需要创建一个变量来保存数组中的位置。

var currentFrame = 0; //Call it a frame because we're making a gif and every image (so every array index) will be a frame
function changePicture(){
    currentFrame++;
}

This should work for now, let's test it:这现在应该有效,让我们测试一下:

 //Set up the array of frames var gifImages = ["https://vignette.wikia.nocookie.net/starpolar/images/9/96/Paul_blart.jpg/revision/latest?cb=20150419171412","https://i.ytimg.com/vi/A5KWYdrOXDk/movieposter.jpg","http://content.tv3.ie/content/images/0647/1_165781.jpg","https://upload.wikimedia.org/wikipedia/en/thumb/4/47/Spongebob-squarepants.svg/1200px-Spongebob-squarepants.svg.png","http://i0.kym-cdn.com/entries/icons/mobile/000/016/958/Dankkkk.jpg"]; var currentFrame = 0; //Call it a frame because we're making a gif and every image (so every array index) will be a frame function changePicture(){ document.getElementById("picture1").src = gifImages[currentFrame]; //Get the gif element and set its source to the current frame currentFrame++; //Increase the current frame by 1 } setInterval(changePicture,1000);
 <!--This is the image that we will change.--> <img id="picture1" src="https://vignette.wikia.nocookie.net/starpolar/images/9/96/Paul_blart.jpg/revision/latest?cb=20150419171412"/>

You should notice 2 things.你应该注意两件事。 The first is that the images have wildly different sizes and length/width ratios, resulting is the image changing size every time.首先是图像的大小和长宽比大不相同,导致图像每次都改变大小。 The second thing you should notice is that when we run out of images, it doesn't loop back.您应该注意的第二件事是,当我们用完图像时,它不会循环返回。 Oops!哎呀! (Side note: I actually made this mistake. Don't be discouraged by mistakes, we all make them!) (旁注:我实际上犯了这个错误。不要因错误而气馁,我们都会犯!)

To remedy the first problem, we can look back to the HTML images documentation and see that there are two properties that can help us: width and height .为了解决第一个问题,我们可以回顾一下HTML 图像文档,看到有两个属性可以帮助我们: widthheight These will lock the image into the specified dimensions.这些会将图像锁定到指定的尺寸。 Frame sizes shouldn't be much of a problem with an actual gif, since the frames would probably all be the same size, but it doesn't hurt to be safe:帧大小对于实际的 gif 应该不是什么大问题,因为帧可能都是相同的大小,但安全一点也不会有什么坏处:

<img id="picture1" width="100px" height="100px" src="https://vignette.wikia.nocookie.net/starpolar/images/9/96/Paul_blart.jpg/revision/latest?cb=20150419171412"/>

The second problem is a bit harder.第二个问题有点难。 But looking through the code, we should be able to spot the bug fairly quickly.但是查看代码,我们应该能够相当快地发现错误。 (Note: An experienced developer such as myself might be able to see a problem like this in a small, simple program almost instantly. Don't be discouraged if you can't; we all started somewhere and becoming a 1337 hax0r comes with time.) (注意:像我这样有经验的开发人员几乎可以立即在一个简单的小程序中看到这样的问题。如果你不能,不要气馁;我们都是从某个地方开始的,随着时间的推移成为 1337 hax0r .)

If we look at how our program operates, we could say it works like this:如果我们看看我们的程序是如何运行的,我们可以说它是这样工作的:

  • Loop forever:永远循环:
    • Set the image to the current frame将图像设置为当前帧
    • Increase the frame增加帧数

It becomes apparent that while we have a limited number of frames, we keep increasing the current one without going back down!很明显,虽然我们的帧数有限,但我们会不断增加当前的帧数而不会退缩! Our progress through the gif would look like this (skipping to every 3rd frame and assuming 10 frames total):我们通过 gif 的进度看起来像这样(跳到每 3 帧并假设总共 10 帧):

|--------- |---------

---|------ ---|------

------|--- -------|---

---------| ---------|

---------- | ---------- | <-- ???? <-- ???? oh no不好了

This can be solved with a simple if statement that resets the current frame to 0 when we go past the end of our gif (line above is also shown for clarity):这可以通过一个简单的if语句来解决,当我们越过 gif 的末尾时,该语句将当前帧重置为 0(为了清晰起见,还显示了上面的行):

currentFrame++; //Increase the current frame by 1
if(currentFrame >= gifImages.length){ //If we've gone past the end of our array of frames, then:
    currentFrame = 0; //Reset back to frame 0
}

With those changes, our gif looks like this:有了这些变化,我们的 gif 看起来像这样:

 //Set up the array of frames var gifImages = ["https://vignette.wikia.nocookie.net/starpolar/images/9/96/Paul_blart.jpg/revision/latest?cb=20150419171412","https://i.ytimg.com/vi/A5KWYdrOXDk/movieposter.jpg","http://content.tv3.ie/content/images/0647/1_165781.jpg","https://upload.wikimedia.org/wikipedia/en/thumb/4/47/Spongebob-squarepants.svg/1200px-Spongebob-squarepants.svg.png","http://i0.kym-cdn.com/entries/icons/mobile/000/016/958/Dankkkk.jpg"]; var currentFrame = 0; //Call it a frame because we're making a gif and every image (so every array index) will be a frame function changePicture(){ document.getElementById("picture1").src = gifImages[currentFrame]; //Get the gif element and set its source to the current frame currentFrame++; //Increase the current frame by 1 if(currentFrame >= gifImages.length){ //If we've gone past the end of our array of frames, then: currentFrame = 0; //Reset back to frame 0 } } setInterval(changePicture,1000);
 <!--This is the image that we will change.--> <img id="picture1" width="100px" height="100px" src="https://vignette.wikia.nocookie.net/starpolar/images/9/96/Paul_blart.jpg/revision/latest?cb=20150419171412"/>

Now all we need to do is get the right frames into the array and speed it up!现在我们需要做的就是将正确的帧放入数组并加快速度! For a real gif, assuming this is a website you're making, the files will probably be named something like gif-frame-1 , gif-frame-2 , gif-frame-3 , etc. Because of this, we can automate making the array, putting it into a for loop:对于真正的 gif,假设这是您正在制作的网站,文件可能会被命名为gif-frame-1gif-frame-2gif-frame-3等。因此,我们可以自动化制作数组,将其放入for循环:

var gifImages = [];
for(var i=0;i<200;i++){ //Change 200 to the number of frames your gif has
    gifImages[i] = "pictures/gif-frame-"+i+".png";
}

That code probably won't work with your website right away-- you have to change around the names of the images and number of frames and things-- but it should help you.该代码可能无法立即与您的网站一起使用——您必须更改图像名称、帧数和内容——但它应该对您有所帮助。 If you specify where these pictures are, how they're named, how many there are, etc. then I could help you more, but I don't have enough information to write that part.如果您指定这些图片的位置、它们的名称、有多少等,那么我可以为您提供更多帮助,但我没有足够的信息来编写该部分。 Also note that this can be sped up about 50 times faster than it's going at the moment, but it looks weird without real frames to be used.另请注意,这可以比目前的速度快约 50 倍,但如果没有使用真正的帧,它看起来很奇怪。 For now, we can consider our final code to be:现在,我们可以认为我们的最终代码是:

 //Set up the array of frames var gifImages = ["https://vignette.wikia.nocookie.net/starpolar/images/9/96/Paul_blart.jpg/revision/latest?cb=20150419171412","https://i.ytimg.com/vi/A5KWYdrOXDk/movieposter.jpg","http://content.tv3.ie/content/images/0647/1_165781.jpg","https://upload.wikimedia.org/wikipedia/en/thumb/4/47/Spongebob-squarepants.svg/1200px-Spongebob-squarepants.svg.png","http://i0.kym-cdn.com/entries/icons/mobile/000/016/958/Dankkkk.jpg"]; var currentFrame = 0; //Call it a frame because we're making a gif and every image (so every array index) will be a frame function changePicture(){ document.getElementById("picture1").src = gifImages[currentFrame]; //Get the gif element and set its source to the current frame currentFrame++; //Increase the current frame by 1 if(currentFrame >= gifImages.length){ //If we've gone past the end of our array of frames, then: currentFrame = 0; //Reset back to frame 0 } } setInterval(changePicture,100);
 <!--This is the image that we will change.--> <img id="picture1" width="100px" height="100px" src="https://vignette.wikia.nocookie.net/starpolar/images/9/96/Paul_blart.jpg/revision/latest?cb=20150419171412"/>

It's possible to touch it up (for example, you could move the function inside the setInterval itself) but this should work fine.可以修改它(例如,您可以将函数移动到setInterval本身内),但这应该可以正常工作。

I hope this answer has helped you to learn how to figure these things out!我希望这个答案能帮助您学习如何解决这些问题!

I ended up just writing a script to replace the image in a div every second.我最终只是编写了一个脚本来每秒替换 div 中的图像。 It's not technically a gif, but it works very similarly.从技术上讲,它不是 gif,但它的工作原理非常相似。

                    eval('var frame' + word + ' = 0;');
                    var bigFrame = 0;
               
                setInterval(function(){ //everysecond
                    var noSpaces = input.replace(/\s/g, '');
    
                        var cLetter = noSpaces[bigFrame];
                        var thisSource = 'media/signs/alphabet/' + cLetter + '.jpeg';
                        $('#video').attr("src", thisSource);
                        $('#video').attr("alt", thisSource);
                        $('#video').attr("height", "350");
    
                        if(bigFrame + 1 >= noSpaces.length){
                            bigFrame = 0;
                        } else{
                            bigFrame = bigFrame +1;
                        }
    
                    for(word = 0; word < wordList.length; word ++){ //for every word
                        var currentFrame = eval('frame' + word);
                        currentWord = wordList[word];
                        currentWord = currentWord.toLowerCase();
                        console.log('current word is ' + currentWord);
                        var letterList = currentWord.split('');
                        var currentLetter = letterList[currentFrame];
                        var currentSource = 'media/signs/alphabet/' + currentLetter + '.jpeg';
                        var currentImage = "#" + eval('"image' + word + '"');
                        $(currentImage).attr("src", currentSource);
                        $(currentImage).attr("alt", currentSource);
                        $(currentImage).attr("height", "200");
                        if(currentFrame + 1 >= letterList.length){
                            eval('frame' + word + ' = 0');
                        } else{
                            eval('frame' + word + ' = currentFrame + 1;');
                        }
                    }
                }, 1000);

I don't know if this is helpful, or even understandable, but it might help someone.我不知道这是否有帮助,甚至可以理解,但它可能对某人有所帮助。 Also, I haven't bothered to edit the code, so there are definitely bits that won't make sense and weird variable names.此外,我没有费心编辑代码,所以肯定有一些没有意义的位和奇怪的变量名。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM