@zh-achieve/uni-vue3-canvas
v1.0.0
Published
uniapp-canvas方法
Downloads
7
Readme
uniapp一些操作canvas方法的封装
🛠️ 方法介绍
<script setup lang="ts">
import { useCanvas } from "@zh-achieve/uni-vue3-canvas"
const {
canvasCtx, // UniApp.CanvasContext对象
canvasImg, // 生成的图片
getCanvasTextWidth, // 测量文字渲染的宽度 getCanvasTextWidth(text: string): number
setCanvasStyle, // 设置canvas颜色供下一次绘制使用setCanvasStyle(color: string): void
setCanvasWH, // 设置画布宽高大小setCanvasWH(width: number, height: number)
setCanvasImg, // 在画布上画图片,见下方
drawRoundRect, // 绘制内容的容器的圆角矩形,见下方
getImageInfo, // 依据线上地址生成图片本地地址getImageInfo(imgSrc: string): Promise<any>
rpxToPx, // rpx转为px rpxToPx(rpx: number): number
drawRoundImg, // 绘制带有圆角的图片, 可以绘制头像,见下方
beginDraw, // 开始渲染 beginDraw(): Promise<void>
createCanvasImg, // 创建图片需要在beginDraw完成之后再执行 createCanvasImg(): Promise<string> | undefined
setCanvasFontText // 设置canvas填充文字,使用此方法前记得先设置颜色和字体大小,加下方
} = useCanvas("my-canvas")
/**
* 在画布上画图片
* @param img
* @param x
* @param y
* @param maxwidth
*/
// setCanvasImg(img: string, x: number, y: number, width: number, height: number)
/**
* 绘制内容的容器的圆角矩形
* 带有radius的边框
* @param x 开始点横坐标
* @param y 开始点纵坐标
* @param width 宽度
* @param height 高度
* @param radius 圆角
* @param color 背景颜色
*/
// drawRoundRect(x: number, y: number, width: number, height: number, radius: number, color: string)
/**
* 绘制带有圆角的图片, 可以绘制头像
* @param img
* @param x 起点x坐标
* @param y 起点y坐标
* @param width 宽度
* @param height 高度
* @param radius 圆角
*/
// drawRoundImg(img: string, x: number, y: number, width: number, height: number, radius = 0)
/**
* 设置canvas填充文字,使用此方法前记得先设置颜色和字体大小
* @param text 规定在画布上输出的文本。
* @param x 开始绘制文本的 x 坐标位置(相对于画布)。
* @param y 开始绘制文本的 y 坐标位置(相对于画布)。
* @param color 颜色
* @param font 符合css的font规则,至少需要提供字体大小和字体族名, 默认值"16px sans-serif"
* @param maxWidth 可选。允许的最大文本宽度,以像素计。
*/
// setCanvasFontText(
// text: string,
// x: number,
// y: number,
// color = "#000",
// font = "16px sans-serif",
// maxwidth?: number
// )
</script>
🛠️ 使用举例
<template>
<view class="content" v-if="isShow" @click.stop="isShow = false">
<canvas
class="my-canvas"
@click.stop=""
:style="{ width: canvasW + 'px', height: canvasH + 'px' }"
canvas-id="my-canvas"
></canvas>
<view class="save-btn" @click.stop="saveImage">保存图片</view>
<image :style="{ width: canvasW + 'px', height: canvasH + 'px' }" :src="canvasImg" mode="scaleToFill" />
</view>
</template>
<script setup lang="ts">
import { useCanvas } from "@zh-achieve/uni-vue3-canvas"
const canvasImg = ref("")
const {
canvasCtx,
setCanvasStyle,
setCanvasWH,
setCanvasFontSize,
setCanvasText,
setCanvasImg,
drawRoundRect,
getImageInfo,
rpxToPx,
drawDashLine,
drawEmptyRound,
beginDraw,
drawRoundImg,
createCanvasImg
} = useCanvas("my-canvas")
onBeforeUnmount(() => {
canvasCtx.value = null
})
const isShow = ref(false)
const canvasW = ref(rpxToPx(550))
const canvasH = ref(rpxToPx(900))
const headerImg = ref("https://tva3.sinaimg.cn/large/ceeb653ely1fj7edfnsv7j20i20i2q3k.jpg")
const title = ref("titletitletitletitle")
const content = ref("contentcontentcontentcontentcontent")
const subTitle = ref("subTitlesubTitlesubTitlesubTitlesubTitlesubTitle")
const showCanvas = () => {
isShow.value = true
if (!canvasImg.value) {
init()
}
}
// 保存图片到相册
const saveImage = () => {
console.log("saveImage")
}
const init = async () => {
//初始化画布
// uni.showLoading({
// title: "加载中...",
// mask: true
// })
//设置画布背景透明
setCanvasStyle("rgba(255, 255, 255, 0)")
//设置画布大小
setCanvasWH(canvasW.value, canvasH.value)
//绘制圆角背景
drawRoundRect(0, 0, canvasW.value, canvasH.value, rpxToPx(18), "#FFFFFF")
//获取标题图片
let headerImgLocal = await getImageInfo(headerImg.value)
let hW = rpxToPx(500)
let hH = rpxToPx(500)
//绘制标题图
drawRoundImg(headerImgLocal, (canvasW.value - hW) / 2, (canvasW.value - hW) / 2, hW, hH, rpxToPx(16))
//绘制标题
canvasCtx.value?.setFontSize(14) //设置标题字体大小
setCanvasStyle("#333") //设置标题文本颜色
setCanvasText(title.value, (canvasW.value - hW) / 2, (canvasW.value - hW) / 2 + hH + rpxToPx(60))
//绘制副标题
setCanvasFontSize(14)
setCanvasStyle("#858585")
// 计算副标题的长度
let sWidth = canvasCtx.value?.measureText(subTitle.value).width
if (sWidth && sWidth > hW) {
setCanvasText(
subTitle.value.slice(0, 17) + "...",
(canvasW.value - hW) / 2,
(canvasW.value - hW) / 2 + hH + rpxToPx(110)
)
} else {
setCanvasText(subTitle.value, (canvasW.value - hW) / 2, (canvasW.value - hW) / 2 + hH + rpxToPx(110))
}
// 绘制价格
if (content.value) {
//console.log(this.content)
// setCanvasFontSize(14)
setCanvasStyle("#999")
/* this.ctx.fillText('¥',((canvasW.value-hW) / 2),(((canvasW.value-hW) / 2) + hH + rpxToPx(120))) */
setCanvasFontSize(12)
setCanvasText(content.value, (canvasW.value - hW) / 2 + rpxToPx(36), (canvasW.value - hW) / 2 + hH + rpxToPx(120))
}
//绘制虚线
drawDashLine(
rpxToPx(20),
(canvasW.value - hW) / 2 + hH + rpxToPx(150),
canvasW.value - rpxToPx(20),
(canvasW.value - hW) / 2 + hH + rpxToPx(150),
5
)
//左边实心圆
drawEmptyRound(0, (canvasW.value - hW) / 2 + hH + rpxToPx(150), rpxToPx(20), "rgba(0, 0, 0, .4)")
//右边实心圆
drawEmptyRound(canvasW.value, (canvasW.value - hW) / 2 + hH + rpxToPx(150), rpxToPx(20), "rgba(0, 0, 0, .4)")
//提示文案
setCanvasFontSize(12)
setCanvasStyle("#858585")
setCanvasText("测试文字", (canvasW.value - hW) / 2 + rpxToPx(20), (canvasW.value - hW) / 2 + hH + rpxToPx(200))
//底部广告
let BottomAdImg = await getImageInfo("https://tva3.sinaimg.cn/large/ceeb653ely1fj7edfnsv7j20i20i2q3k.jpg")
setCanvasImg(BottomAdImg, 50, 380, 50, 50)
//小程序码
let qrcodeImg = await getImageInfo("https://hot.online.sh.cn/images/attachement/jpeg/site1/20161229/IMGf48e3894467143297155510.jpeg")
setCanvasImg(qrcodeImg, rpxToPx(384), (canvasW.value - hW) / 2 + hH + rpxToPx(200), rpxToPx(156), rpxToPx(156))
//延迟渲染
beginDraw().then(() => {
createCanvasImg()?.then((url) => {
canvasImg.value = url
uni.hideLoading()
})
})
}
onMounted({
showCanvas
})
</script>
<style scoped lang="scss">
.content {
position: fixed;
inset: 0;
z-index: 9999999;
background: rgb(0 0 0 / 40%);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.my-canvas {
position: absolute;
left: -100%;
}
.save-btn {
margin-top: 35rpx;
color: #fff;
background: linear-gradient(to right, #fe726b, #fe956b);
padding: 15rpx 40rpx;
border-radius: 50rpx;
}
}
</style>