|
@@ -29,7 +29,7 @@ if (!window.OffscreenCanvas) {
|
|
|
}
|
|
|
|
|
|
const preset: any = presets.offscreen()
|
|
|
-const blobToBase64 = (blob: any) => {
|
|
|
+export const blobToBase64 = (blob: any) => {
|
|
|
return new Promise(resolve => {
|
|
|
const reader = new FileReader()
|
|
|
reader.onloadend = () => resolve(reader.result)
|
|
@@ -37,32 +37,24 @@ const blobToBase64 = (blob: any) => {
|
|
|
})
|
|
|
}
|
|
|
|
|
|
-// export const svgtopng = async (svg: any, width: any, height: any) => {
|
|
|
-// // eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
|
-// // @ts-ignore
|
|
|
-// const canvas = new OffscreenCanvas(width, height)
|
|
|
-// const ctx = canvas.getContext("2d")!
|
|
|
-// const v = await Canvg.fromString(ctx!, svg, preset)
|
|
|
-
|
|
|
-// /**
|
|
|
-// * Resize SVG to fit in given size.
|
|
|
-// * @param width
|
|
|
-// * @param height
|
|
|
-// * @param preserveAspectRatio
|
|
|
-// */
|
|
|
-// v.resize(width * 2, height * 2, "xMidYMid meet")
|
|
|
-
|
|
|
-// // Render only first frame, ignoring animations and mouse.
|
|
|
-// await v.start()
|
|
|
-// const blob = await canvas.convertToBlob()
|
|
|
-// const base64 = await blobToBase64(blob)
|
|
|
-// return base64
|
|
|
-// }
|
|
|
+export const addMusicTitle = (canvas: any, title: any) => {
|
|
|
+ canvas.getContext("2d")
|
|
|
+ const water = document.createElement("canvas")
|
|
|
+
|
|
|
+ // 小水印画布大小
|
|
|
+ water.width = canvas.width
|
|
|
+ water.height = canvas.height + 120
|
|
|
+ const waterCtx = water.getContext("2d") as CanvasRenderingContext2D
|
|
|
+ waterCtx.font = `66pt Calibri`
|
|
|
+ waterCtx.fillStyle = "#000"
|
|
|
+ waterCtx.textAlign = "center"
|
|
|
+ waterCtx.drawImage(canvas, 0, 40)
|
|
|
+ waterCtx.fillText(title, canvas.width / 2, 160)
|
|
|
+ return water
|
|
|
+}
|
|
|
|
|
|
let canvas = null as any
|
|
|
-export const svgtopng = async (svg: any, width: any, height: any) => {
|
|
|
- // console.log(canvas, +new Date() + '-----')
|
|
|
-
|
|
|
+export const svgtoblob = async (svg: any, width: any, height: any, name: string) => {
|
|
|
if (!canvas) {
|
|
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
|
// @ts-ignore
|
|
@@ -84,39 +76,84 @@ export const svgtopng = async (svg: any, width: any, height: any) => {
|
|
|
await v.start()
|
|
|
// const blob = await canvas.convertToBlob()
|
|
|
// const base64 = await blobToBase64(blob)
|
|
|
- const base64 = await canvasAddPadding(canvas)
|
|
|
+ const base64 = await canvasAddPadding(canvas, name)
|
|
|
ctx.clearRect(0, 0, canvas.width, canvas.height)
|
|
|
await v.stop()
|
|
|
v = null
|
|
|
return base64
|
|
|
}
|
|
|
|
|
|
-const convertToBlob = (canvas: any) => {
|
|
|
- return new Promise(resolve => {
|
|
|
- canvas.toBlob(resolve)
|
|
|
+const convertToBlob = (canvas: any, type = "image/png") => {
|
|
|
+ return new Promise((resolve, reject) => {
|
|
|
+ canvas.toBlob((blob: Blob) => {
|
|
|
+ if (blob) {
|
|
|
+ resolve(blob)
|
|
|
+ } else {
|
|
|
+ reject(new Error("转换失败"))
|
|
|
+ }
|
|
|
+ }, type)
|
|
|
})
|
|
|
}
|
|
|
|
|
|
-const canvasAddPadding = async (sourceCanvas: any) => {
|
|
|
+const canvasAddPadding = async (sourceCanvas: any, name: string) => {
|
|
|
const targetCanvas = document.createElement("canvas")
|
|
|
targetCanvas.width = sourceCanvas.width + 400
|
|
|
- targetCanvas.height = sourceCanvas.height + 100
|
|
|
+ targetCanvas.height = sourceCanvas.height + 200
|
|
|
+
|
|
|
// 坐标(0,0) 表示从此处开始绘制,相当于偏移。
|
|
|
const targetContext = targetCanvas.getContext("2d") as CanvasRenderingContext2D
|
|
|
|
|
|
- const sourceContext = sourceCanvas.getContext("2d") as CanvasRenderingContext2D
|
|
|
+ // const sourceContext = sourceCanvas.getContext("2d") as CanvasRenderingContext2D
|
|
|
|
|
|
// 从源canvas中获取图像数据
|
|
|
- const imageData = sourceContext.getImageData(0, 0, sourceCanvas.width, sourceCanvas.height)
|
|
|
+ // const imageData = sourceContext.getImageData(0, 0, sourceCanvas.width, sourceCanvas.height)
|
|
|
|
|
|
// 清空目标canvas
|
|
|
targetContext.clearRect(0, 0, targetCanvas.width, targetCanvas.height)
|
|
|
|
|
|
// 将图像数据绘制到目标canvas上,并添加边距
|
|
|
- targetContext.putImageData(imageData, 200, 50)
|
|
|
+ // targetContext.putImageData(imageData, 200, 100)
|
|
|
+ targetContext.fillStyle = "#fff"
|
|
|
+ targetContext.fillRect(0, 0, targetCanvas.width, targetCanvas.height)
|
|
|
+ // targetCanvas = await addMusicTitle(targetCanvas, name)
|
|
|
+
|
|
|
+ // 小水印画布大小
|
|
|
+ // const waterCtx = water.getContext("2d") as CanvasRenderingContext2D
|
|
|
+ targetContext.font = `66pt Calibri`
|
|
|
+ targetContext.fillStyle = "#000"
|
|
|
+ targetContext.textAlign = "center"
|
|
|
+ targetContext.drawImage(canvas, 200, 240)
|
|
|
+ targetContext.fillText(name, canvas.width / 2, 200)
|
|
|
|
|
|
const blob = await convertToBlob(targetCanvas)
|
|
|
- const base64 = await blobToBase64(blob)
|
|
|
+ // const base64 = await blobToBase64(blob)
|
|
|
targetContext.clearRect(0, 0, targetCanvas.width, targetCanvas.height)
|
|
|
- return base64
|
|
|
+ return blob
|
|
|
+}
|
|
|
+
|
|
|
+// // 获取文件blob格式
|
|
|
+export const imgToCanvas = async (url: string) => {
|
|
|
+ const img = document.createElement("img")
|
|
|
+ img.setAttribute("crossOrigin", "anonymous")
|
|
|
+ // 为了处理base64 和 连接加载不同的
|
|
|
+ if (url && typeof url == "string" && url.includes("data:image")) {
|
|
|
+ img.src = url
|
|
|
+ } else {
|
|
|
+ img.src = url + `?t=${+new Date()}`
|
|
|
+ }
|
|
|
+
|
|
|
+ // 防止跨域引起的 Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.
|
|
|
+ await new Promise(resolve => (img.onload = resolve))
|
|
|
+ // 创建canvas DOM元素,并设置其宽高和图片一样
|
|
|
+ const canvas = document.createElement("canvas")
|
|
|
+ canvas.width = img.width
|
|
|
+ canvas.height = img.height
|
|
|
+ // 坐标(0,0) 表示从此处开始绘制,相当于偏移。
|
|
|
+ const ctx = canvas.getContext("2d") as CanvasRenderingContext2D
|
|
|
+
|
|
|
+ ctx.fillStyle = "rgb(255, 255, 255)"
|
|
|
+ ctx.fillStyle = "#fff"
|
|
|
+ ctx.fillRect(0, 0, img.width, img.height)
|
|
|
+ ctx.drawImage(img, 0, 0)
|
|
|
+ return canvas
|
|
|
}
|