博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
一个不错的抛物线js效果
阅读量:6988 次
发布时间:2019-06-27

本文共 7597 字,大约阅读时间需要 25 分钟。

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;        }/* 元素 */ 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(); };

转载地址:http://xnzvl.baihongyu.com/

你可能感兴趣的文章
第六次作业:素数判断及求和
查看>>
「学习笔记——Linux」Linux软件管理(RPM,Dpkg,APT)
查看>>
Soft NMS
查看>>
Linux命令的那些事(二)
查看>>
强制转https
查看>>
Ubuntu下GTK的安装、编译和测试
查看>>
javascript中window.open()与window.location.href的区别
查看>>
Respond.js的作用
查看>>
FCN笔记(Fully Convolutional Networks for Semantic Segmentation)
查看>>
外部线程停止Java子线程的方法
查看>>
OpenMP并行编程
查看>>
网络编程
查看>>
【ZJOI2016】线段树
查看>>
ActiveMQ-自定义用户验证
查看>>
IOS 项目加入SDL库 --- FFMPEG+SDL学习 之 二
查看>>
mysql的sql文件的备份与还原
查看>>
Java API —— 泛型
查看>>
十三周进度报告
查看>>
「APIO2018」选圆圈
查看>>
单例模式的那些事
查看>>