From fa4a3acb038c80e18f7dcaddf3802b07c04b7d0e Mon Sep 17 00:00:00 2001 From: Arvin Xu Date: Tue, 27 Apr 2021 16:22:04 +0800 Subject: [PATCH] =?UTF-8?q?:bug:=20fix:=20=E4=BF=AE=E6=AD=A3=E6=9E=84?= =?UTF-8?q?=E5=BB=BA=E7=9A=84=20bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/image-gallery/src/utils.ts | 127 ------------------ packages/image-gallery/src/utils/clipboard.ts | 19 +++ packages/image-gallery/src/utils/helper.ts | 17 +++ packages/image-gallery/src/utils/index.ts | 2 + .../src/{utils.test.ts => utils/png.test.ts} | 2 +- packages/image-gallery/src/utils/png.ts | 65 +++++++++ packages/image-gallery/src/utils/svg.ts | 51 +++++++ packages/image-gallery/tsconfig.json | 3 +- .../{types.d.ts => types/index.d.ts} | 0 9 files changed, 157 insertions(+), 129 deletions(-) delete mode 100644 packages/image-gallery/src/utils.ts create mode 100644 packages/image-gallery/src/utils/clipboard.ts create mode 100644 packages/image-gallery/src/utils/helper.ts create mode 100644 packages/image-gallery/src/utils/index.ts rename packages/image-gallery/src/{utils.test.ts => utils/png.test.ts} (75%) create mode 100644 packages/image-gallery/src/utils/png.ts create mode 100644 packages/image-gallery/src/utils/svg.ts rename packages/image-gallery/{types.d.ts => types/index.d.ts} (100%) diff --git a/packages/image-gallery/src/utils.ts b/packages/image-gallery/src/utils.ts deleted file mode 100644 index b26e4bc0..00000000 --- a/packages/image-gallery/src/utils.ts +++ /dev/null @@ -1,127 +0,0 @@ -/* istanbul ignore file */ -import { message } from 'antd'; - -/** - * 利用 Canvas 生成 png dataURL - * @param image - * @param scale 缩放 - */ -const getImageBase64 = (image: HTMLImageElement, scale = 8) => { - const canvas = document.getElementById('canvas') as HTMLCanvasElement; - canvas.width = image.width * scale; - canvas.height = image.height * scale; - - const context = canvas.getContext('2d'); - context?.drawImage(image, 0, 0); - - return canvas.toDataURL('image/png'); -}; - -/** - * 复制 Png 到剪切板 - * @param url - */ -export const copyPngFromSvg = async (url: string) => { - const res = await fetch(url); - const svgBlob = await res.blob(); - const svgUrl = URL.createObjectURL(svgBlob); - - const image = new Image(); - image.src = svgUrl; - - image.onload = async () => { - const { state } = await navigator.permissions.query({ - name: 'clipboard-write', - }); - - // 如果浏览器支持 navigator.clipboard 接口 - // 就使用 write 接口 - if (navigator.clipboard && state === 'granted') { - const result = await fetch(getImageBase64(image, 1)); - await navigator.clipboard.write([ - new ClipboardItem({ 'image/png': await result.blob() }), - ]); - } - // 不然就用降级方案 - else { - // 创建 image 对象 - const img = document.createElement('img'); - img.src = getImageBase64(image); - img.contentEditable = 'true'; - document.body.appendChild(img); - - // 复制 - const selection = window.getSelection(); - const range = document.createRange(); - range.selectNode(img); - selection?.removeAllRanges(); - selection?.addRange(range); - document.execCommand('Copy'); - img.remove(); - } - - message.success('🎉 复制成功!'); - }; -}; - -/** - * 复制 SVG - * @param url - */ -export const copySVG = async (url: string) => { - const res = await fetch(url); - const svgString = await res.text(); - - const input = document.createElement('input'); - document.body.appendChild(input); - input.setAttribute('value', svgString); - input.select(); - if (document.execCommand('copy')) { - document.execCommand('copy'); - message.success('🎉 复制成功!'); - } - document.body.removeChild(input); -}; - -/** - * 下载 SVG - * @param url - * @param title - */ -export const downloadSVG = async (url: string, title: string) => { - const res = await fetch(url); - const svgBlob = await res.blob(); - - const filename = `${title}.svg`; - - const a = document.createElement('a'); - document.body.appendChild(a); // 兼容火狐,将a标签添加到body当中 - - a.href = URL.createObjectURL(svgBlob); - - a.download = filename; - a.target = '_blank'; // a标签增加target属性 - a.click(); - a.remove(); // 移除a标签 -}; - -/** - * 下载 Png - * @param url - * @param title - */ -export const downloadPng = async (url: string, title: string) => { - const res = await fetch(url); - const svgBlob = await res.blob(); - const svgUrl = URL.createObjectURL(svgBlob); - - const image = new Image(); - image.src = svgUrl; - - image.onload = () => { - const a = document.createElement('a'); - a.download = `${title}.png`; - a.href = getImageBase64(image); - a.click(); - }; -}; diff --git a/packages/image-gallery/src/utils/clipboard.ts b/packages/image-gallery/src/utils/clipboard.ts new file mode 100644 index 00000000..1221947f --- /dev/null +++ b/packages/image-gallery/src/utils/clipboard.ts @@ -0,0 +1,19 @@ +/* istanbul ignore file */ + +/** + * 利用 Clipboard 剪切板 + * @param type + * @param blob + */ +export const copyToClipboard = async (type: string, blob: Blob) => { + const { state } = await navigator.permissions.query({ + name: 'clipboard-write', + }); + + const isAllowed = state === 'granted'; + if (navigator.clipboard && isAllowed) { + await navigator.clipboard.write([new ClipboardItem({ [type]: blob })]); + } + + return isAllowed; +}; diff --git a/packages/image-gallery/src/utils/helper.ts b/packages/image-gallery/src/utils/helper.ts new file mode 100644 index 00000000..3d1e66a7 --- /dev/null +++ b/packages/image-gallery/src/utils/helper.ts @@ -0,0 +1,17 @@ +/* istanbul ignore file */ + +/** + * 利用 Canvas 生成 png dataURL + * @param image + * @param scale 缩放 + */ +export const getImageBase64 = (image: HTMLImageElement, scale = 8) => { + const canvas = document.getElementById('canvas') as HTMLCanvasElement; + canvas.width = image.width * scale; + canvas.height = image.height * scale; + + const context = canvas.getContext('2d'); + context?.drawImage(image, 0, 0); + + return canvas.toDataURL('image/png'); +}; diff --git a/packages/image-gallery/src/utils/index.ts b/packages/image-gallery/src/utils/index.ts new file mode 100644 index 00000000..508ad75e --- /dev/null +++ b/packages/image-gallery/src/utils/index.ts @@ -0,0 +1,2 @@ +export * from './svg'; +export * from './png'; diff --git a/packages/image-gallery/src/utils.test.ts b/packages/image-gallery/src/utils/png.test.ts similarity index 75% rename from packages/image-gallery/src/utils.test.ts rename to packages/image-gallery/src/utils/png.test.ts index 13114079..8604ddf2 100644 --- a/packages/image-gallery/src/utils.test.ts +++ b/packages/image-gallery/src/utils/png.test.ts @@ -1,4 +1,4 @@ -import { copyPngFromSvg } from './utils'; +import { copyPngFromSvg } from './png'; describe('copyPng', () => { it('初始值', async () => { diff --git a/packages/image-gallery/src/utils/png.ts b/packages/image-gallery/src/utils/png.ts new file mode 100644 index 00000000..ea56ad53 --- /dev/null +++ b/packages/image-gallery/src/utils/png.ts @@ -0,0 +1,65 @@ +/* istanbul ignore file */ + +import { message } from 'antd'; +import { getImageBase64 } from './helper'; +import { copyToClipboard } from './clipboard'; + +/** + * 复制 Png 到剪切板 + * @param url + */ +export const copyPngFromSvg = async (url: string) => { + const res = await fetch(url); + const svgBlob = await res.blob(); + const svgUrl = URL.createObjectURL(svgBlob); + + const image = new Image(); + image.src = svgUrl; + + image.onload = async () => { + const result = await fetch(getImageBase64(image, 1)); + // 如果浏览器支持 navigator.clipboard 接口 + // 就使用 write 接口 + const isSuccess = await copyToClipboard('image/png', await result.blob()); + // 不然就用降级方案 + if (!isSuccess) { + // 创建 image 对象 + const img = document.createElement('img'); + img.src = getImageBase64(image); + img.contentEditable = 'true'; + document.body.appendChild(img); + + // 复制 + const selection = window.getSelection(); + const range = document.createRange(); + range.selectNode(img); + selection?.removeAllRanges(); + selection?.addRange(range); + document.execCommand('Copy'); + img.remove(); + } + + message.success('🎉 复制成功!'); + }; +}; + +/** + * 下载 Png + * @param url + * @param title + */ +export const downloadPng = async (url: string, title: string) => { + const res = await fetch(url); + const svgBlob = await res.blob(); + const svgUrl = URL.createObjectURL(svgBlob); + + const image = new Image(); + image.src = svgUrl; + + image.onload = () => { + const a = document.createElement('a'); + a.download = `${title}.png`; + a.href = getImageBase64(image); + a.click(); + }; +}; diff --git a/packages/image-gallery/src/utils/svg.ts b/packages/image-gallery/src/utils/svg.ts new file mode 100644 index 00000000..c817d19d --- /dev/null +++ b/packages/image-gallery/src/utils/svg.ts @@ -0,0 +1,51 @@ +/* istanbul ignore file */ + +// import { copyToClipboard } from './clipboard'; +import { message } from 'antd'; + +/** + * 复制 SVG + * @param url + */ +export const copySVG = async (url: string) => { + const res = await fetch(url); + // const svgBlob = await res.text(); + // console.log(svgBlob); + // 如果浏览器支持 navigator.clipboard 接口 + // 就使用 write 接口 + // const isSuccess = await copyToClipboard('text/plain', new Blob([svgBlob], { type: 'text/plain' })); + + // if (!isSuccess) { + const svgString = await res.text(); + const input = document.createElement('input'); + document.body.appendChild(input); + input.setAttribute('value', svgString); + input.select(); + document.execCommand('copy'); + document.body.removeChild(input); + // } + + message.success('🎉 复制成功!'); +}; + +/** + * 下载 SVG + * @param url + * @param title + */ +export const downloadSVG = async (url: string, title: string) => { + const res = await fetch(url); + const svgBlob = await res.blob(); + + const filename = `${title}.svg`; + + const a = document.createElement('a'); + document.body.appendChild(a); // 兼容火狐,将a标签添加到body当中 + + a.href = URL.createObjectURL(svgBlob); + + a.download = filename; + a.target = '_blank'; // a标签增加target属性 + a.click(); + a.remove(); // 移除a标签 +}; diff --git a/packages/image-gallery/tsconfig.json b/packages/image-gallery/tsconfig.json index a8957d2e..2d59716f 100644 --- a/packages/image-gallery/tsconfig.json +++ b/packages/image-gallery/tsconfig.json @@ -11,6 +11,7 @@ /* 模块导入配置项 */ "esModuleInterop": true, "lib": ["ESNext", "DOM"], - "types": ["../../types", "@types/jest", "types"] + "baseUrl": ".", + "types": ["../../types", "@types/jest", "./types"] } } diff --git a/packages/image-gallery/types.d.ts b/packages/image-gallery/types/index.d.ts similarity index 100% rename from packages/image-gallery/types.d.ts rename to packages/image-gallery/types/index.d.ts