优秀的编程知识分享平台

网站首页 > 技术文章 正文

关于canvas的那些东西(canvas例子)

nanyue 2024-09-10 16:14:15 技术文章 5 ℃

canvas画图问题


  1. drawImage()、getImageData()或toDataURL()操作图片时,有时会遇到跨域问题,首先服务器允许跨域的图片基本上都可以drawImage到画布上,但想获取图片信息时,会报跨域问题,增加img.crossOrigin = ''即可,虽然js代码这里设置的是空字符串,实际上起作用的属性值是anonymous.


2. 绘制字体自动换行实现,如何让canvas支持自动换行?原理的核心是measureText(text)这个API,可以用来测量文本的一些数据 ,此方法返回的字符宽度值非常精确,下面就是扩展的文本自动换行方法JS代码:


CanvasRenderingContext2D.prototype.wrapText = function (text, x, y, maxWidth, lineHeight) {
    if (typeof text != 'string' || typeof x != 'number' || typeof y != 'number') {
        return;
    }
    
    var context = this;
    var canvas = context.canvas;
    
    if (typeof maxWidth == 'undefined') {
        maxWidth = (canvas && canvas.width) || 300;
    }
    if (typeof lineHeight == 'undefined') {
        lineHeight = (canvas && parseInt(window.getComputedStyle(canvas).lineHeight)) || parseInt(window.getComputedStyle(document.body).lineHeight);
    }
    
    // 字符分隔为数组
    var arrText = text.split('');
    var line = '';
    
    for (var n = 0; n < arrText.length; n++) {
        var testLine = line + arrText[n];
        var metrics = context.measureText(testLine);
        var testWidth = metrics.width;
        if (testWidth > maxWidth && n > 0) {
            context.fillText(line, x, y);
            line = arrText[n];
            y += lineHeight;
        } else {
            line = testLine;
        }
    }
    context.fillText(line, x, y);
};复制代码


其中text, x, y 3个参数和fillText()方法中的这3个参数含义是一样的。而maxWidth表示最大需要换行的宽度,此参数可缺省,默认会使用canvas画布的width宽度作为maxWidth;lineHeight表示行高,默认会使用<canvas>元素在DOM中继承的line-height作为行高。 用法很简单,使用wrapText代替原生的fillText即可! 详情=> 张大大

3. 图片画到画布上后,有的电脑会出现画布模糊问题

原因是设备的devicePixelRatio值不同,(该 Window 属性 devicePixelRatio 能够返回当前显示设备的物理像素分辨率与 CSS 像素分辨率的比率。此值也可以解释为像素大小的比率:一个 CSS 像素的大小与一个物理像素的大小的比值。简单地说,这告诉浏览器应该使用多少个屏幕的实际像素来绘制单个 CSS 像素。这在处理标准显示与 HiDPI 或 Retina 显示之间的差异时很有用,它使用更多屏幕像素绘制相同对象,从而产生更清晰的图像。)一些高清屏上会出现画面模糊,解决放法:无论devicePixelRatio值为多少、统一将canvas节点的width属性设置为其csswidth属性的两倍,将height属性也设置为cssheight属性的两倍,因为canvas属性width和css中width表达的含义是不同的,这样整个canvas的坐标系范围就扩大为两倍,但是在浏览器的显示大小没有变,canvas画图的时候,按照扩大化的坐标系来显示,不清晰的问题就得以改善了。


<canvas width="320" height="180" style="width:160px;height:90px;"></canvas>


4、上传图片方向的问题,有时候上传图片是有方向要求的,比如必须上传正向人像照片,这时就需要注意了 ,因为不同手机之间是存在兼容性问题的,这里推荐一个插件,读取图像方向信息 exif.js 一把吧图片信息传给后端后 ,后端会返回你需要的各种方向的图片,

5、 利用canvas实现图片压缩上传,先上代码,解释基本都注释了

//压缩
canvasImg(url,name){  
 let canva=document.createElement('canvas'),oImg=new Image();  
 oImg.crossOrigin = ''; 
 oImg.onload=()=>{    
//根据原图大小设置画布高最高720,宽最宽1080,小于这个尺寸的不考虑,然后等比例缩放 ,根据需求自定义
  oImg.width <= oImg.height ? canva.height=720 : canva.width=1080;   
  oImg.width <= oImg.height ? canva.width=720*oImg.width/oImg.height : canva.height=1080*oImg.height/oImg.width;
  console.log(canva.width,canva.height)    
  const cantext=canva.getContext('2d')     
  cantext.drawImage(oImg,0,0,canva.width,canva.height) //吧原图缩放后画到画布上    
  canva.toBlob((blob)=>{ //然后转为blob数据准备上传      
     let param = new FormData(); 
     param.append('file', blob, '111.jpg');  
     param.set('orientation',this.imgInfo); //=增加了一个图片方向参数  
    uploadImgApi(param).then(res=>{ //上传      
    if(!res.code){ //获取返回值           
       this.fileId = res.data.fileId;         
      }else  {     
          Toast({duration: 1500, message: res.msg})   
      }    
     }).catch(err=>{  
         Toast.clear()     
          console.log(err)   
     })     
 },'image/jpeg')  
 }  
 oImg.src=url
}

canvas实现橡皮擦,还原图片等功能

1、橡皮擦功能,先上代码,

主要用到的是canvsa中 save()、ctx.beginPath()、 ctx.arc()、ctx.clip()、ctx.clearRect()、ctx.restore()等相关方法,具体含义与作用 可以去官网查看 点这里;

 //画图
  let oImg=new Image(),cans=document.getElementById('canvas');    const ctx=cans.getContext('2d');  
  oImg.crossOrigin='';  
  oImg.onload=function(){   
    cans.width=oImg.width;    
    cans.height=oImg.height;    
    ctx.drawImage(oImg,0,0);   
};   
 oImg.src="http://deeplor.oss-cn-hangzhou.aliyuncs.com/matting_original/2019/11/15/824e91700851429eb71c8a6a474dd065.png";

cans.onmousedown=function(e){//按下事件
    document.onmousemove=(e)=>{//移动事件
        const ev=e || window.event,r=10;//r是擦除范围的半径
        let x=ev.clientX-cans.offsetLeft;
        let y=ev.clientY-cans.offsetTop;
        ctx.save();
        ctx.beginPath();
        ctx.arc( x, y,r, 0, Math.PI * 2, false );
        ctx.clip();
        ctx.clearRect( 0, 0, cans.width, cans.height );
        ctx.restore();
    }
    document.onmouseup=(e)=>{//鼠标弹起事件
        document.onmousemove=null;
        document.onmouseup=null;
    }}

2、实现图片还原功能(画笔功能类似,只不过不画图换成画线)

就是在画布上按照鼠标的轨迹一点点吧图片画上画布上面去。先上代码,这里需要注意的是在画图之前一定要确保图片已经onload了

  let oImg=new Image(),cans=document.getElementById('canvas');
    const ctx=cans.getContext('2d');  
  oImg.crossOrigin='';  
  oImg.onload=function(){   
    cans.width=oImg.width;    
    cans.height=oImg.height;    
    cans.onmousedown=function(e){
    document.onmousemove=(e)=>{
        const ev=e || window.event,r=10;//r是还原范围的半径
        let x=ev.clientX-cans.offsetLeft;
        let y=ev.clientY-cans.offsetTop;
        ctx.save();
        ctx.beginPath();
        ctx.arc( x, y, r, 0, Math.PI * 2, false );
        ctx.clip();
        ctx.drawImage( oImg, 0, 0, cans.width, cans.height )
        ctx.restore();
    }
    document.onmouseup=(e)=>{
        document.onmousemove=null;
        document.onmouseup=null;
    }}
};   
 oImg.src="http://deeplor.oss-cn-hangzhou.aliyuncs.com/matting_original/2019/11/15/824e91700851429eb71c8a6a474dd065.png";

canvas导出图片并下载兼容性问题

一般下载图片是利用canvas的toDataURL()方法导出base64地址在利用a标签download属性下载的,单数在ie上有兼容性问题,解决方法、此方法可以解决高版本id游览器,低版本的有问题可以去参考官网的 ,这里不再赘述 点这里

总结

其实canvas还有很多问题,不过大多数都是能查到的,这些问题呢,都是不太能查到的,我是结合查询了总结出的一些问题,对于我而言是学习到了,接下来会研究下canvas一些特效,canvas是可以实现很多我们意想不到的效果的,期待以后的学习

Tags:

最近发表
标签列表