func plotLine(xy plotter.XYs) (image.Image, error) { p, err := plot.New() if err != nil { return nil, err } p.HideAxes() p.BackgroundColor = &color.RGBA{0, 0, 0, 255} //s, err := NewSparkLines(xy) s, err := plotter.NewLine(xy) if err != nil { return nil, err } s.Color = &color.RGBA{0, 255, 0, 128} p.Add(s) // Draw the plot to an in-memory image. // _, rows, _ := terminal.GetSize(0) charWidth := optCharWidth charHeight := optCharHeight //width := cols * charWidth height := optRows * charHeight img := image.NewRGBA(image.Rect(0, 0, 5+(len(xy)*charWidth), height)) canvas := vgimg.NewImage(img) da := plot.MakeDrawArea(canvas) p.Draw(da) return img, nil }
// crosshair draws a plus at the given point. func crosshair(img draw.Image, x, y int, str string) { c := vgimg.NewImage(img) // drawPlots here because NewImage // clears the canvas. Instead, the canvas // should just be stored instead of being // recreated at each redraw. drawPlots(img) c.SetColor(color.RGBA{R: 255, A: 255}) xc := vg.Inches(float64(x) / c.DPI()) yc := vg.Inches(float64(y) / c.DPI()) radius := vg.Points(5) var p vg.Path p.Move(xc-radius, yc) p.Line(xc+radius, yc) c.Stroke(p) p = vg.Path{} p.Move(xc, yc+radius) p.Line(xc, yc-radius) c.Stroke(p) c.SetColor(color.Black) c.FillString(font, vg.Length(0), vg.Length(0), str) }
// drawPlots draws the plots to an image. func drawPlots(img draw.Image) { c := vgimg.NewImage(img) da := plot.MakeDrawArea(c) textAreaSize := vg.Points(12) da.Min.Y += textAreaSize da.Size.Y -= textAreaSize left := da left.Size.X /= 2 ps[0].plot.Draw(left) ps[0].dataArea = ps[0].plot.DataDrawArea(left) right := da right.Min.X = left.Min.X + left.Size.X right.Size.X /= 2 ps[1].plot.Draw(right) ps[1].dataArea = ps[1].plot.DataDrawArea(right) }
func marshalPNG(r *http.Request, results []*metricData) []byte { p, err := plot.New() if err != nil { panic(err) } // set bg/fg colors bgcolor := string2Color(getString(r.FormValue("bgcolor"), "black")) p.BackgroundColor = bgcolor fgcolorstr := getString(r.FormValue("fgcolor"), "white") fgcolor := string2Color(fgcolorstr) p.Title.Color = fgcolor p.X.LineStyle.Color = fgcolor p.Y.LineStyle.Color = fgcolor p.X.Tick.LineStyle.Color = fgcolor p.Y.Tick.LineStyle.Color = fgcolor p.X.Tick.Label.Color = fgcolor p.Y.Tick.Label.Color = fgcolor p.X.Label.Color = fgcolor p.Y.Label.Color = fgcolor p.Legend.Color = fgcolor // set grid grid := plotter.NewGrid() grid.Vertical.Color = fgcolor grid.Horizontal.Color = fgcolor p.Add(grid) // line mode (ikruglow) TODO check values lineMode := getString(r.FormValue("lineMode"), "slope") // width and height width := getInt(r.FormValue("width"), 330) height := getInt(r.FormValue("height"), 250) // need different timeMarker's based on step size p.Title.Text = r.FormValue("title") p.X.Tick.Marker = makeTimeMarker(results[0].GetStepTime()) hideLegend := getBool(r.FormValue("hideLegend"), false) graphOnly := getBool(r.FormValue("graphOnly"), false) if graphOnly { p.HideAxes() } if len(results) == 1 && results[0].color == "" { results[0].color = fgcolorstr } var lines []plot.Plotter for i, r := range results { l := NewResponsePlotter(r) l.LineStyle.Color = fgcolor // consolidate datapoints l.maybeConsolidateData(width) if r.drawAsInfinite { l.lineMode = "drawAsInfinite" } else { l.lineMode = lineMode } if r.color != "" { l.Color = string2Color(r.color) } else { l.Color = plotutil.Color(i) } lines = append(lines, l) if !graphOnly && !hideLegend { p.Legend.Add(r.GetName(), l) } } p.Add(lines...) p.Y.Max *= 1.05 p.Y.Min *= 0.95 // Draw the plot to an in-memory image. img := image.NewRGBA(image.Rect(0, 0, width, height)) da := plot.MakeDrawArea(vgimg.NewImage(img)) p.Draw(da) var b bytes.Buffer if err := png.Encode(&b, img); err != nil { panic(err) } return b.Bytes() }