Skip to content
Welcome to vote for your favorite component! You can also tell me anything you want to say! (*´∀`)~♥

Render Glitch Card card

A tribute to the Windows XP window-dragging ghost trail bug.

Usage Examples

Basic Usage

Try dragging the window! ( ´ ▽ ` )ノ

Hello, Windows XP!

Try dragging this window

View example source code
vue
<template>
  <div class="w-full flex flex-col gap-4 py-4">
    <div class="flex items-center justify-center py-[8vh]">
      <card-render-glitch
        v-slot="{ bindHandle }"
        :draggable
        class="window z-50 overflow-hidden border rounded-xl shadow-xl"
      >
        <div
          :ref="bindHandle"
          class="handle w-full flex items-center px-4"
          :class="draggable ? 'cursor-move' : 'cursor-no-drop'"
        >
          <div class="flex-1 select-none text-center text-sm font-medium">
            Hello, Windows XP!
          </div>

          <button class="mb-1 text-2xl">
            ×
          </button>
        </div>

        <div class="flex flex-col gap-2 p-8 px-12">
          <base-checkbox
            v-model="draggable"
            :label="t('enableDrag')"
          />

          <p class="leading-relaxed">
            {{ t('tryDrag') }}
          </p>
        </div>
      </card-render-glitch>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { useI18n } from 'vue-i18n'
import BaseCheckbox from '../../base-checkbox.vue'
import CardRenderGlitch from '../card-render-glitch.vue'

const draggable = ref(true)

const { t } = useI18n()
</script>

<style lang="sass" scoped>
:deep(.window)
  background: light-dark(#FFF, #1e1e1e)
  border-color: light-dark(#d0d0d0, #888)
  color: light-dark(#374151, #d1d5db)
  .handle
    background: light-dark(#f3f4f6, #111827)
    color: light-dark(#1f2937, #d1d5db)
</style>

How It Works

Converts the DOM into an image, then continuously draws the image onto a canvas.

How to convert DOM to Image?

The original implementation idea was to use v-for to generate multiple default slot contents like btn-ninja, but the performance was terrible, so canvas was used instead.

The challenge was: "How to draw DOM onto a canvas? ლ(╹ε╹ლ)"

Both html2canvas and dom-to-image were not ideal. Later, a complete implementation was found in the vfx.js library.

So I copied it over and slightly modified it to fit my needs. ◝( •ω• )◟

Source Code

API

Props

interface Props {
  draggable?: boolean;
  throttle?: number;
}

Methods

interface Expose {
  clearArtifacts: () => void;
}

Slots

interface SlotScope {
  isDragging: boolean;
  /**
   * 用於綁定拖動把手
   * @param el - 要綁定的元素
   */
  bindHandle: (el: any) => void;
}

interface Slots {
  default?: (params: SlotScope) => unknown;
}

v0.60.0