效果图:
实例主要依赖张鑫旭大神的抛物线js,我稍作了一些改造,具体代码如下。
<html>
<head>
<meta charset="utf-8">
<title>抛物线运动效果title>
<style type="text/css">
body {
overflow: hidden;
}
.boll {
width: 20px;
height: 20px;
position: absolute;
top: 55%;
left: 55%;
background: url("redpack_show.jpg");
background-size: contain;
}
.red-bag {
position: absolute;
left: 50%;
top:50%;
width: 200px;
height: 200px;
border-radius: 50%;
background: url("red_bag.png") no-repeat;
background-size: contain;
z-index:10;
}
style>
<script type="text/javascript" src="jquery-2.1.4.js">script>
<script type="text/javascript" src="parabola.js">script>
head>
<body>
<div class="btns" style="margin-top:20px">
<a href="http://www.css88.com/archives/5355" target="_blank">回到JavaScript实现的抛物线运动效果a>
div>
<div class="btns" style="margin-top:20px">
<a href="#" class="btnA btn-danger" id="run" rel="popover" title="A Title" style="">runa>
div>
<div class="red-bag">div>
<div id="target" class="target">div>
<script type="text/javascript">
let track = [];
function createTrack(obj) {
for(let i=0;i<10;i++){
track.push({
left:-getRandom(obj.minX,obj.maxX),
top:getRandom(200,600),
curvature:getRandom(obj.minC,obj.maxC),
duration:getRandom(1000,2500)
})
}
}
createTrack({
minX:400,maxX:500,
minC:0.005,maxC:0.01,
});
createTrack({
minX:250,maxX:350,
minC:0.01,maxC:0.01,
});
createTrack({
minX:100,maxX:150,
minC:0.09,maxC:0.09,
});
createTrack({
minX:100,maxX:150,
minC:0.2,maxC:0.2,
});
createTrack({
minX:50,maxX:200,
minC:0.5,maxC:0.5,
});
createTrack({
minX:400,maxX:500,
minC:0.5,maxC:0.5,
});
createTrack({
minX:-400,maxX:-500,
minC:0.005,maxC:0.01,
});
createTrack({
minX:-250,maxX:-350,
minC:0.01,maxC:0.01,
});
createTrack({
minX:-100,maxX:-150,
minC:0.09,maxC:0.09,
});
createTrack({
minX:-100,maxX:-150,
minC:0.2,maxC:0.2,
});
createTrack({
minX:-50,maxX:-200,
minC:0.5,maxC:0.5,
});
createTrack({
minX:-400,maxX:-500,
minC:0.5,maxC:0.5,
});
track.sort(function(){ return 0.5 - Math.random() });
console.log(track.length);
for(let i=1;i<500;i++){
$("body").append(`class='boll boll${i}'>div>`);
let bool = "bool"+i;
createSingle(bool,i,track[Math.floor(getRandom(0,track.length))]);
console.log(i)
}
function createSingle(bool,i,track) {
bool = new Parabola({
el: ".boll"+i,
offset: [track.left, track.top],
curvature: track.curvature,
duration: track.duration,
callback:function(){
// alert("完成后回调")
},
stepCallback:function(x,y){
// console.log(x,y);
let color = `rgb(${Math.floor(getRandom(0,255)) },${Math.floor(getRandom(0,255)) },${Math.floor(getRandom(0,255)) })`;
$("<div>").appendTo("body").css({
"position": "absolute",
"top": this.elOriginalTop + y,
"left":this.elOriginalLeft + x,
"background":color,
"width":"2px",
"height":"2px",
"border-radius": "2px"
});
}
});
$("#run").click(function (event) {
event.preventDefault();
bool.start();
});
}
function getRandom(min,max) {
return Math.random()*(max-min)+min;
}
script>
body>
html>
(function () {
var _$ = function (_this) {
return _this.constructor == jQuery ? _this : $(_this);
};
// 获取当前时间
function now() {
return +new Date();
}
// 转化为整数
function toInteger(text) {
text = parseInt(text);
return isFinite(text) ? text : 0;
}
var Parabola = function (options) {
this.initialize(options);
};
Parabola.prototype = {
constructor: Parabola,
/**
* 初始化
* @classDescription 初始化
* @param {Object} options 插件配置 .
*/
initialize: function (options) {
this.options = this.options || this.getOptions(options);
var ops = this.options;
if (!this.options.el) {
return;
}
this.$el = _$(ops.el);
this.timerId = null;
this.elOriginalLeft = toInteger(this.$el.css("left"));
this.elOriginalTop = toInteger(this.$el.css("top"));
// this.driftX X轴的偏移总量
//this.driftY Y轴的偏移总量
if (ops.targetEl) {
this.driftX = toInteger(_$(ops.targetEl).css("left")) - this.elOriginalLeft;
this.driftY = toInteger(_$(ops.targetEl).css("top")) - this.elOriginalTop;
} else {
this.driftX = ops.offset[0];
this.driftY = ops.offset[1];
}
this.duration = ops.duration;
// 处理公式常量
this.curvature = ops.curvature;
// 根据两点坐标以及曲率确定运动曲线函数(也就是确定a, b的值)
//a=this.curvature
/* 公式: y = a*x*x + b*x + c;
*/
/*
* 因为经过(0, 0), 因此c = 0
* 于是:
* y = a * x*x + b*x;
* y1 = a * x1*x1 + b*x1;
* y2 = a * x2*x2 + b*x2;
* 利用第二个坐标:
* b = (y2+ a*x2*x2) / x2
*/
// 于是
this.b = ( this.driftY - this.curvature * this.driftX * this.driftX ) / this.driftX;
//自动开始
if (ops.autostart) {
this.start();
}
},
/**
* 初始化 配置参数 返回参数MAP
* @param {Object} options 插件配置 .
* @return {Object} 配置参数
*/
getOptions: function (options) {
if (typeof options !== "object") {
options = {};
}
options = $.extend({}, defaultSetting, _$(options.el).data(), (this.options || {}), options);
return options;
},
/**
* 定位
* @param {Number} x x坐标 .
* @param {Object} y y坐标 .
* @return {Object} this
*/
domove: function (x, y) {
this.$el.css({
position: "absolute",
left: this.elOriginalLeft + x,
top: this.elOriginalTop + y
});
return this;
},
/**
* 每一步执行
* @param {Data} now 当前时间 .
* @return {Object} this
*/
step: function (now) {
var ops = this.options;
var x, y;
if (now > this.end) {
// 运行结束
x = this.driftX;
y = this.driftY;
this.domove(x, y);
this.stop();
if (typeof ops.callback === 'function') {
ops.callback.call(this);
}
} else {
//x 每一步的X轴的位置
x = this.driftX * ((now - this.begin) / this.duration);
//每一步的Y轴的位置y = a*x*x + b*x + c; c==0;
y = this.curvature * x * x + this.b * x;
this.domove(x, y);
if (typeof ops.stepCallback === 'function') {
ops.stepCallback.call(this,x,y);
}
}
return this;
},
/**
* 设置options
* @param {Object} options 当前时间 .
*/
setOptions: function (options) {
this.reset();
if (typeof options !== "object") {
options = {};
}
this.options = $.extend(this.options,options);
this.initialize(this.options);
return this;
},
/**
* 开始
*/
start: function () {
var self = this;
// 设置起止时间
this.begin = now();
this.end = this.begin + this.duration;
if (this.driftX === 0 && this.driftY === 0) {
// 原地踏步就别浪费性能了
return;
}
/*timers.push(this);
Timer.start();*/
if (!!this.timerId) {
clearInterval(this.timerId);
this.stop();
}
this.timerId = setInterval(function () {
var t = now();
self.step(t);
}, 13);
return this;
},
/**
* 重置
*/
reset: function (x, y) {
this.stop();
x = x ? x : 0;
y = y ? y : 0;
this.domove(x, y);
return this;
},
/**
* 停止
*/
stop: function () {
if (!!this.timerId) {
clearInterval(this.timerId);
}
return this;
}
};
var defaultSetting = {
el: null,
//偏移位置
offset: [0, 0],
//终点元素,这时就会自动获取该元素的left、top,设置了这个参数,offset将失效
targetEl: null,
//运动的时间,默认500毫秒
duration: 500,
//抛物线曲率,就是弯曲的程度,越接近于0越像直线,默认0.001
curvature: 0.001,
//运动后执行的回调函数
callback: null,
// 是否自动开始,默认为false
autostart: false,
//运动过程中执行的回调函数
stepCallback: null
};
window.Parabola = Parabola;
})();
链接地址:http://www.css88.com/archives/5355
张鑫旭抛物线地址:http://www.zhangxinxu.com/wordpress/2013/12/javascript-js