Search code examples
jquerykineticjs

Animate image on curve


I want to animate an image in curve and at the end of curve Image should rotate. I tried with .animate with a curve but it is generating error

TypeError: jQuery.easing[this.easing] is not a function


Solution

  • This can be achieved by using canvas and kinetic js.Just include

    <script src="https://cdnjs.cloudflare.com/ajax/libs/kineticjs/5.0.1/kinetic.min.js"></script>

    Add below script to body

    <div id="container"></div>
    <script type="text/javascript">
    function sleep(milliseconds) {
      var start = new Date().getTime();
      for (var i = 0; i < 1e7; i++) {
        if ((new Date().getTime() - start) > milliseconds){
          break;
        }
      }
    }
    window.onload = function() {
      // set up stage,layer and quadratic-curve
      var stage = new Kinetic.Stage({
          container: 'container',
          width: 350,
          height: 350
      });
      var layer = new Kinetic.Layer();
      stage.add(layer);
    
    
       // vars related to the images
      var bone, dog;
      var boneScale = 1;
      var boneOffset = {
          x: -11,
          y: 0
      };
      var dogScale = 0.50;
    
      // vars related to the quadratic curve
      var qStart = {
          x: 115,
          y: 85
      };
      var qControl = {
          x: 155,
          y: 108
      };
      var qEnd = {
          x: 200,
          y: 88
      };
      var startXY = getQuadraticBezierXYatT(qStart, qControl, qEnd, 0, 00);
      var pathData = "M " + qStart.x + " " + qStart.y;
      pathData += " Q " + qControl.x + " " + qControl.y;
      pathData += " " + qEnd.x + " " + qEnd.y;
    
      // vars related to calculating points on the curve
      var T = 0;
      var TDirection = 1;
    
    
      // set up quadratic-curve
      var path = new Kinetic.Path({
          x: 0,
          y: 0,
          data: pathData,
          stroke: 'green',
          strokeWidth: 3,
      });
      layer.add(path);
      layer.draw();
    
    
      // load 2 images
      var loaded = 0;
      var boneImg = new Image();
      boneImg.onload = function () {
          loaded++;
          if (loaded == 2) {
              start();
          }
      }
      boneImg.src = "<%=asset_path 'flight.png'%>";
      var dogImg = new Image();
      dogImg.onload = function () {
          loaded++;
          if (loaded == 2) {
              start();
          }
      }
      dogImg.src = "<%=asset_path 'your-logo.png'%>";
      var circle0 = new Kinetic.Circle({
        x: 100,
        y: 56,
        id: 'circle0',
        radius: 9,
        fill: 'yellow',
        stroke: 'white',
        strokeWidth: 0
      });
      layer.add(circle0);
    
      // create Kinetic.Images
      function start() {
          var pos = getQuadraticBezierXYatT(qStart, qControl, qEnd, 0.00);
          bone = new Kinetic.Image({
              x: pos.x + boneOffset.x,
              y: pos.y + boneOffset.y,
              id: 'bone',
              image: boneImg,
              width: boneImg.width * boneScale,
              height: boneImg.height * boneScale,
          });
          layer.add(bone);
          dog = new Kinetic.Image({
              x: 30,
              y: 15,
              image: dogImg,
              width: 300,
              height: 90
          });
          layer.add(dog);
          layer.draw();
    
          animation.start();
      }
    
    var imageObj = new Image({id: 'bone'});
    imageObj.src = "<%=asset_path 'mirror_flight.png'%>";
    var flight = new Image({id: 'flight'});
    flight.src = "<%=asset_path 'flight.png'%>";
      // create animation along quadratic curve
      var animation = new Kinetic.Animation(function (frame) {
    
          var pos = getQuadraticBezierXYatT(qStart, qControl, qEnd, T / 150);
          pos.x += boneOffset.x;
          pos.y += boneOffset.y;
          bone.setPosition(pos);
    
          T += TDirection;
          if (T < 0 || T > 150) {
              TDirection *= -1;
              T += TDirection
              if (T==150) {
                layer.get('#circle0')[0].remove();
                layer.get('#bone')[0].setImage(imageObj);
                var circle = new Kinetic.Circle({
                  x: 221,
                  y: 56,
                  id: 'circle',
                  radius: 9,
                  fill: 'yellow',
                  stroke: 'white',
                  strokeWidth: 0
                });
    
                // add the shape to the layer
                layer.add(circle);
    
    
                sleep(1000);
                // layer.get('#circle')[0].remove();
              } else if(T==0){
                layer.get('#circle')[0].remove();
                 var circle0 = new Kinetic.Circle({
                  x: 100,
                  y: 56,
                  id: 'circle0',
                  radius: 9,
                  fill: 'yellow',
                  stroke: 'black',
                  strokeWidth: 0
                });
                 layer.add(circle0);
                layer.get('#bone')[0].setImage(flight);
                sleep(1000);
              };
          }
    
      }, layer);
    
      // Calc an XY along a quadratic curve at interval T
      // T==0.00 at start of curve, T==1.00 at end of curve
      function getQuadraticBezierXYatT(startPt, controlPt, endPt, T) {
          var x = Math.pow(1 - T, 2) * startPt.x + 2 * (1 - T) * T * controlPt.x + Math.pow(T, 2) * endPt.x;
          var y = Math.pow(1 - T, 2) * startPt.y + 2 * (1 - T) * T * controlPt.y + Math.pow(T, 2) * endPt.y;
          return ({
              x: x,
              y: y
          });
      }
    }
    
    </script>
    

    You can simply control the arc of curve from var qControl just put your images in place of dogImg.src ,imageObj.src ,flight.src

    Note: The imageObj and flight.src should be mirror images of each other