zoukankan      html  css  js  c++  java
  • js 抛物线 笔记备份

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

      

    学习版本

    <!DOCTYPE html>
    <html lang="en" >
    
    <head>
    
      <meta charset="UTF-8">
      <link rel="shortcut icon" type="image/x-icon" href="https://static.codepen.io/assets/favicon/favicon-8ea04875e70c4b0bb41da869e81236e54394d63638a1ef12fa558a4a835f1164.ico" />
      <link rel="mask-icon" type="" href="https://static.codepen.io/assets/favicon/logo-pin-f2d2b6d2c61838f7e76325261b7195c27224080bc099486ddd6dccb469b8e8e6.svg" color="#111" />
      <title>CodePen - gwcpwx</title>
      
      
      
      
          <style>
          #goods {  
      cursor: pointer;
      width: 100px;
      height: 40px;
      line-height: 40px;
      border: 1px solid deeppink;
      text-align: center;
      color: deeppink;  
    }  
    #goods:hover {  
      color: #fff;  
      background-color: deeppink;  
    }
    #cart {
      position: fixed;
      right: 0;
      bottom: 100px;
      color: deeppink;
      border: 1px solid deeppink;  
    }  
        </style>
    
      <script>
    
    </script>
    
     
    
    </head>
    
    <body translate="no" >
    y = ax² + bx + c
      <div id="goods"> 
    商品
    </div> 
    
    
    <br><br><br><br>
    <br><br><br><br><br> 
    <br><br><br><br><br>
    <div id="cart"> 
    购物车  
    </div>
    
     
    
        <script >
              var goodsDom = document.querySelector("#goods");
        var cartDom = document.querySelector("#cart");
        goodsDom.onclick = function () {
        var goodsXLeft = goodsDom.offsetLeft;
        var goodsYTop = goodsDom.offsetTop;
        var startX = goodsXLeft + 100;
        var startY = goodsYTop - document.body.scrollTop + 12;
        var endX = cartDom.offsetLeft;
        var endY = cartDom.offsetTop;
        var diffX = endX - startX;
        var diffY = endY - startY;
        //  假设中点(0, 0),也就是方程中的c为0
        var c = 0;
        var a = (endY/endX-startY/startX)/(endX - startX);
        var b = endY/endX - a*endX;
        // 创建一个移动的dom
        var movingDom = document.createElement("div");
        movingDom.style.position = 'fixed';
        movingDom.style.left = startX + 'px';
        movingDom.style.top = startY + 'px';
        movingDom.style.height = '16px';
        movingDom.style.width = '16px';
        movingDom.style.borderRadius = '8px';
        movingDom.style.background = 'red';
        document.body.appendChild(movingDom)
        // 定义移动的dom的x, y
        var x = startX;
        var y = startY;
        var ax2 = 0;
        var bx = 0;
        var time = setInterval(function(){
          if(x < endX) {
            x = x + 2;
            ax2 = a*x*x;
            bx = b*x;
            y = ax2 + bx;
            console.log(ax2, bx, y)
            movingDom.style.left = x + 'px';
            movingDom.style.top = y + 'px';
          } else {
            movingDom.parentNode.removeChild(movingDom)
            clearInterval(time);
          }
         },10)
        }
          //# sourceURL=pen.js
        </script>
    
    
    
      
      
    
    </body>
    
    </html>
     

     vue实现抛物线

    <template>
      
          <div>   
              <ul class="lists">
                  <li>商品1商品1<i @click="ball_fly($event)">+</i></li>
                  <li>商品12商品1<i @click="ball_fly($event)">+</i></li>
                  <li>商品13商品1<i @click="ball_fly($event)">+</i></li>
                  
                  <li>商品1商品1<i @click="ball_fly($event)">+</i></li>
                  <li>商品12商品1<i @click="ball_fly($event)">+</i></li>
                  <li>商品13商品1<i @click="ball_fly($event)">+</i></li>
                  
                  <li>商品1商品1<i @click="ball_fly($event)">+</i></li>
                  <li>商品12商品1<i @click="ball_fly($event)">+</i></li>
                  <li>商品13商品1<i @click="ball_fly($event)">+</i></li>
                  
                  <li>商品1商品1<i @click="ball_fly($event)">+</i></li>
                  <li>商品12商品1<i @click="ball_fly($event)">+</i></li>
                  <li>商品13商品1<i @click="ball_fly($event)">+</i></li>
              </ul>
              
                  <div class="targetbox"><div class="target car_icon"  ref="carIcon">购物车</div>  </div> 
    
          </div>
       
         
        </template>
    <script>
    
    export default {
      name: 'business',
      data () {
        return {
          showMe: false,
          // 计算商品区域高度
          computedContentHeight: window.innerHeight - (window.innerWidth / 10 * 4.2),
         
        };
      },
      
       
      
      methods: {
        // 初始化
        init () {
         
          // 给购物车添加animationend事件,动画结束后去掉有animation的class
          this.$refs.carIcon.addEventListener('animationend', () => {
            this.$refs.carIcon.classList.remove('tantantan');
          }, false);
        },
     
       
    
    
        // 修改版抛球效果,使用css3中的贝塞尔曲线实现
        ball_fly (e) {
          // 被点元素位置
          var bound = e.target.getBoundingClientRect();
          var boundTop = bound.top;// 点击top值
          var boundLeft = bound.left;// 点击left值
          // 目标元素位置
          var target = this.$refs.carIcon;
          var targetData = target.getBoundingClientRect();
          var targetTop = targetData.top;// 目标top值
          var targetLeft = targetData.left;// 目标left值
          // 创建父球(父球横向运动)
          var father = document.createElement('div');
          father.className = 'father flyball';
          // 创建子球(子球垂直css3贝塞尔曲线运动,先上后下,得到抛球效果)
          var child = document.createElement('div');
          child.className = 'child inner';
          father.appendChild(child);
          // 设置父盒子生成的位置
          // father.style.cssText = 'top:' + boundTop + 'px;left:' + boundLeft + 'px;';
          father.style.top = boundTop + 'px';
          father.style.left = boundLeft + 'px';
          // append小球到页面中
          document.body.appendChild(father);
          setTimeout(() => {
            // 目标left - 所点元素left + 目标元素宽度的一半(修正落点)
            father.style.transform = 'translate3d(' + (targetLeft - boundLeft + targetData.width / 2) + 'px, 0px, 0px)';
            child.style.cssText = 'transform: translate3d(0px, ' + (targetTop - boundTop) + 'px, 0px);';
            // 运动结束后删掉小球
            setTimeout(() => {
              // 移除小球
              father.parentNode.removeChild(father);
              // 购物车添加弹弹弹的css
              this.$refs.carIcon.classList.add('tantantan');
               // 给购物车添加animationend事件,动画结束后去掉有animation的class
          this.$refs.carIcon.addEventListener('animationend', () => {
            this.$refs.carIcon.classList.remove('tantantan');
          }, false);
              
            }, 500);
          }, 10);
        }
        // 生成小球抛出 计算left top 生成动画 不流畅 (css3的没想好)
        /* ball_fly (e) {
          // 被点元素宽高
          var bound = e.target.getBoundingClientRect(); // 被点元素位置
          // 创造元素
          var qiu = document.createElement('div');
          qiu.className = 'qiu';
          qiu.style.top = bound.top + 'px';
          qiu.style.left = bound.left + 'px';
          document.body.appendChild(qiu);
          // 目标元素位置
          var dsa = this.$refs.carIcon;
          var mubiao = dsa.getBoundingClientRect();
          var mubiaoT = mubiao.top;
          var mubiaoL = mubiao.left;
          var timer = null;
          // top差值 left差值
          var chaTop = mubiaoT - bound.top;
          // 要减掉目标宽度一半 让落点对准目标中心
          var chaLeft = bound.left - mubiaoL - dsa.offsetWidth / 2;
          // 规定上抛初速度为 top 差值的55分之1
          var g = chaTop / 55;
          // 规定上抛初速度为 top 差值的15分之1
          var vTop = chaTop / 15;
          timer = setInterval(() => {
            qiu.style.top = (qiu.getBoundingClientRect().top + (-vTop + g)) + 'px';
            qiu.style.left = (qiu.getBoundingClientRect().left + (-chaLeft / 14)) + 'px';
            // 每次 g 对速度的影响
            vTop -= g;
            if (qiu.getBoundingClientRect().top >= mubiaoT) {
              clearInterval(timer);
              qiu.parentNode.removeChild(qiu);
              this.$refs.carIcon.classList.add('tantantan');
            }
          }, 1000 / 25);
        } */
      }
    };
    </script>
    
    <style lang="less">
    .business_box{
      100%;
      height:100%;
      
      } 
     @keyframes mymove {
    0% {
        transform: scale(1);
    }
    25% {
        transform: scale(0.8);
    }
    50% {
        transform: scale(1.1);
    }
    75% {
        transform: scale(0.9);
    }
    100% {
        transform: scale(1);
    }
    }
    /* 购物车弹弹弹 */
    .tantantan {
      animation: mymove 1s;
    }
    /* 修正版抛球效果所需CSS */
    .flyball {
        position:fixed;
        top:0;
        left:0;
        -webkit-transition:-webkit-transform .5s linear;
        transition:-webkit-transform .5s linear;
        transition:transform .5s linear;
        transition:transform .5s linear, -webkit-transform .5s linear
    }
    .flyball .inner {
        position:absolute;
        top:0;
        left:0;
        background-color:#3190e8;
        border-radius:50%
    }
    .flyball, .flyball .inner {
        will-change:transform;/* css3自带的开启GPU加速 */
        -webkit-transform:translateZ(0);
        transform:translateZ(0)
    }
    .flyball .inner {
        -webkit-transition:-webkit-transform .5s cubic-bezier(.3, -.2, 1, 0);
        transition:-webkit-transform .5s cubic-bezier(.3, -.2, 1, 0);
        transition:transform .5s cubic-bezier(.3, -.2, 1, 0);
        transition:transform .5s cubic-bezier(.3, -.2, 1, 0), -webkit-transform .5s cubic-bezier(.3, -.2, 1, 0)
    }
    
    /* 父盒子的样式 */
    .father{
       20px;;
      height:20px;
      position: fixed;
      z-index: 999;
    }
    /* 子盒子(小球)的样式 */
    .child{
       20px;;
      height:20px;
      background: #3190e8;
      position: absolute;
      top: 0;
      left: 0;
    }
    
    .lists{  100%;  height: auto;; overflow: hidden;}
    
    .lists li{ height: 44px; line-height: 40px; background: #f1f1f1; margin-bottom: 20px; position: relative; padding: 0 10px;}
    .lists li i{  20px;  height: 20px; text-align: center;; line-height: 19px;; display: block; border-radius: 15px; overflow: hidden; position: absolute; right: 20px; top:10px;; background: #3190e8; color: #fff; ;}
    .targetbox{ position: fixed; bottom: 54px; left: 0;  100%; height: 54px; background: #666;}
    .target{   50px; height: 50px; color: #fff; line-height: 50px; text-align: center;}
    .car_icon {
      
       
       
        background: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zd…48Y2lyY2xlIGN4PSIxMiIgY3k9IjUxIiByPSI0IiBmaWxsPSIjRkZGIi8+PC9nPjwvc3ZnPg==) #3190e8 center no-repeat;
       
        border-radius: 50%;
        background-size: 60% auto;
    }
    </style>

     css 实现抛物线

    <!DOCTYPE html>
    <html lang="en" style="100%;height:100%;">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width">
        <style>
            * {
                padding: 0;
                margin: 0;
            }
            #ball {
                12px;
                height:12px;
                background: #5EA345;
                border-radius: 50%;
                position: fixed;
                transition: left 1s linear, top 1s ease-in;
            }
        </style>
        <title>CSS3 水平抛物线动画</title>
    </head>
    <body style="100%;height:100%;">
        <div id="ball"></div>
    </body>
    <script>
        var $ball = document.getElementById('ball');
        document.body.onclick = function (evt) {
            console.log(evt.pageX,evt.pageY)
            $ball.style.top = evt.pageY+'px';
            $ball.style.left = evt.pageX+'px';
            $ball.style.transition = 'left 0s, top 0s';
            setTimeout(()=>{
                $ball.style.top = window.innerHeight+'px';
                $ball.style.left = '0px';
                $ball.style.transition = 'left 1s linear, top 1s ease-in';
            }, 20)
        }
    </script>
    </html>
    

      

    小程序

    cartAnimation(x, y) { // x y 为手指点击的坐标,即球的起始坐标
        let self = this,
            cartY = app.globalData.winHeight - 50, // 结束位置(购物车图片)纵坐标
            cartX = 50, // 结束位置(购物车图片)的横坐标
            animationX = flyX(cartX, x), // 创建球的横向动画
            animationY = flyY(cartY, y) // 创建球的纵向动画
        this.setData({
              ballX: x,
              ballY: y,
              showBall: true
        })
        setTimeoutES6(100).then(() => { // 100 ms 延时,确保球已经到位并显示
            self.setData({
                animationX: animationX.export(),
                animationY: animationY.export(),
            })
            return setTimeoutES6(400) // 400 ms 是球的抛物线动画时长
        }).then(() => { // 400 ms 延时后隐藏球
            this.setData({
                showBall: false,
            })
        })
    }
     
    function setTimeoutES6(sec) { // Promise 化 setTimeout
        return new Promise((resolve, reject) => {
            setTimeout(() => {resolve()}, sec)
        })
    }
     
    function flyX(cartX, oriX) { // 水平动画
        let animation = wx.createAnimation({
            duration: 400,
            timingFunction: 'linear',
        })
        animation.left(cartX).step()
        return animation
    }
     
    function flyY(cartY, oriY) { // 垂直动画
        let animation = wx.createAnimation({
            duration: 400,
            timingFunction: 'ease-in',
        })
        animation.top(cartY).step()
        return animation
    }
    

      

    222

        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();
     };

    333

    <!doctype html >
    <html>
    <head>
      <meta charset="utf-8"/>
      <title>抛物线运动</title>
      <style>
        .pwx_rect{position:absolute;left:10px;top:300px;background-color:#888;height:50px;50px;}
        .pwx_hr{border-top:2px solid #ddd;position:absolute;98%;left:0px;top:350px;}
      </style>
      <script>
        test = function(){
          var rect = document.getElementById("rect");
          pwx(rect,60,5); //参数2:抛物线角度,参数3:横向速度每次增加5
        }
        function pwx(rect,radian,step){
          var animate = function(opt){
            var cos = Math.cos(opt.radian*Math.PI/180);//邻边比斜边,60度的话等于1/2
            var sin = Math.sin(opt.radian*Math.PI/180);//对边比斜边,30度的话等于1/2
            var left = opt.rect.offsetLeft;
            var top = opt.rect.offsetTop;
            if(opt.radian>0){
              left+=opt.step;
              opt.radian-=1; //角度递减1
              var a = left - opt.initLeft;
              var c = (a/cos);
              var b = (sin*c);
              opt.rect.style.left = opt.initLeft+a+"px";
              opt.rect.style.top = opt.initTop-b+"px";
              setTimeout(function(){
                animate(opt);
              },10);
            }else{
              opt.rect.style.left = left+opt.step+"px";
              opt.rect.style.top = opt.initTop+"px";
            }
          }
          animate({
            step : step,
            rect : rect,
            radian : radian,
            initTop : rect.offsetTop,
            initLeft : rect.offsetLeft
          });
        }
      </script>
    </head>
    <body>
    
    <input type="button" value="抛物线" onclick="test()"/>
      <div class="pwx_rect" id="rect"></div>
      <div class="pwx_hr"></div>
    </body>
    </html>
    

      

    /*!
     * parabola trajectory v1.0
     *
     * Contact: https://github.com/xiaolin3303
     * 2016-09-30
     *
     * Designed and built with all the love of Web
     */
    ;(function (window, Math) {
        /*
         * @params Object opts
         */
        function Parabola (opts) {
            opts = opts || {};
            // required `startPos`, `endPos` params in opts
            if (!opts.startPos) {
                throw new Error('`startPos` is required in init options');
            }
    
            if (!opts.endPos) {
                throw new Error('`endPos` is required in init options');
            }
            // opts.curvature = opts.curvature || 0.003;
            opts.duration = opts.duration || 2000;
    
            this.opts = opts;
    
            this.calCurvature();
        }
    
        Parabola.prototype.calCurvature = function () {
    
            this.opts.driftX = this.opts.endPos.left - this.opts.startPos.left;
            this.opts.driftY = this.opts.endPos.top - this.opts.startPos.top;
    
            // 在不超出屏幕范围的前提下,尽量抛得更高,计算合适的曲率 (a)
            var yMin = -1 * this.opts.startPos.top;
    
            var a = this.power(this.opts.driftX, 4);
            var b = (4 * yMin - 2 * this.opts.driftY) * this.power(this.opts.driftX, 2);
            var c = this.power(this.opts.driftY, 2);
    
            this.opts.curvature = (-1 * b + Math.sqrt((this.power(b, 2) - 4 * a * c))) / (2 * a);
    
            this.opts.b = (this.opts.driftY - this.opts.curvature * this.opts.driftX * this.opts.driftX) / this.opts.driftX;
        }
    
        Parabola.prototype.power = function (v, n) {
            if (n === 1) {
                return v;
            } else {
                return v * arguments.callee(v, (n - 1));
            }
        }
    
        Parabola.prototype.calPosition = function (progress) {
            // 当前进度下的X轴的位置
            x = this.opts.driftX * progress;
            // 当前进度下的Y轴的位置
            // y = a*x*x + b*x + c,  c = 0
            y = this.opts.curvature * x * x + this.opts.b * x;
    
            return {
                left: Math.round(x + this.opts.startPos.left),
                top: Math.round(y + this.opts.startPos.top)
            }
        }
    
        Parabola.prototype.start = function () {
            var opts = this.opts;
            var me = this;
            var startTimeStamp = +new Date();
            var animationFrame = window.requestAnimationFrame  ||
                window.webkitRequestAnimationFrame  ||
                window.mozRequestAnimationFrame     ||
                window.oRequestAnimationFrame       ||
                window.msRequestAnimationFrame      ||
                function (callback) { window.setTimeout(callback, 1000 / 60); };
    
            function step () {
                var currentTimeStamp = +new Date();
    
                var progress = Math.min((currentTimeStamp - startTimeStamp) / opts.duration, 1);
                if (progress === 1) {
                    // 动画结束
                    return false;
                } else {
                    var position = me.calPosition(progress);
                    opts.onStep && opts.onStep(position);
    
                    return true;
                }
            }
    
            function progress () {
                if (step()) {
                    animationFrame(progress);
                } else {
                    if (typeof opts.onFinish === 'function') {
                        opts.onFinish(opts.endPos);
                    }
                }
            }
    
            animationFrame(progress);
        }
    
        if ( typeof module !== 'undefined' && module.exports ) {
            module.exports = Parabola;
        } else if ( typeof define === 'function' && define.amd ) {
            define( function () { return Parabola; } );
        } else {
            window.Parabola = Parabola;
        }
    
    })(window, Math)
    
    window.onload = function () {
        var btn = document.querySelector('button');
    		var target = document.querySelector('.dot');
    		var parabola = new Parabola({
    			startPos: {
    				left: 100,
    				top: 60
    			},
    			endPos: {
    				left: 500,
    				top: 200
    			},
          duration: 1000,
    			onStep (pos) {
    				target.style.left = pos.left + 'px';
    				target.style.top = pos.top + 'px';
    			},
    			onFinish (pos) {
            target.classList.add('scaleAnimation');
    				console.log('Animation Finished!');
    			}
    		});
    
    		// parabola.start();
        btn.addEventListener('click', function () {
            target.classList.remove('scaleAnimation');
            parabola.start();
        }, false);
    }
    

    fly.js

    /*
     * jquery.fly
     * 
     * 抛物线动画
     * @github https://github.com/amibug/fly
     * Copyright (c) 2014 wuyuedong
     * copy from tmall.com
     */
    (function ($) {
      $.fly = function (element, options) {
        // 默认值
        var defaults = {
          version: '1.0.0',
          autoPlay: true,
          vertex_Rtop: 20, // 默认顶点高度top值
          speed: 1.2,
          start: {}, // top, left, width, height
          end: {},
          onEnd: $.noop
        };
    
        var self = this,
          $element = $(element);
    
        /**
         * 初始化组件,new的时候即调用
         */
        self.init = function (options) {
          this.setOptions(options);
          !!this.settings.autoPlay && this.play();
        };
    
        /**
         * 设置组件参数
         */
        self.setOptions = function (options) {
          this.settings = $.extend(true, {}, defaults, options);
          var settings = this.settings,
            start = settings.start,
            end = settings.end;
    
          $element.css({marginTop: '0px', marginLeft: '0px', position: 'fixed'}).appendTo('body');
          // 运动过程中有改变大小
          if (end.width != null && end.height != null) {
            $.extend(true, start, {
               $element.width(),
              height: $element.height()
            });
          }
          // 运动轨迹最高点top值
          var vertex_top = Math.min(start.top, end.top) - Math.abs(start.left - end.left) / 3;
          if (vertex_top < settings.vertex_Rtop) {
            // 可能出现起点或者终点就是运动曲线顶点的情况
            vertex_top = Math.min(settings.vertex_Rtop, Math.min(start.top, end.top));
          }
    
          /**
           * ======================================================
           * 运动轨迹在页面中的top值可以抽象成函数 y = a * x*x + b;
           * a = curvature
           * b = vertex_top
           * ======================================================
           */
    
          var distance = Math.sqrt(Math.pow(start.top - end.top, 2) + Math.pow(start.left - end.left, 2)),
            // 元素移动次数
            steps = Math.ceil(Math.min(Math.max(Math.log(distance) / 0.05 - 75, 30), 100) / settings.speed),
            ratio = start.top == vertex_top ? 0 : -Math.sqrt((end.top - vertex_top) / (start.top - vertex_top)),
            vertex_left = (ratio * start.left - end.left) / (ratio - 1),
            // 特殊情况,出现顶点left==终点left,将曲率设置为0,做直线运动。
            curvature = end.left == vertex_left ? 0 : (end.top - vertex_top) / Math.pow(end.left - vertex_left, 2);
    
          $.extend(true, settings, {
            count: -1, // 每次重置为-1
            steps: steps,
            vertex_left: vertex_left,
            vertex_top: vertex_top,
            curvature: curvature
          });
        };
    
        /**
         * 开始运动,可自己调用
         */
        self.play = function () {
          this.move();
        };
    
        /**
         * 按step运动
         */
        self.move = function () {
          var settings = this.settings,
            start = settings.start,
            count = settings.count,
            steps = settings.steps,
            end = settings.end;
          // 计算left top值
          var left = start.left + (end.left - start.left) * count / steps,
            top = settings.curvature == 0 ? start.top + (end.top - start.top) * count / steps : settings.curvature * Math.pow(left - settings.vertex_left, 2) + settings.vertex_top;
          // 运动过程中有改变大小
          if (end.width != null && end.height != null) {
            var i = steps / 2,
              width = end.width - (end.width - start.width) * Math.cos(count < i ? 0 : (count - i) / (steps - i) * Math.PI / 2),
              height = end.height - (end.height - start.height) * Math.cos(count < i ? 0 : (count - i) / (steps - i) * Math.PI / 2);
            $element.css({ width + "px", height: height + "px", "font-size": Math.min(width, height) + "px"});
          }
          $element.css({
            left: left + "px",
            top: top + "px"
          });
          settings.count++;
          // 定时任务
          var time = window.requestAnimationFrame($.proxy(this.move, this));
          if (count == steps) {
            window.cancelAnimationFrame(time);
            // fire callback
            settings.onEnd.apply(this);
          }
        };
    
        /**
         * 销毁
         */
        self.destroy = function(){
          $element.remove();
        };
    
        self.init(options);
      };
    
      // add the plugin to the jQuery.fn object
      $.fn.fly = function (options) {
        return this.each(function () {
          if (undefined == $(this).data('fly')) {
            $(this).data('fly', new $.fly(this, options));
          }
        });
      };
    })(jQuery);
    <script>
    $(function() {
        var offset = $("#end").offset();
        $(".addcar").click(function(event){
            var addcar = $(this);
            var img = addcar.parent().find('img').attr('src');
            var flyer = $('<img class="u-flyer" src="'+img+'">');
            flyer.fly({
                start: {
                    left: event.pageX,
                    top: event.pageY
                },
                end: {
                    left: offset.left+10,
                    top: offset.top+10,
                     0,
                    height: 0
                },
                onEnd: function(){
                    $("#msg").show().animate({ '250px'}, 200).fadeOut(1000);
                    addcar.css("cursor","default").removeClass('orange').unbind('click');
                    this.destory();
                }
            });
        });
    });
    </script>

      

  • 相关阅读:
    现代软件工程 第一章 概论 第4题——邓琨
    现代软件工程 第一章 概论 第9题——邓琨
    现代软件工程 第一章 概论 第7题——张星星
    现代软件工程 第一章 概论 第5题——韩婧
    hdu 5821 Ball 贪心(多校)
    hdu 1074 Doing Homework 状压dp
    hdu 1074 Doing Homework 状压dp
    hdu 1069 Monkey and Banana LIS变形
    最长上升子序列的初步学习
    hdu 1024 Max Sum Plus Plus(m段最大子列和)
  • 原文地址:https://www.cnblogs.com/surfaces/p/6699219.html
Copyright © 2011-2022 走看看