今天,我将向您展示如何创建一个允许您的用户决定是否要播放 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的资料请关注编程网其它相关文章!