详解JavaScript如何创建一个非自动播放的GIF网络组件
今天,我将向您展示如何创建一个允许您的用户决定是否要播放 gif 的 web 组件!让我们开始吧。
一些很可爱的测试数据
这里用的gif是小骆驼和猫的这种可爱互动:
哇,太可爱了!我可以看一天这个
构建 web 组件
对于这个 web 组件,我们需要一些东西:
- 画布(“缩略图”所在的位置)
- 一张图片(实际的 gif)
- 标有“gif”的标签
- 一些造型
让我们这样做:
const noautoplaygiftemplate = document.createelement('template') noautoplaygiftemplate.innerhtml = ` <style> .no-autoplay-gif { --size: 30px; cursor: pointer; position: relative; } .no-autoplay-gif .gif-label { border: 2px solid #000; background-color: #fff; border-radius: 100%; width: var(--size); height: var(--size); text-align: center; font: bold calc(var(--size) * 0.4)/var(--size) sans-serif; position: absolute; top: calc(50% - var(--size) / 2); left: calc(50% - var(--size) / 2); } .no-autoplay-gif .hidden { display: none; } </style> <div class="no-autoplay-gif"> <canvas /> <span class="gif-label" aria-hidden="true">gif</span> <img class="hidden"> </div>
接下来,我们将创建一个派生自 htmlelement 的类。 此类稍后将包含播放/停止切换行为。
class noautoplaygif extends htmlelement { constructor() { super() // 在此处添加设置 } loadimage() { // 在此处添加渲染 } static get observedattributes() { return ['src', 'alt']; } attributechangedcallback(name, oldval, newval) { if (oldval !== newval || oldval === null) { this.loadimage() } } }
这里还有一些样板:一个空的渲染函数,它将加载图像并显示缩略图,以及一个构造函数和一些特定于 web 组件的方法。
好的,这已经是很多代码了。让我解释。
该loadimage
函数不会自动调用,我们需要自己调用。该函数attributechangedcallback
让我们定义当任何指定属性发生observedattributes
变化时会发生什么。在这种情况下:加载图像并显示它。浏览器大致做的是这样的:
- 遇到 web 组件
- 调用它的构造函数(调用
constructor()
) - 将其属性一一设置为 dom 中的设置(因此,
src="llama.gif"
调用.setattribute('src', 'llama.gif')
-
attributechangedcallback
对每个更改的属性执行
签入构造函数时,这些属性一开始是空的,稍后才会填充。如果我们需要一个或多个属性来实际进行渲染,那么如果我们 知道 这些属性不存在,那么调用该loadimage
函数是没有意义的。所以我们不在构造函数中调用它,但只有在有可能存在属性时才调用它。**
为了完成样板化,让我们将这个类定义为我们的自定义 web 组件:
class noautoplaygif extends htmlelement { // ... } window.customelements.define('no-autoplay-gif', noautoplaygif)
我们现在可以像这样使用这个组件:
<no-autoplay-gif src="..." alt="llama and cat" />
逻辑
有趣的来了。我们需要添加noautoplaygiftemplate
作为组件的shadow dom。src
这已经可以渲染 dom,但是如果没有andalt
属性,我们仍然不能做很多事情。因此我们只从 shadow dom 中收集一些我们稍后需要的元素,并且已经附加了一个单击侦听器来切换启动/停止模式。
class noautoplaygif extends htmlelement { constructor() { super() // 添加 shadow dom this._shadowroot = this.attachshadow({ mode: 'open' }) // 从上面添加模板 this._shadowroot.appendchild( noautoplaygiftemplate.content.clonenode(true) ) // 我们稍后会需要这些 this.canvas = this._shadowroot.queryselector('canvas') this.img = this._shadowroot.queryselector('img') this.label = this._shadowroot.queryselector('.gif-label') this.container = this._shadowroot.queryselector('.no-autoplay-gif') // 使整个东西可点击 this._shadowroot.queryselector('.no-autoplay-gif').addeventlistener('click', () => { this.toggleimage() }) } // ... }
为了不遇到未定义的方法错误,我们还添加了这三个方法:
class noautoplaygif extends htmlelement { // ... toggleimage(force = undefined) { this.img.classlist.toggle('hidden', force) // we need to check for undefined values, as js does a distinction here. // we cannot simply negate a given force value (i.e. hiding one thing and unhiding another) // as an undefined value would actually toggle the img, but // always hide the other two, because !undefined == true this.canvas.classlist.toggle('hidden', force !== undefined ? !force : undefined) this.label.classlist.toggle('hidden', force !== undefined ? !force : undefined) } start() { this.toggleimage(false) } stop() { this.toggleimage(true) } // ... }
start/stop 方法允许我们强制启动或强制停止 gif。理论上,我们现在可以这样做:
const gif = document.queryselector('no-autoplay-gif') gif.start() gif.stop() gif.toggleimage()
最后,我们可以添加图片加载部分。让我们先做一些验证:
class noautoplaygif extends htmlelement { // ... loadimage() { const src = this.getattribute('src') const alt = this.getattribute('alt') if (!src) { console.warn('a source gif must be given') return } if (!src.endswith('.gif')) { console.warn('provided src is not a .gif') return } // more stuff } // ... }
最后一步,我们可以加载图像,设置一些宽度和高度并使用画布:
class noautoplaygif extends htmlelement { // ... loadimage() { // validation this.img.onload = event => { const width = event.currenttarget.width const height = event.currenttarget.height // set width and height of the entire thing this.canvas.setattribute('width', width) this.canvas.setattribute('height', height) this.container.setattribute('style', ` width: ${width}px; height: ${height}px; `) // "draws" the gif onto a canvas, i.e. the first // frame, making it look like a thumbnail. this.canvas.getcontext('2d').drawimage(this.img, 0, 0) } // trigger the loading this.img.src = src this.img.alt = alt } // ... }
我们完成了!
结果
演示地址:haiyong.site/gif
以上就是详解javascript如何创建一个非自动播放的gif网络组件的详细内容,更多关于javascript播放gif的资料请关注其它相关文章!