canvas画海报

实现了canvas画海报并修复多图片异步加载,绘制完成回调

由vue的vue-canvas-poster改造及完善通用js版

2020-10-12 //修復儅父元素未设置宽高的页面卡死的情况

使用示例

var tct = new TB_CanvasTools({
            	
            	//包裹图片的jq对象
            	"pcontent":$("#hb"),
            	//背景颜色
            	"backgroundColor":"#fff",
            	//渲染完成回调事件
            	"callback":function(params){
            		
            		var imageBase64 = params.imageBase64;console.log(imageBase64);
            		$("#hbImage").attr("src",imageBase64);
            	}
            	
            });
            
            //要画的元素集
            var views = [{
            	//类型 image/text
                type: 'image',
                //如果是图片的话,图片地址
                url: '${ctxStatic}/newcontract4.0/images/dianxin_logo_icon.png',
                //css,这里的值都是比例
                css: {
                    top: 0.05,
                    left: 0.05,
                    width: 0.3
                },
                list: [{
                    type: 'image',
                    url: '${ctxStatic}/newcontract4.0/images/haibao.png',
                    css: {
                        top: 0.15,
                        left: 0.05,
                        width: 0.9
                    }
                },
                {
                     type: 'text',
                     text: `今天你消费 我买单!`,
                     css: {
                         color: '#FF9601',
                         fontSize: 20,
                         top: 0.8,
                         left: 0.05
                     }
                 }]
            }]
            
            tct.drawCanvas({
            	
            	"views":views
            	
            });

 

工具代码

var TB_CanvasTools = function(params){
	
	var $this = this;
	
	if(!params){
		params = {};
	}
	
	//包裹图片的元素jq对象
	var pcontent = params.pcontent;
	var backgroundColor = params.backgroundColor;
    var callback = params.callback;
	
	$this.pcontent = pcontent;
	$this.backgroundColor = backgroundColor;
	$this.callback = callback;
	
	//canvas 的宽和高
	$this.width = $this.pcontent.width();
	$this.height = $this.pcontent.height();
    //修復儅父元素为设置宽高的情况
    if($this.width == 0 && $this.height == 0){
		
		$this.width = 400;
		$this.height = 400;
		
	}
	
	$this.width = ($this.width == 0?$this.height:$this.width);
	$this.height = ($this.height == 0?$this.width:$this.height);
	
	//要绘制的内容数
	$this.viewsSize = 0;
	
	//创建canvas对象
	var canvas=document.createElement("canvas");
	canvas.width=$this.width;
	canvas.height=$this.height;
	
	var ctx = canvas.getContext("2d");
	$this.ctx = ctx;
	$this.canvas = canvas;
	
	$this.ctx.rect(0, 0, $this.width, $this.height);
    $this.ctx.fillStyle = $this.backgroundColor;
    $this.ctx.fill();
	
    //进行绘制的方法
    $this.drawCanvas = function(params){
    	
      $this.views = params.views;	
      
      if(!params){
    	  params = {}
      }
    
      $this.viewsSize = 0;
      
      $this.views.forEach(cur => {
    	initViewSize(cur);
      })
      
      $this.views.forEach(cur => {
        drawView(cur)
      })
    }
    
    //绘制图片
    var _drawImage = function(view){
    	
		 if(!view.url){
		   return ;
		 }
		 let {
		   top,left,width,height
		 } = view.css;
		 
		 var image = view.image;
		 var iw = image.width;
		 var ih = image.height;
		 //计算宽高
		 width = getWidth(width);
		 //height = getHeight(height);
		 height = width/iw*ih;
		 top = getHeight(top);
		 left = getWidth(left);
		 
		 if (typeof view.url === 'string') {
		   $this.ctx.fillStyle = '#ddd'
		   $this.ctx.fillRect(left, top, width, height);
		   $this.ctx.restore()
		   return
		 }
		 $this.ctx.save();
		 
		 $this.ctx.drawImage(view.url, left, top, width, height);
		 $this.ctx.restore();
		 
		 //绘制记录数减一
		 $this.viewsSize--;
		 if($this.viewsSize == 0){
			 //如果记录数减为0则回调
		 	  finish();
		 }
		 
		 //绘制子
		 if (view.list && view.list.length > 0) {
		   view.list.forEach(cur => drawView(cur))
		 }
    }
    
    /**
     * 绘制文字 
     **/
    var _drawText = function(view, ctx) {
    	
      let css = {
        color: '#333333',
        lineHeight: 30,
        textAlign: 'start',
        maxLines: 3,
        fontSize: 20,
        top: 0,
        left: 0,
        width: 1,
        textBaseline: 'alphabetic'
      }
      
      css = { ...css, ...view.css };

      //设置宽
      css.width = getWidth(css.width);
	  css.top = getHeight(css.top);
	  css.left = getWidth(css.left);
      
      $this.ctx.save();
      $this.ctx.textAlign  = css.textAlign;
      $this.ctx.textBaseline = css.textBaseline;
      $this.ctx.fillStyle = css.color;
      $this.ctx.font = css.fontSize + 'px  Arial';
      let result = breakLinesForCanvas(view.text, css.width, ctx);
      for (let i = 0; i < result.length; i++) {
    	  
        if (i <= css.maxLines - 1) {
          let str = result[i];
          if ((i === css.maxLines - 1) && ($this.ctx.measureText(str+"...").width > css.width)) {
            result[i] = str.substring(0, str.length - 1)+"...";
          }
        } else {
          break;
        }
        $this.ctx.fillText(result[i], css.left, css.top + i * css.lineHeight, css.width);
      }
      $this.ctx.restore();

      $this.viewsSize--;
      if($this.viewsSize == 0){
    	  finish();
      }
      if(view.list && view.list.length > 0){
        view.list.forEach(cur => drawView(cur))
      }
    };
    
	/**
	 * 
	 * ==================================function====================================
	 * 
	 */
	/**
	 * 获取内容的宽
	 * 
	 * @params widthScale 宽的比例
	 */
	var getWidth = function(widthScale){
		
		return widthScale*$this.width;
		
	}
	
	/**
	 * 获取内容的高
	 * 
	 * @params heightScale 高的比例
	 */
	var getHeight = function(heightScale){
		
		return heightScale*$this.height;
		
	}
	
	/**
     * 打断文本,返回给canvas绘制
     * */
    var breakLinesForCanvas = function(text, width, ctx) {
    	
      let result = [];
      let breakPoint = 0;
      while ((breakPoint = findBreakPoint(text, width, ctx)) !== -1) {
        result.push(text.substr(0, breakPoint));
        text = text.substr(breakPoint);
      }

      if (text) {
        result.push(text);
      }
      return result;
    }
    
    /**
     * 获取文本换行断点
     * */
    var findBreakPoint = function(text, width, ctx) {
      var min = 0;
      var max = text.length - 1;
      while (min <= max) {
        var middle = Math.floor((min + max) / 2);
        var middleWidth = $this.ctx.measureText(text.substr(0, middle)).width;
        var oneCharWiderThanMiddleWidth = $this.ctx.measureText(text.substr(0, middle + 1)).width;
        if (middleWidth <= width && oneCharWiderThanMiddleWidth > width) {
          return middle;
        }
        if (middleWidth < width) {
          min = middle + 1;
        } else {
          max = middle - 1;
        }
      }
      return -1;
    }
    
    /**
     * 绘制
     */
    var drawView = function(cur){
    	
    	var $this = this;
    	
      switch (cur.type) {
        case 'image':
          if (cur.url) {
            downloadImage(cur.url).then(image => {
              cur.url = image;
              cur.image = image;
              _drawImage(cur);
            });
          }
          break;
        case 'text':
        	_drawText(cur, this.ctx)
          break;
        default:
          break;
      }
    }
    
   /**
    * 绘制完成后
    */
    var finish = function(){
    	
    	var imageBase64 = $this.canvas.toDataURL('image/png')
    	//回调
    	if($this.callback){
    		$this.callback({
    			
    			"imageBase64":imageBase64
    			
    		});
    	}
    }
    
    /**
     * 
     * 初始化内容元素数量
     * 
     */
    var initViewSize = function(view){

        $this.viewsSize++;
    	
    	if(view.list){

    		view.list.forEach(cur => initViewSize(cur))
    		
    	}
    }
    
    var downloadImage = function(src){
        return new Promise((resolve, reject) => {
          if (src.startsWith('#')) {
            resolve(src)
            return
          }
          const img = new Image()
          img.onload = () => resolve(img)
          img.onerror = () => reject(`下载图片失败`+src)
          img.crossOrigin = 'anonymous'
          img.src = src
          if (img.complete === true) {
            setTimeout(() => resolve(img), 500)
          }
        })
      }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
在uniapp中,你可以使用canvas来绘制和生成海报。首先,你需要将网络图片下载到本地,可以使用uni.downloadFile函数来实现。使用该函数将网络图片下载到本地后,你可以将其转换为base64格式。你可以使用pathToBase64函数将图片路径转换为base64编码。接下来,你可以使用canvas渲染海报,将下载并转换后的图片绘制在canvas上。最后,你可以通过uni.canvasToTempFilePath函数将canvas导出为临时文件,从而生成海报。你可以将导出的海报保存到本地或者分享给其他用户。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [uniapp 生成海报图片base64转换 ](https://download.csdn.net/download/qq_36003998/12330793)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [uniapp使用canvas海报](https://blog.csdn.net/Yadira9/article/details/128726482)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [uniapp使用canvas海报二维码](https://blog.csdn.net/Blue54/article/details/124832963)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值