赞
踩
wrapperHeight
是根据海报的内容计算出来海报的高度 <view class="preview-card-wrap" @tap.stop>
<view class="poster-box" :class="{ show: isDrew }">
<canvas
id="myCanvas"
canvas-id="myCanvas"
:style="{
width: '750rpx',
height: wrapperHeight + 'rpx',
}"
></canvas>
</view>
</view>
class Poster { canvasId: string; instanceComponent: ReturnType<typeof getCurrentInstance> | undefined; ctx: UniApp.CanvasContext | undefined = undefined; width = 0; height = 0; isPixel: boolean; drawSteps: DrawSteps = []; constructor( canvasId: string, instance?: ReturnType<typeof getCurrentInstance>, { isPixel = true } = <InitConfig>{} ) { this.canvasId = canvasId; this.instanceComponent = instance; this.ctx = uni.createCanvasContext(canvasId, instance); this.isPixel = isPixel; } /** * 设置画布大小 * @param width 画布宽度 * @param height 画布高度 */ public setCanvasSize(width: number, height: number) { this.width = width; this.height = height; } /** * 清空画布 */ clearAll() { this.ctx?.clearRect( 0, 0, this.getPixel(this.width), this.getPixel(this.height) ); // clearRect() 方法只是将指定区域的像素设置为透明,但不会直接触发画布的重新绘制。 // 因此,需要在清除画布后显式调用 draw() 方法,才能使清除的效果立即生效,即将空白画布展示在页面上。 // 这个方法只是为了更新画布 this.ctx?.draw(); } } export default Poster;
import { getCurrentInstance, ref } from "vue";
const poster = ref<Poster | undefined | any>(undefined);
poster.value = new Poster("myCanvas", self, { isPixel: false });
const self = getCurrentInstance();
// 设置画布大小
poster.value.setCanvasSize(750, wrapperHeight.value);
// 绘制前先清空画布
poster.value.clearAll();
/**
* 获取大小
* @param size
*/
getPixel(size: number) {
return this.isPixel ? size : rpx2px(size);
}
/** * 获取文字宽度 * @param text 文字 * @param fontStyle 字体样式,同 css 的 font 属性 * @returns {number} 文字宽度 */ public getTextWidth(text: string, fontStyle?: string) { if (!this.ctx || !text.trim()) return 0; this.ctx.save(); this.ctx.font = fontStyle || "14px sans-serif"; const dimension = this.ctx.measureText(text); this.ctx.restore(); return this.isPixel ? dimension.width : px2rpx(dimension.width); }
// 给文字加上省略号 public correctEllipsisText(text: string, width: number, fontStyle?: string) { let resultText = ""; const strSplits = text.split(""); while (strSplits.length > 0) { const s = strSplits.shift(); const isGtWidth = this.getPixel(this.getTextWidth(resultText + s, fontStyle)) > this.getPixel(width); if (isGtWidth) { resultText = resultText.substring(0, resultText.length) + "..."; break; } resultText += s; } return resultText; }
/** * 绘制文字 * @param text 文字 * @param x 横向绘制点 * @param y 纵向绘制点 * @param maxWidth 绘制区域最大宽度,文字宽度超过则换行 * @param color 文字颜色 * @param fontSize 文字大小 * @param fontWeight 文字粗细 * @param borderWidth 文字描边粗细 * @param borderColor 文字描边样式 * @param lineHeight 行高,即文字行与行之间的间距 * @param UseEllipsis 当超出文字宽度是否使用省略号 */ public async drawText({ text, x, y, maxWidth, color, fontSize, fontFamily, fontWeight = 500, borderWidth, borderColor, lineHeight = 1.2, UseEllipsis = true, }: TextDrawStep) { if (!this.ctx) return; const fontStyle = `${fontWeight} ${ fontSize ? this.getPixel(fontSize) : 14 }px ${`${fontFamily}` || "sans-serif"}`; this.ctx.save(); this.ctx.setTextBaseline("top"); this.ctx.font = fontStyle; color && (this.ctx.fillStyle = color); if (borderColor) this.ctx.strokeStyle = borderColor; // 绘制文字边框样式 if (borderWidth) { this.ctx.lineWidth = borderWidth; } if (UseEllipsis) { // 将超出canvas宽度的文字用...展示 const drawText = this.correctEllipsisText( text, maxWidth || this.width, fontStyle ); if (borderWidth) { this.ctx.strokeText( drawText, this.getPixel(x), this.getPixel(y), maxWidth ? this.getPixel(maxWidth) : maxWidth ); } this.ctx.fillText( drawText, this.getPixel(x), this.getPixel(y), maxWidth ? this.getPixel(maxWidth) : maxWidth ); } else { // 将文本分割成数组 const words = text.split(""); let line = ""; // 当前行的文字内容 let yPos = y; // 当前行的纵坐标位置 for (let i = 0; i < words.length; i++) { const testLine = line + words[i]; // 当前行加上当前单词 // 测量当前行的宽度 const textWidth = this.getTextWidth(testLine, fontStyle); // 如果当前行的宽度超过最大的宽度 需要换行 if (textWidth > this.getPixel(maxWidth || this.width)) { // 讲当前行绘制到canvas上 if (borderWidth) { this.ctx.strokeText( line, this.getPixel(x), this.getPixel(y), maxWidth ? this.getPixel(maxWidth) : maxWidth ); this.ctx.fillText( line, this.getPixel(x), this.getPixel(yPos), maxWidth ? this.getPixel(maxWidth) : maxWidth ); // 开始新一行 yPos += lineHeight * (fontSize ? this.getPixel(fontSize) : 14); } else { line = testLine; } } } this.ctx.strokeText(line, this.getPixel(x), this.getPixel(y)); this.ctx.fillText(line, this.getPixel(x), this.getPixel(yPos)); } this.ctx.restore(); }
/** * 绘制直边形状 * @param lines 坐标数组第一个为设置落笔点,坐标数组最后一个如果和第一个一样可省略 * @param fillColor 填充颜色 */ public drawLineShape({ lines, fillColor }: LineShapeDrawStep) { if (!this.ctx || !lines.length) return; this.ctx.save(); // 开始绘制路径 this.ctx.beginPath(); const [x, y] = lines[0]; this.ctx.moveTo(this.getPixel(x), this.getPixel(y)); // 遍历坐标数组,绘制直线段 for (let i = 1; i < lines.length; i++) { const [ix, iy] = lines[i]; this.ctx.lineTo(this.getPixel(ix), this.getPixel(iy)); } if (this.ctx && fillColor) { this.ctx.fillStyle = fillColor; this.ctx.fill(); } else { this.ctx.closePath(); } this.ctx.restore(); }
/** * 绘制圆形 */ public drawCircleShape({ x, y, radius, startAngle, endAngle, anticlockwise, fillColor, }: CircleShapeDrawStep) { if (!this.ctx) return; this.ctx.save(); this.ctx.beginPath(); this.ctx.arc( this.getPixel(x), this.getPixel(y), this.getPixel(radius), this.getPixel(startAngle), this.getPixel(endAngle), anticlockwise ); if (this.ctx && fillColor) { this.ctx.setFillStyle(fillColor); this.ctx.fill(); } else { this.ctx.closePath(); } this.ctx.restore(); }
/** * 绘制圆角矩形 * @param x x坐标 * @param y y坐标 * @param width 宽度 * @param height 高度 * @param radius 圆角半径 * @param fillColor 填充颜色 */ public roundRect = ({ x, y, width, height, radius, fillColor, }: roundRectShapeDrawStep) => { if (!this.ctx) return; const dx = this.getPixel(x); const dy = this.getPixel(y); const dRadius = this.getPixel(radius); const dWidth = this.getPixel(width); const dHeight = this.getPixel(height); this.ctx.beginPath(); this.ctx.moveTo(dx + dRadius, dy); // 下面三个点形成切线来画出圆弧 this.ctx.lineTo(dx + dWidth - dRadius, dy); this.ctx.arcTo(dx + dWidth, dy, dx + dWidth, dy + dRadius, dRadius); this.ctx.lineTo(dx + dWidth, dy + dHeight - dRadius); this.ctx.arcTo( dx + dWidth, dy + dHeight, dx + dWidth - dRadius, dy + dHeight, dRadius ); this.ctx.lineTo(dx + dRadius, dy + dHeight); this.ctx.arcTo(dx, dy + dHeight, dx, dy + dHeight - dRadius, dRadius); this.ctx.lineTo(dx, dy + dRadius); this.ctx.arcTo(dx, dy, dx + dRadius, dy, dRadius); this.ctx.closePath(); this.ctx.fillStyle = fillColor; this.ctx.fill(); };
/** * 绘制图片 * @param image 图片路径,必须为本地路径或临时路径 * @param x 横向绘制点 * @param y 纵向绘制点 * @param width 绘制宽度 * @param height 绘制高度 * @param isCircle 是否为圆形图, 宽高需相等 */ public async drawImage({ image, x, y, width, height, isCircle = false, clipConfig, }: ImageDrawStep) { if (!this.ctx) return; this.ctx.save(); if (isCircle) { const r = Math.floor(this.getPixel(width) / 2); // context.arc(x, y, radius, startAngle, endAngle, anticlockwise); this.ctx.arc( this.getPixel(x) + r, this.getPixel(y) + r, r, 0, 2 * Math.PI ); // 只有在剪切路径范围内的内容才会被保留,超出剪切路径范围的部分会被裁剪掉。 this.ctx.clip(); } await sleep(50); let clipParams: number[] = []; if (clipConfig) { clipParams = [ clipConfig.x, clipConfig.y, clipConfig.width, clipConfig.height, ]; } this.ctx.drawImage( image, ...clipParams, this.getPixel(x), this.getPixel(y), this.getPixel(width), this.getPixel(height) ); // console.log(this.ctx, "查看图片的上下文"); this.ctx.restore(); }
/** * 执行绘制 */ async draw(callback?: Function) { // 初始化绘图步骤数组的索引 let index = 0; // 循环遍历绘图步骤数组 while (index < this.drawSteps.length) { // 从当前绘图步骤中提取出类型和其他属性 const { type, ...otherProps } = <DrawStep>this.drawSteps[index]; const stepProps = <AnyObject>otherProps; const props = <AnyObject>{}; // 合并其他属性到 props 中 Object.assign( props, stepProps.getProps ? await stepProps.getProps(this.drawSteps, index) : stepProps ); // this.drawSteps[index].drawData = { // ...props, // ...(this.drawSteps[index].drawData || {}), // }; // 根据类型执行相应的绘图操作 if (type === DrawType.Text) { await this.drawText(<TextDrawStep>props); } else if (type === DrawType.Image) { await this.drawImage(<ImageDrawStep>props); } else if (type === DrawType.LineShape) { await this.drawLineShape(<LineShapeDrawStep>props); } else if (type === DrawType.CircleShape) { await this.drawCircleShape(<CircleShapeDrawStep>props); } else if (type === DrawType.RoundRectShape) { await this.roundRect(<roundRectShapeDrawStep>props); } // 如果当前绘图步骤需要立即绘制,则执行绘图同步操作 props.immediateDraw && (await this.syncDraw()); // 移动到下一个绘图步骤 index += 1; } // 执行最终的绘图操作,并在绘制完成后执行回调函数 this.ctx?.draw(true, (res) => { callback?.(res); }); }
import type { getCurrentInstance } from "vue"; import { px2rpx, rpx2px } from "@/utils/view"; import type { DrawStep, DrawSteps, ImageDrawStep, InitConfig, LineShapeDrawStep, TextDrawStep, CircleShapeDrawStep, roundRectShapeDrawStep, } from "./poster"; import { DrawType } from "./poster"; import { sleep } from "@/utils"; class Poster { canvasId: string; instanceComponent: ReturnType<typeof getCurrentInstance> | undefined; ctx: UniApp.CanvasContext | undefined = undefined; width = 0; height = 0; isPixel: boolean; drawSteps: DrawSteps = []; constructor( canvasId: string, instance?: ReturnType<typeof getCurrentInstance>, { isPixel = true } = <InitConfig>{} ) { this.canvasId = canvasId; this.instanceComponent = instance; this.ctx = uni.createCanvasContext(canvasId, instance); this.isPixel = isPixel; } /** * 获取大小 * @param size */ getPixel(size: number) { return this.isPixel ? size : rpx2px(size); } public getCanvasSize() { return { width: this.width, height: this.height, }; } /** * 设置画布大小 * @param width 画布宽度 * @param height 画布高度 */ public setCanvasSize(width: number, height: number) { this.width = width; this.height = height; } /** * 获取文字宽度 * @param text 文字 * @param fontStyle 字体样式,同 css 的 font 属性 * @returns {number} 文字宽度 */ public getTextWidth(text: string, fontStyle?: string) { if (!this.ctx || !text.trim()) return 0; this.ctx.save(); this.ctx.font = fontStyle || "14px sans-serif"; const dimension = this.ctx.measureText(text); this.ctx.restore(); return this.isPixel ? dimension.width : px2rpx(dimension.width); } // 给文字加上省略号 public correctEllipsisText(text: string, width: number, fontStyle?: string) { let resultText = ""; const strSplits = text.split(""); while (strSplits.length > 0) { const s = strSplits.shift(); const isGtWidth = this.getPixel(this.getTextWidth(resultText + s, fontStyle)) > this.getPixel(width); if (isGtWidth) { resultText = resultText.substring(0, resultText.length) + "..."; break; } resultText += s; } return resultText; } /** * 绘制图片 * @param image 图片路径,必须为本地路径或临时路径 * @param x 横向绘制点 * @param y 纵向绘制点 * @param width 绘制宽度 * @param height 绘制高度 * @param isCircle 是否为圆形图, 宽高需相等 */ public async drawImage({ image, x, y, width, height, isCircle = false, clipConfig, }: ImageDrawStep) { if (!this.ctx) return; this.ctx.save(); if (isCircle) { const r = Math.floor(this.getPixel(width) / 2); // context.arc(x, y, radius, startAngle, endAngle, anticlockwise); this.ctx.arc( this.getPixel(x) + r, this.getPixel(y) + r, r, 0, 2 * Math.PI ); // 只有在剪切路径范围内的内容才会被保留,超出剪切路径范围的部分会被裁剪掉。 this.ctx.clip(); } await sleep(50); let clipParams: number[] = []; if (clipConfig) { clipParams = [ clipConfig.x, clipConfig.y, clipConfig.width, clipConfig.height, ]; } this.ctx.drawImage( image, ...clipParams, this.getPixel(x), this.getPixel(y), this.getPixel(width), this.getPixel(height) ); // console.log(this.ctx, "查看图片的上下文"); this.ctx.restore(); } /** * 绘制文字 * @param text 文字 * @param x 横向绘制点 * @param y 纵向绘制点 * @param maxWidth 绘制区域最大宽度,文字宽度超过则换行 * @param color 文字颜色 * @param fontSize 文字大小 * @param fontWeight 文字粗细 * @param borderWidth 文字描边粗细 * @param borderColor 文字描边样式 * @param lineHeight 行高,即文字行与行之间的间距 * @param UseEllipsis 当超出文字宽度是否使用省略号 */ public async drawText({ text, x, y, maxWidth, color, fontSize, fontFamily, fontWeight = 500, borderWidth, borderColor, lineHeight = 1.2, UseEllipsis = true, }: TextDrawStep) { if (!this.ctx) return; const fontStyle = `${fontWeight} ${ fontSize ? this.getPixel(fontSize) : 14 }px ${`${fontFamily}` || "sans-serif"}`; this.ctx.save(); this.ctx.setTextBaseline("top"); this.ctx.font = fontStyle; color && (this.ctx.fillStyle = color); if (borderColor) this.ctx.strokeStyle = borderColor; // 绘制文字边框样式 if (borderWidth) { this.ctx.lineWidth = borderWidth; } if (UseEllipsis) { // 将超出canvas宽度的文字用...展示 const drawText = this.correctEllipsisText( text, maxWidth || this.width, fontStyle ); if (borderWidth) { this.ctx.strokeText( drawText, this.getPixel(x), this.getPixel(y), maxWidth ? this.getPixel(maxWidth) : maxWidth ); } this.ctx.fillText( drawText, this.getPixel(x), this.getPixel(y), maxWidth ? this.getPixel(maxWidth) : maxWidth ); } else { // 将文本分割成数组 const words = text.split(""); let line = ""; // 当前行的文字内容 let yPos = y; // 当前行的纵坐标位置 for (let i = 0; i < words.length; i++) { const testLine = line + words[i]; // 当前行加上当前单词 // 测量当前行的宽度 const textWidth = this.getTextWidth(testLine, fontStyle); // 如果当前行的宽度超过最大的宽度 需要换行 if (textWidth > this.getPixel(maxWidth || this.width)) { // 讲当前行绘制到canvas上 if (borderWidth) { this.ctx.strokeText( line, this.getPixel(x), this.getPixel(y), maxWidth ? this.getPixel(maxWidth) : maxWidth ); this.ctx.fillText( line, this.getPixel(x), this.getPixel(yPos), maxWidth ? this.getPixel(maxWidth) : maxWidth ); // 开始新一行 yPos += lineHeight * (fontSize ? this.getPixel(fontSize) : 14); } else { line = testLine; } } } this.ctx.strokeText(line, this.getPixel(x), this.getPixel(y)); this.ctx.fillText(line, this.getPixel(x), this.getPixel(yPos)); } this.ctx.restore(); } /** * 绘制直边形状 * @param lines 坐标数组第一个为设置落笔点,坐标数组最后一个如果和第一个一样可省略 * @param fillColor 填充颜色 */ public drawLineShape({ lines, fillColor, gradients }: LineShapeDrawStep) { if (!this.ctx || !lines.length) return; this.ctx.save(); this.ctx.beginPath(); const [x, y] = lines[0]; this.ctx.moveTo(this.getPixel(x), this.getPixel(y)); for (let i = 1; i < lines.length; i++) { const [ix, iy] = lines[i]; this.ctx.lineTo(this.getPixel(ix), this.getPixel(iy)); } if (this.ctx && fillColor) { this.ctx.fillStyle = fillColor; this.ctx.fill(); } else if (this.ctx && gradients?.length) { var lineargradient = this.ctx.createLinearGradient( gradients[0], gradients[1], gradients[2], gradients[3] ); lineargradient.addColorStop(0, "#363636"); lineargradient.addColorStop(1, "white"); this.ctx.setFillStyle(lineargradient); this.ctx.fill(); } else { this.ctx.closePath(); } this.ctx.restore(); } /** * 绘制圆形 */ public drawCircleShape({ x, y, radius, startAngle, endAngle, anticlockwise, fillColor, }: CircleShapeDrawStep) { if (!this.ctx) return; this.ctx.save(); this.ctx.beginPath(); this.ctx.arc( this.getPixel(x), this.getPixel(y), this.getPixel(radius), this.getPixel(startAngle), this.getPixel(endAngle), anticlockwise ); if (this.ctx && fillColor) { this.ctx.setFillStyle(fillColor); this.ctx.fill(); } else { this.ctx.closePath(); } this.ctx.restore(); } syncDraw(): Promise<void> { return new Promise((resolve) => { this.ctx?.draw(true, async () => { await sleep(30); resolve(); }); }); } /** * 绘制圆角矩形 * @param x x坐标 * @param y y坐标 * @param width 宽度 * @param height 高度 * @param radius 圆角半径 * @param fillColor 填充颜色 */ public roundRect = ({ x, y, width, height, radius, fillColor, }: roundRectShapeDrawStep) => { if (!this.ctx) return; const dx = this.getPixel(x); const dy = this.getPixel(y); const dRadius = this.getPixel(radius); const dWidth = this.getPixel(width); const dHeight = this.getPixel(height); this.ctx.beginPath(); this.ctx.moveTo(dx + dRadius, dy); // 下面三个点形成切线来画出圆弧 this.ctx.lineTo(dx + dWidth - dRadius, dy); this.ctx.arcTo(dx + dWidth, dy, dx + dWidth, dy + dRadius, dRadius); this.ctx.lineTo(dx + dWidth, dy + dHeight - dRadius); this.ctx.arcTo( dx + dWidth, dy + dHeight, dx + dWidth - dRadius, dy + dHeight, dRadius ); this.ctx.lineTo(dx + dRadius, dy + dHeight); this.ctx.arcTo(dx, dy + dHeight, dx, dy + dHeight - dRadius, dRadius); this.ctx.lineTo(dx, dy + dRadius); this.ctx.arcTo(dx, dy, dx + dRadius, dy, dRadius); this.ctx.closePath(); this.ctx.fillStyle = fillColor; this.ctx.fill(); }; /** * 执行绘制 */ async draw(callback?: Function) { // 初始化绘图步骤数组的索引 let index = 0; // 循环遍历绘图步骤数组 while (index < this.drawSteps.length) { // 从当前绘图步骤中提取出类型和其他属性 const { type, ...otherProps } = <DrawStep>this.drawSteps[index]; const stepProps = <AnyObject>otherProps; const props = <AnyObject>{}; // 合并其他属性到 props 中 Object.assign( props, stepProps.getProps ? await stepProps.getProps(this.drawSteps, index) : stepProps ); // this.drawSteps[index].drawData = { // ...props, // ...(this.drawSteps[index].drawData || {}), // }; // 根据类型执行相应的绘图操作 if (type === DrawType.Text) { await this.drawText(<TextDrawStep>props); } else if (type === DrawType.Image) { await this.drawImage(<ImageDrawStep>props); } else if (type === DrawType.LineShape) { await this.drawLineShape(<LineShapeDrawStep>props); } else if (type === DrawType.CircleShape) { await this.drawCircleShape(<CircleShapeDrawStep>props); } else if (type === DrawType.RoundRectShape) { await this.roundRect(<roundRectShapeDrawStep>props); } // 如果当前绘图步骤需要立即绘制,则执行绘图同步操作 props.immediateDraw && (await this.syncDraw()); // 移动到下一个绘图步骤 index += 1; } // 执行最终的绘图操作,并在绘制完成后执行回调函数 this.ctx?.draw(true, (res) => { callback?.(res); }); } /** * 将绘制内容转成图片 * @returns {Promise<string>} 图片临时路径 */ canvas2Image(): Promise<UniApp.CanvasToTempFilePathRes> | undefined { if (!this.ctx) return; return new Promise((resolve) => { uni.canvasToTempFilePath( { canvasId: this.canvasId, x: 0, y: 0, width: this.width, height: this.height, success: resolve, }, this.instanceComponent ); }); } /** * 清空画布 */ clearAll() { this.ctx?.clearRect( 0, 0, this.getPixel(this.width), this.getPixel(this.height) ); // clearRect() 方法只是将指定区域的像素设置为透明,但不会直接触发画布的重新绘制。 // 因此,需要在清除画布后显式调用 draw() 方法,才能使清除的效果立即生效,即将空白画布展示在页面上。 // 这个方法只是为了更新画布 this.ctx?.draw(); } } export default Poster;
export enum DrawType { Text = "text", Image = "image", LineShape = "lineShape", CircleShape = "circleShape", RoundRectShape = "roundRectShape", } export interface InitConfig { isPixel: boolean; } export type BaseDrawStep = { x: number; y: number; }; export type GetProps<O> = { getProps: (steps: DrawSteps, index: number) => O | Promise<O>; }; export type TextDrawStep = BaseDrawStep & { text: string; maxWidth?: number; color?: string; fontSize?: number; fontFamily?: string; fontWeight?: number; borderWidth?: number; borderColor?: string; lineHeight?: number; UseEllipsis?: boolean; }; export type ImageDrawStep = BaseDrawStep & { image: string; width: number; height: number; isCircle?: boolean; clipConfig?: { x: number; y: number; width: number; height: number; }; }; export type LineShapeDrawStep = { lines: Array<[number, number]>; fillColor?: string; strokeStyle?: string; gradients?: Array<number>; }; export type CircleShapeDrawStep = { x: number; y: number; radius: number; startAngle: number; endAngle: number; anticlockwise: boolean; fillColor?: string; }; export type roundRectShapeDrawStep = { ctx: CanvasRenderingContext2D; x: number; y: number; width: number; height: number; radius: number; fillColor: any; }; export type DrawStep = | ({ type: DrawType.Text } & (TextDrawStep | GetProps<TextDrawStep>)) | ({ type: DrawType.Image } & (ImageDrawStep | GetProps<ImageDrawStep>)) | ({ type: DrawType.LineShape } & ( | LineShapeDrawStep | GetProps<LineShapeDrawStep> )); export type DrawSteps = Array< DrawStep & { drawData?: AnyObject; immediateDraw?: boolean } >;
export const px2rpx = (px: number) => px / (uni.upx2px(100) / 100);
export const rpx2px = (rpx: number) => uni.upx2px(rpx);
import { getCurrentInstance, ref } from "vue"; const poster = ref<Poster | undefined | any>(undefined); poster.value = new Poster("myCanvas", self, { isPixel: false }); const self = getCurrentInstance(); // 设置画布大小 poster.value.setCanvasSize(750, wrapperHeight.value); // 绘制前先清空画布 poster.value.clearAll(); poster.value.drawSteps = [ { // 背景高斯模糊图片 type: DrawType.Image, getProps: (steps: DrawSteps) => { return { image: flurBg.path, x: 0, y: 0, width: 750, height: 308, }; }, }, ]; await poster.value.draw((res: any) => { uni.hideLoading(); });
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。