zoukankan      html  css  js  c++  java
  • 一步一步教大家用canvas做 图片滑动解锁

    几天有需求做滑动解锁,想来点新鲜的,于是想挑战一下,cavas做图片滑动解锁;

    原文链接:https://www.jb51.net/article/137129.htm

    我们想实现这样的效果:

     首先随便找一张图片渲染到canvas上,这里#canvas作为画布,#block作为裁剪出来的小滑块。

    <canvas width="310" height="155" id="canvas" style="border:1px solid red;"></canvas>
    <canvas width="310" height="155" id="block" style="border:1px solid green;"></canvas>

    script:

    // 将两张图片渲染在cavas上
        var canvas = document.getElementById('canvas');
        var block = document.getElementById('block');
        var canvas_ctx = canvas.getContext('2d');
        var block_ctx = block.getContext('2d');
        var img = document.createElement('img');
        img.onload = function() {
          canvas_ctx.drawImage(img, 0, 0, 310, 155);
          block_ctx.drawImage(img, 0, 0, 310, 155);
        };
        img.src = './touxiang.png';

     再教大家裁剪小真方形:

    script:

    // 将两张图片渲染在cavas上
        var canvas = document.getElementById('canvas');
        var block = document.getElementById('block');
        var canvas_ctx = canvas.getContext('2d');
        var block_ctx = block.getContext('2d');
        var img = document.createElement('img');
        img.onload = function() {
          canvas_ctx.drawImage(img, 0, 0, 310, 155);
          block_ctx.drawImage(img, 0, 0, 310, 155);
        };
        img.src = './touxiang.png';
        // 先利用clip()方法裁剪出个方块儿,让大家认识裁剪
        var x = 150, y = 40, w = 42, r = 10, PI = Math.PI;//x坐标、y坐标、正方形的宽、圆的半径、圆周率(3.14...)
        function draw(ctx) {
          ctx.beginPath();//拿笔
          ctx.moveTo(x, y);//把笔尖点到画布上这个点
          ctx.lineTo(x + w, y);
          ctx.lineTo(x + w, y + w);
          ctx.lineTo(x, y + w);
          ctx.clip();//剪刀裁剪
        }
        draw(canvas_ctx);
        draw(block_ctx);

     上面大家学会了画正方形,裁剪正方形,下面裁剪出我们想要的形状,把原来的draw方法改写一下:

    // 将两张图片渲染在cavas上
        var canvas = document.getElementById('canvas');
        var block = document.getElementById('block');
        var canvas_ctx = canvas.getContext('2d');
        var block_ctx = block.getContext('2d');
        var img = document.createElement('img');
        img.onload = function() {
          canvas_ctx.drawImage(img, 0, 0, 310, 155);
          block_ctx.drawImage(img, 0, 0, 310, 155);
        };
        img.src = './touxiang.png';
        // 先利用clip()方法裁剪出个方块儿,让大家认识裁剪
        var x = 150, y = 40, w = 42, r = 10, PI = Math.PI;//x坐标、y坐标、正方形的宽、圆的半径、圆周率(3.14...)
        function draw(ctx) {
          ctx.beginPath();//拿笔
          ctx.moveTo(x,y);//把笔尖点到这个点
          ctx.lineTo(x+w/2,y);//笔尖画到  正方形上边线中间
          ctx.arc(x+w/2,y-r+2, r,0,2*PI); //在坐标点(x+w/2,y-r+2)画一个r为半径的圆,角度开始为0,结束角度为2π,顺时针画个圆
          ctx.lineTo(x+w/2,y);//笔尖移动到 正方形上边线中间
          ctx.lineTo(x+w,y);//笔尖画到 正方形的上边线的右侧
          ctx.lineTo(x+w,y+w/2);//笔尖再画到正方形的右边线中间点
          ctx.arc(x+w+r-2,y+w/2,r,0,2*PI) //在合适的位置画个圆
          ctx.lineTo(x+w,y+w/2);//笔尖画到正方形的 右边线中间点
          ctx.lineTo(x+w,y+w);//笔尖画到正方形右边线的底部
          ctx.lineTo(x,y+w);//再画到正方形的下边线的左侧
          ctx.lineTo(x,y);//再画到正方形的起始点 形成闭环
          ctx.clip();//用剪刀裁剪
        }
        draw(canvas_ctx);
        draw(block_ctx);

     由于clip是裁剪路径内的部分,因此直接像上面画圆是不行的,我们开启一条新的路径,然后画圆将这个正方形“遮盖”出一个缺口,这里会用到 globalCompositeOperation 属性,'xor'顾名思义。代码接上边:

    // 将两张图片渲染在cavas上
        var canvas = document.getElementById('canvas');
        var block = document.getElementById('block');
        var canvas_ctx = canvas.getContext('2d');
        var block_ctx = block.getContext('2d');
        var img = document.createElement('img');
        img.onload = function() {
          canvas_ctx.drawImage(img, 0, 0, 310, 155);
          block_ctx.drawImage(img, 0, 0, 310, 155);
        };
        img.src = './touxiang.png';
        // 先利用clip()方法裁剪出个方块儿,让大家认识裁剪
        var x = 150, y = 40, w = 42, r = 10, PI = Math.PI;//x坐标、y坐标、正方形的宽、圆的半径、圆周率(3.14...)
        function draw(ctx) {
          ctx.beginPath();//拿笔
          ctx.moveTo(x,y);//把笔尖点到这个点
          ctx.lineTo(x+w/2,y);//笔尖画到  正方形上边线中间
          ctx.arc(x+w/2,y-r+2, r,0,2*PI); //在坐标点(x+w/2,y-r+2)画一个r为半径的圆,角度开始为0,结束角度为2π,顺时针画个圆
          ctx.lineTo(x+w/2,y);//笔尖移动到 正方形上边线中间
          ctx.lineTo(x+w,y);//笔尖画到 正方形的上边线的右侧
          ctx.lineTo(x+w,y+w/2);//笔尖再画到正方形的右边线中间点
          ctx.arc(x+w+r-2,y+w/2,r,0,2*PI) //在合适的位置画个圆
          ctx.lineTo(x+w,y+w/2);//笔尖画到正方形的 右边线中间点
          ctx.lineTo(x+w,y+w);//笔尖画到正方形右边线的底部
          ctx.lineTo(x,y+w);//再画到正方形的下边线的左侧
          ctx.lineTo(x,y);//再画到正方形的起始点 形成闭环
          ctx.clip();//用剪刀裁剪
    
          ctx.beginPath();//重新开始画
          ctx.arc(x,y+w/2, r,1.5*PI,0.5*PI) // 只需要画正方形内的半圆就行,方便背景图片的裁剪
          ctx.globalCompositeOperation = "xor";//将原图遮盖出一个缺口
          ctx.fill();//填充颜色 前面没加fillStyle就是白色
        }
        draw(canvas_ctx);
        draw(block_ctx);

     现在一个基本的拼图形状有了,我们调整#block的大小,并将裁剪出来的滑块放入#block中:

    // 将两张图片渲染在cavas上
        var canvas = document.getElementById('canvas');
        var block = document.getElementById('block');
        var canvas_ctx = canvas.getContext('2d');
        var block_ctx = block.getContext('2d');
        var img = document.createElement('img');
        img.onload = function() {
          canvas_ctx.drawImage(img, 0, 0, 310, 155);
          block_ctx.drawImage(img, 0, 0, 310, 155);
    
          var blockWidth = w + r * 2;//滑块实际宽度
          var _y = y - r * 2 + 2 // 滑块实际的y坐标
          var ImageData = block_ctx.getImageData(x, _y, blockWidth, blockWidth);//拿到滑块的像素数据
          block.width = blockWidth;//将滑块dom元素的宽度设置成滑块的掉
          block_ctx.putImageData(ImageData, 0, _y)
        };
        img.crossOrigin = 'Anonymous';//防止图片报跨域的错
        img.src = 'http://kexiepingtaieposter.hoohui.cn//registFile/fa5df7c9-445d-4b58-97c4-ad8b86a92241/Z0134_20200224232124.png?time='+ new Date();//加事件戳 防止图片报跨域的错
        // 先利用clip()方法裁剪出个方块儿,让大家认识裁剪
        var x = 150, y = 40, w = 42, r = 10, PI = Math.PI;//x坐标、y坐标、正方形的宽、圆的半径、圆周率(3.14...)
        function draw(ctx) {
          ctx.beginPath();//拿笔
          ctx.moveTo(x,y);//把笔尖点到这个点
          ctx.lineTo(x+w/2,y);//笔尖画到  正方形上边线中间
          ctx.arc(x+w/2,y-r+2, r,0,2*PI); //在坐标点(x+w/2,y-r+2)画一个r为半径的圆,角度开始为0,结束角度为2π,顺时针画个圆
          ctx.lineTo(x+w/2,y);//笔尖移动到 正方形上边线中间
          ctx.lineTo(x+w,y);//笔尖画到 正方形的上边线的右侧
          ctx.lineTo(x+w,y+w/2);//笔尖再画到正方形的右边线中间点
          ctx.arc(x+w+r-2,y+w/2,r,0,2*PI) //在合适的位置画个圆
          ctx.lineTo(x+w,y+w/2);//笔尖画到正方形的 右边线中间点
          ctx.lineTo(x+w,y+w);//笔尖画到正方形右边线的底部
          ctx.lineTo(x,y+w);//再画到正方形的下边线的左侧
          ctx.lineTo(x,y);//再画到正方形的起始点 形成闭环
          ctx.clip();//用剪刀裁剪
    
          ctx.beginPath();//重新开始画
          ctx.arc(x,y+w/2, r,1.5*PI,0.5*PI) // 只需要画正方形内的半圆就行,方便背景图片的裁剪
          ctx.globalCompositeOperation = "xor";//将原图遮盖出一个缺口
          ctx.fill();//填充颜色 前面没加fillStyle就是白色
        }
        draw(canvas_ctx);
        draw(block_ctx);

     现在我们需要把左边画布展示原来的图片,并且抠掉中间滑块的部分,这里画路径的过程都是一样的,唯一不同只是clip()那里改成fill()即可实现效果,我们前面已经把画路径的过程封装成函数了,稍作改动即可:

    // 将两张图片渲染在cavas上
        var canvas = document.getElementById('canvas');
        var block = document.getElementById('block');
        var canvas_ctx = canvas.getContext('2d');
        var block_ctx = block.getContext('2d');
        var img = document.createElement('img');
        img.onload = function() {
          canvas_ctx.drawImage(img, 0, 0, 310, 155);
          block_ctx.drawImage(img, 0, 0, 310, 155);
    
          var blockWidth = w + r * 2;//滑块实际宽度
          var _y = y - r * 2 + 2 // 滑块实际的y坐标
          var ImageData = block_ctx.getImageData(x, _y, blockWidth, blockWidth);//拿到滑块的像素数据
          block.width = blockWidth;//将滑块dom元素的宽度设置成滑块的掉
          block_ctx.putImageData(ImageData, 0, _y)
        };
        img.crossOrigin = 'Anonymous';//防止图片报跨域的错
        img.src = 'http://kexiepingtaieposter.hoohui.cn//registFile/fa5df7c9-445d-4b58-97c4-ad8b86a92241/Z0134_20200224232124.png?time='+ new Date();//加事件戳 防止图片报跨域的错
        // 先利用clip()方法裁剪出个方块儿,让大家认识裁剪
        var x = 150, y = 40, w = 42, r = 10, PI = Math.PI;//x坐标、y坐标、正方形的宽、圆的半径、圆周率(3.14...)
        function draw(ctx, operation) {
          ctx.beginPath();//拿笔
          ctx.moveTo(x,y);//把笔尖点到这个点
          ctx.lineTo(x+w/2,y);//笔尖画到  正方形上边线中间
          ctx.arc(x+w/2,y-r+2, r,0,2*PI); //在坐标点(x+w/2,y-r+2)画一个r为半径的圆,角度开始为0,结束角度为2π,顺时针画个圆
          ctx.lineTo(x+w/2,y);//笔尖移动到 正方形上边线中间
          ctx.lineTo(x+w,y);//笔尖画到 正方形的上边线的右侧
          ctx.lineTo(x+w,y+w/2);//笔尖再画到正方形的右边线中间点
          ctx.arc(x+w+r-2,y+w/2,r,0,2*PI) //在合适的位置画个圆
          ctx.lineTo(x+w,y+w/2);//笔尖画到正方形的 右边线中间点
          ctx.lineTo(x+w,y+w);//笔尖画到正方形右边线的底部
          ctx.lineTo(x,y+w);//再画到正方形的下边线的左侧
          ctx.lineTo(x,y);//再画到正方形的起始点 形成闭环
          // ctx.clip();//用剪刀裁剪  注释掉
          ctx.fillStyle = '#fff';
          ctx[operation]();
    
          ctx.beginPath();//重新开始画
          ctx.arc(x,y+w/2, r,1.5*PI,0.5*PI) // 只需要画正方形内的半圆就行,方便背景图片的裁剪
          ctx.globalCompositeOperation = "xor";//将原图遮盖出一个缺口
          ctx.fill();//填充颜色 前面没加fillStyle就是白色
        }
        draw(canvas_ctx,"fill");
        draw(block_ctx,"clip");

     下面就是编写拖动代码了。。。后续补上

  • 相关阅读:
    什么是数据挖掘?
    Oracle 泵导入导出
    如何创建一个 mongo 数据库并为它添加一个认证用户?
    如何提高 windows 的使用效率?--巧用运行命令
    在 vs2017 中使用 C# 7 新特性。
    什么是按引用传递和按值传递?
    Vue、Vuex+Cookie 实现自动登陆 。
    Web.config 灵活配置
    远程终端
    js框架总结
  • 原文地址:https://www.cnblogs.com/fqh123/p/12359355.html
Copyright © 2011-2022 走看看