【微信小程序】canvas生成分享图片海报模糊解决方法

本文介绍了如何使用微信小程序canvas在保持海报质量的同时,通过设置正确的画布尺寸和导出图片尺寸来避免模糊。重点讲解了文字居中、头像绘制和图片保存的优化方法,确保图片在下载时不失真。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

利用展示(drawImage)和保存(canvasToTempFilePath)设置尺寸不同,保存设置正常图片像素的大小

一、制作正常页面显示海报,实际canvas画布生成二倍图隐藏,下载时缩小显示即可解决模糊问题。二倍海报图屏幕仅能展示一半。保存图为750*940,实际canvas大小应为375px*470px ,此处二倍画图设置canvas大小为750px*940px

代码如下:

<!--index.wxml-->
<view class="container">
    <view class="show">
      <image src="{{cardPath}}" alt="" class="card"></image>
      <text class="name">{{sendName}}</text>
      <image src="{{headPath}}" class="header"></image>
    </view>
    <view class="btn" bindtap="saveImage">保存图片</view>
    <view class="canvasBox" style="width:0;height:0;overflow: hidden;opacity:0;position:absolute;left:-750px;top:0;">
      <canvas canvas-id='myCanvas' style='width:750px;height:1000px;'></canvas>
    </view>
</view>

二、canvas绘图过程:文字居中显示时设置let x = ctx.width/2  画布宽度一半,设置文字时距离左边像素为x,既为中心位置

/*画图*/
  drawCanvas: function () {
    let that = this;
    let ctx = wx.createCanvasContext('myCanvas');
    let ctxW = 750;
    let ctxH =940;
    ctx.width = 750;
    ctx.height =940;
    let x = ctx.width / 2;//canvas宽的一半
 
    // 垂直渐变
    const grd = ctx.createLinearGradient(0, 0, 0, ctxH);
    grd.addColorStop(0, '#ffffff');
    grd.addColorStop(1, '#ffffff');
    ctx.setFillStyle(grd);
 
    ctx.fillRect(0, 0, ctxW, ctxH);
 
    wx.getImageInfo({
      src: that.data.cardPath,
      success: (res) => {
        ctx.drawImage(res.path, 0, 0, 750,940); //card
        
        ctx.setFontSize(32) //字体大小
        ctx.setFillStyle('red') //字体颜色
        ctx.textAlign = "center"; //文字居中
        ctx.fillText(that.data.sendName, x, 34)
        ctx.stroke();
 
        wx.getImageInfo({
          src: that.data.headPath,
          success: (res) => {
            ctx.save();
            ctx.beginPath(); //开始绘制
            ctx.arc(150,358,50, 0, 2 * Math.PI)
            ctx.fill()
            ctx.clip(); //剪切
            ctx.drawImage(res.path,100, 308, 100, 100); //userHeader  // 推进去图片必须是https
            ctx.restore(); //恢复之前保存的绘图上下文 继续绘制
            /**/ 
            ctx.save();
            ctx.draw();
          }
        })
 
      }
    })
  },

三、wx.canvasToTempFilePath(Object object, Object this)下载保存图片(重点在这里,设置正常宽高)

把当前画布指定区域的内容导出生成指定大小的图片。在 draw() 回调里调用该方法才能保证图片导出成功。

参数

/* 保存图片 */
  saveImage: function (e) {
    wx.canvasToTempFilePath({
      x: 0, //指定的画布区域的左上角横坐标	
      y: 0, //指定的画布区域的左上角纵坐标	
      width: 750, //指定的画布区域的宽度
      height: 940, //指定的画布区域的高度
      destWidth: 750, //输出的图片的宽度 
      destHeight: 940, //输出的图片的高度
      canvasId: 'myCanvas',
      fileType: 'jpg', //图片的质量,目前仅对 jpg 有效。取值范围为 (0, 1],不在范围内时当作 1.0 处理。
      quality: 1,
      success: function (res) {
        wx.saveImageToPhotosAlbum({
          filePath: res.tempFilePath,
          success(result) {
            wx.showToast({
              title: '图片保存成功',
              icon: 'success',
              duration: 2000
            })
          }
        })
      }
    })
  },

tips:该文档解决两个问题

(1)文字居中显示

(2)生成图模糊

(3)圆形头像绘制,另一篇文档实际上线项目中手机端头像保存为空,此版本优化。

(6)canva绘制海报时可添加透明背景。
 

// 垂直渐变
const grd = ctx.createLinearGradient(0, 0, 0, ctxH);
grd.addColorStop(0, 'transparent');
grd.addColorStop(1, 'transparent');
ctx.setFillStyle(grd);

<template> <view class="lime-painter" ref="limepainter"> <view v-if="canvasId && size" :style="styles"> <!-- #ifndef APP-NVUE --> <canvas class="lime-painter__canvas" v-if="use2dCanvas" :id="canvasId" type="2d" :style="size"></canvas> <canvas class="lime-painter__canvas" v-else :canvas-id="canvasId" :style="size" :id="canvasId" :width="boardWidth * dpr" :height="boardHeight * dpr"></canvas> <!-- #endif --> <!-- #ifdef APP-NVUE --> <web-view :style="size" ref="webview" src="/uni_modules/lime-painter/static/index.html" class="lime-painter__canvas" @pagefinish="onPageFinish" @error="onError" @onPostMessage="onMessage"> </web-view> <!-- #endif --> </view> <slot /> </view> </template> <script> import { parent } from '../common/relation' import props from './props' import {toPx, base64ToPath, pathToBase64, isBase64, sleep, getImageInfo}from './utils'; // #ifndef APP-NVUE import { compareVersion } from './utils'; import Painter from './painter' // import Painter from '@lime/' const nvue = {} // #endif // #ifdef APP-NVUE import nvue from './nvue' // #endif export default { name: 'lime-painter', mixins: [props, parent('painter'), nvue], data() { return { // #ifdef MP-WEIXIN || MP-TOUTIAO || MP-ALIPAY use2dCanvas: true, // #endif // #ifndef MP-WEIXIN || MP-TOUTIAO || MP-ALIPAY use2dCanvas: false, // #endif canvasHeight: 150, canvasWidth: null, parentWidth: 0, inited: false, progress: 0, firstRender: 0, done: false }; }, computed: { styles() { return `${this.size}${this.customStyle||''};` }, canvasId() { return `l-painter${this._uid || this._.uid}` }, size() { if (this.boardWidth && this.boardHeight) { return `width:${this.boardWidth}px; height: ${this.boardHeight}px;`; } }, dpr() { return this.pixelRatio || uni.getAppBaseInfo().pixelRatio; //todo ivan getSystemInfoSync }, boardWidth() { cons
最新发布
03-14
<think>好的,用户的问题是关于如何正确配置和使用lime-painter自定义组件,特别是涉及canvas和web-view的兼容性处理以及Painter的实现逻辑。我需要先了解lime-painter的基本信息,然后结合用户提供的引用内容,找出相关的实现细节和常见问题。 首先,根据引用[^1],lime-painter是基于Vue-cli、uni-app、Vue2和uView开发的,用于生成海报。用户提到的功能包括生成带个人信息的海报分享到微信好友、收藏和保存到相册。因此,配置步骤可能涉及这些框架的使用。 接下来,配置步骤可能包括安装依赖、引入组件、处理兼容性。uni-app在处理不同平台(如H5和小程序)时,可能需要条件编译,特别是web-view的使用。例如,小程序中可能需要使用原生组件,而H5使用HTML5的canvas,这需要不同的配置。 兼容性处理方面,需要注意不同平台的canvas差异。uni-app的API如uni.canvasToTempFilePath在不同平台的行为可能不同,需要参数调整。此外,图片跨域问题在H5中常见,需要设置crossOrigin属性和服务器CORS配置。 关于Painter实现逻辑,数据驱动绘制是关键。用户需要定义JSON配置来描述海报元素的位置和样式,然后lime-painter解析并渲染到canvas。性能优化方面,可能需要图片预加载和离屏canvas来减少重复渲染。 最后,用户可能需要示例代码来展示基本配置和数据传递。同时,要提醒常见问题,如层级问题、动态内容处理和真机调试的重要性。需要确保回答结构清晰,分步骤说明,并引用提供的资料。</think>### 如何配置和使用 lime-painter 自定义组件 #### 一、基础配置步骤 1. **依赖安装与引入** 在 `vue.config.js` 中添加 `transpileDependencies` 配置以兼容 uni-app: ```javascript transpileDependencies: ['lime-painter'] ``` 在页面中局部注册组件: ```vue import LimePainter from 'lime-painter' export default { components: { LimePainter } } ``` 2. **组件模板声明** 通过 `ref` 获取实例并指定画布类型: ```vue <lime-painter ref="painter" type="2d" :board="posterData" @success="onRenderSuccess" @fail="onRenderFail" /> ``` 3. **平台兼容处理** - **小程序端**:需在 `manifest.json` 中声明 `web-view` 组件权限 - **H5 端**:通过 `<canvas>` 原生标签渲染,需添加 CSS 容器尺寸限制: ```css .canvas-container { width: 100vw; height: 80vh; } ``` #### 二、关键兼容性解决方案 1. **Canvas 渲染差异** - 使用 `uni.canvasToTempFilePath` 时需显式传递 `canvasId` 参数 - 安卓端需添加延迟渲染逻辑: ```javascript setTimeout(() => { this.$refs.painter.render() }, 300) ``` 2. **跨平台图像处理** - 实现图片预加载拦截器: ```javascript LimePainter.setPreloader((url) => { return new Promise((resolve) => { uni.downloadFile({ url, success: res => resolve(res.tempFilePath) }) }) }) ``` 3. **微信分享封装** 封装多平台分享逻辑: ```javascript const shareType = uni.getSystemInfoSync().platform === 'android' ? 'base64' : 'file' ``` #### 三、Painter 核心实现逻辑 1. **DSL 解析引擎** 采用 JSON 驱动的布局系统: ```json { "views": [ { "type": "image", "src": "/static/logo.png", "css": {"top": "20rpx","left": "20rpx","width": "100rpx"} } ] } ``` 2. **混合渲染管道** 实现层级合并优化算法: ```javascript function mergeLayers(baseLayer, dynamicLayer) { return [...baseLayer.views, ...dynamicLayer.views] .sort((a,b) => a.zIndex - b.zIndex) } ``` 3. **自适应布局系统** 通过百分比计算实现响应式布局: ```javascript function calcRelativeSize(val, base) { return val.includes('%') ? base * parseFloat(val)/100 : parseFloat(val) } ``` #### 四、典型问题解决方案 1. **iOS 模糊问题** 添加像素比适配逻辑: ```javascript const dpr = uni.getSystemInfoSync().pixelRatio ctx.scale(dpr, dpr) ``` 2. **文字溢出处理** 实现文本截断算法: ```javascript function ellipsisText(ctx, text, maxWidth) { let width = ctx.measureText(text).width if (width <= maxWidth) return text return ellipsisText(ctx, text.slice(0,-1), maxWidth) + '...' } ``` 3. **跨端保存策略** 封装统一保存接口: ```javascript function universalSave(path) { if (process.env.VUE_APP_PLATFORM === 'h5') { const link = document.createElement('a') link.href = path link.download = 'poster.png' link.click() } else { uni.saveImageToPhotosAlbum({ filePath: path }) } } ``` >[!NOTE] >具体实现需参考项目最新文档,部分 API 可能随版本迭代变更[^1]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值