一、canvas实现水滴扩散效果
<canvas id="myCanvas" width="800" height="800" style="border:1px solid #c3c3c3;">
Your browser does not support the canvas element.
</canvas>
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
// 保存图片路径的数组
var urlArr = ["https://image-static.segmentfault.com/186/861/1868615973-5b87dbe4c8e85_articlex",
"https://image-static.segmentfault.com/374/956/3749561513-5b87dbe6a9436"];
// imgArr 保存加载后的图片的数组,imgArr中保存的是真实的图片
// loadImg 函数用来加载 urlArr 中所有的图片
// 并返回一个保存所有图片的数组
var imgArr = loadImg(urlArr);
// flag 用来限制 点击事件,一张图片只会产生一次效果
var flag = false;
function loadImg(urlArr) {
var index = 0;
var res = [];
// 每次给 load 函数传入一个图片路径,来加载图片
load(urlArr[index]);
function load(url) {
// 如果 index 等于 urlArr.length,
// 表示加载完 全部图片了,就结束 load函数
if (index == urlArr.length) {
// 加载完全部图片,调用 init 函数
init();
return;
}
var img = new Image();
img.src = url;
// 不管当前图片是否加载成功,都要加载下一张图片
img.onload = next;
img.onerror = function () {
console.log(res[index] + "加载失败");
next();
}
// next 用来加载下一张图片
function next() {
// 把加载后的图片,保存到 res 中
res[index] = img;
load(urlArr[++index])
}
}
// 最后返回保存所有真实图片的数组
return res;
}
function init() {
// 先在canvas上画黑白的图片,然后再设置背景是彩色的图片
// 避免先显示出彩色图片,再显示出黑白的图片
context.globalCompositeOperation = "source-over";
context.drawImage(imgArr[0], 0, 0, 400, 250);
canvas.style.background = 'url(https://image-static.segmentfault.com/374/956/3749561513-5b87dbe6a9436)';
canvas.style.backgroundSize = "100% 100%";
// flag 是 true 时,鼠标点击才有水滴扩散的效果
flag = true;
// canvas 绑定点击事件,点击时产生水滴扩散效果
canvas.onclick = diffusion;
}
// width 表示 不规则形状的图片的尺寸
var width = 0;
// speed 表示扩散效果的速度
var speed = 8;
// diffusion 函数根据鼠标坐标,产生效果
function diffusion(e) {
console.log(222, e)
if (flag) {
flag = false;
context.globalCompositeOperation = "destination-out";
window.requestAnimationFrame(draw);
// 根据鼠标坐标,画扩散效果
function draw() {
// 这里不一定需要是 1800 ,但必须是一个足够大的数,可以扩散出整张背景图
if (width > 1800) {
flag = true;
return;
}
width += speed;
// 获取鼠标相对于 canvas 的坐标
var x = e.layerX;
var y = e.layerY;
// 画不规则形状的图片,逐渐增大图片尺寸
context.drawImage(imgArr[1], x - (width / 2), y - (width / 2), width, width);
window.requestAnimationFrame(draw);
}
}
}
、
二、刮刮卡效果
<canvas id="canvas" width="400px" height="250px"></canvas>
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
// canvas的宽度
var width = 400;
// canvas的高度
var height = 250;
init()
function init() {
// 先在canvas上画一个灰色的矩形
context.fillStyle = '#ddd';
context.fillRect(0, 0, width, height);
// 设置canvas的背景为一张图片
canvas.style.background =
'url("https://www.kkkk1000.com/images/globalCompositeOperation/bg3.jpg") no-repeat center';
canvas.style.backgroundSize = "100% 100%";
// 设置画的线的宽度
context.lineWidth = 35;
// 设置线交汇时,是圆角的
context.lineJoin = "round";
}
canvas.addEventListener('mousedown', mouseDown, false);
canvas.addEventListener('mousemove', mouseMove, false);
canvas.addEventListener('mouseup', mouseUp, false);
/* 如果需要移动端也可以生效,
需要绑定touchstart、touchmove、touchend 事件,并且获取触摸点的坐标
*/
//canvas.addEventListener('touchstart', mouseDown, false);
//canvas.addEventListener('touchmove', mouseMove, false);
//canvas.addEventListener('touchend', mouseUp, false);
// 判断是否可以画线
var isDrawing;
// 保存开始画线时,线的起点的X坐标
var startX = 0;
// 保存开始画线时,线的起点的Y坐标
var startY = 0;
// 按下鼠标按钮时,调用mouseDown
function mouseDown(e) {
isDrawing = true;
// 保存鼠标点击时 X坐标为,画线时,线的起点的X坐标
startX = e.layerX;
// 保存鼠标点击时 Y坐标为,画线时,线的起点的Y坐标
startY = e.layerY;
/* 移动端使用下面的方法 获取 startX 和 startY
startX = e.touches[0].clientX;
startY = e.touches[0].clientY;
*/
}
// 鼠标移动时,调用mouseDown
function mouseMove(e) {
if (isDrawing) {
// 获取鼠标相对于 canvas 的坐标
var x = e.layerX;
var y = e.layerY;
/* 移动端使用下面的方法 获取 x 和 y
var x = e.touches[0].clientX;
var y = e.touches[0].clientY;
*/
context.globalCompositeOperation = "destination-out";
// 开始画线
context.beginPath();
// 起点坐标为 startX 和 startY
context.moveTo(startX, startY);
// 结束的坐标为这次移动时的坐标
context.lineTo(x, y);
context.closePath();
context.stroke();
// 设置这次移动结束时的坐标,为下次开始画线时的坐标
startX = x;
startY = y;
}
}
// 松开鼠标按钮时,调用的事件
function mouseUp(e) {
// isDrawing 为false时,不可以画线
isDrawing = false;
// 获取图片像素信息
var data = context.getImageData(0, 0, width, height).data;
console.log("图片像素信息", data);
var length = data.length;
var k = 0;
// 如果一个像素是透明的(值都是0),k就+1
for (var i = 0; i < length - 3; i += 4) {
if (data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 0 && data[i + 3] == 0) {
k++;
}
}
// 当k > width*height*0.2 时,
// 也就是说有20%的面积是透明的时,就把整个canvas的背景显示出来
if (k > width * height * 0.2) {
context.fillStyle = "blue";
context.fillRect(0, 0, width, height);
}
}
三、翻牌动画
//css
/* The properties in this rule are only necessary for the 'flip' transition.
* We need specify the perspective to create a projection matrix. This will add
* some depth as the element flips. The depth number represents the distance of
* the viewer from the z-plane. According to the CSS3 spec, 1000 is a moderate
* value.
*/
.viewport-flip {
-webkit-perspective: 1000;
perspective: 1000;
position: absolute;
}
.flip {
-webkit-backface-visibility: hidden;
-webkit-transform: translateX(0); /* Needed to work around an iOS 3.1 bug that causes listview thumbs to disappear when -webkit-visibility:hidden is used. */
backface-visibility: hidden;/*backface-visibility 属性定义当元素不面向屏幕时是否可见*/
transform: translateX(0);
}
.flip.out {
-webkit-transform: rotateY(-90deg) scale(.9);
-webkit-animation-name: flipouttoleft;
-webkit-animation-duration: 175ms;
transform: rotateY(-90deg) scale(.9);
animation-name: flipouttoleft;
animation-duration: 175ms;
}
.flip.in {
-webkit-animation-name: flipintoright;
-webkit-animation-duration: 225ms;
animation-name: flipintoright;
animation-duration: 225ms;
}
.flip.out.reverse {
-webkit-transform: rotateY(90deg) scale(.9);
-webkit-animation-name: flipouttoright;
transform: rotateY(90deg) scale(.9);
animation-name: flipouttoright;
}
.flip.in.reverse {
-webkit-animation-name: flipintoleft;
animation-name: flipintoleft;
}
@-webkit-keyframes flipouttoleft {
from { -webkit-transform: rotateY(0); }
to { -webkit-transform: rotateY(-90deg) scale(.9); }
}
@keyframes flipouttoleft {
from { transform: rotateY(0); }
to { transform: rotateY(-90deg) scale(.9); }
}
@-webkit-keyframes flipouttoright {
from { -webkit-transform: rotateY(0) ; }
to { -webkit-transform: rotateY(90deg) scale(.9); }
}
@keyframes flipouttoright {
from { transform: rotateY(0); }
to { transform: rotateY(90deg) scale(.9); }
}
@-webkit-keyframes flipintoleft {
from { -webkit-transform: rotateY(-90deg) scale(.9); }
to { -webkit-transform: rotateY(0); }
}
@keyframes flipintoleft {
from { transform: rotateY(-90deg) scale(.9); }
to { transform: rotateY(0); }
}
@-webkit-keyframes flipintoright {
from { -webkit-transform: rotateY(90deg) scale(.9); }
to { -webkit-transform: rotateY(0); }
}
@keyframes flipintoright {
from { transform: rotateY(90deg) scale(.9); }
to { transform: rotateY(0); }
}
//html
<div id="box" class="box viewport-flip" title="点击翻面">
<a href="/" class="list flip out"><img src="http://image.zhangxinxu.com/image/blog/201210/puke-k.png" alt="纸牌正面"></a>
<a href="/" class="list flip"><img src="http://image.zhangxinxu.com/image/blog/201210/puke-back.png" alt="纸牌背面"></a>
</div>
//js
// 在前面显示的元素,隐藏在后面的元素
var eleBack = null, eleFront = null,
// 纸牌元素们
eleList = $(".list");
// 确定前面与后面元素
var funBackOrFront = function() {
eleList.each(function() {
if ($(this).hasClass("out")) {
eleBack = $(this);
} else {
eleFront = $(this);
}
});
};
funBackOrFront();
$("#box").bind("click", function() {
// 切换的顺序如下
// 1. 当前在前显示的元素翻转90度隐藏, 动画时间225毫秒
// 2. 结束后,之前显示在后面的元素逆向90度翻转显示在前
// 3. 完成翻面效果
eleFront.addClass("out").removeClass("in");
setTimeout(function() {
eleBack.addClass("in").removeClass("out");
// 重新确定正反元素
funBackOrFront();
}, 225);
return false;
});
效果连接:www.zhangxinxu.com/study/20121…
翻牌效果二
//html
<div class="row">
<!--翻纸牌效果 -->
<div class="col-1-of-3">
<div class="card">
<div class="card__side card__side--front-1">
<a href="#">
<img src="img/fanmian.jpg">
</a>
</div>
<div class="card__side card__side--back card__side--back-1">
<a href="#">
<img src="img/zhengmian.jpg">
</a>
</div>
</div>
</div>
<!--翻纸牌效果 -->
<!--翻纸牌效果 -->
<div class="col-1-of-3"> <div class="card">
<div class="card__side card__side--front-1">
<a href="#">
<img src="img/fanmian.jpg">
</a>
</div>
<div class="card__side card__side--back card__side--back-1">
<a href="#">
<img src="img/zhengmian.jpg">
</a>
</div>
</div>
</div>
<!--翻纸牌效果 -->
<!--翻纸牌效果 -->
<div class="col-1-of-3"> <div class="card">
<div class="card__side card__side--front-1">
<a href="#">
<img src="img/fanmian.jpg">
</a>
</div>
<div class="card__side card__side--back card__side--back-1">
<a href="#">
<img src="img/zhengmian.jpg">
</a>
</div>
</div>
</div>
<!--翻纸牌效果 -->
</div>
//css
/* body { -webkit-box-sizing: border-box; box-sizing: border-box;} */
.row {
width: 1200px;
margin: 0 auto;
}
.card {
-webkit-perspective: 150rem;
perspective: 150rem;
-moz-perspective: 150rem;
position: relative;
height: 366px;
}
.card__side {
height: 366px;
-webkit-transition: all 0.8s ease;
transition: all 0.8s ease;
position: absolute;
top: 0;
left: 0;
width: 238px;
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
border-radius: 10px;
overflow: hidden;
-webkit-box-shadow: 0 1.5rem 4rem rgba(0, 0, 0, 0.15);
box-shadow: 0 1.5rem 4rem rgba(0, 0, 0, 0.15);
}
.card__side--back {
-webkit-transform: rotateY(180deg);
transform: rotateY(180deg);
}
.card:hover .card__side--front-1 {
-webkit-transform: rotateY(-180deg);
transform: rotateY(-180deg);
}
.card:hover .card__side--back {
-webkit-transform: rotateY(0);
transform: rotateY(0);
}
.row .col-1-of-3 {
width:238px;
float: left;
margin:31px;
}
效果地址:www.bootstrapmb.com/item/6120/p…
洗牌效果
//html
<div class="container">
<div class="card card-one">1111</div>
<div class="card card-two">222</div>
<div class="card card-three">3333</div>
</div>
//css
@keyframes rotate-one {
10% {
transform: translate(200px, 0px);
z-index: 5;
background:#ff0000
}
20% {
transform: translate(-200px, 0px);
z-index: 3;
background:#ff0000
}
30% {
transform: translate(100px, 0px);
z-index: 4;
background:#ff0000
}
40% {
transform: translate(100px, 0px);
z-index: 3;
background:#ff0000
}
50% {
transform: translate(-100px, 0px);
z-index: 5;
background:#ff0000
}
60% {
transform: translate(0px, 0px);
z-index: 3;
background:#ff0000
}
70% {
transform: translate(-100px, 0px);
z-index: 4;
background:#ff0000
}
80% {
transform: translate(0px, 0px);
z-index: 4;
background:#ff0000
}
90% {
transform: translate(100px, 0px);
z-index: 5;
background:#ff0000
}
100% {
transform: translate(0px, 0px);
z-index: 3;
background:#ff0000
}
}
@keyframes rotate-two {
10% {
transform: translate(0px, 0px);
z-index: 3;
}
20% {
transform: translate(0px, 0px);
z-index: 5;
}
30% {
transform: translate(-100px, 0px);
z-index: 4;
}
40% {
transform: translate(-100px, 0px);
z-index: 5;
}
50% {
transform: translate(100px, 0px);
z-index: 3;
}
60% {
transform: translate(200px, 0px);
z-index: 5;
}
70% {
transform: translate(-100px, 0px);
z-index: 4;
}
80% {
transform: translate(-100px, 0px);
z-index: 4;
}
90% {
transform: translate(-100px, 0px);
z-index: 3;
}
100% {
transform: translate(200px, 0px);
z-index: 5;
}
}
@keyframes rotate-three {
10% {
transform: translate(-200px, 0px);
z-index: 4;
}
20% {
transform: translate(200px, 0px);
z-index: 5;
}
30% {
transform: translate(0px, 0px);
z-index: 4;
}
40% {
transform: translate(100px, 0px);
z-index: 4;
}
50% {
transform: translate(0px, 0px);
z-index: 4;
}
60% {
transform: translate(-200px, 0px);
z-index: 5;
}
70% {
transform: translate(0px, 0px);
z-index: 4;
}
80% {
transform: translate(100px, 0px);
z-index: 4;
}
90% {
transform: translate(0px, 0px);
z-index: 4;
}
100% {
transform: translate(-200px, 0px);
z-index: 5;
}
}
body {
background-color: #2c3e50;
}
.container {
position: absolute;
width: 300px;
height: 100px;
top: 50%;
left: 50%;
margin: -50px;
display: flex;
}
.card{
position:relative;
display: inline-flex;
width: 100px;
height: 100%;
}
.card-one{
background: #ff0000;
animation: rotate-one 2.5s 1;
animation-timing-function: ease-in;
}
.card-two{
background: #00ff00;
animation: rotate-two 2.5s 1;
animation-timing-function: ease-in;
}
.card-three{
background: #0000ff;
animation: rotate-three 2.5s 1;
animation-timing-function: ease-in;
}
四、抽奖转盘动画
html
<div class="g-wrap">
<div class='u-cards J_cards'>
<div class="card-box">
<img src="./static/images/card1.png">
</div>
<div class="card-box">
<img src="./static/images/card2.png">
</div>
<div class="card-box">
<img src="./static/images/card3.png">
</div>
<div class="card-box">
<img src="./static/images/card4.png">
</div>
<div class="card-box">
<img src="./static/images/card5.png">
</div>
</div>
</div>
css
html, body{
width: 100%;
height: 100%;
margin: 0;
background: linear-gradient(#22a29d, #0d6964)
}
.g-wrap{
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column
}
.card-box{
display: inline-block;
position:relative;
}
.card-box.card-normal:after {
position: absolute;
left: 7px;
top: 1px;
display: block;
width: 193px;
height: 263px;
content: '';
transition: all 0.5s ease;
border-radius: 7px;
box-shadow: 0 3px 10px 5px #3cdad4;
}
.card-box.card-mask:after{
position: absolute;
left: 7px;
top: 1px;
display: block;
width: 193px;
height: 263px;
background-color: rgba(0, 0, 0, 0.3);
content: '';
transition: all 0.5s ease;
border-radius: 7px;
}
.card-box.card-checked:after{
position: absolute;
left: 7px;
top: 1px;
display: block;
width: 193px;
height: 263px;
content: '';
transition: all 0.5s ease;
border-radius: 7px;
box-shadow: 0 0 8px 8px #f9f5e9;
}
.gf-ft {
margin-top: 20px;
text-align: center;
}
.gf-btn {
display: inline-block;
background: linear-gradient(to top, #d46a33, #ce4f1f);
line-height: 64px;
border-radius: 32px;
font-size: 26px;
letter-spacing: 3px;
color: #f9dc9f;
padding: 0px 70px;
box-shadow: 0 5px 20px #f9dc9f;
}
js
$(function(){
// 当前位置(每执行一次,会加1,也可理解当前执行次数
var lotteryNum = 0;
var startTimeout = 100;// 初始定时器时长
scrollTimeout = null;
var _circleTimes = 3,// 需要转几轮
_breakTime = 10,// 每次增加的时长
_allNum = 5;// 总共有几个奖品
function lottery(id, callback){
// id 为后端传回来的用户抽到的奖品,_stepNum 为动画总共执行多少次。 var _stepNum = _allNum * _circleTimes + id;
$('.J_cards .card-box').removeClass('card-normal').removeClass('card-checked').addClass('card-mask');
$('.card-box' + (lotteryNum % _allNum)).removeClass('card-mask').addClass('card-checked');
scrollTimeout = setTimeout(function(){
lottery(id, callback);
}, startTimeout+_breakTime);
lotteryNum++;
startTimeout+=_breakTime;
//停止动画
if(lotteryNum >=_stepNum){
clearTimeout(scrollTimeout);
lotteryNum = 0;
startTimeout = 100;
if(callback){
callback();
}
}
}
$('.J_getGf').on('click', getGift);
function getGift(){
// ģ��齱
var giftId = Math.floor(Math.random() * 5);
lottery(giftId, function(){});
}
})