Skip to content

Latest commit

 

History

History
104 lines (94 loc) · 2.77 KB

image-filters.md

File metadata and controls

104 lines (94 loc) · 2.77 KB

Image Filters

image-filter-view.js

export default class ImageFilterView extends HTMLElement {
  constructor() {
    super()
    this.attachShadow({mode: 'open'})
    this.imageEl = document.createElement('img')
    this.imageEl.src = this.dataUrl
    this.radioListEl = document.createElement('div')
    this.radioListEl.append(...['no filter', 'sepia', 'grayscale', 'blur'].map(name => {
      const label = document.createElement('label')
      const el = document.createElement('input')
      el.name = 'filter'
      el.type = 'radio'
      el.value = name
      if (name === 'no filter') {
        el.checked = true
      }
      el.addEventListener('change', (e) => {
        if (!this.imageStyle) {
          this.imageStyle = document.createElement('style')
          this.imageStyle.textContent = ''
          this.shadowRoot.append(this.imageStyle)
        }
        if (e.target.value === 'no filter') {
          this.imageStyle.textContent = ''
        } else if (e.target.value === 'sepia') {
          this.imageStyle.textContent = 'img { filter: sepia(.7) }'
        } else if (e.target.value === 'grayscale') {
          this.imageStyle.textContent = 'img { filter: grayscale(1) }'
        } else if (e.target.value === 'blur') {
          this.imageStyle.textContent = 'img { filter: blur(3px) }'
        } 
      })
      label.append(el, name)
      return label
    }))
    this.shadowRoot.append(this.imageEl, this.radioListEl)
  }

  connectedCallback() {
    const globalStyle = document.createElement('style')
    globalStyle.textContent = `
      body {
        margin: 0;
        padding: 0;
        color: rgb(191, 207, 205);
      }
    `
    document.head.append(globalStyle)
    const style = document.createElement('style')
    style.textContent = `
      :host {
        display: flex;
        height: 100vh;
        flex-direction: column;
        align-items: center;
        justify-content: space-around;
      }
    `
    this.shadowRoot.append(style)
  }

  get dataUrl() {
    for (const block of readBlocksWithNames(__source)) {
      if (block.name === 'image.png') {
        const data = __source.slice(...block.contentRange)
        return `data:image/png;base64,${data}`
      }
    }
  }
}

customElements.define('image-filter-view', ImageFilterView)

app.js

async function setup() {
  const imageFilterView = document.createElement('image-filter-view')
  document.body.replaceChildren(imageFilterView)
}

await setup()

thumbnail.svg

<svg viewBox="0 0 128 128" xmlns="http://www.w3.org/2000/svg">
  <style>
    svg {
      filter: sepia(.7);  // filters on more specific elemtns are not showing in Safari
    }
  </style>
  <g transform="scale(1.4)">
    <image href="${image('image.png.md/image.png')}" width="128" height="128" />
  </g>
</svg>