js抛物线动画——加入购物车动效
参考文章:http://www.zhangxinxu.com/wordpress/2013/12/javascript-js-元素-抛物线-运动-动画/
parapola.js
/*!
* by zhangxinxu(.com) 2012-12-27
* you can visit http://www.zhangxinxu.com/wordpress/?p=3855 to get more infomation
* under MIT license
*/
var funParabola = function(element, target, options) {
/*
* 网页模拟现实需要一个比例尺
* 如果按照1像素就是1米来算,显然不合适,因为页面动不动就几百像素
* 页面上,我们放两个物体,200~800像素之间,我们可以映射为现实世界的2米到8米,也就是100:1
* 不过,本方法没有对此有所体现,因此不必在意
*/ var defaults = {
speed: 166.67, // 每帧移动的像素大小,每帧(对于大部分显示屏)大约16~17毫秒
curvature: 0.001, // 实际指焦点到准线的距离,你可以抽象成曲率,这里模拟扔物体的抛物线,因此是开口向下的
progress: function() {},
complete: function() {}
}; var params = {}; options = options || {}; for (var key in defaults) {
params[key] = options[key] || defaults[key];
} var exports = {
mark: function() { return this; },
position: function() { return this; },
move: function() { return this; },
init: function() { return this; }
}; /* 确定移动的方式
* IE6-IE8 是margin位移
* IE9+使用transform
*/
var moveStyle = "margin", testDiv = document.createElement("div");
if ("oninput" in testDiv) {
["", "ms", "webkit"].forEach(function(prefix) {
var transform = prefix + (prefix? "T": "t") + "ransform";
if (transform in testDiv.style) {
moveStyle = transform;
}
});
} // 根据两点坐标以及曲率确定运动曲线函数(也就是确定a, b的值)
/* 公式: y = a*x*x + b*x + c;
*/
var a = params.curvature, b = 0, c = 0; // 是否执行运动的标志量
var flagMove = true; if (element && target && element.nodeType == 1 && target.nodeType == 1) {
var rectElement = {}, rectTarget = {}; // 移动元素的中心点位置,目标元素的中心点位置
var centerElement = {}, centerTarget = {}; // 目标元素的坐标位置
var coordElement = {}, coordTarget = {}; // 标注当前元素的坐标
exports.mark = function() {
if (flagMove == false) return this;
if (typeof coordElement.x == "undefined") this.position();
element.setAttribute("data-center", [coordElement.x, coordElement.y].join());
target.setAttribute("data-center", [coordTarget.x, coordTarget.y].join());
return this;
} exports.position = function() {
if (flagMove == false) return this; var scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft,
scrollTop = document.documentElement.scrollTop || document.body.scrollTop; // 初始位置
if (moveStyle == "margin") {
element.style.marginLeft = element.style.marginTop = "0px";
} else {
element.style[moveStyle] = "translate(0, 0)";
} // 四边缘的坐标
rectElement = element.getBoundingClientRect();
rectTarget = target.getBoundingClientRect(); // 移动元素的中心点坐标
centerElement = {
x: rectElement.left + (rectElement.right - rectElement.left) / 2 + scrollLeft,
y: rectElement.top + (rectElement.bottom - rectElement.top) / 2 + scrollTop
}; // 目标元素的中心点位置
centerTarget = {
x: rectTarget.left + (rectTarget.right - rectTarget.left) / 2 + scrollLeft,
y: rectTarget.top + (rectTarget.bottom - rectTarget.top) / 2 + scrollTop
}; // 转换成相对坐标位置
coordElement = {
x: 0,
y: 0
};
coordTarget = {
x: -1 * (centerElement.x - centerTarget.x),
y: -1 * (centerElement.y - centerTarget.y)
}; /*
* 因为经过(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
*/
// 于是
b = (coordTarget.y - a * coordTarget.x * coordTarget.x) / coordTarget.x; return this;
}; // 按照这个曲线运动
exports.move = function() {
// 如果曲线运动还没有结束,不再执行新的运动
if (flagMove == false) return this; var startx = 0, rate = coordTarget.x > 0? 1: -1; var step = function() {
// 切线 y'=2ax+b
var tangent = 2 * a * startx + b; // = y / x
// y*y + x*x = speed
// (tangent * x)^2 + x*x = speed
// x = Math.sqr(speed / (tangent * tangent + 1));
startx = startx + rate * Math.sqrt(params.speed / (tangent * tangent + 1)); // 防止过界
if ((rate == 1 && startx > coordTarget.x) || (rate == -1 && startx < coordTarget.x)) {
startx = coordTarget.x;
}
var x = startx, y = a * x * x + b * x; // 标记当前位置,这里有测试使用的嫌疑,实际使用可以将这一行注释
element.setAttribute("data-center", [Math.round(x), Math.round(y)].join()); // x, y目前是坐标,需要转换成定位的像素值
if (moveStyle == "margin") {
element.style.marginLeft = x + "px";
element.style.marginTop = y + "px";
} else {
element.style[moveStyle] = "translate("+ [x + "px", y + "px"].join() +")";
} if (startx !== coordTarget.x) {
params.progress(x, y);
window.requestAnimationFrame(step);
} else {
// 运动结束,回调执行
params.complete();
flagMove = true;
}
};
window.requestAnimationFrame(step);
flagMove = false; return this;
}; // 初始化方法
exports.init = function() {
this.position().mark().move();
};
} return exports;
}; /*! requestAnimationFrame.js
* by zhangxinxu 2013-09-30
*/
(function() {
var lastTime = 0;
var vendors = ['webkit', 'moz'];
for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame'];
window.cancelAnimationFrame = window[vendors[x] + 'CancelAnimationFrame'] || // name has changed in Webkit
window[vendors[x] + 'CancelRequestAnimationFrame'];
} if (!window.requestAnimationFrame) {
window.requestAnimationFrame = function(callback, element) {
var currTime = new Date().getTime();
var timeToCall = Math.max(0, 16.7 - (currTime - lastTime));
var id = window.setTimeout(function() {
callback(currTime + timeToCall);
}, timeToCall);
lastTime = currTime + timeToCall;
return id;
};
}
if (!window.cancelAnimationFrame) {
window.cancelAnimationFrame = function(id) {
clearTimeout(id);
};
}
}());
使用:
/* 元素 */
var element = document.getElementById("element"),
target = document.getElementById("target");
// 抛物线元素的的位置标记
var parabola = funParabola(element, target).mark();
// 抛物线运动的触发
document.body.onclick = function() {
element.style.marginLeft = "0px";
element.style.marginTop = "0px";
parabola.init();
};
加入购物车实战:
/* 本demo演示脚本基于ieBetter.js, 项目地址:https://github.com/zhangxinxu/ieBetter.js */ // 元素以及其他一些变量
var eleFlyElement = document.querySelector("#flyItem"), eleShopCart = document.querySelector("#shopCart");
var numberItem = 0;
// 抛物线运动
var myParabola = funParabola(eleFlyElement, eleShopCart, {
speed: 400,
curvature: 0.002,
complete: function() {
eleFlyElement.style.visibility = "hidden";
eleShopCart.querySelector("span").innerHTML = ++numberItem;
}
});
// 绑定点击事件
if (eleFlyElement && eleShopCart) {
[].slice.call(document.getElementsByClassName("btnCart")).forEach(function(button) {
button.addEventListener("click", function() {
// 滚动大小
var scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft || 0,
scrollTop = document.documentElement.scrollTop || document.body.scrollTop || 0; eleFlyElement.style.left = event.clientX + scrollLeft + "px";
eleFlyElement.style.top = event.clientY + scrollTop + "px";
eleFlyElement.style.visibility = "visible"; // 需要重定位
myParabola.position().move();
});
});
}
js抛物线动画——加入购物车动效的更多相关文章
- js实现文字逐个出现动效
效果 首先看下效果,这是在h5页面中常见的一中文字展现方式,那么是怎么实现的呢?其实很简单 思路 用一个定时器将预制的文字通过.substring(0, i)方法不断的赋给要显示的区域,i在定时器里面 ...
- fly.js抛物线连续不断加入购物车
http://yanshi.sucaihuo.com/jquery/2/298/demo/
- 基于jquery fly插件实现加入购物车抛物线动画效果,jquery.fly.js
在购物网站中,加入购物车的功能是必须的功能,有的网站在用户点击加入购物车按钮时,就会出现该商品从点击出以抛物线的动画相似加入购物车,这个功能看起来非常炫,对用户体验也有一定的提高.下面介绍基于jque ...
- js加入购物车抛物线动画
天猫将商品加入购物车会有一个抛物线动画,告诉用户操作成功以及购物车的位置,业务中需要用到类似的效果,记录一下实现过程备忘,先上demo 一开始没有想到用抛物线函数去做,也已经忘记还有这么个函数了,想着 ...
- 【js】插件—动效Velocity.js
Velocity.js——加速JavaScript动画 一款替代jQuery的$ .animate()动效的插件.兼容IE8和Android2.3及以上. 相比较优点: 1.它比JQuery更快,并实 ...
- 动效解析工厂:Mask 动画
转载自:http://www.cocoachina.com/ios/20160214/15250.html 前言:很多动效都是多种动画的组合,有时候你可能只是需要其中某个动画,但面对庞杂的代码库或是教 ...
- Android 利用二次贝塞尔曲线模仿购物车加入物品抛物线动画
Android 利用二次贝塞尔曲线模仿购物车加入物品抛物线动画 0.首先.先给出一张效果gif图. 1.贝塞尔曲线原理及相关公式參考:http://www.jianshu.com/p/c0d7ad79 ...
- JS运动 - 无缝滚动和缓动动画
JS运动 - 无缝滚动和缓动动画 无缝滚动原理:首先先复制两张图片(第一张和第二张)放到最后面;ul绝对定位,如果ul的left值大于等于4张图片的宽度,就应该快速复原为0. html <!DO ...
- iOS动画进阶 - 实现炫酷的上拉刷新动效
移动端訪问不佳,请訪问我的个人博客 近期撸了一个上拉刷新的小轮子.仅仅要遵循一个协议就能自己定义自己动效的上拉刷新和载入,我自己也写了几个动效进去,以下是一个比較好的动效的实现过程 先上效果图和git ...
随机推荐
- JFinal 项目 在tomcat下部署
原文:http://my.oschina.net/jfinal/blog/353062 首先明确一下 JFinal 项目是标准的 java web 项目,其部署方式与普通 java web 项目没有任 ...
- iOS开发--OC调用JS篇
OC调用JS篇 其中相对应的html部分如下: <html> <header> <meta http-equiv="Content-Type" con ...
- easyui与ueditor合用问题
在联合使用easyui与ueditor的时候,当在dialog中通过href打开一个页面,页面中含有ueditor,如果使用dialog的close方法,可以理解为只是将dialog给隐藏了,再将点击 ...
- 【转】线程及同步的性能 - 线程池 / ThreadPoolExecutors / ForkJoinPool
线程池和ThreadPoolExecutors 虽然在程序中可以直接使用Thread类型来进行线程操作,但是更多的情况是使用线程池,尤其是在Java EE应用服务器中,一般会使用若干个线程池来处理来自 ...
- writing
1.作文类型和结构2.作文的四个评分标准3.作文的常用句型4.作文的逻辑观点 大作文分为几类:1.A类(Argument): 这类作文实际上是比较常见的,比如:Caring for children ...
- HTML5学习总结-番外04 Cordova/PhoneGap
一 PhoneGap 1 PhoneGap简绍 http://www.cnblogs.com/JustRun1983/p/3819433.html 2 环境安装 http://cordova.apac ...
- @Column
@Column标记表示所持久化属性所映射表中的字段,该注释的属性定义如下: @Target({METHOD, FIELD}) @Retention(RUNTIME) public @interface ...
- tomcat集群学习记录1--初识apache http server
起因 平时开发的时候我都是用eclipse把代码部署到本地tomcat的,当然只会去跑1台tomcat啦... 偶尔有时候解决问题需要去公司测试环境找日志.连上公司测试环境以后发现竟然有2台weblo ...
- asp.net MVC4 异步文件上传
1.下载ajaxfileupload.js 2.在控制器内创建如下方法 //文件上传 public ActionResult uploadFile(HttpPostedFileBase file) { ...
- 每天写点shell--命令行参数
1.读取参数:位置参数变量是标准的数字: $0是程序名, $1是第一个参数, $2是第二个参数... #!/bin/bash # using one command line parameter fa ...