根据用户点击的位置旋转画布显示

时间:2014-03-18 03:08:28

标签: javascript jquery canvas html5-canvas

我有一个html5 canvas显示,我想在用户点击后旋转。我试图找出允许动画生效的最佳方法。我希望旋转平滑,无论用户点击所选面板的哪个位置都会旋转到顶部。

我不确定最好的方法,因为这是我的第一个画布项目,我想我会为你们所有人开场。

这是一个小提琴:http://jsfiddle.net/JRgtg/

提前感谢您的帮助!

1 个答案:

答案 0 :(得分:2)

你的任务相当复杂:

  • 为圆圈周围的每个弧段创建一个对象
  • 将弧形对象保存在arcs []数组
  • 创建一个以指定角度绘制指定弧的函数
  • (弧线绘制为路径)
  • 听mousedown事件
  • 在mousedown处理程序中,使用context.isPointInPath查看用户是否单击了arc-segment-path
  • 如果单击,则使用动画
  • 将单击的圆弧旋转到圆的顶部

点击金弧之前和之后的弧位置图示。

金弧旋转到顶部:

enter image description here enter image description here

注释示例代码和演示:http://jsfiddle.net/m1erickson/ZUtL8/

<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
    body{ background-color: ivory; }
    canvas{border:1px solid red;}
</style>
<script>
$(function(){

    // canvas and context reference variables
    var canvas=document.getElementById("canvas");
    var ctx=canvas.getContext("2d");
    var $canvas=$("#canvas");
    var canvasOffset=$canvas.offset();
    var offsetX=canvasOffset.left;
    var offsetY=canvasOffset.top;

    // save PI to variables since they are used often
    var PI=Math.PI;
    var PI2=Math.PI*2;

    // animation variables
    var rotation;
    var desiredRotation;
    var deltaRotation=PI/120;  // rotate at about 360 degrees over 2 seconds

    // define a color for each segment
    var colors=["red","green","blue","gold","purple"];
    var topAngle=clampAngle(PI*3/2-(PI2/colors.length)/2);
    var gapAngle=2*PI/180; // 3 degree gap between arcs

    // hold the arc objects in an arcs[] array
    var arcs=createArcs(150,150,50,75,colors);

    // draw the arcs 
    for(var i=0;i<arcs.length;i++){
        drawArc(arcs[i],true);
    }

    // listen for mouse events
    $("#canvas").mousedown(function(e){handleMouseDown(e);});

    // utility function
    // make sure angles are expressed between 0 & 2*PI
    function clampAngle(a){
        return((a+PI2*2)%PI2);
    }

    // create arc objects for each color
    function createArcs(cx,cy,insideRadius,outsideRadius,colors){
        var arcs=[];
        for(var i=0;i<colors.length;i++){
            var a1=clampAngle(i*PI2/colors.length+topAngle);
            var a2=clampAngle(a1+PI2/colors.length-gapAngle);
            arcs.push({
                segment:i,
                x:cy, 
                y:cy, 
                r1:insideRadius, 
                r2:outsideRadius,
                a1:a1,
                a2:a2,
                color:colors[i],
                rotation:0
            });
        }
        return(arcs);
    }

    // draw one arc
    function drawArc(arc,draw){
        var x = arc.x + arc.r1 * Math.cos(arc.a2);
        var y = arc.y + arc.r1 * Math.sin(arc.a2);
        // define
        ctx.beginPath();
        ctx.arc(arc.x,arc.y,arc.r2,arc.a1,arc.a2);
        ctx.lineTo(x, y);
        ctx.arc(arc.x,arc.y,arc.r1,arc.a2,arc.a1,true);
        ctx.closePath();
        // 
        if(draw){
            ctx.fillStyle=arc.color;
            ctx.fill();
        }
    }

    // handle mouse events
    function handleMouseDown(e){
      e.preventDefault();
      mouseX=parseInt(e.clientX-offsetX);
      mouseY=parseInt(e.clientY-offsetY);

      // hit test each arc 
      var hit=-1;
      for(var i=0;i<arcs.length;i++){
          // define the target arc
          drawArc(arcs[i]);
          if(ctx.isPointInPath(mouseX,mouseY)){
              hit=i;
          }
      }
      // if use clicked on arc, rotate it to the top
      if(hit>=0){
          rotation=0;
          desiredRotation=clampAngle(topAngle-arcs[hit].a1);
          animate();
      }
    }

    // animate the rotation of the clicked arc
    function animate(){

        // stop animating if the arc has been rotated to the top
        if(rotation<=desiredRotation){ requestAnimationFrame(animate); }

        if(rotation>desiredRotation){ rotation=desiredRotation; }

        // clear the canvas
        ctx.clearRect(0,0,canvas.width,canvas.height);

        // add a rotation increment to each arc
        for(var i=0;i<arcs.length;i++){
            var arc=arcs[i];
            arc.a1=clampAngle(arc.a1+deltaRotation);
            arc.a2=clampAngle(arc.a2+deltaRotation);
            drawArc(arc,true);
        }

        // increase the rotation angle by the rotation increment
        rotation=clampAngle(rotation+deltaRotation);
    }


}); // end $(function(){});
</script>
</head>
<body>
    <h4>Click on a color-arc and it will rotate to top.</h4>
    <canvas id="canvas" width=300 height=300></canvas>
</body>
</html>