在Javascript中从多个图像制作GIF,没有任何库



有没有办法在没有任何库的情况下在Javascript中制作GIF?我搜索了一半的互联网,但一无所获。

给潜在反对者的说明

我知道这是一个低质量的问题。但是,我认为不回答的通常理由已被取消。鉴于距离被问到已经快一个月了,我怀疑我会做他们的功课,因为此时可能已经过期了几周。至于他们没有花时间自己研究这个问题,我正在通过教他们如何研究它来解决问题。

请注意,我回答这个问题时假设您知道一些Javascript,但不是全部,并且您想学习如何编写您可能还不知道该怎么做的代码。如果您只是在寻找解决方案,请随时复制粘贴它或其他任何内容。但是通读这篇文章并了解我用来解决这个问题的过程,比如如何思考和查找问题,将在未来对你有所帮助。如果你学会了如何学习,你会变得更好。

现在,首先,我们需要一种显示图像的方法。我从经验中知道有两种主要方法可以做到这一点。一个涉及使用画布元素绘制图像;这是更复杂的方法。方法 2 使用图像标记,<img>。我认为这是您想要的方法。如果你不知道如何使用HTML和Javascript绘制图像,一个简单的谷歌搜索(这是另一个)可以解决这个问题。(实际上,第二个主要返回 canvas 方法 - 但您可能已经知道图像标签了。

接下来,我们需要一种方法来更改显示的图像。好吧,这应该像更改告诉图像首先显示的内容一样简单。第一个示例搜索的顶部结果是一个不错的文档页面 - 完美。通读,我得到了这一部分:

HTML 图像语法

在 HTML 中,图像是使用标记定义的。

该标记为空,它仅包含属性,并且没有结束标记。

src 属性指定图像的 URL(网址):

<img src="url">

好吧,这看起来像是控制图像是什么。因此,我们只需要制作一个定期更改此属性的 Javascript 脚本。要做到这一点,我们需要一个等待指定时间的 JS 方法。在谷歌中搜索"javascript wait",我看到第二个结果来自告诉我图像的同一源网页,所以我会选择那个。在文档中,我看到这个:

setInterval() 方法

setInterval() 方法在每个给定的时间间隔重复给定的函数。

window.setInterval(function, milliseconds);

window.setInterval() 方法可以在没有窗口前缀的情况下编写。

第一个参数是要执行的函数。

第二个参数指示每次执行之间的时间间隔长度。

(它甚至举了一个例子!

这似乎是我们想要的。使用这种方法,我可以制作一个简单的代码,每秒在两个图像之间切换(右侧的解释性注释,滚动以更好地查看它们):

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"/>

现在,这是一个好的开始 - 我们可以在2个不同的完全随机图像之间切换。

但我们需要更多。我们不想手动编写每个新图像;我们需要的是一个数组。通过搜索很难知道这一点,但是如果您参加过入门课程或自己学习了一些JS,那么您应该非常熟悉数组,并且可能会意识到它们在这里是一个不错的选择。因此,我们设置了包含我们希望它在其之间更改的所有图像的数组(向右滚动以查看全部):

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(){
currentFrame++;
}

这现在应该有效,让我们测试一下:

//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"/>

你应该注意到两件事。首先是图像的大小和长/宽比差异很大,导致图像每次的大小都会发生变化。您应该注意的第二件事是,当我们用完图像时,它不会循环回来。哎呀!(旁注:我实际上犯了这个错误。不要因错误而气馁,我们都会犯错误!

为了解决第一个问题,我们可以回顾一下HTML图像文档,发现有两个属性可以帮助我们:widthheight.这些会将图像锁定到指定的尺寸。对于实际的 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"/>

第二个问题有点难。但是查看代码,我们应该能够相当快地发现错误。(注意:像我这样经验丰富的开发人员可能几乎可以立即在一个小而简单的程序中看到这样的问题。如果你做不到,不要气馁;我们都是从某个地方开始的,随着时间的推移,成为 1337 HAX0R。

如果我们看一下我们的程序是如何运作的,我们可以说它的工作原理是这样的:

  • 永远循环:
    • 将图像设置为当前帧
    • 增加框架

很明显,虽然我们的帧数量有限,但我们不断增加当前帧而不会回落!我们通过 gif 的进度如下所示(跳到每 3 帧并假设总共 10 帧):

|---------

---|------

------|---

---------|

---------- | <-- ????哦不

这可以通过一个简单的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
}

通过这些更改,我们的 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"/>

现在我们需要做的就是将正确的帧放入阵列并加快速度!对于真正的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";
}

该代码可能不会立即与您的网站一起使用 - 您必须更改图像的名称以及帧数和事物 - 但它应该对您有所帮助。如果你指定这些图片在哪里,它们是如何命名的,有多少张等等,那么我可以帮你更多,但我没有足够的信息来写那部分。另请注意,这可以比目前快 50 倍左右,但如果没有使用真正的帧,它看起来很奇怪。现在,我们可以将最终代码视为:

//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"/>

可以对其进行修饰(例如,您可以将函数移动到setInterval本身),但这应该可以正常工作。

我希望这个答案能帮助你学习如何弄清楚这些事情!

我最终只是编写了一个脚本来每秒替换div 中的图像。从技术上讲,它不是 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);

我不知道这是否有帮助,甚至是可以理解的,但它可能会帮助某人。另外,我没有费心编辑代码,所以肯定有一些没有意义的部分和奇怪的变量名称。

最新更新