2012-01-26 31 views
1

我正在寻找一个javascript(jQuery for preference)控件,它允许选择一个圆的一部分。我不能使用标准的jQuery滑块,因为它是线性的;我正在从事的基础模型是一个旋转系统,我试图说在用户可选的角度范围内(如发动机中的凸轮轴)开启了某些功能。任何人都可以指向任何代码,让我从一开始?圆形范围选择控件

+0

[RaphaelJS](http://raphaeljs.com/)可能有些帮助! – Arj

+0

@ a12jun我没有问题绘制我需要的东西。我只是想避免自己编写所有的代码。 –

+0

好吧,我想也许他们可能是一个插件,它可以做你想做的事情 – Arj

回答

4

我已经试验了一段时间,使这个代码:

JSFiddle

function Dial(id, size, properties) { 
    var props = properties || {}; 
    var dial = this; 
    var div = $(id); 
    var canvas = $("<canvas width=\""+size+"\" height=\""+size+"\"></canvas>"); 
    var ctx = canvas.appendTo(div)[0].getContext("2d"); 
    canvas = canvas[0]; 
    var pi2 = Math.PI*2; 

    this.label = props.label; 
    this.from = (props.from==null ? 0 : props.from) % pi2; 
    if (this.from > Math.PI) 
     this.from -= pi2; 
    else if (this.from < -Math.PI) 
     this.from += pi2; 
    this.to = (props.to==null ? 2 : props.to) % pi2; 
    if (this.to > Math.PI) 
     this.to -= pi2; 
    else if (this.to < -Math.PI) 
     this.to += pi2; 
    this.selectedFrom = false; 
    this.selectedTo = false; 
    this.radius = size/2-10; 
    if (props.change) 
     div.bind("change", props.change); 
    if (props.startchange) 
     div.bind("startchange", props.startchange); 
    if (props.stopchange) 
     div.bind("stopchange", props.stopchange); 

    this.reset = function(from, to) { 
     this.from = from % pi2; 
     if (this.from > Math.PI) 
      this.from -= pi2; 
     else if (this.from < -Math.PI) 
      this.from += pi2; 
     this.to = to % pi2; 
     if (this.to > Math.PI) 
      this.to -= pi2; 
     else if (this.to < -Math.PI) 
      this.to += pi2; 
     this.selectedFrom = this.selectedTo = false; 
     this.movingFrom = this.movingTo = false; 
     this.draw(); 
    }; 

    this.draw = function() { 
     ctx.save(); 
     ctx.clearRect(0,0,size,size); 
     ctx.translate(size/2,size/2); 

     ctx.beginPath(); 
     ctx.strokeStyle = "silver"; 
     ctx.lineWidth = 5; 
     ctx.arc(0, 0, this.radius, 0, 2*Math.PI); 
     ctx.stroke(); 

     ctx.beginPath(); 
     ctx.strokeStyle = "black"; 
     ctx.lineWidth = 9; 
     var f = 1.5 * Math.PI - this.from; 
     var t = 1.5 * Math.PI - this.to; 
     ctx.arc(0, 0, this.radius, f, t, true); 
     ctx.stroke(); 

     ctx.beginPath(); 
     ctx.lineWidth = 1; 
     ctx.fillStyle = this.selectedFrom ? "red" : "green"; 
     ctx.strokeStyle = this.selectedFrom ? "black" : "silver"; 
     ctx.arc(-this.radius*Math.sin(this.from), 
       -this.radius*Math.cos(this.from), 
       8, 0, 2*Math.PI); 
     ctx.fill(); 
     ctx.stroke(); 
     ctx.beginPath(); 
     ctx.fillStyle = this.selectedTo ? "red" : "green"; 
     ctx.strokeStyle = this.selectedTo ? "black" : "silver"; 
     ctx.arc(-this.radius*Math.sin(this.to), 
       -this.radius*Math.cos(this.to), 
       8, 0, 2*Math.PI); 
     ctx.fill(); 
     ctx.stroke(); 
     if (this.label) { 
      ctx.strokeStyle = "black"; 
      ctx.fillStyle = "black"; 
      ctx.textAlign = "center"; 
      ctx.textBaseline = "middle"; 
      ctx.fillText(this.label, 0, 0); 
     } 
     ctx.restore(); 
    }; 

    var getMousePos = function(canvas, evt){ 
     // get canvas position 
     var obj = canvas; 
     var top = 0; 
     var left = 0; 
     while (obj && obj.tagName != 'BODY') { 
      top += obj.offsetTop; 
      left += obj.offsetLeft; 
      obj = obj.offsetParent; 
     } 
     // return relative mouse position 
     var mouseX = evt.clientX - left + window.pageXOffset; 
     var mouseY = evt.clientY - top + window.pageYOffset; 
     return { 
      x: mouseX, 
      y: mouseY 
     }; 
    }; 

    if (!Math.hypot) { 
     Math.hypot = function(x,y) { 
      return Math.sqrt(x*x + y*y); 
     }; 
    } 
    var inTo = function(pos) { 
     return Math.hypot(size/2-dial.radius*Math.sin(dial.to)-pos.x, 
          size/2-dial.radius*Math.cos(dial.to)-pos.y) <= 8; 
    }; 
    var inFrom = function(pos) { 
     return Math.hypot(size/2-dial.radius*Math.sin(dial.from)-pos.x, 
          size/2-dial.radius*Math.cos(dial.from)-pos.y) <= 8; 
    }; 

    canvas.addEventListener("mousemove", function(evt) { 
     var pos = getMousePos(canvas, evt); 
     var redraw = false; 
     if (dial.movingFrom) { 
      if (pos.x == size/2 && pos.y == size/2) 
       return; 
      dial.from = Math.atan2(size/2-pos.x,size/2-pos.y); 
      redraw = true; 
      div.trigger("change", [dial.from, dial.to]); 
     } else if (dial.movingTo) { 
      if (pos.x == size/2 && pos.y == size/2) 
       return; 
      dial.to = Math.atan2(size/2-pos.x,size/2-pos.y); 
      redraw = true; 
      div.trigger("change", [dial.from, dial.to]); 
     } else if (inTo(pos)) { 
      // In "To" handle 
      if (dial.selectedFrom) { 
       dial.selectedFrom = false; 
       redraw = true; 
      } 
      if (!dial.selectedTo) { 
       dial.selectedTo = true; 
       redraw = true; 
      } 
     } else if (inFrom(pos)) { 
      // In "From" handle 
      if (!dial.selectedFrom) { 
       dial.selectedFrom = true; 
       redraw = true; 
      } 
      if (dial.selectedTo) { 
       dial.selectedTo = false; 
       redraw = true; 
      } 
     } else { 
      // In neither handle 
      if (dial.selectedFrom) { 
       dial.selectedFrom = false; 
       redraw = true; 
      } 
      if (dial.selectedTo) { 
       dial.selectedTo = false; 
       redraw = true; 
      } 
     } 
     if (redraw) { 
      dial.draw(); 
     } 
    }, false); 

    canvas.addEventListener("mousedown", function(evt) { 
     var pos = getMousePos(canvas, evt); 
     if (inTo(pos)) { 
      dial.movingTo = true; 
      div.trigger("startchange", ["to"]); 
     } else if (inFrom(pos)) { 
      dial.movingFrom = true; 
      div.trigger("startchange", ["from"]); 
     } 
    }, false); 

    canvas.addEventListener("mouseup", function(evt) { 
     if (dial.movingTo) { 
      div.trigger("stopchange", ["to", dial.to]); 
     } else if (dial.movingFrom) { 
      div.trigger("stopchange", ["from", dial.from]); 
     } 
     dial.movingTo = dial.movingFrom = false; 
    }, false); 

    this.draw(); 
}; 

,然后可以通过应用它:

new Dial("#dial", 150); 
$("#dial").bind("change", function(e, from, to) { 
    console.log("from="+from+", to="+to); 
}); 

它的丑陋,无法访问,但它确实提供了我需要什么。

+0

太棒了 - 做得好 – mplungjan

+0

看到更新,请 – mplungjan

+0

美丽 - 增加JSfiddle来展示它 –

0

如何jGauge

或者jquery-ui-dial

这里是一个小提琴,很简陋的形象,我重复4次

http://jsfiddle.net/mplungjan/hsnGc/

+0

唉,不。这只是输出。我正在寻找直接与它互动。 (太遗憾了,它看起来很漂亮。) –

+0

我可能做错了什么,但它不会为我显示任何东西(在Safari中),即使我添加了背景图片。 –

+0

他的演示缺少knob.png - 我认为它是一个多图像文件。我稍后会看看 – mplungjan