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

详解JavaScript如何创建一个非自动播放的GIF网络组件的更多相关文章

  1. 基于JavaScript编写一个图片转PDF转换器

    本文为大家介绍了一个简单的 JavaScript 项目,可以将图片转换为 PDF 文件。你可以从本地选择任何一张图片,只需点击一下即可将其转换为 PDF 文件,感兴趣的可以动手尝试一下

  2. HTML5数字输入仅接受整数的实现代码

    这篇文章主要介绍了HTML5数字输入仅接受整数的实现代码,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  3. amaze ui 的使用详细教程

    这篇文章主要介绍了amaze ui 的使用详细教程,本文通过多种方法给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  4. html5简介_动力节点Java学院整理

    这篇文章主要介绍了html5简介,用于指定构建网页的元素,这些元素中的大多数都用于描述网页内容,有兴趣的可以了解一下

  5. ios 8 Homescreen webapp,关闭和打开iPad停止javascript

    我有一个适用于iPad的全屏HTML5网络应用程序,并且刚刚安装了IOS8来试用它,它一切正常,直到你关闭并重新启动iPad.一旦web应用程序重新启动javascript就会停止并加载新页面不会重新启动它.在iPad上的Safari中打开同一页面时,关闭和打开iPad会继续按预期工作.其他人注意到了这个或想出了一个解决方案吗?解决方法这似乎是我在iOS8.1.1更新中解决的.

  6. iOS 6 javascript与object.defineProperty的间歇性问题

    当访问使用较新的Object.defineProperty语法定义属性的对象的属性时,有没有其他人注意到新iOS6javascript引擎中的间歇性错误/问题?https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/defineProperty我正在看到javascript失败的情况,说

  7. ios – 如何使用JSExport导出内部类的方法

    解决方法似乎没有办法将内部类函数导出到javascript.我将内部类移出并创建了独立的类,它起作用了.

  8. 静音iOS推送通知与React Native应用程序在后台

    我有一个ReactNative应用程序,我试图获得一个发送到JavaScript处理程序的静默iOS推送通知.我看到的行为是AppDelegate中的didReceiveRemoteNotification函数被调用,但是我的JavaScript中的处理程序不会被调用,除非应用程序在前台,或者最近才被关闭.我很困惑的事情显然是应用程序正在被唤醒,并且它的didReceiveRemoteNotifi

  9. ios – 内存泄漏与UIWebView和Javascript

    清楚地包含一个Javascript文件到我的HTML是使UIWebView泄漏内存.当我重复使用相同的UIWebView对象时,或者每当我有内容实例化一个新的漏洞时,会出现泄漏的事实,导致我认为必须有一些JavaScript文件被loadHTMLString处理,导致泄漏.有人知道如何解决这个问题吗?

  10. iOS应用程序的UI自动化测试如何与乐器和Javascript

    从WWDC2010视频会议中了解iOS应用程序的自动化UI测试,但没有实践.从代码项目project,我们可以有一个例子.这个问题在这里听到有涉及这个的人.任何限制?解决方法我建议从AlexWollmer开始使用thisblogpost.他创建了一个非常有用的JavaScript库:tuneup_jswithtest()函数,它允许测试分离和有用的帮助者以及为自动化仪器编写测试的断言.

随机推荐

  1. js中‘!.’是什么意思

  2. Vue如何指定不编译的文件夹和favicon.ico

    这篇文章主要介绍了Vue如何指定不编译的文件夹和favicon.ico,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  3. 基于JavaScript编写一个图片转PDF转换器

    本文为大家介绍了一个简单的 JavaScript 项目,可以将图片转换为 PDF 文件。你可以从本地选择任何一张图片,只需点击一下即可将其转换为 PDF 文件,感兴趣的可以动手尝试一下

  4. jquery点赞功能实现代码 点个赞吧!

    点赞功能很多地方都会出现,如何实现爱心点赞功能,这篇文章主要为大家详细介绍了jquery点赞功能实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  5. AngularJs上传前预览图片的实例代码

    使用AngularJs进行开发,在项目中,经常会遇到上传图片后,需在一旁预览图片内容,怎么实现这样的功能呢?今天小编给大家分享AugularJs上传前预览图片的实现代码,需要的朋友参考下吧

  6. JavaScript面向对象编程入门教程

    这篇文章主要介绍了JavaScript面向对象编程的相关概念,例如类、对象、属性、方法等面向对象的术语,并以实例讲解各种术语的使用,非常好的一篇面向对象入门教程,其它语言也可以参考哦

  7. jQuery中的通配符选择器使用总结

    通配符在控制input标签时相当好用,这里简单进行了jQuery中的通配符选择器使用总结,需要的朋友可以参考下

  8. javascript 动态调整图片尺寸实现代码

    在自己的网站上更新文章时一个比较常见的问题是:文章插图太宽,使整个网页都变形了。如果对每个插图都先进行缩放再插入的话,太麻烦了。

  9. jquery ajaxfileupload异步上传插件

    这篇文章主要为大家详细介绍了jquery ajaxfileupload异步上传插件,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. React学习之受控组件与数据共享实例分析

    这篇文章主要介绍了React学习之受控组件与数据共享,结合实例形式分析了React受控组件与组件间数据共享相关原理与使用技巧,需要的朋友可以参考下

返回
顶部