-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* chore: update html2canvas * docs: screenshot doc init * fix: fix hover icon color * fix: options types * feat: screenshot style * feat: class module screenshot * refactor: change screenshot class to function * feat: add new screenshot option * feat: replace screenshot insert image url * docs: update screenshot * fix: html2canvas get empty image * docs: update options * refactor: options extract * docs: add screenshot upload server demo * fix: the toolbar hover color at snow theme * docs: update image replace logic
- Loading branch information
Showing
14 changed files
with
5,377 additions
and
4,368 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
<script setup lang="ts"> | ||
import { onMounted, ref } from 'vue' | ||
import Html2Canvas from 'html2canvas' | ||
let editor | ||
const editorRef = ref<HTMLElement>() | ||
const TOOLBAR_CONFIG = [ | ||
[{ header: [] }], | ||
['bold', 'italic', 'underline', 'link'], | ||
[{ list: 'ordered' }, { list: 'bullet' }], | ||
['clean'], | ||
['screenshot'], | ||
] | ||
// to solve html2canvas get image empty | ||
const imgToBase64 = (imageUrl: string) => new Promise<string>((resolve, reject) => { | ||
let canvas = document.createElement('canvas') | ||
let img = new Image() | ||
img.crossOrigin = 'Anonymous' | ||
img.src = imageUrl | ||
img.onload = function () { | ||
const ctx = canvas.getContext('2d') | ||
if (ctx) { | ||
canvas.height = img.height | ||
canvas.width = img.width | ||
ctx.clearRect(0, 0, canvas.width, canvas.height) | ||
ctx.drawImage(img, 0, 0) | ||
const dataURL = canvas.toDataURL('image/png', 1) | ||
resolve(dataURL) | ||
} | ||
} | ||
img.onerror = function () { | ||
reject(new Error('Could not load image at ' + imageUrl)) | ||
} | ||
}) | ||
onMounted(() => { | ||
// ssr compat, reference: https://vitepress.dev/guide/ssr-compat#importing-in-mounted-hook | ||
import('@opentiny/fluent-editor').then((module) => { | ||
const FluentEditor = module.default | ||
if (!editorRef.value) return | ||
editor = new FluentEditor(editorRef.value, { | ||
theme: 'snow', | ||
modules: { | ||
toolbar: TOOLBAR_CONFIG, | ||
}, | ||
screenshot: { | ||
Html2Canvas, | ||
onclone: async (doc: Document) => { | ||
const imgs = doc.querySelectorAll('img') | ||
const promises = Array.from(imgs).map(async (img) => { | ||
img.src = await imgToBase64(img.src) | ||
}) | ||
await Promise.all(promises) | ||
}, | ||
}, | ||
}) | ||
}) | ||
}) | ||
</script> | ||
|
||
<template> | ||
<div ref="editorRef" /> | ||
</template> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
<script setup lang="ts"> | ||
import { onMounted, ref } from 'vue' | ||
import Html2Canvas from 'html2canvas' | ||
let editor | ||
const editorRef = ref<HTMLElement>() | ||
const TOOLBAR_CONFIG = [ | ||
[{ header: [] }], | ||
['bold', 'italic', 'underline', 'link'], | ||
[{ list: 'ordered' }, { list: 'bullet' }], | ||
['clean'], | ||
['screenshot'], | ||
] | ||
// to solve html2canvas get image empty | ||
const imgToBase64 = (imageUrl: string) => new Promise<string>((resolve, reject) => { | ||
let canvas = document.createElement('canvas') | ||
let img = new Image() | ||
img.crossOrigin = 'Anonymous' | ||
img.src = imageUrl | ||
img.onload = function () { | ||
const ctx = canvas.getContext('2d') | ||
if (ctx) { | ||
canvas.height = img.height | ||
canvas.width = img.width | ||
ctx.clearRect(0, 0, canvas.width, canvas.height) | ||
ctx.drawImage(img, 0, 0) | ||
const dataURL = canvas.toDataURL('image/png', 1) | ||
resolve(dataURL) | ||
} | ||
} | ||
img.onerror = function () { | ||
reject(new Error('Could not load image at ' + imageUrl)) | ||
} | ||
}) | ||
onMounted(() => { | ||
// ssr compat, reference: https://vitepress.dev/guide/ssr-compat#importing-in-mounted-hook | ||
import('@opentiny/fluent-editor').then((module) => { | ||
const FluentEditor = module.default | ||
if (!editorRef.value) return | ||
editor = new FluentEditor(editorRef.value, { | ||
theme: 'snow', | ||
modules: { | ||
toolbar: TOOLBAR_CONFIG, | ||
}, | ||
screenshot: { | ||
Html2Canvas, | ||
onclone: async (doc: Document) => { | ||
const imgs = doc.querySelectorAll('img') | ||
const promises = Array.from(imgs).map(async (img) => { | ||
img.src = await imgToBase64(img.src) | ||
}) | ||
await Promise.all(promises) | ||
}, | ||
beforeCreateImage(canvas) { | ||
return new Promise((resolve) => { | ||
canvas.toBlob( | ||
(data: Blob | null) => { | ||
if (!data) return | ||
const file = new File([data], `screenshot.png`, { type: 'image/jpeg' }) | ||
// here can upload file to server. demo just use setTimeout to simulate | ||
setTimeout(() => { | ||
// return the final image url | ||
resolve('https://res.hc-cdn.com/tiny-vue-web-doc/3.18.9.20240902190525/static/images/mountain.png') | ||
}, 1000) | ||
}, | ||
'image/png', | ||
1, | ||
) | ||
}) | ||
}, | ||
}, | ||
}) | ||
}) | ||
}) | ||
</script> | ||
|
||
<template> | ||
<div ref="editorRef" /> | ||
</template> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
# 截屏 | ||
|
||
截屏功能依赖 [`html2canvas`](https://github.com/niklasvh/html2canvas),请自行导入 | ||
|
||
初始化编辑器前请将变量 `Html2Canvas` 暴露在 `window` 上。模块化项目可将导入变量整体传入选项 | ||
|
||
## 基础使用 | ||
|
||
:::demo src=demos/screenshot/base.vue | ||
::: | ||
|
||
## 上传截图 | ||
|
||
可通过在 `beforeCreateImage` 中处理截屏图片,进行上传获取其他操作,最终返回显示的图片 url | ||
|
||
:::demo src=demos/screenshot/upload.vue | ||
::: | ||
|
||
## options | ||
|
||
可传递 html2canvas 支持的配置选项, 具体请查看[官方文档](https://html2canvas.hertzen.com/configuration) | ||
|
||
除 html2canvas 支持的配置选项外,还支持以下配置 | ||
|
||
| 名称 | 类型 | 说明 | 默认值 | | ||
| ---------------------- | ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------ | ------ | | ||
| Html2Canvas | `html2canvas` | html2canvas 模块 | - | | ||
| beforeCreateCanvas | `() => void` | canvas 绘制前执行函数, 可在此阶段对页面 dom 进行处理 | - | | ||
| beforeCreateImage | `(canvas: HTMLCanvasElement) => HTMLCanvasElement \| string` | canvas 绘制完成后执行函数, 可通过返回字符串作为最终生成图片的 url 路径, 否则默认生成 base64 作为图片 url. 也可对 canvas 绘制进行调整 | - | | ||
| useCORS | `boolean` | html2canvas 配置选项 | `true` | | ||
| foreignObjectRendering | `boolean` | html2canvas 配置选项 | `true` | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
|
||
.ql-screenshot{ | ||
&-wrapper { | ||
--ql-screenshot-color-bg: rgba(0, 0, 0, 0.5); | ||
--ql-screenshot-color-confirm: #2196F3; | ||
--ql-screenshot-color-cancel: #ef1749; | ||
|
||
.ql-screenshot-cancel, | ||
.ql-screenshot-confirm { | ||
position: relative; | ||
height: 16px; | ||
width: 16px; | ||
cursor: pointer; | ||
} | ||
.ql-screenshot-confirm { | ||
background-color: var(--ql-screenshot-color-confirm); | ||
&::after { | ||
content: ''; | ||
position: absolute; | ||
left: 6px; | ||
top: 3px; | ||
width: 5px; | ||
height: 10px; | ||
border: solid #fff; | ||
border-width: 0 3px 3px 0; | ||
transform: rotate(45deg); | ||
} | ||
} | ||
.ql-screenshot-cancel { | ||
background-color: var(--ql-screenshot-color-cancel); | ||
&::after { | ||
content: ''; | ||
position: absolute; | ||
left: 7px; | ||
top: 2px; | ||
width: 2px; | ||
height: 12px; | ||
border: solid #fff; | ||
border-width: 0 3px 3px 0; | ||
transform: rotate(45deg); | ||
} | ||
&::before { | ||
content: ''; | ||
position: absolute; | ||
left: 7px; | ||
top: 2px; | ||
width: 2px; | ||
height: 12px; | ||
border: solid #fff; | ||
border-width: 0 3px 3px 0; | ||
transform: rotate(-45deg); | ||
} | ||
} | ||
} | ||
&-mask { | ||
position: fixed; | ||
inset: 0; | ||
background-color: var(--ql-screenshot-color-bg); | ||
z-index: 50; | ||
|
||
} | ||
&-cutter { | ||
position: fixed; | ||
border: 1px solid #fff; | ||
z-index: 50; | ||
} | ||
&-coordinate, | ||
&-done { | ||
position: absolute; | ||
bottom: 0; | ||
right: 0; | ||
font-size: 14px; | ||
white-space: nowrap; | ||
} | ||
&-done { | ||
display: flex; | ||
border-top: 1px solid #333; | ||
border-left: 1px solid #333; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.