小程序 画布 cavas
<template> <view> <!-- <img width="100%" height="90vh" :src="showImg" show-menu-by-longpress /> <button class="saveLocalShow" @click="saveLocal">保存本地</button> v-show="!showImg"--> <canvas canvas-id="mycanvas" class="canvas" id="mycanvas" /> </view> </template> <script> import { wrapText, roundRect } from "@/utils/canvas"; export default { data() { return { windowWidth: "", windowHeight: "", showImg: "", erweimaCode: "https://res.zhixinren.work/prod/5c19e3ea-397d-4fa4-992a-89b60d6f94df/0b1ffd9d-71cd-4bd5-b8de-a5a328b3877c.png", imgBack: "https://res.zhixinren.work/prod/93e10b03-4abf-4a42-bfb8-e9e6021539bb/52df853c-d6d7-4100-b26b-b55b4536af2a.png", logo: "https://res.zhixinren.work/prod/efff0f1d-5bd5-449d-a302-d67b0caa1c7f/caf56d6c-eff4-4646-8656-4d084d526052.png" }; }, methods: { previewImage() { this.canvasToFilePath(filePath => { console.log("123", filePath); this.showImg = filePath; }); }, saveLocal() { uni.showLoading({ title: "图片保存中..." }); this.canvasToFilePath(filePath => { console.log(filePath, 555); uni.saveImageToPhotosAlbum({ filePath: filePath, success: res => { uni.showToast({ title: "保存成功", duration: 2000 }); uni.hideLoading(); }, fail: err => { if ( err.errMsg === "saveImageToPhotosAlbum:fail:auth denied" || err.errMsg === "saveImageToPhotosAlbum:fail auth deny" || err.errMsg === "saveImageToPhotosAlbum:fail authorize no response" ) { uni.showModal({ title: "提示", content: "需要您授权保存相册", showCancel: false, success: modalSuccess => { uni.openSetting({ success(settingdata) { console.log(settingdata, 8888); if (settingdata.authSetting["scope.writePhotosAlbum"]) { uni.showToast({ title: "保存成功", duration: 2000 }); console.log("获取权限成功,给出再次点击图片保存到相册的提示。"); } else { uni.showToast({ title: "获取权限失败", duration: 2000 }); console.log("获取权限失败,给出不给权限就无法正常使用的提示"); } } }); } }); } // 4 不管成功失败都关闭提示信息!!! console.log("saveImageToPhotosAlbum 失败"); uni.hideLoading(); } }); }); }, canvasToFilePath(cb) { const width = wx.getSystemInfoSync().windowWidth; const height = wx.getSystemInfoSync().windowHeight; this.windowWidth = width; this.windowHeight = height - 45; uni.canvasToTempFilePath({ x: 0, y: 0, width: width, height: height, destWidth: width * this.dpr, destHeight: (height - 45) * this.dpr, // * this.dpr canvasId: "mycanvas", quality: 1, success: function(res) { cb(res.tempFilePath); }, fail: function(err) { console.log("debug log --> ", err); } }); }, canvas(bgPicturePath1, logo, erweimaCode) { console.log("bgPicturePath1", bgPicturePath1); const _this = this; var ctx = wx.createCanvasContext("mycanvas"); // ctx.scale(this.dpr, this.dpr); const { dpr } = this; const width = wx.getSystemInfoSync().windowWidth; const height = wx.getSystemInfoSync().windowHeight - 45; // const bgPicturePath = require("./img/back.png"); ctx.width = width * dpr; ctx.height = height * dpr; // ctx.scale(dpr, dpr); // 背景 ctx.drawImage(bgPicturePath1, 0, 0, width, height); // 白色框 roundRect(ctx, 16, 48, width - 16 * 2, 224, 8); // this.fillRoundRect(ctx, 16, 58, width - 32, 230, 10, "#fff"); // 绘制职位信息 const startW = 16 + 16; const startH = 48 + 24; const nametxt = "产品经理"; const nameWidth = ctx.measureText(nametxt).width; console.log(nameWidth); ctx.font = "normal bold 16px sans-serif"; ctx.textBaseline = "top"; ctx.fillStyle = "#3C3D43"; ctx.fillText(nametxt, startW, startH, nameWidth, 16); // 急招标签 const jzTag = true; if (jzTag) { // box roundRect(ctx, startW + nameWidth + 8, startH, 32, 16, 2, "#FF8657"); // boxText ctx.font = "normal normal 10px sans-serif"; ctx.textBaseline = "top"; ctx.fillStyle = "#fff"; ctx.fillText("急招", startW + nameWidth + 8 + 6, startH + 4, 32, 16); } // 全职标签 const qzTag = true; if (qzTag) { // box const qzstartW = jzTag ? startW + nameWidth + 8 + 32 : startW + nameWidth + 8; roundRect(ctx, qzstartW + 8, startH, 32, 16, 2, "#fff", 1, "#4686FF"); // boxText ctx.font = "normal normal 10px sans-serif"; ctx.textBaseline = "top"; ctx.fillStyle = "#4686FF"; ctx.fillText("全职", qzstartW + 8 + 6, startH + 4, 32, 16); } // 城市 const cityTxt = "山东省 青岛市"; const cityWidth = ctx.measureText(cityTxt).width; const citystartW = width - 16 - 16 - cityWidth; ctx.font = "normal normal 12px sans-serif"; ctx.textBaseline = "top"; ctx.fillStyle = "#ACAFC5"; ctx.fillText(cityTxt, citystartW, startH + 4, cityWidth, 16); // 钱数money const moneystartH = startH + 16 + 12; const moneyTxt = "6000-7000元"; const moneyWidth = ctx.measureText(moneyTxt).width; ctx.font = "normal bold 18px sans-serif"; ctx.textBaseline = "top"; ctx.fillStyle = "#3070FF"; ctx.fillText(moneyTxt, startW, moneystartH, moneyWidth, 18); // 第三行 年限等 const yearstartH = moneystartH + 18 + 12; const yearTxt = "3-5年wqe"; const yearWidth = ctx.measureText(yearTxt).width; ctx.font = "normal normal 12px sans-serif"; ctx.textBaseline = "top"; ctx.fillStyle = "#767885"; ctx.fillText(yearTxt, startW, yearstartH, yearWidth, 12); // | ctx.font = "normal normal 12px sans-serif"; ctx.textBaseline = "top"; ctx.fillStyle = "#767885"; ctx.fillText("|", startW + yearWidth - 9, yearstartH, 1, 12); // 学历 const xueliTxt = "专科以上"; const xueliWidth = ctx.measureText(xueliTxt).width; ctx.font = "normal normal 12px sans-serif"; ctx.textBaseline = "top"; ctx.fillStyle = "#767885"; ctx.fillText(xueliTxt, startW + yearWidth + 8 + 1, yearstartH, xueliWidth, 12); // 五险一金标签; const wxyjTag = true; const wxyjArr = ["五险一金", "定期体检", "管吃管住"]; if (wxyjTag) { let TapNum = -ctx.measureText(wxyjArr[0]).width; wxyjArr.map((i, index) => { // const Tap = ctx.measureText(i).width; const TapBox = ctx.measureText(i).width + 8 + 8; TapNum += TapBox; // boxText ctx.font = "normal normal 12px sans-serif"; ctx.textBaseline = "top"; ctx.fillStyle = "#4686FF"; ctx.fillText(i, startW + 8 + TapNum, startH + 83 + 5, 48, 20); // box roundRect(ctx, startW + TapNum, yearstartH + 12 + 12, TapBox, 22, 2, "rgba(70, 134, 255, 0.1)", 1, "rgba(70, 134, 255, 0.6)"); }); } // 横线 roundRect(ctx, startW, yearstartH + 12 + 12 + 22 + 12, width - 16 * 4, 0.5, 0, "#E3E6F1"); // 公司信息 const companystartH = yearstartH + 12 + 12 + 22 + 12 + 16; ctx.drawImage(this.erweimaCode, startW, companystartH, 48, 48); // const companyImg = canvas.createImage(); // companyImg.src = this.erweimaCode; // companyImg.onload = () => { // ctx.drawImage(companyImg, startW, companystartH, 48, 48); // }; // 公司名称 const companyTxt = "网络科技有限公司"; const companyWidth = ctx.measureText(companyTxt).width; ctx.font = "normal 500 14px sans-serif"; ctx.textBaseline = "top"; ctx.fillStyle = "#55565D"; ctx.fillText(companyTxt, startW + 48 + 8, companystartH + 5, companyWidth, 14); // 行业 const industryTxt = "青岛市 互联网"; const industryWidth = ctx.measureText(industryTxt).width; ctx.font = "normal 400 12px sans-serif"; ctx.textBaseline = "top"; ctx.fillStyle = "#767885"; ctx.fillText(industryTxt, startW + 48 + 8, companystartH + 5 + 14 + 12, industryWidth, 14); // const enterpriseTxt = "企业服务"; const enterpriseWidth = ctx.measureText(enterpriseTxt).width; ctx.font = "normal 400 12px sans-serif"; ctx.textBaseline = "top"; ctx.fillStyle = "#767885"; ctx.fillText(enterpriseTxt, startW + 48 + 8 + industryWidth + 5, companystartH + 5 + 14 + 12, enterpriseWidth, 14); // Logo // const logoImg = canvas.createImage(); // logoImg.src = "/shareCanvas/img/logo.png"; // logoImg.onload = () => { // ctx.drawImage(logoImg, 16, height - 114, 86, 28); // }; ctx.drawImage(erweimaCode, width - 16 - 188, height - 170, 166, 166); // // 调用draw()开始绘制 ctx.draw(); this.previewImage(); }, circleImg(ctx, img, x, y, r) { ctx.save(); var d = 2 * r; var cx = x + r; var cy = y + r; ctx.arc(cx, cy, r, 0, 2 * Math.PI); ctx.clip(); ctx.drawImage(img, x, y, d, d); ctx.restore(); }, // 二维码图片 handleNetImg(imageUrl) { const that = this; return new Promise((resolve, reject) => { // console.log("imageUrl1", imageUrl); uni.getImageInfo({ src: imageUrl, success: function(res) { resolve(res); }, fail: function(err) { reject(err); } }); }); }, fillRoundRect(cxt, x, y, width, height, radius, fillColor) { // 圆的直径必然要小于矩形的宽高 if (2 * radius > width || 2 * radius > height) { return false; } cxt.save(); cxt.translate(x, y); // 绘制圆角矩形的各个边 this.drawRoundRectPath(cxt, width, height, radius); cxt.fillStyle = fillColor || "#000"; // 若是给定了值就用给定的值否则给予默认值 cxt.fill(); cxt.restore(); }, drawRoundRectPath(cxt, width, height, radius) { cxt.beginPath(0); // 从右下角顺时针绘制,弧度从0到1/2PI cxt.arc(width - radius, height - radius, radius, 0, Math.PI / 2); // 矩形下边线 cxt.lineTo(radius, height); // 左下角圆弧,弧度从1/2PI到PI cxt.arc(radius, height - radius, radius, Math.PI / 2, Math.PI); // 矩形左边线 cxt.lineTo(0, radius); // 左上角圆弧,弧度从PI到3/2PI cxt.arc(radius, radius, radius, Math.PI, (Math.PI * 3) / 2); // 上边线 cxt.lineTo(width - radius, 0); // 右上角圆弧 cxt.arc(width - radius, radius, radius, (Math.PI * 3) / 2, Math.PI * 2); // 右边线 cxt.lineTo(width, height - radius); cxt.closePath(); }, async goCanvas() { const code = await this.handleNetImg(`${this.imgBack}`); const logo = await this.handleNetImg(`${this.logo}`); const erweimaCode = await this.handleNetImg(`${this.erweimaCode}`); this.canvas(code.path, logo.path, erweimaCode.path); } }, mounted() { this.dpr = wx.getSystemInfoSync().pixelRatio; this.goCanvas(); }, onLoad() {} }; </script> <style scoped> img { position: fixed; left: 0; right: 0; top: 0; z-index: 999; bottom: 70px; width: 100% !important; height: 90vh !important; } .canvas { position: absolute; top: 0; left: 0; z-index: 0; width: 100vw; height: 100vh; } .saveLocalShow { position: absolute; bottom: 0px; z-index: 7777777; width: 100%; color: #3070ff; } </style>