动力学性能滞后

时间:2014-05-07 15:06:54

标签: javascript html5 kineticjs

我正在研究类似于HTML5幸运轮的径向控制。我在这里修改了原件,并提供了我需要的一些附加功能的示例:http://jsfiddle.net/fEm9P/当您单击内部动力学楔块时,它们将在较大的楔块内收缩和扩展。不幸的是,当我旋转滚轮时,它落后于指针。它在这里并不算太差,但它在移动设备上真的很明显。

我知道这是因为我没有缓存方向盘。当我对轮子进行缓存(取消注释线239-249)时,内部楔块不再响应鼠标/触摸,但旋转响应是完美的。我还尝试将内楔添加到单独的层并仅缓存主轮。然后我用外轮旋转内轮。这样做有点好,但在移动设备上仍然不可行。

任何建议都将不胜感激。

斯蒂芬

  //constants
  var MAX_ANGULAR_VELOCITY = 360 * 5;
  var NUM_WEDGES = 25;
  var WHEEL_RADIUS = 410;
  var ANGULAR_FRICTION = 0.2;

  // globals
  var angularVelocity = 360;
  var lastRotation = 0;
  var controlled = false;
  var target, activeWedge, stage, layer, wheel, 
      pointer, pointerTween, startRotation, startX, startY;
  var currentVolume, action;

  function purifyColor(color) {
    var randIndex = Math.round(Math.random() * 3);
    color[randIndex] = 0;
    return color;
  }
  function getRandomColor() {
    var r = 100 + Math.round(Math.random() * 55);
    var g = 100 + Math.round(Math.random() * 55);
    var b = 100 + Math.round(Math.random() * 55);
    var color = [r, g, b];
    color = purifyColor(color);
    color = purifyColor(color);

    return color;
  }
  function bind() {
    wheel.on('mousedown', function(evt) {
      var mousePos = stage.getPointerPosition();
      angularVelocity = 0;
      controlled = true;
      target = evt.targetNode;
      startRotation = this.rotation();
      startX = mousePos.x;
      startY = mousePos.y;
    });
    // add listeners to container
    document.body.addEventListener('mouseup', function() {
      controlled = false;
        action = null;
      if(angularVelocity > MAX_ANGULAR_VELOCITY) {
        angularVelocity = MAX_ANGULAR_VELOCITY;
      }
      else if(angularVelocity < -1 * MAX_ANGULAR_VELOCITY) {
        angularVelocity = -1 * MAX_ANGULAR_VELOCITY;
      }

      angularVelocities = [];
    }, false);

    document.body.addEventListener('mousemove', function(evt) {
      var mousePos = stage.getPointerPosition();
      var x1, y1;
      if(action == 'increase') {
            x1 = (mousePos.x-(stage.getWidth() / 2));
            y1 = (mousePos.y-WHEEL_RADIUS+20);
            var r = Math.sqrt(x1 * x1 + y1 * y1);
            if (r>500){
                r=500;
            } else if (r<100){
                r=100;
            };          
            currentVolume.setRadius(r);
            layer.draw();            
      } else {  
          if(controlled && mousePos && target) {
            x1 = mousePos.x - wheel.x();
            y1 = mousePos.y - wheel.y();
            var x2 = startX - wheel.x();
            var y2 = startY - wheel.y();
            var angle1 = Math.atan(y1 / x1) * 180 / Math.PI;
            var angle2 = Math.atan(y2 / x2) * 180 / Math.PI;
            var angleDiff = angle2 - angle1;

            if ((x1 < 0 && x2 >=0) || (x2 < 0 && x1 >=0)) {
              angleDiff += 180;
            }

            wheel.setRotation(startRotation - angleDiff);
          }
      };
    }, false);
  }
  function getRandomReward() {
    var mainDigit = Math.round(Math.random() * 9);
    return mainDigit + '\n0\n0';
  }
  function addWedge(n) {
    var s = getRandomColor();
    var reward = getRandomReward();
    var r = s[0];
    var g = s[1];
    var b = s[2];
    var angle = 360 / NUM_WEDGES;

    var endColor = 'rgb(' + r + ',' + g + ',' + b + ')';
    r += 100;
    g += 100;
    b += 100;

    var startColor = 'rgb(' + r + ',' + g + ',' + b + ')';

    var wedge = new Kinetic.Group({
      rotation: n * 360 / NUM_WEDGES,
    });

    var wedgeBackground = new Kinetic.Wedge({
      radius: WHEEL_RADIUS,
      angle: angle,
      fillRadialGradientStartRadius: 0,
      fillRadialGradientEndRadius: WHEEL_RADIUS,
      fillRadialGradientColorStops: [0, startColor, 1, endColor],
      fill: '#64e9f8',
      fillPriority: 'radial-gradient',
      stroke: '#ccc',
      strokeWidth: 2,
      rotation: (90 + angle/2) * -1
    });

    wedge.add(wedgeBackground);

    var text = new Kinetic.Text({
      text: reward,
      fontFamily: 'Calibri',
      fontSize: 50,
      fill: 'white',
      align: 'center',
      stroke: 'yellow',
      strokeWidth: 1,
      listening: false

    });

    text.offsetX(text.width()/2);
    text.offsetY(WHEEL_RADIUS - 15);

    wedge.add(text);
    volume = createVolumeControl(angle, endColor);
    wedge.add(volume);

    wheel.add(wedge);
  }

  var activeWedge;

function createVolumeControl(angle, colour){
    var volume = new Kinetic.Wedge({
        radius: 100,
        angle: angle,
        fill: colour,
        stroke: '#000000',
        rotation: (90 + angle/2) * -1
    });

    volume.on("mousedown touchstart", function() {
        currentVolume = this;
        action='increase';
    });
    return volume;
}



  function animate(frame) {
    // wheel
    var angularVelocityChange = angularVelocity * frame.timeDiff * (1 - ANGULAR_FRICTION) / 1000;
    angularVelocity -= angularVelocityChange;

    if(controlled) {
      angularVelocity = ((wheel.getRotation() - lastRotation) * 1000 / frame.timeDiff);
    }
    else {
      wheel.rotate(frame.timeDiff * angularVelocity / 1000);
    }
    lastRotation = wheel.getRotation();

    // pointer
    var intersectedWedge = layer.getIntersection({x: stage.width()/2, y: 50});

    if (intersectedWedge && (!activeWedge || activeWedge._id !== intersectedWedge._id)) {
      pointerTween.reset();
      pointerTween.play();
      activeWedge = intersectedWedge; 
    }
  }

  function init() {
    stage = new Kinetic.Stage({
      container: 'container',
      width: 578,
      height: 500
    });
    layer = new Kinetic.Layer();
    wheel = new Kinetic.Group({
      x: stage.getWidth() / 2,
      y: WHEEL_RADIUS + 20
    });

    for(var n = 0; n < NUM_WEDGES; n++) {
      addWedge(n);
    }
    pointer = new Kinetic.Wedge({
      fillRadialGradientStartPoint: 0,
      fillRadialGradientStartRadius: 0,
      fillRadialGradientEndPoint: 0,
      fillRadialGradientEndRadius: 30,
      fillRadialGradientColorStops: [0, 'white', 1, 'red'],
      stroke: 'white',
      strokeWidth: 2,
      lineJoin: 'round',
      angle: 30,
      radius: 30,
      x: stage.getWidth() / 2,
      y: 20,
      rotation: -105,
      shadowColor: 'black',
      shadowOffset: {x:3,y:3},
      shadowBlur: 2,
      shadowOpacity: 0.5
    });

    // add components to the stage
    layer.add(wheel);
    layer.add(pointer);
    stage.add(layer);

    pointerTween = new Kinetic.Tween({
      node: pointer,
      duration: 0.1,
      easing: Kinetic.Easings.EaseInOut,
      y: 30
    });

    pointerTween.finish();

    var radiusPlus2 = WHEEL_RADIUS + 2;

    wheel.cache({
      x: -1* radiusPlus2,
      y: -1* radiusPlus2,
      width: radiusPlus2 * 2,
      height: radiusPlus2 * 2
    }).offset({
      x: radiusPlus2,
      y: radiusPlus2
    });

    layer.draw();

    // bind events
    bind();

    var anim = new Kinetic.Animation(animate, layer);

    //document.getElementById('debug').appendChild(layer.hitCanvas._canvas);

    // wait one second and then spin the wheel
    setTimeout(function() {
      anim.start();
    }, 1000);
  }
  init();

1 个答案:

答案 0 :(得分:0)

我对脚本进行了一些更改,大大改善了响应时间。第一个是用layer.batchDraw()替换layer.draw()。由于在每次touchmove事件中都调用了draw函数,因此它使交互变得笨拙。另一方面,BatchDraw将在内部叠加绘制请求并且#34;根据每秒的最大帧数限制每秒的重绘次数&#34; (http://www.html5canvastutorials.com/kineticjs/html5-canvas-kineticjs-batch-draw)。

当我缓存/清除滚轮时,我最初看到的画布跳转是因为当我清除缓存时我没有重置滚轮上的偏移量。 http://jsfiddle.net/leydar/a7tkA/5

wheel.clearCache().offset({
  x: 0,
  y: 0
});

我希望这对其他人有益。它仍然没有完全响应,但它至少朝着正确的方向发展。

斯蒂芬