I'm incredibly new to javascript, so sorry if this idea isn't using the proper vocab but anything y'all can help me with would be great!

Does anyone know how to make a circular canvas that allows users to fill a portion of the circle based on a click and drag points within the circle?

I think I could probably make a circular canvas for them to color in, but I'd like to make it so they don't have to scribble all over the circle to color it in.

有帮助吗?

解决方案

A Demo: http://jsfiddle.net/m1erickson/LVgwV/

You can use the context.arc command to draw your pie wedge.

Listen for mouse events and in mousedown set the beginning angle of the wedge:

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

      // Put your mousedown stuff here
      var dx=mouseX-cx;
      var dy=mouseY-cy;
      begin=Math.atan2(dy,dx);
      isDown=true;
    }

In mousemove you can set your ending angle of the wedge:

    function handleMouseMove(e){
      if(!isDown){return;}
      e.preventDefault();
      mouseX=parseInt(e.clientX-offsetX);
      mouseY=parseInt(e.clientY-offsetY);
      var dx=mouseX-cx;
      var dy=mouseY-cy;
      end=Math.atan2(dy,dx);
      draw();
    }

Example code:

<!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(){

    var canvas=document.getElementById("canvas");
    var ctx=canvas.getContext("2d");
    ctx.strokeStyle="lightgray";
    ctx.lineWidth=3;
    ctx.fillStyle="skyblue";

    var $canvas=$("#canvas");
    var canvasOffset=$canvas.offset();
    var offsetX=canvasOffset.left;
    var offsetY=canvasOffset.top;
    var scrollX=$canvas.scrollLeft();
    var scrollY=$canvas.scrollTop();

    var isDown=false;
    var startX;
    var startY;

    var cx=150;
    var cy=150;
    var begin,end;

    function draw(){
        ctx.clearRect(0,0,canvas.width,canvas.height);
        ctx.beginPath();
        ctx.moveTo(cx,cy);
        ctx.arc(cx,cy,75,begin,end);
        ctx.closePath();
        ctx.fill();
        ctx.stroke();
    }

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

      // Put your mousedown stuff here
      var dx=mouseX-cx;
      var dy=mouseY-cy;
      begin=Math.atan2(dy,dx);
      isDown=true;
    }

    function handleMouseUp(e){
      e.preventDefault();
      isDown=false;
    }

    function handleMouseOut(e){
      e.preventDefault();
      isDown=false;
    }

    function handleMouseMove(e){
      if(!isDown){return;}
      e.preventDefault();
      mouseX=parseInt(e.clientX-offsetX);
      mouseY=parseInt(e.clientY-offsetY);
      var dx=mouseX-cx;
      var dy=mouseY-cy;
      end=Math.atan2(dy,dx);
      draw();
    }

    $("#canvas").mousedown(function(e){handleMouseDown(e);});
    $("#canvas").mousemove(function(e){handleMouseMove(e);});
    $("#canvas").mouseup(function(e){handleMouseUp(e);});
    $("#canvas").mouseout(function(e){handleMouseOut(e);});



}); // end $(function(){});
</script>

</head>

<body>
    <h4>Drag on canvas to create pie-wedge.</h4>
    <canvas id="canvas" width=300 height=300></canvas>
</body>
</html>

其他提示

If I understand correctly, you already know how to make the canvas circular and how to capture click-and-drags.

To get the canvas to only fill within the circle you define, use .clip.

It restricts the area in which all future plotting will be done to what is inside the current path.

The Mozilla Developer Network has an example.

I am assuming that when you say you want to allow the user to fill a portion of the circle, this means that the user can fill in slices similar to those in a pie chart. More specifically, you want to fill in "sectors" of a circle.

Also, all canvas elements will actually be rectangular. However, the user doesn't need to know that, because you can choose to only process touches within the circle and/or to only render on the canvas within the circle.

Doing what you're asking involves a few different steps, but all of them are pretty straight-forward.

  1. Capture mouse/touch events.
    • The logic will be different depending on whether you are working with touch devices or mouse-based devices.
  2. Compute where this event occurs relative to your circle.
    • From this, you can determine how large of a slice of the circle to fill in.
    • I'll let you figure out the math for this on your own (but let me know if you need some pointers).
  3. Draw the actual slice of the circle.
    • I recommend using a ... for this.
    • Here is a small code example showing how to draw a filled in sector of a circle:
    // cx and cy are the x and y coordinates of the circle center
    // r is the radius of the circle
    context.moveTo(cx, cy);
    context.arc(cx, cy, r, startAngle, endAngle);
    context.lineTo(cx, cy);
    context.fill(); // and/or context.stroke()

This is a simple tutorial that might be helpful for you. It gives more detail (with code) for working with touches in a canvas: http://simonsarris.com/blog/510-making-html5-canvas-useful.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top