Skip to content

Instantly share code, notes, and snippets.

@donfelipo
Forked from kevinkub/scriptable-line-chart.js
Last active December 10, 2020 22:24
Show Gist options
  • Save donfelipo/25e633b2d8d76af20ce0601af5b67562 to your computer and use it in GitHub Desktop.
Save donfelipo/25e633b2d8d76af20ce0601af5b67562 to your computer and use it in GitHub Desktop.
Simple line chart class for https://scriptable.app πŸ“ˆ
// Variables used by Scriptable.
// These must be at the very top of the file. Do not edit.
// icon-color: orange; icon-glyph: magic;
class LineChart {
// LineChart by https://kevinkub.de/
constructor(width, height, values) {
this.ctx = new DrawContext();
this.ctx.size = new Size(width, height);
this.values = values;
}
_calculatePath() {
let maxValue = Math.max(...this.values);
let minValue = Math.min(...this.values);
let difference = maxValue - minValue;
let count = this.values.length;
let step = this.ctx.size.width / (count - 1);
let points = this.values.map((current, index, all) => {
let x = step*index;
let y = this.ctx.size.height - (current - minValue) / difference * this.ctx.size.height;
return new Point(x, y);
});
return this._getSmoothPath(points);
}
_getSmoothPath(points) {
let path = new Path();
path.move(new Point(0, this.ctx.size.height));
path.addLine(points[0]);
for(let i = 0; i < points.length-1; i++) {
let xAvg = (points[i].x + points[i+1].x) / 2;
let yAvg = (points[i].y + points[i+1].y) / 2;
let avg = new Point(xAvg, yAvg);
let cp1 = new Point((xAvg + points[i].x) / 2, points[i].y);
let next = new Point(points[i+1].x, points[i+1].y);
let cp2 = new Point((xAvg + points[i+1].x) / 2, points[i+1].y);
path.addQuadCurve(avg, cp1);
path.addQuadCurve(next, cp2);
}
path.addLine(new Point(this.ctx.size.width, this.ctx.size.height));
path.closeSubpath();
return path;
}
configure(fn) {
let path = this._calculatePath();
if(fn) {
fn(this.ctx, path);
} else {
this.ctx.addPath(path);
this.ctx.fillPath(path);
}
return this.ctx;
}
}
// Demo
let data = [20, 10, 15, 5, 10, 30, 20, 10, 10, 10, 20, 10];
let widget = new ListWidget();
let chart = new LineChart(700, 338, data).configure((ctx, path) => {
ctx.opaque = false;
ctx.setFillColor(new Color("888888", .5));
ctx.addPath(path);
ctx.fillPath(path);
}).getImage();
widget.addText("Hello Charts!");
widget.addSpacer();
let image = widget.addImage(chart);
Script.setWidget(widget);
if (!config.runsInWidget) {
await widget.presentSmall();
}
Script.complete();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment