JavaScript实现的抛物线运动效果 – WEB前端开发

我是创始人李岩:很抱歉!给自己产品做个广告,点击进来看看。  

最近做购物车功能,看到天猫上的购物车有元素抛物线运动效果,所以也想凑热闹实现一个。

网上搜索了一下,看了一下张鑫旭的《 小折腾:JavaScript与元素间的抛物线轨迹运动 》,原理张鑫旭已经讲的很清楚了,多说了也没什么意思,就是数学公式。不过看代码个人觉得有点变扭,那不是我的习惯,所以自己重新写了一个。

先看demo: http://www.css88.com/demo/parabola/index.html

如何使用:

运动位移的元素必须设置为 position: absolute ,通过绝对定位控制 lefttop 来实现的;

首先你可以 new 一个对象:

		var bool = new Parabola({
		el: "#boll",
		offset: [500, 100],
		curvature: 0.005,
		duration: 3000,
		callback: function () {
		alert("完成后回调")
		},
		stepCallback: function (x, y) {
		console.log(x, y);
		$("<div>").appendTo("body").css({
		"position": "absolute",
		"top": this.elOriginalTop + y,
		"left": this.elOriginalLeft + x,
		"background-color": "#CDCDCD",
		"width": "5px",
		"height": "5px",
		"border-radius": "5px"
		});
		}
		});
	

参数说明:

参数名 数据类型 默认值 描述
el jQuery||String(选择器) null 必须填写的参数,要移动的元素,可以是jQuery对象或选择器
offset Array [0, 0] 表示移动元素在X,Y轴的偏移位置,设置了targetEl参数后,该参数将失效
targetEl jQuery||String(选择器) null 终点元素,这时就会自动获取该元素的left、top值,来表示移动元素在X,Y轴的偏移位置;设置了这个参数,offset将失效
duration Number 500 运动的时间,默认500毫秒
curvature Number 0.001 抛物线曲率,就是弯曲的程度,越接近于0越像直线,默认0.001
callback Function null 运动后执行的回调函数,this指向该对象
stepCallback Function null 运动过程中执行的回调函数,this指向该对象,接受x,y参数,分别表示X,Y轴的偏移位置。
autostart Boolean false 是否自动开始运动,默认为false

方法:

.reset()

重置元素的位置

.start()

开始执行动画

.stop()

停止动画

.setOptions(options)

重置options参数

先看demo: http://www.css88.com/demo/parabola/index.html

JS代码:

		;
		(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);
		}
		}
		return this;
		},
		/**
		* 设置options
		*  @param {Object} options 当前时间 .
		*/
		setOptions: function (options) {
		this.reset();
		if (typeof options !== "object") {
		options = {};
		}
		this.options = this.getOptions(options);
		this.initialize('parabola', 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;
		})();
	

本文被转载1次

首发媒体 Web前端开发 | 转发媒体

随意打赏

提交建议
微信扫一扫,分享给好友吧。