2013-05-04 3 views
3

Я создал круг, в котором я могу выбрать две точки по окружности круга.Raphael js. Заполните цвет вдоль кривой

Я хочу заполнить часть между этими двумя точками.

Demo

Если вы видите демо, я хочу, чтобы заполнить угол между двумя точками.

JS:

(function (Raphael) { 
    Raphael.colorwheel = function (x, y, size, initcolor, element) { 
     return new ColorWheel(x, y, size, initcolor, element); 
    }; 
    var pi = Math.PI, 
     doc = document, 
     win = window, 
     ColorWheel = function (x, y, size, initcolor, element) { 
      size = size || 200; 
      var w3 = 3 * size/200, 
       w1 = size/200, 
       fi = 1.6180339887, 
       segments = 3,//pi * size/50, 
       size20 = size/20, 
       size2 = size/2, 
       padding = 2 * size/200, 
       t = this; 

      var H = 1, S = 1, B = 1, s = size - (size20 * 4); 
      var r = element ? Raphael(element, size, size) : Raphael(x, y, size, size), 
       xy = s/6 + size20 * 2 + padding, 
       wh = s * 2/3 - padding * 2; 
      w1 < 1 && (w1 = 1); 
      w3 < 1 && (w3 = 1); 



      // ring drawing 
      var a = pi/2 - pi * 2/segments * 1.3, 
       R = size2 - padding, 
       R2 = size2 - padding - size20 * 2, 
       path = ["M", size2, padding, "A", R, R, 0, 0, 1, R * Math.cos(a) + R + padding, R - R * Math.sin(a) + padding, "L", R2 * Math.cos(a) + R + padding, R - R2 * Math.sin(a) + padding, "A", R2, R2, 0, 0, 0, size2, padding + size20 * 2, "z"].join(); 

      for (var i = 0; i < segments; i++) { 
       r.path(path).attr({ 
        stroke: "none", 
        fill: "#8fd117", 
        transform: "r" + [(360/segments) * i, size2, size2] 
       }); 
      } 

      r.path(["M", size2, padding, "A", R, R, 0, 1, 1, size2 - 1, padding, "l1,0", "M", size2, padding + size20 * 2, "A", R2, R2, 0, 1, 1, size2 - 1, padding + size20 * 2, "l1,0"]).attr({ 
       "stroke-width": w3, 
       stroke: "#fff" 
      }); 

      t.startCursor = r.set(); 
      var h = size20 * 2 + 2; 
      t.startCursor.push(r.rect(size2 - h/fi/2, padding - 1, h/fi, h, 3 * size/200).attr({ 
       stroke: "#00A0C6", 
       opacity: .5, 
       "stroke-width": w3 
      })); 
      t.startCursor.push(t.startCursor[0].clone().attr({ 
       stroke: "#00A0C6", 
       opacity: 1, 
       "stroke-width": w1 
      })); 


      t.endCursor = r.set(); 
      var h = size20 * 2 + 2; 
      t.endCursor.push(r.rect(size2 - h/fi/2, padding - 1, h/fi, h, 3 * size/200).attr({ 
       stroke: "#F96E5B", 
       opacity: .5, 
       "stroke-width": w3 
      })); 

      t.endCursor.push(t.endCursor[0].clone().attr({ 
       stroke: "#F96E5B", 
       opacity: 1, 
       "stroke-width": w1 
      })); 



      t.ring = r.path(["M", size2, padding, "A", R, R, 0, 1, 1, size2 - 1, padding, "l1,0M", size2, padding + size20 * 2, "A", R2, R2, 0, 1, 1, size2 - 1, padding + size20 * 2, "l1,0"]).attr({ 
       fill: "#000", 
       opacity: 0, 
       stroke: "none" 
      }); 

      t.H = t.S = t.B = 1; 
      t.raphael = r; 
      t.size2 = size2; 
      t.wh = wh; 
      t.x = x; 
      t.xy = xy; 
      t.y = y; 


      t.endCursor.attr({transform: "r" + [50, t.size2, t.size2]}); 

      // events 
      t.ring.drag(function (dx, dy, x, y) { 
       t.docOnMove(dx, dy, x, y); 
      }, function (x, y) { 
       // Rotate on click 
       t.setH(x - t.x - t.size2, y - t.y - t.size2); 
      }, function() { 
      }); 
     }, 
     proto = ColorWheel.prototype; 

    proto.setH = function (x, y) { 

     var d = Raphael.angle(x, y, 0, 0); 

     this.H = (d + 90)/360; 
     var a = 0; 

     if(d > 270) { 
      d = d - 270; 
     } 
     else { 
      d = d + 90; 
     } 

     var m = Math.abs(d - this.startCursor[0]._.deg); 
     var n = Math.abs(d - this.endCursor[0]._.deg); 

     if(m > 180) { 
      m = 360 - m ; 
     } 
     if(n > 180) { 
      n = 360 - n; 
     }  

     if(m <= n) { 
      this.startCursor.attr({transform: "r" + [d, this.size2, this.size2]}); 
     } 
     else { 
      this.endCursor.attr({transform: "r" + [d, this.size2, this.size2]}); 
     } 

     m = this.startCursor[0]._.deg ; 
     n = this.endCursor[0]._.deg; 

     if(m > 360) { 
      m = m - 360; 
     } 
     if(n > 360) { 
      n = n - 360; 
     } 

     var diff = m > n ? m - n : n - m; 

     this.onchange(m,n,diff); 
    }; 

    proto.docOnMove = function (dx, dy, x, y) { 
     this.setH(x - this.x - this.size2, y - this.y - this.size2); 

    }; 

})(window.Raphael); 



window.onload = function() { 
    var cp2 = Raphael.colorwheel(60, 20, 200, "#eee"); 
    var X = document.getElementById('x'); 
    var Y = document.getElementById('y'); 
    var angle = document.getElementById('angle'); 

    cp2.onchange = function (x, y, ang) { 
     X.innerHTML = Math.round(x * 100)/100; 
     Y.innerHTML = Math.round(y * 100)/100; 
     angle.innerHTML = Math.round(ang * 100)/100; 
    } 
}; 

HTML:

<div id="wrapper">X : <span id="x">0</span> 
    <br>Y: <span id="y">50</span> 
    <br>Angle: <span id="angle">50</span> 
</div> 

CSS:

body { 
     background: #e6e6e6; 
    } 
    #wrapper { 
     position: absolute; 
     top: 240px; 
     left: 100px; 
    } 

UPDATE:

С помощью Криса,

я получил некоторый успех.

См Demo

Bugs:
1. Если вы начинаете зеленые, красные первые разрывы,
2. Если вы начинаете красный первой и делает угол более 180 градусов, а когда зеленый уменьшает, что ниже 180 градусов, он снова ломается.

UPDATE 2
DEMO
ОШИБКИ:
1. Если вы начинаете красный первый и делает угол более 180 градусов, и когда зеленый уменьшает, что ниже 180 градусов, он ломает снова.
2. Иногда дуги в противоположном направлении.

+0

Получил jsfiddle? –

+0

Я уже включил ссылку на jsfiddle. Я смелый, что сейчас – Jashwant

+0

Может быть, это поможет? http://stackoverflow.com/questions/5061318/drawing-centered-arcs-in-raphael-js –

ответ

4

Вот рабочий раствор:

Demo

(function (Raphael) { 
    Raphael.colorwheel = function (x, y, size, initcolor, element) { 
     return new ColorWheel(x, y, size, initcolor, element); 
    }; 
    var pi = Math.PI, 
     doc = document, 
     win = window, 
     ColorWheel = function (x, y, size, initcolor, element) { 
      size = size || 200; 
      var w3 = 3 * size/200, 
       w1 = size/200, 
       fi = 1.6180339887, 
       segments = 3,//pi * size/50, 
       size20 = size/20, 
       size2 = size/2, 
       padding = 2 * size/200, 
       t = this; 

      var H = 1, S = 1, B = 1, s = size - (size20 * 4); 
      var r = element ? Raphael(element, size, size) : Raphael(x, y, size, size), 
       xy = s/6 + size20 * 2 + padding, 
       wh = s * 2/3 - padding * 2; 
      w1 < 1 && (w1 = 1); 
      w3 < 1 && (w3 = 1); 

      // ring drawing 
      var a = pi/2 - pi * 2/segments * 1.3, 
       R = size2 - padding, 
       R2 = size2 - padding - size20 * 2, 
       path = ["M", size2, padding, "A", R, R, 0, 0, 1, R * Math.cos(a) + R + padding, R - R * Math.sin(a) + padding, "L", R2 * Math.cos(a) + R + padding, R - R2 * Math.sin(a) + padding, "A", R2, R2, 0, 0, 0, size2, padding + size20 * 2, "z"].join(); 
      for (var i = 0; i < segments; i++) { 
       r.path(path).attr({ 
        stroke: "none", 
        fill: "#8fd117", 
        transform: "r" + [(360/segments) * i, size2, size2] 
       }); 
      } 

      r.path(["M", size2, padding, "A", R, R, 0, 1, 1, size2 - 1, padding, "l1,0", "M", size2, padding + size20 * 2, "A", R2, R2, 0, 1, 1, size2 - 1, padding + size20 * 2, "l1,0"]).attr({ 
       "stroke-width": w3, 
       stroke: "#fff" 
      }); 


      t.startCursor = r.set(); 
      var h = size20 * 2 + 2; 

      t.startCursor.push(r.rect(size2 - h/fi/2, padding - 1, h/fi, h, 3 * size/200).attr({ 
       stroke: "#00A0C6", 
       opacity: 1, 
       "stroke-width": w3 
      })); 
      t.startCursor.push(t.startCursor[0].clone().attr({ 
       stroke: "#00A0C6", 
       fill : "#8fd117", 
       opacity: 1, 
       "stroke-width": w1 
      })); 

      t.endCursor = r.set(); 
      var h = size20 * 2 + 2; 

      t.endCursor.push(r.rect(size2 - h/fi/2, padding - 1, h/fi, h, 3 * size/200).attr({ 
       stroke: "#F96E5B", 
       opacity: 1, 
       "stroke-width": w3, 

      })); 

      t.endCursor.push(t.endCursor[0].clone().attr({ 
       stroke: "#F96E5B", 
       fill : "#8fd117", 
       opacity: 1, 
       "stroke-width": w1 
      })); 

      t.ring = r.path(["M", size2, padding, "A", R, R, 0, 1, 1, size2 - 1, padding, "l1,0M", size2, padding + size20 * 2, "A", R2, R2, 0, 1, 1, size2 - 1, padding + size20 * 2, "l1,0"]).attr({ 
       fill: "#000", 
       opacity: 0, 
       stroke: "none" 
      }); 

      t.H = t.S = t.B = 1; 
      t.raphael = r; 
      t.size2 = size2; 
      t.wh = wh; 
      t.x = x; 
      t.xy = xy; 
      t.y = y; 

      t.endCursor.attr({transform: "r" + [50, t.size2, t.size2]}); 

      t.x0 = t.startCursor[0].attr("x") + t.startCursor[0].attr("width")/2; 
      t.y0 = t.startCursor[0].attr("y") + t.startCursor[0].attr("height")/2; 
      t.initX0 = t.x0; 
      t.initY0 = t.y0; 
      t.R1 = (R2 + R)/2; 
      t.x1 = t.x0 + t.R1 * Math.sin(50 * Math.PI/180); 
      t.y1 = t.y0 + t.R1 - t.R1 * Math.cos(50 * Math.PI/180); 
      t.initX1 = t.x1; 
      t.initY1 = t.y1; 
      var path = "M" + t.x0 + "," + t.y0 + "A" + t.R1 + "," + t.R1 + " 50 0,1 " + t.x1 + "," + t.y1; 

      t.arc = r.path(path) 
      .attr({ 
       stroke: "#009900", 
       "stroke-width": 10 
      }); 


      t.startCursor.drag(function (dx, dy, x, y) { 
        t.docOnMove(dx, dy, x, y,'startCursor'); 
       }, function (x, y) { 
        t.setH(x - t.x - t.size2, y - t.y - t.size2,'startCursor'); 
       }, function() { 

      }); 

      t.endCursor.drag(function (dx, dy, x, y) { 
        t.docOnMove(dx, dy, x, y,'endCursor'); 
       }, function (x, y) { 
        t.setH(x - t.x - t.size2, y - t.y - t.size2,'endCursor'); 
       }, function() { 

      }); 

      t.startCursor.toFront(); 
      t.endCursor.toFront(); 
     }, 
     proto = ColorWheel.prototype; 

    proto.setH = function (x, y,cursor) { 
     var d = Raphael.angle(x, y, 0, 0); 
     if(d > 270) { 
      d = d - 270; 
     } 
     else { 
      d = d + 90; 
     } 

     if((cursor === 'startCursor' && d > this.endCursor[0]._.deg) || (cursor === 'endCursor' && d <= this.startCursor[0]._.deg)) { 
      return; 
     } 

     if(cursor === 'startCursor') { 
      this.startCursor.attr({transform: "r" + [d, this.size2, this.size2]}); 
     } 
     else { 
      this.endCursor.attr({transform: "r" + [d, this.size2, this.size2]}); 
     } 

     var m = this.startCursor[0]._.deg ; 
     var n = this.endCursor[0]._.deg; 
     var t = this;   
     var flag = 0; 

     if(m > 360) { 
      m = m - 360; 
      flag = 1; 
     } 

     if(n > 360) { 
      n = n - 360; 
     } 


     var diff = Math.abs(m - n); 

     if (diff > 180) { 
      flag = 1; 
     } 

     var path = ""; 
     var sweep = 1; 

     if(cursor === 'endCursor') { 
      t.x1 = t.initX0 + t.R1 * Math.sin(n * Math.PI/180); 
      t.y1 = t.initY0 + t.R1 - t.R1 * Math.cos(n * Math.PI/180); 
     } 
     else { 
      t.x0 = t.initX0 + t.R1 * Math.sin(m * Math.PI/180); 
      t.y0 = t.initY0 + t.R1 - t.R1 * Math.cos(m * Math.PI/180); 
     } 

     console.log(m,t.x0,t.y0,t.x1,t.y1); 

     path = "M" + t.x0 + "," + t.y0 + "A" + t.R1 + "," + t.R1 + " " + diff + " " + flag + "," + sweep + " " + t.x1 + "," + t.y1; 

     t.arc = t.arc.attr("path", path); 

     this.onchange(m,n,diff); 
    }; 

    proto.docOnMove = function (dx, dy, x, y,cursor) { 
     this.setH(x - this.x - this.size2, y - this.y - this.size2,cursor); 

    }; 

})(window.Raphael); 

window.onload = function() { 
    var cp2 = Raphael.colorwheel(60, 20, 200, "#eee"); 
    var X = document.getElementById('x'); 
    var Y = document.getElementById('y'); 
    var angle = document.getElementById('angle'); 

    cp2.onchange = function (x, y, ang) { 
     X.innerHTML = Math.round(x * 100)/100; 
     Y.innerHTML = Math.round(y * 100)/100; 
     angle.innerHTML = Math.round(ang * 100)/100; 


    } 
}; 
4

Прохладный проект. Вам просто нужно добавить эллиптическую дугу в цветовое колесо и перерисовать путь в событии onchange.

Я получил вас на полпути здесь: он работает, если вы перемещаете оранжевый курсор, полностью ломается, если вы перемещаете синий курсор.

Для начала:

 t.x0 = t.startCursor[0].attr("x") + t.startCursor[0].attr("width")/2; 
     t.y0 = t.startCursor[0].attr("y") + t.startCursor[0].attr("height")/2; 
     t.R1 = (R2 + R)/2; 
     t.x1 = t.x0 + t.R1 * Math.sin(50 * Math.PI/180); 
     t.y1 = t.y0 + t.R1 - t.R1 * Math.cos(50 * Math.PI/180); 

     t.arc = r.path("M" + t.x0 + "," + t.y0 + "A" + t.R1 + "," + t.R1 + " 50 0,1 " + t.x1 + "," + t.y1) 
     .attr({ 
      stroke: "#009900", 
      "stroke-width": 10 
     }); 

На обновление:

if (n > 180) { 
     flag = 1; 
    } 

    var diff = m > n ? m - n : n - m; 

    t.x0 = t.x0 + t.R1 * Math.sin(m * Math.PI/180); 
    t.y0 = t.y0 + t.R1 - t.R1 * Math.cos(m * Math.PI/180); 
    t.x1 = t.x0 + t.R1 * Math.sin(diff * Math.PI/180); 
    t.y1 = t.y0 + t.R1 - t.R1 * Math.cos(diff * Math.PI/180); 

    t.arc = t.arc.attr("path", "M" + t.x0 + "," + t.y0 + "A" + t.R1 + "," + t.R1 + " " + diff + " " + flag + ",1 " + t.x1 + "," + t.y1); 

jsfiddle

Должно быть в состоянии принять его здесь.

UPDATE, 8 мая:

Вы можете исправить свою первую проблему, изменив флаг на дифф, а не на второй угол:

if (diff > 180) { 
     flag = 1; 
    } 

Событие, который запускающего вторая проблема является вторым угол (красная ручка), проходящий с отметкой 0 градусов. Самый простой способ поймать это просто добавить 360 на угол, если он меньше, чем первый угол:

var m = this.startCursor[0]._.deg ; 
    var n = this.endCursor[0]._.deg; 
    var t = this;   
    var flag = 0; 
    var sweep = 1; 

    var path = ""; 
    if (n < m) { 
     m += 360; 
    } 

    var diff = Math.abs(m - n); 

    if (diff > 180) { 
     flag = 1; 
    } 

Here's the fiddle

Примечание: Вы ловя ситуации, когда (n > 360) и (m > 360), но это не появятся необходимые - углы достигают этой точки в коде, уже установленном ниже 360, по крайней мере в Chrome.

+0

ничего себе, большая попытка. Я попытаюсь взять это отсюда. Но это был мой первый раз с raphael, и мне будет довольно сложно это сделать. Но +1 – Jashwant

+0

Вам просто нужно вычислить положение первого курсора и убедиться, что вы правильно установили флаги эллиптической дуги. Испытание и ошибка должны сделать трюк. –

+0

Я упростил много кода. Можете ли вы указать, что это не работает? http://jsfiddle.net/jashwant/CDBk6/4/ – Jashwant

Смежные вопросы