javascript - Canvas - fyll område under eller över linjer
Okej, jag har ett svårt problem att lösa. Jag har en HTML5-canvas där jag ritar två diagram (linjer). Jag har punkterna för varje diagram där linjerna är kopplade och jag har två y-värden (X,Y i bilden) där jag måste rita en linje och fylla ovanför eller under diagrammet. Jag verkar verkligen inte kunna få det att fungera eftersom jag försöker färga allt ovanför det viss diagram och klippa det med en rektangel, men jag har två diagram så jag måste ha två klippområden vilket ger en felaktig lösning.
Det finns en bild bifogad till inlägget för att se ärendet
Så jag har ett rött diagram och ett brunt diagram och värden för X och Y (vilket är de färgglada linjerna). X är ljusblå - höjden till där jag vill färga grafen nedanför. Y är ljusgrå och är höjden för att färga ovanför det bruna diagrammet.
Hur kan jag implementera detta utan att känna till korsningspunkten för diagrammen och X eller Y?
Koden jag använder är denna. Jag anropar den två gånger för varje diagram. Jag har utelämnat koden för att rita diagrammet - det ritas med hjälp av "points"-arrayen. Tyvärr har jag inte punkterna för korsningen mellan slutet av färgområdet och diagrammet (korsningen mellan rött och ljusblått; brunt och ljusgrått)
ctx.rect(clipX, clipY, clipWidth, clipHeight);
ctx.stroke();
ctx.clip();
//fill the area of the chart above or below
ctx.globalAlpha = 0.4;
ctx.strokeStyle = color;
ctx.fillStyle = color;
ctx.beginPath();
ctx.moveTo(points[0].x, points[0].y + visibleGraphicSpace);
for (var i = 1; i < points.length; i++) {
ctx.lineTo(points[i].x, points[i].y + visibleGraphicSpace);
}
ctx.closePath();
ctx.fill();Först ritar jag en rektangel för det synliga området, sedan ritar jag diagrammet med den givna punktsarrayen, stänger det och fyller allt ovanför eller nedanför tills slutet av duken. Men denna lösning tar endast den andra fyllningen korrekt eftersom den skriver över den första.
PS: Jag behöver fylla i båda färgläggningarna, inte bara en av dem.
Jag hoppas att jag lyckades förklara det tillräckligt bra. Om du har några frågor, tveka inte att fråga. Tack på förhand för hjälpen.
Svar #1
Du kan skapa ett klippområde (med context.clip) för att säkerställa att dina blå och grå fyllningar hålls inom de spår som skapats av ditt diagram. När du ställer in ett klippområde kommer alla nya ritningar inte att visas utanför klippområdet.
- Spara några diagramdata i en array.
- Spara det övre och nedre området av fyllning inom de plottade punkterna
- Definiera diagramvägen (==plotta punkterna utan att rita punkterna)
- Skapa ett klippområde från vägen (all ny ritning kommer att vara inom klippområdet och kommer inte att synas utanför området)
- Fyll klippområdet (med dina blå och grå fyllningar)
- Stryk över stigen (med dina röda och mörkröda strykningar)
Observera: När du skapar en avklippsväg kan den bara "avklippas" genom att omsluta avklippskoden med context.save & context.restore.
Här är kommenterad kod och en demo:
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
var pts0=[
{x:119,y:239},
{x:279,y:89},
{x:519,y:249},
{x:739,y:83},
{x:795,y:163},
];
var fill0={top:75,bottom:133};
var pts1=[
{x:107,y:342},
{x:309,y:523},
{x:439,y:455},
{x:727,y:537},
{x:757,y:389}
];
var fill1={top:473,bottom:547};
filledChart(pts0,fill0,'red','skyblue');
filledChart(pts1,fill1,'maroon','lightgray');
function filledChart(pts,fill,strokecolor,fillcolor){
// define the path
// This doesn't stroke the path, it just "initializes" it for use
ctx.beginPath();
ctx.moveTo(pts[0].x,pts[0].y);
for(var i=0;i<pts.length;i++){
var pt=pts[i];
ctx.lineTo(pt.x,pt.y);
}
// save the un-clipped context state
ctx.save();
// Create a clipping area from the path
// All new drawing will be contained inside
// the clipping area
ctx.clip();
// fill some of the clipping area
ctx.fillStyle=fillcolor;
ctx.fillRect(0,fill.top,cw,fill.bottom-fill.top);
// restore the un-clipped context state
// (the clip is un-done)
ctx.restore();
// stroke the path
ctx.strokeStyle=strokecolor;
ctx.lineWidth=2;
ctx.stroke();
}body{ background-color: ivory; }
#canvas{border:1px solid red; }<canvas id="canvas" width=800 height=550></canvas>Svar #2
Du kan försöka göra 'fyllningen' innan diagrammet.
- Du skapar fyllningsfärgen.
- Du skapar 'masken' (vit färg)
- Du skapar diagramlinjen
Ett exempel, med bara ett diagram, men kan enkelt ändras för att använda två diagram: https://jsfiddle.net/eLwc96fj/
var c2 = document.getElementById('test').getContext('2d');
// Create a colored rectangle
c2.fillStyle = '#0f0';
c2.rect(80,0, 200,70);
c2.fill();
// Create the 'mask' - it has the same path than the chart, but then follow the above rectangle.
c2.beginPath();
c2.fillStyle = '#fff';
c2.moveTo(80, 80);
c2.lineTo(120,50);
c2.lineTo(180, 90);
c2.lineTo(250, 40);
c2.lineTo(280, 120);
c2.lineTo(280, 0);
c2.lineTo(80, 0);
c2.closePath();
c2.fill();
// Draw the chart itself
c2.strokeStyle = '#f00';
c2.beginPath();
c2.moveTo(80, 80);
c2.lineTo(120,50);
c2.lineTo(180, 90);
c2.lineTo(250, 40);
c2.lineTo(280, 120);
c2.stroke();

