Análisis de varios problemas de lienzo (Compatible, actualizado en tiempo real)

wxml:

<view class='warp_'>
 <view class='box_'>
	<view style=''>
  	<canvas canvas-id="myCanvas" style="width:{
   
   {266 * rpx}}px;height:{
   
   {393 * rpx}}px;" />
  	<view style='padding-bottom: 0;box-sizing: border-box;'>
   	 	<view class='note'>* 图片将保存到相册 *</view>
    	<view bindtap='saveImg' class='btn'>保存图片</view>
  	</view>
	</view>
</view>
</view>

wxss:

page{background: #f2f2f2;}
.btn{width: 250rpx;height: 88rpx;line-height: 88rpx;font-size: 28rpx;border-radius: 88rpx;background: #fff;text-align: center;color: #333;margin: 		auto;box-shadow: 0 2px 20px 0 #FFC800;font-weight: bold;}
image{border-radius: 0 !important;}
.note{text-align: center;color: #753300;margin-bottom: 28rpx;font-size: 26rpx;margin-top: 60rpx;opacity: 0.52;}
.warp_{width: 100vw;height: 100vh;display: flex;justify-content: center;align-items: flex-start;padding-top: 40rpx;box-sizing: border-box;line-height: 1.5;}
.warp_ .box_{background: #FFC800;padding: 30rpx;}

js:

Page({
 data: {
 img: "/image/brandBg.png",
 code: "/image/erweima.jpg",
 image: {
  	src: "/image/none.png",
  	width: 46,
  	heigth: 46
	},
	rpx: ''
},

onLoad: function (options) {
 this.canvasImg();
},

// Hacer lienzo

canvasImg() {
let that = this;
var res = wx.getSystemInfoSync()       //获取屏幕宽度
var rpx = res.windowWidth / 375			//计算比例,做兼容

that.setData({
  rpx: res.windowWidth / 375
})

const ctx = wx.createCanvasContext('myCanvas');    //声明页面中的画布id

ctx.setFillStyle('#fff');                             //为创建的canvans上下文添充颜色  如果没有设置 fillStyle,默认颜色为 black。若写成透明,可能会导致画布中的图片出不来
ctx.fillRect(0, 0, 266 * rpx, 393 * rpx)   //设置画布的大小

ctx.save(); // 下面要制作原型图片,需要先保存状态,已便于画完圆再用

//先画个圆  
ctx.arc(35 * rpx, 35 * rpx, 23 * rpx, 0, Math.PI * 2, false);  //false代表顺时针    参数值(圆心的X值,圆心的Y值,圆的半径,圆的七点,圆的终点,顺时针)
ctx.setStrokeStyle('#fff');   //给圆添加个边框,不然会导致圆形不生效   
ctx.stroke();			//结束边框的绘制
ctx.clip();//画了圆 再剪切  原始画布中剪切任意形状和尺寸。一旦剪切了某个区域,则所有之后的绘图都会被限制在被剪切的区域内
ctx.drawImage(that.data.image.src, 12 * rpx, 12 * rpx, that.data.image.width * rpx, that.data.image.heigth * rpx); // 推进去图片,注意:这里的X,Y值为图片本身的左上角的位置,需通过圆的位置计算出准确的图片的位置
ctx.restore(); //恢复之前保存的绘图上下文 恢复之前保存的绘图上下文即状态 可以继续绘制

// 制作圆角矩形
this.roundRect(ctx, 50 * rpx, 80 * rpx, 100 * rpx, 100 * rpx, 10 * rpx);     //参数值(X,Y,width,hieght,r)

//向画布中添加文字,如果需要加粗的文字,可以放到画布的最后,不然会使下面的文字也加粗,以下文字不一一叙述

ctx.setFillStyle("#333");
ctx.setTextAlign('left');                        //是否居中显示,参考点画布中线
ctx.font = 'normal normal 12px PingFang SC';
ctx.fillText('分享给你一个商品', 70 * rpx, 50 * rpx);

//向画布中添加图片
ctx.drawImage(this.data.code, 186 * rpx, 295 * rpx, 70 * rpx, 70 * rpx);

ctx.setFillStyle("#999");
ctx.setFontSize(14 * rpx);                               //字大小
ctx.setTextAlign('left');                        //是否居中显示,参考点画布中线
ctx.fillText('长按图片识别二维码', 10 * rpx, 352 * rpx);


ctx.drawImage(this.data.img, 10 * rpx, 90 * rpx, 246 * rpx, 113 * rpx);

//多行文字
ctx.setFillStyle("#000");
ctx.setTextAlign('left');                        
ctx.font = 'normal bold 16px PingFang SC';
var name = '之前一直在做肉制品供应商,给国内十大火锅连锁店其中的几家在供货,开始不好做,因为那时进口货和假货横行,老百姓都找便宜货,所以横空出现了鸭肉装羊肉的行业悲剧';
this.dealWords({
  ctx: ctx,//画布上下文
  fontSize: 14,//字体大小
  word: name,//需要处理的文字
  maxWidth: 246 * rpx,//一行文字最大宽度
  x: 10 * rpx,//文字在x轴要显示的位置
  y: 218 * rpx,//文字在y轴要显示的位置
  maxLine: 2//文字最多显示的行数
})

//在画布中制作一条线
ctx.setFillStyle('#f2f2f2');
ctx.fillRect(0 * rpx, 276 * rpx, 266 * rpx, 1 * rpx);

//从这开始加粗,以下出现的文字均会加粗
ctx.setFillStyle("#000");
ctx.setTextAlign('left');                        //是否居中显示,参考点画布中线
ctx.font = 'normal bold 16px PingFang SC';
ctx.fillText('王富贵', 70 * rpx, 31 * rpx);

ctx.setFillStyle("#F03523");
ctx.setTextAlign('left');                        //是否居中显示,参考点画布中线
ctx.font = 'normal bold 15px PingFang SC';
ctx.fillText('¥', 10 * rpx, 325 * rpx);

ctx.setFillStyle("#F03523");
ctx.setTextAlign('left');                        //是否居中显示,参考点画布中线
ctx.font = 'normal bold 28px PingFang SC';
ctx.fillText('19.99', 25 * rpx, 325 * rpx);

ctx.draw();    //画布闭合
},

// Varias líneas de texto

 dealWords: function (options) {
	options.ctx.setFontSize(options.fontSize);//设置字体大小
	var allRow = Math.ceil(options.ctx.measureText(options.word).width / options.maxWidth);//实际总共能分多少行
	 var count = allRow >= options.maxLine ? options.maxLine : allRow;//实际能分多少行与设置的最大显示行数比,谁小就用谁做循环次数
 var endPos = 0;//当前字符串的截断点
 for (var j = 0; j < count; j++) {
  var nowStr = options.word.slice(endPos);//当前剩余的字符串
  var rowWid = 0;//每一行当前宽度  
  if (options.ctx.measureText(nowStr).width > options.maxWidth) {//如果当前的字符串宽度大于最大宽度,然后开始截取
    for (var m = 0; m < nowStr.length; m++) {
      rowWid += options.ctx.measureText(nowStr[m]).width;//当前字符串总宽度
      if (rowWid > options.maxWidth) {
        if (j === options.maxLine - 1) { //如果是最后一行
          options.ctx.fillText(nowStr.slice(0, m - 1) + '...', options.x, options.y + (j + 1) * 18);  //(j+1)*18这是每一行的高度    
        } else {
          options.ctx.fillText(nowStr.slice(0, m), options.x, options.y + (j + 1) * 18);
        }
        endPos += m;//下次截断点
        break;
      }
    }
  } else {//如果当前的字符串宽度小于最大宽度就直接输出
    options.ctx.fillText(nowStr.slice(0), options.x, options.y + (j + 1) * 18);
  }
}
 },

/ **

  • 制作圆角
    
  • @param {CanvasContext} ctx contexto del lienzo

  • @param {número} x La coordenada x de la esquina superior izquierda de la selección del rectángulo redondeado

  • @param {número} y La coordenada y de la esquina superior izquierda de la selección del rectángulo redondeado

  • @param {número} w El ancho de la selección del rectángulo redondeado

  • @param {número} h La altura de la selección del rectángulo redondeado

  • @param {número} r radio de la esquina redondeada
    * /

    // La esquina redondeada hace referencia a this.roundRect (ctx, 50 * rpx, 80 * rpx, 100 * rpx, 100 * rpx, 10 * rpx);

      roundRect(ctx, x, y, w, h, r) {
      	ctx.save();
      	// 开始绘制
      	ctx.beginPath()
      	 // 因为边缘描边存在锯齿,最好指定使用 transparent 填充
      	// 这里是使用 fill 还是 stroke都可以,二选一即可
       ctx.setFillStyle('red')
      // 左上角
      ctx.arc(x + r, y + r, r, Math.PI, Math.PI * 1.5)
      // border-top
      ctx.moveTo(x + r, y)
      ctx.lineTo(x + w - r, y)
      ctx.lineTo(x + w, y + r)
      // 右上角
      ctx.arc(x + w - r, y + r, r, Math.PI * 1.5, Math.PI * 2)
      // border-right
      ctx.lineTo(x + w, y + h - r)
      ctx.lineTo(x + w - r, y + h)
      // 右下角
      ctx.arc(x + w - r, y + h - r, r, 0, Math.PI * 0.5)
      // border-bottom
      ctx.lineTo(x + r, y + h)
      ctx.lineTo(x, y + h - r)
      // 左下角
      ctx.arc(x + r, y + h - r, r, Math.PI * 0.5, Math.PI)
      // border-left
      ctx.lineTo(x, y + r)
      ctx.lineTo(x + r, y)
       // 这里是使用 fill 还是 stroke都可以,二选一即可,但是需要与上面对应
      ctx.fill()
      // ctx.stroke()
      ctx.closePath()
      // 剪切
      ctx.clip()
      ctx.restore();
      },
    

    // Guarde el evento de clic de la imagen

      saveImg() {
       let that = this;
      var res = wx.getSystemInfoSync()
      var rpx = res.windowWidth / 375
      that.setData({
    		rpx: res.windowWidth / 375
       })
      wx.canvasToTempFilePath({
       x: 0,
    	y: 0,
       width: 266 * rpx,                     //画布宽高
    	height: 393 * rpx,
       destWidth: 798 * rpx,                 //画布宽高*dpr 以iphone6为准
    	destHeight: 1179 * rpx,                //放大2倍以上,解决保存的图片模糊的问题
    	canvasId: 'myCanvas',
    	success: function (res) {
      	console.log(res.tempFilePath) //生成的临时图片路径
      	wx.saveImageToPhotosAlbum({
       	 filePath: res.tempFilePath,
        	success: function (res) {
         		 console.log(res);
          	wx.showToast({
            	title: '保存成功',
         	 })
       	 },
        	fail: function () {
          	console.log('a')
            }
     	 })
    	}
      })
      }
      })
    

Caso:
Inserte la descripción de la imagen aquí

Información adicional, espero poder ayudarte:

  1. Si hay varias líneas de texto en el lienzo, es posible que sea necesario determinar si el texto se muestra en una o dos líneas. Puede juzgar el ancho del texto. No se recomienda juzgar por el número de palabras. Si aparece en inglés, el ancho de la cadena puede ser incorrecto;

    var name = '假装这里有一大段文字'
    const width = ctx.measureText(name).width
    console.log(width)
    
    //让文字的宽度与上面多行文本的宽度相比,可用判断设置文字单行和多行时的位置
    
  2. Cuando el texto debe colocarse encima de la imagen, la imagen es una imagen de red cargada, puede parecer que la imagen se carga lentamente, cubriendo el texto sobre la imagen; la
    respuesta: simplemente coloque el texto en la función del evento de carga de imagen exitoso, deje Una vez que la imagen se haya cargado correctamente, ejecute el dibujo del texto en la imagen;

  3. Cuando necesite juzgar la visualización y la ocultación del lienzo, no puede usar wx: if = '' para juzgar la visualización o la ocultación, porque no habrá ningún problema al cargar por primera vez, pero no hay contenido cuando vuelva a hacer clic. Se recomienda configurar el lienzo en la pantalla con posicionamiento CSS Además, haga clic para volver al área que debería aparecer, o use el atributo hidden = '' para determinar si mostrar u ocultar;

Supongo que te gusta

Origin blog.csdn.net/jiaodeqiangs/article/details/91439165
Recomendado
Clasificación