H5canvas(保存图片,globalCompositeOperation)

保存图片

前言

canvas是画布的概念,那么canvas在浏览器表现出来的是一张图片

那么我们可以把这张图片右键保存(把canvas以图片的形式保存)(保存的图片格式是png(底部的透明的) )

那么怎么用js代码下载canvas图片

先在canvas上面画出一个实心圆来吧

CSS样式代码

<style>
    *{
        margin:0;
        padding:0;
    }
    canvas{
        display: block;
        margin: 50px auto;
        border: 2px  blue solid;
    }

</style>

HTML和JS代码

<body>
    <canvas id="canvas1" width="500" height="500"></canvas>
    <script>
        var canvas = document.getElementById('canvas1');
        var cxt = canvas.getContext('2d');
        //绘画一个圆
        cxt.beginPath();
        cxt.arc(250,250,250,0,Math.PI*2);
        cxt.fill();
    </script>
</body>

方法一 通过todataURL转换成base64位的字符串赋值给了href(缺点base65位的字符串太大了)

基础知识

  1.  canvas节点.toDataURL(),方法返回结果是base64位的字符串(这些字符串的结果就是一张图片)
  2. a节点.download,通过a标签的download修改了下载图片的名字

  3. a节点.click(),表示在JS脚本内部手动点击a标签(a标签独有)

把需要下载的图片放到一个函数里,让这个函数先执行,然后创建一个a标签,在用toDataURL方法获取到base64位的字符赋值给a标签的href属性,在通过a标签的download属性修改下载图片的名字,在通过click函数自动点击图下载

var canvas = document.getElementById('canvas1');
var cxt = canvas.getContext('2d');
//绘画一个圆
cxt.beginPath();
cxt.arc(250,250,250,0,Math.PI*2);
cxt.fill();

download();
function download(){
    //创建一个a标签
    var link = document.createElement('a');

    // canvas.toDataURL()函数执行时 返回结果是base64位的字符串 这些字符串的结果就是一张图片
    //把a标签的href属性赋值到canvas图片的地址
    link.href = canvas.toDataURL();

    // 通过a标签的download属性修改下载图片的名字
    link.download = 'canvas.png';

    //让a标签的click函数,直接下载图片
    link.click();//这句代码的作用就是相当于手动点击a标签
};

方法二 通过Bole构造函数生成一个图片对象在进行操作

基础知识

  1. canvas节点.toBlob函数执行,能够把canvas节点变成Bolb数据

  2. canvas节点.toBlob()函数执行时内部支持回调函数 ,第一参数就存储着当画布被转换成Bolb数据时就把Bolb数据给这个参数

  3. URL.createObjectURL(Blob数据);  把Blob数据传递到URL.createObjectURL生成一个URL

把需要下载的图片放到一个函数里,让这个函数先执行,在调用canvas节点上面的toBlob函数,当函数执行时传递一个参数这个参数就是Blob数据,然后把blob数据传递到URL.createObjectURL生成一个URL,然后在创建一个a标签在把a标签的href属性赋值到url里用download属性修改一下下载图片的名字,然后在JS内部click自动点击一次就好了

var canvas = document.getElementById('canvas1');
var cxt = canvas.getContext('2d');
//绘画一个圆
cxt.beginPath();
cxt.arc(250,250,250,0,Math.PI*2);
cxt.fill();
downBolb()
function downBolb() {
    //canvas.toBlob函数能够把这个画布变成Bolb数据
    
    //当画布转换成Blob数据时触发回调函数
    canvas.toBlob((blob) => {
        //把blob传递到URL.createObjectURL生成一个URL
        var url = URL.createObjectURL(blob);

        //创建一个a标签
        var link = document.createElement('a');
        //把a标签的href属性赋值到生成好了的url
        link.href = url;

        //通过a标签的download属性修改下载图片的名字
        link.download = 'blob.png';
        //让a标签的click函数,直接下载图片
        link.click();
    })
}

globalCompositeOperation

基础知识

设置画布的透明度

  1. 画笔.globalAlpha//查询当前画布的透明度(默认是1)

  2. 画笔.globalAlpha = 数值(0-1); 设置当前画布的透明度

var canvas = document.getElementById('canvas');
var cxt = canvas.getContext('2d');
//设置画布的透明度
//cxt.globalAlpha(0-1)透明度
console.log(cxt.globalAlpha);//查询当前画布的透明度(默认是1)
cxt.globalAlpha = 0.2;//设置当前画布的透明度 
//绘制矩形
cxt.fillRect(0,0,100,100);
//绘制圆
cxt.beginPath();
cxt.fillStyle = 'pink';
cxt.arc(100,100,100,0,Math.PI*2);
cxt.fill();

globalCompositeOperation

globalCompositeOperation表示融合的部分 Composite(融合) Operation(操作活动)

可以通过通过属性来设置两个图片融合的部分

globalCompositeOperation 设置两个图片的重合部分的显示情况

目标图像和源图像

以cxt.globalCompositeOperation这句代码为分割点

  • 上面的一个图形(路径)叫做目标图像

  • 下面的一个图形(路径)叫做源图像

globalCompositeOperation一般是写在beginPath之前的

基础知识

cxt.globalCompositeOperation  设置两个图片的重合部分的显示情况

source-over 默认  源图像在上面

  1. source-atop     超过目标图像的源图像全都不可见  目标图像是可见的

  2. source-in       只有在目标图像之内的源图像是可见的 目标图像是不见的

  3. source-out      只有在目标图像之外的源图像是可见的 目标图像是不见的

destination-over  目标图像在上面

  1. destination-atop  超过源图像的目标图像全都不可见  源图像是可见的

  2.  destination-in    只有在源图像之内的目标图像是可见的 源图像是不见的

  3. destination-out   只有在源图像之外的目标图像是可见的 源图像是不见的

 xor 设置两个图像重合的部分透明

var canvas = document.getElementById('canvas1');
var cxt = canvas.getContext('2d');
//目标图像
cxt.fillRect(0,0,100,100);

// cxt.globalCompositeOperation('source-over'); 
//source-over原图像在上面(默认值)   source(表示源) over(上面)
// cxt.globalCompositeOperation('source-atop');
//source-atop目标图像超过原图像的部分都不可见  atop(上顶)
// cxt.globalCompositeOperation('source-in');
//source-in 只要在目标之内的源图像是可见的  in(在..内)
// cxt.globalCompositeOperation('source-out');
//source-out  超过目标图像之外的源图像是可见的  out(出来)


// cxt.globalCompositeOperation('destination-over'); 
//destination-over目标图像在上面 destination(目的地)
// cxt.globalCompositeOperation('destination-atop'); 
//destination-atop 超过源图像的目标图像全都不可见
// cxt.globalCompositeOperation('destination-in'); 
// destination-in   只有在源图像之内的目标图像是可见的 源图像是不见的
// cxt.globalCompositeOperation('destination-out'); 
//destination-out  只有在源图像之外的目标图像是可见的 源图像是不见的

cxt.globalCompositeOperation('xor');         
// xor设置两个图像重合的部分透明

cxt.beginPath();
// 源图像
cxt.fillStyle = 'pink';
cxt.arc(100,100,100,0,Math.PI*2);
cxt.fill();

补充(清除画布)

  1. 清除画布 clearRect(x,y,w,h)
  2. cxt.clearRect(清除图片的水平距离,清除图片的竖直距离,清除宽度,清除高度)

var canvas = document.getElementById('canvas1');
var cxt = canvas.getContext('2d');
cxt.fillRect(0,0,500,500);
//在水平方向为0和竖直方向为0,清除范围为宽200高200
//清除画布
cxt.clearRect(0,0,200,200);

练习canvas时钟

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        *{
            margin:0;
            padding: 0;
        }

        canvas{
            display: block;
            border:2px solid blue;
            margin:50px auto;
            border-radius: 50%;
        }
    </style>
</head>
<body>
    <canvas id="canvas" width="500" height="500"></canvas>
    
    <script>
    	var canvas = document.getElementById('canvas');
    	var cxt = canvas.getContext('2d');
    	function getTime(){
    		//修改时针的背景颜色
    		canvas.style.backgroundColor = "#" + Math.random().toString(16).slice(2,8)

    		//清除长方形(清除图形)
    		//cxt.clearRect(清除图片的水平距离,清除图片的竖直距离,清除宽度,清除高度)
    		// 清除画布 clearRect(x,y,w,h)
    		cxt.clearRect(0,0,500,500);

            //绘制外部的大圆形
            cxt.strokeStyle = 'red';//设置画笔的颜色
            cxt.lineWidth = 2;//设置画笔的线宽
            cxt.beginPath();//闭合上一次路径
            cxt.arc(250, 250, 250, 0, Math.PI * 2);//绘制圆形轨迹
            cxt.closePath();//闭合下一次路径
            cxt.stroke();//绘制空心圆形

            //绘制内部的圆饼
            cxt.beginPath();
            cxt.fillStyle = 'blue';
            cxt.arc(250, 250, 10, 0, Math.PI * 2);
            cxt.closePath();
            cxt.fill();//绘制实心的圆形
            //通过fill画出空心的圆,其实空心的圆外部还有条圆线可以通过stroke给他画出来
            //绘制圆饼的线条
            cxt.stroke();
    		
    		//绘制指针
            var nowTime = new Date;//获取现在时间
            var h = nowTime.getHours();//获取小时
            var m = nowTime.getMinutes();//获取分钟
            var s = nowTime.getSeconds();//获取秒钟

            //绘制时间文字
            cxt.font = '25px 微软雅黑';
            cxt.fillStyle = 'red';
            cxt.textAlign = 'center';
            cxt.fillText(toTwo(h)+':'+toTwo(m)+':'+ toTwo(s),252,400);

            //处理获取的小时 变成12进制的时间
            h = h>12 ? h-12 : h;

            //12个小时 对应的是 360° 则应该1小时旋转30°
            var rotateH = h*Math.PI/6;
            //60分钟对应的是 360° 则应该1分钟旋转6°
            var rotateM = m*Math.PI/30;
            //60秒对应的是 360° 则应该1秒旋转6°
            var rotateS = s*Math.PI/30;


            for(var i=1;i<=12;i++){//for循环中的变量i是index的缩写
            	cxt.save();//保存上一次画布的状态
            	cxt.translate(250,250);//设置画布(字)的起始位置

            	cxt.fillStyle = 'black';//设置字体的颜色
            	//设置字体
            	cxt.font = '20px 微软雅黑';

            	cxt.textAlign = 'center';
            	cxt.textBaseline = 'middle'

            	var x = 230*Math.sin(Math.PI*i/6)
                var y = 230*Math.cos(Math.PI*i/6)
            	//画出实心的字体
            	cxt.fillText(i,x,-y);

            	cxt.restore();//释放上一次画布的状态
            };

            //绘制时针
            drawPointer({
            	rotate:rotateH,//旋转角度
            	color:'green',//颜色
            	width:5,//针的宽度
            	length:100,//针的长度
            })
            //绘制分针
            drawPointer({
            	rotate:rotateM,//旋转角度
            	color:'blue',//颜色
            	width:4,//针的宽度
            	length:150,//针的长度
            })
            //绘制秒针
            drawPointer({
            	rotate:rotateS,//旋转角度
            	color:'purple',//颜色
            	width:3,//针的宽度
            	length:200,//针的长度
            })
    	}

        //把 1这样的数字变成 01 给个位数补充一个字符串0
        function toTwo(num){
            return num<10 ? '0' + num : num;
        }

    	//绘制分针 时针 秒针
    	function drawPointer(options){
            cxt.save(); 
            cxt.translate(250,250);//设置画布(针)的起始位置
            cxt.beginPath();
            //设置针的旋转角度
            cxt.rotate(options.rotate);
            cxt.strokeStyle = options.color;//设置秒针的颜色
            cxt.lineWidth = options.width;//设置秒针的线宽
            cxt.moveTo(0,0);
            cxt.lineTo(0,-options.length);
            cxt.closePath();
            cxt.stroke();
            cxt.restore();//释放上一次画布的状态

            //cxt.translate和cxt.rotate方法都是有叠加效果的
    	}
    	//开启定时器每个一段时间 获取 时 分秒  
        getTime();
    	setInterval(getTime,1000);
    </script>
</body>
</html>
发布了134 篇原创文章 · 获赞 109 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/qq_44607694/article/details/102155328