Astro Component - Ixmage

Component - Out of this world imaging.

astroixmage

I discovered Astro recently and fell in love with it. Sorry Nuxt.js.

I re-did a marketing website ixmage.com and went away from Nuxt.js, which was giving me SPA behavior and required ”enhancing” it with multiple add-ons to make it behave like a normal website.

Because the site was mainly Vue, and is not very big, it took me like 2 days to convert over to Astro.

Pre-requisites

Intention

Original image

I grabbed this image from unsplash.com and searched for pokemon, it is 2.5 MB in size, with dimensions of 5184x3456. I have placed it here with a width="300"

Unsplash also uses dynamic imaging on their site so they are not actually showing originals.

<img src="https://images.unsplash.com/photo-1596743343697-bd2c1e5a8c81" width="300" />



Using the original image, and telling the browser to display it at 300px width. This will download the 2.5MB image. The original image is of type image/jpeg.

Optimized Image

Using the same src, but with the Ixmage component

<Ixmage src="https://images.unsplash.com/photo-1596743343697-bd2c1e5a8c81" width="300" token="TQKkCpGYGK" />



Requesting the same image, but leveraging the ixmage service. Because I am using Microsoft Edge browser, the image came back as image/webp. The image size is 8.6 kB.

<Ixmage src="https://images.unsplash.com/photo-1596743343697-bd2c1e5a8c81" width="300" format="jpg" token="..." />



Above, explicitly requesting the image to be image/jpg comes back in a size of 11.9 kB.

Ixmage Component

Version 1.0 is done in vue.
It does not require client-side interactivity so no vue javascript is bundled.

The ixmage service brings into play a CDN, and the image optimization processing. Ixmage will also choose to deliver a webp image when the browser hints its capabilities, but this can be overriden by explicitly asking for a format.

<template>
  <img :src="theurl" :width="width" :height="height" :alt="alt" :title="title||alt||''" />
</template>

<script>
export default {
  props: {
    token: { type: String, required: true },
    src: { type: String, required: true },
    alt: { type: String, required: false },
    width: { type: String, required: false },
    height: { type: String, required: false },
    title: { type: String, required: false },
    bgc: { type: String, default: 'transparent' },
    format: { type: String, default: '' },
    flip: { type: Boolean, default: false },
    flop: { type: Boolean, default: false },
    quality: { type: Number, default: 0 },
    behavior: { type: String, default: '' },
    allowenl: { type: Boolean, default: false },
    sharpen: { type: Boolean, default: false },
    dpr: { type: Number, required: false },
    pixelate: { type: Number, default: 0 },
    blur: { type: Number, default: 0 },
    brightness: { type: Number, default: 0 },
    hue: { type: Number, default: 0 },
    saturation: { type: Number, default: 0 },
    sepia: { type: Number, default: 0 },
    grayscale: { type: Boolean, default: false },
  },
  data () {
    return {
      baseUri: 'https://cdn.ixmage.com/v2/'
    };
  },
  computed: {
    theurl () {
      let xfs = '?v=1';
      if (this.width) xfs += `&w=${this.width}`;
      if (this.height) xfs += `&h=${this.height}`;
      if (this.format) xfs += `&f=${this.format}`;
      if (this.format.toLowerCase() === 'jpg') xfs += '&fmt=jpg';
      if (this.format.toLowerCase() === 'png') xfs += '&fmt=png';
      if (this.format.toLowerCase() === 'gif') xfs += '&fmt=gif';
      if (this.format.toLowerCase() === 'webp') xfs += '&fmt=webp';
      if (this.allowenl) xfs += `&allowenl=1`;
      if (this.sharpen) xfs += `&sharp=1`;
      if (this.flip) xfs += `&flip=1`;
      if (this.flop) xfs += `&flop=1`;
      if (this.quality) xfs += `&q=${this.quality}`;
      if (this.behavior.toLowerCase() === 'extend') xfs += `&extend=1`;
      if (this.behavior.toLowerCase() === 'cover') xfs += `&cover=1`;
      if (this.dpr) xfs += `&dpr=${this.dpr}`;
      if (this.pixelate && this.pixelate !== '0') xfs += `&pixelate=${this.pixelate}`;
      if (this.blur && this.blur !== '0') xfs += `&blur=${this.blur}`;
      if (this.brightness) xfs += `&mod=${this.brightness}`;
      if (this.hue) xfs += `&hue=${this.hue}`;
      if (this.saturation) xfs += `&sat=${this.saturation}`;
      if (this.sepia) xfs += `&sepia=${this.sepia}`;
      if (this.grayscale) xfs += `&grey=1`;
      xfs += `&bgc=${this.bgc}`;
      return this.baseUri + this.token + '/' + this.src + xfs;
    }
  }
}
</script>

Template

The template portion is just an img tag and its main attributes.

A later version will make it a bit more complex to allow setting a source set to specify a list of sizes so the browser can pick the best one for the situation.

Script

The script portion defines the exposed properties to work on the image. Then, it has the logic to build the image src url that will be used.

Usage

Once you’ve pasted the component code above into /src/components/Ixmage.vue you can then use it in your astro files like:

---
import Ixmage from './../components/Ixmage.vue';
---
<Ixmage src="url-to-image" width="300" token="TtAaCcOoSs" />

The token you will grab from your ixmage account.

Once you familiarize yourself with how ixmage accesses your images, you could mount an alias onto your domain. Let’s say you name the alias my-images and you have an image at https://my-domain.com/my-logo.png, then you could access the image like:

<Ixmage src="/my-images/my-logo.png" token="..." />

and the generated url would be https://cdn.ixmage.com/v2/<token>/my-images/my-logo.png

Basic properties

prop info
token required Your ixmage account token.
src required url to your image.
width Image width, for both the image and the browser.
height Image height, for both the image and the browser.
alt Alt Text.

Less important properties

prop info
title Caption for the img tag title; used as alt text when alt text not supplied.
bgc Background color for the image in case padding is needed. Defaults to transparent
format In case you need your image in this format, else the format will be set automatically depending on the requesting browser capabilites.
quality Set the quality percentage for JPG or WEBP.
behavior Allowed values are extend and cover
allowenl Allow the image to grow more than its original size.
dpr

Effect properties

prop info
flip Vertical mirror reflection of the image.
flop Horizontal mirror reflection of the image.
sharpen Sharpen the resulting image; may enhance the image when the resizing is very drastic.
pixelate Pixelation effect
blur Blur effect
brightness Adjust image brightness
hue Adjust image hue
saturation Adjust image saturation
sepia Sepia effect
grayscale Grayscale effect


Reactions:  

Back to Post List