Raphael js. Fill color along a curve

匿名 (未验证) 提交于 2019-12-03 03:03:02

问题:

I have created a circle in which I can choose two points along the circumference of of circle.

I want to fill the portion between those two points.

Demo

If you see the demo, I want to fill the angle between two points.

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:

With Chris's help,

I have got some success.

See Demo

Bugs :
1. If you start green first, red breaks,
2. If you start red first and makes angle of greater than 180 degree and when green reduces that below 180 degree, it breaks again.

UPDATE 2
DEMO
BUGS:
1. If you start red first and makes angle of greater than 180 degree and when green reduces that below 180 degree, it breaks again.
2. Sometimes arcs in opposite direction.

回答1:

Cool project. You just need to add an elliptical arc to the color wheel and redraw the path on the onchange event.

I got you half the way here: It works if you move the orange cursor, completely breaks if you move the blue cursor.

To start:

        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         }); 

On update:

    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

Should be able to take it from here.

UPDATE, May 8:

You can fix your first problem by changing the flag on the diff, not on the second angle:

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

The event that's triggering the second problem is the second angle (the red handle) passing the 0-degree mark. The easiest way to catch this is just to add 360 to the angle IF it's less than the first angle:

    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

Note: You were catching situations where (n > 360) and (m > 360), but this doesn't appear necessary -- the angles arrive at this point in the code already set below 360, at least in Chrome.



回答2:

Here's working solution:

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;       } }; 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!