1. 程式人生 > >Canvas實現微信紅包照片效果

Canvas實現微信紅包照片效果

本篇文章來源慕課網課程《canvas玩轉紅包照片》,用canvas及css3結合,實現紅包照片的效果,並不做支付過程,代替的是使用2個按鈕,顯示清晰圖片和重置圓圈可見區域。未做移動的螢幕適應

微信紅包照片效果圖一張模糊圖片,只有魚哥小圓圈的區域是清晰可見

原理分析:

  1. 先在頁面放置一張原圖片image,用css3的filter做模糊處理
  2. 在圖片區域上方放置一個與圖片image大小一樣的canvas,放置整張清晰圖片
  3. 通過canvas的圖片剪輯方法,剪輯出一個圓圈區域,就達到了只顯示一個圓圈區域的效果

程式碼及解析
目錄結構:
這裡寫圖片描述
index.html,blur.js,blur.css

index.htm頁面程式碼

<!DOCTYPE html>
<html> <head> <meta charset="utf-8" /> <meta name="viewport" content="height=device-height,width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no"/> <title>模糊紅包效果</title> <link rel="stylesheet" href
="css/blur.css" />
<script type="text/javascript" src="js/jquery-2.1.0.js"></script> </head> <body> <div id="blur-div"> <img id="blur-image" src="img/gd.jpg" /> <canvas id="canvas"></canvas><!--大小要在js設定,不要在css設定-->
<a href="javascript:reset()" class="button" id="reset-button">重置</a> <a href="javascript:show()" class="button" id="show-button">顯示</a> </div> <script type="text/javascript" src="js/blur.js"></script> </body> </html>

css程式碼blur.css

*{
    margin:0px;
    padding: 0px;
}

#blur-div{
    width:350px;
    height:220px;
    margin:0 auto;
    position: relative;

    overflow: hidden;
}

.button{
    display: block;
    position: absolute;
    z-index: 200;/*按鈕在最上面*/

    width: 60px;
    height: 30px;

    color: white;
    text-decoration: none;
    text-align: center;
    line-height: 30px;

    border-radius: 2px;
}
#reset-button{
    left: 40px;
    bottom: 20px;   
    background-color: #058;
}
#reset-button:hover{
    background-color: #047;
}
#show-button{
    right: 40px;
    bottom: 20px;   
    background-color: #085;
}
#show-button:hover{
    background-color: #074;
}
#canvas{

    display:block;
    margin:0 auto;

    position: absolute;
    left:0px;
    top:0px;
    /*canvas在image之上,在按鈕下,z-index大於image,小於btn*/
    z-index: 100;
}

#blur-image{
    display:block;
    width:350px;
    height:220px;
    margin:0 auto;

    /*模糊效果*/
    filter:blur(20px);
    -webkit-filter: blur(20px);
    -moz-filter:blur(20px);
    -ms-filter: blur(20px);
    -o-filter:blur(20px);

    position: absolute;
    left:0px;
    top:0px;

    z-index: 0;
}

設定canvas大小要和image大小一樣

javascript程式碼,方法將分片段進行講解:
初始化一些引數

var canvasWidth = window.innerWidth; //最外層div寬=視窗寬高,為了適應
var canvasHeight = window.innerHeight;

var canvas = document.getElementById("canvas");//獲取到canvas元素物件
var context = canvas.getContext("2d");//獲取2d context

//設定canvas大小和最外層div寬高一樣
canvas.width = canvasWidth;
canvas.height = canvasHeight;

//用canvas顯示清晰影象
var image = new Image();
image.src = "img/gd.jpg";

//剪輯區域
var radius = 30;//剪輯區域圓的半徑
var clippingRegion;//剪輯區域物件

底層圖片用css3設定過後就已經可以顯示在頁面上,是一張模糊過的圖片,下一步就是在canvas上繪製剪輯圖片

image.onload = function(e) {
    //此處js程式碼設定blur-div 和canvas寬高調整
    $('#blur-div').css("width", canvasWidth + "px");
    $('#blur-div').css("height", canvasHeight + "px");
    $('#blur-image').css("width", image.width + "px");//因為影象大小變化,所以重新設定
    $('#blur-image').css("height", image.height + "px");

    initCanvas();//這是初始化canvas的方法
}
function initCanvas() {
    //重置剪輯區域,歸位,隨機
    clippingRegion = { //保證剪輯區域一定在有影象的地方
        x: Math.random() * (canvas.width - 2 * radius) + radius, 
        y: Math.random() * (canvas.height - 2 * radius) + radius,
        r: radius
    };
    draw(image, clippingRegion);//這是繪製image的方法
}
//設定剪輯區域
function setClippingRegion(clippingRegion) {
    context.beginPath(); //建立路徑
    context.arc(clippingRegion.x, clippingRegion.y, clippingRegion.r, 0, Math.PI * 2, false); //畫圓形
    context.clip();
}
function draw(image, clippingRegion) {
    context.clearRect(0, 0, canvas.width, canvas.height);
    context.save();
    //影象繪製前,確定剪輯區域
    setClippingRegion(clippingRegion);
    context.drawImage(image, 0, 0);

    context.restore();
}

點選顯示按鈕show,完全顯示清晰影象,複用draw函式,將剪輯區域變大

function show() {
    //新增動畫
    var theAnimation = setInterval(function() {
        clippingRegion.r += 20; //慢慢擴大顯示
        //邊界條件
        if (clippingRegion.r > 2 * Math.max(canvas.width, canvas.height)) { //停止動畫,否則函式執行不停止
            clearInterval(theAnimation);
        }
        draw(image, clippingRegion);//迴圈執行draw方法,慢慢將剪輯區域的半徑擴大,實現動畫效果
    }, 30);//bug,顯示之後立即點選重置,還是會開啟圖片,可能是因為定時器還沒結束
}

重置則再次初始化canvas就行了,在initCanvas已經做了隨機位置,所以每次點選重置都是隨機位置的剪輯區域

//重置,initCanvas
function reset() {
    initCanvas();
}

完整blur.js程式碼

var canvasWidth = window.innerWidth; //最外層div寬=視窗寬高,為了適應
var canvasHeight = window.innerHeight;

var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");

//設定canvas大小和最外層div寬高一樣
canvas.width = canvasWidth;
canvas.height = canvasHeight;

//用canvas顯示清晰影象
var image = new Image();
var radius = 30;
//剪輯區域
var clippingRegion;
image.src = "img/gd.jpg";


//因為影象載入需要時間,所以用onload方法,等待圖片載入完成後再執行函式
image.onload = function(e) {
    //blur-div 和canvas寬高調整
    $('#blur-div').css("width", canvasWidth + "px");
    $('#blur-div').css("height", canvasHeight + "px");

    $('#blur-image').css("width", image.width + "px");
    $('#blur-image').css("height", image.height + "px");

    initCanvas();
}

function initCanvas() {
    //重置剪輯區域,歸位,隨機

    clippingRegion = { //保證剪輯區域一定在有影象的地方
        x: Math.random() * (canvas.width - 2 * radius) + radius, //30-320      0-width  減掉半徑30   350-30*2
        y: Math.random() * (canvas.height - 2 * radius) + radius, //30-190      0-height  減掉半徑30     220-30*2
        r: radius
    };
    draw(image, clippingRegion);
}

//設定剪輯區域
function setClippingRegion(clippingRegion) {
    context.beginPath(); //建立路徑
    context.arc(clippingRegion.x, clippingRegion.y, clippingRegion.r, 0, Math.PI * 2, false); //畫圓形
    context.clip();
}

function draw(image, clippingRegion) {
    context.clearRect(0, 0, canvas.width, canvas.height);

    context.save();
    //影象繪製前,確定剪輯區域
    setClippingRegion(clippingRegion);

    context.drawImage(image, 0, 0); //圖片大於canvas

    context.restore();
}

//完全顯示清晰影象,複用draw函式,將剪輯區域變大
function show() {
    //新增動畫,此函式有缺點
        clippingRegion.r=radius;//給半徑歸位
    var theAnimation = setInterval(function() {
        console.log("anima");
        clippingRegion.r += 20; //慢慢擴大顯示
        //邊界條件
        if (clippingRegion.r > 2 * Math.max(canvas.width, canvas.height)) { //停止動畫,否則函式執行不停止1000
            clearInterval(theAnimation);
        }
        draw(image, clippingRegion);
    }, 30);
}

//重置,initCanvas
function reset() {
    initCanvas();
}