forked from vueuse/vueuse
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.ts
132 lines (120 loc) · 4.03 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
import type { Ref } from 'vue-demi'
import { isRef, ref, unref, watch } from 'vue-demi'
import type { MaybeRef } from '@vueuse/shared'
import { isClient } from '@vueuse/shared'
import { getDefaultSerialization } from './serialization'
export interface ToDataURLOptions {
/**
* MIME type
*/
type?: string | undefined
/**
* Image quality of jpeg or webp
*/
quality?: any
}
export interface UseBase64ObjectOptions<T> {
serializer: (v: T) => string
}
export interface UseBase64Return {
base64: Ref<string>
promise: Ref<Promise<string>>
execute: () => Promise<string>
}
export function useBase64(target: MaybeRef<string>): UseBase64Return
export function useBase64(target: MaybeRef<Blob>): UseBase64Return
export function useBase64(target: MaybeRef<ArrayBuffer>): UseBase64Return
export function useBase64(target: MaybeRef<HTMLCanvasElement>, options?: ToDataURLOptions): UseBase64Return
export function useBase64(target: MaybeRef<HTMLImageElement>, options?: ToDataURLOptions): UseBase64Return
export function useBase64<T extends Record<string, unknown>>(target: MaybeRef<T>, options?: UseBase64ObjectOptions<T>): UseBase64Return
export function useBase64<T extends Map<string, unknown>>(target: MaybeRef<T>, options?: UseBase64ObjectOptions<T>): UseBase64Return
export function useBase64<T extends Set<unknown>>(target: MaybeRef<T>, options?: UseBase64ObjectOptions<T>): UseBase64Return
export function useBase64<T>(target: MaybeRef<T[]>, options?: UseBase64ObjectOptions<T[]>): UseBase64Return
export function useBase64(
target: any,
options?: any,
) {
const base64 = ref('')
const promise = ref() as Ref<Promise<string>>
function execute() {
if (!isClient)
return
promise.value = new Promise<string>((resolve, reject) => {
try {
const _target = unref(target)
if (_target == null) {
resolve('')
}
else if (typeof _target === 'string') {
resolve(blobToBase64(new Blob([_target], { type: 'text/plain' })))
}
else if (_target instanceof Blob) {
resolve(blobToBase64(_target))
}
else if (_target instanceof ArrayBuffer) {
resolve(window.btoa(String.fromCharCode(...new Uint8Array(_target))))
}
else if (_target instanceof HTMLCanvasElement) {
resolve(_target.toDataURL(options?.type, options?.quality))
}
else if (_target instanceof HTMLImageElement) {
const img = _target.cloneNode(false) as HTMLImageElement
img.crossOrigin = 'Anonymous'
imgLoaded(img).then(() => {
const canvas = document.createElement('canvas')
const ctx = canvas.getContext('2d')!
canvas.width = img.width
canvas.height = img.height
ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
resolve(canvas.toDataURL(options?.type, options?.quality))
}).catch(reject)
}
else if (typeof _target === 'object') {
const _serializeFn = options?.serializer || getDefaultSerialization(_target)
const serialized = _serializeFn(_target)
return resolve(blobToBase64(new Blob([serialized], { type: 'application/json' })))
}
else {
reject(new Error('target is unsupported types'))
}
}
catch (error) {
reject(error)
}
})
promise.value.then(res => base64.value = res)
return promise.value
}
if (isRef(target))
watch(target, execute, { immediate: true })
else
execute()
return {
base64,
promise,
execute,
}
}
function imgLoaded(img: HTMLImageElement) {
return new Promise<void>((resolve, reject) => {
if (!img.complete) {
img.onload = () => {
resolve()
}
img.onerror = reject
}
else {
resolve()
}
})
}
function blobToBase64(blob: Blob) {
return new Promise<string>((resolve, reject) => {
const fr = new FileReader()
fr.onload = (e) => {
resolve(e.target!.result as string)
}
fr.onerror = reject
fr.readAsDataURL(blob)
})
}