Skip to content

Instantly share code, notes, and snippets.

@adriaandotcom
Last active January 8, 2023 12:34
Show Gist options
  • Save adriaandotcom/d4ecb935d20bded16774fffcf59bba49 to your computer and use it in GitHub Desktop.
Save adriaandotcom/d4ecb935d20bded16774fffcf59bba49 to your computer and use it in GitHub Desktop.
AQI iOS lock screen widget with waqi.info

Here is how it looks (most left widget):

const waqiToken = "";
function circularRange(val, min, max, width, height) {
let context = new DrawContext()
context.size = new Size(width, height)
context.respectScreenScale = true
context.opaque = false
// background
let rect = new Rect(0, 0, width, height)
context.setFillColor(Color.black())
context.fillRect(rect)
// ring
let lineWidth = 16
context.setLineWidth(lineWidth)
let ring = new Rect(lineWidth/2, lineWidth/2, width - lineWidth, height - lineWidth)
context.setStrokeColor(Color.gray())
context.strokeEllipse(ring)
// mask
let path = new Path()
path.move(new Point(width / 2, height / 2))
let end = Math.PI / 6
let my = ((1 + Math.tan(end)) / 2) * height
path.addLine(new Point(0, my))
path.addLine(new Point(0, height))
path.addLine(new Point(width, height))
path.addLine(new Point(width, my))
context.addPath(path)
context.setFillColor(Color.black())
context.fillPath()
// rounded ends
let lx = ((1 - Math.cos(end)) / 2) * (width - lineWidth)
let ly = ((1 + Math.sin(end)) / 2) * (height - lineWidth)
let lend = new Rect(lx, ly, lineWidth, lineWidth)
let rx = ((1 + Math.cos(end)) / 2) * (width - lineWidth)
let rend = new Rect(rx, ly, lineWidth, lineWidth)
context.setFillColor(Color.gray())
context.fillEllipse(lend)
context.fillEllipse(rend)
// value
let a = (195 - (val - min) / (max - min) * 210) * Math.PI / 180
let vx = ((1 + Math.cos(a)) / 2) * (width - lineWidth)
let vy = ((1 - Math.sin(a)) / 2) * (height - lineWidth)
let value = new Rect(vx, vy, lineWidth, lineWidth)
context.setLineWidth(lineWidth * 3/4)
context.setStrokeColor(Color.black())
context.strokeEllipse(value)
context.setFillColor(Color.white())
context.fillEllipse(value)
// labels
context.setTextColor(Color.white())
context.setFont(Font.mediumSystemFont(25))
context.setTextAlignedCenter()
context.drawTextInRect("AQI", new Rect(0, 30, width, height))
context.setTextColor(Color.white())
context.setFont(Font.mediumSystemFont(66))
context.setTextAlignedCenter()
context.drawTextInRect(val > 0 ? `${val}` : ".....", new Rect(0, 50, width, height))
context.setTextColor(Color.white())
context.setFont(Font.regularSystemFont(25))
context.setTextAlignedLeft()
context.drawTextInRect(min.toString(), new Rect(width/5, height * 7/10, width * 3/10, height * 3/10))
context.setTextAlignedRight()
context.drawTextInRect(max.toString(), new Rect(width/2, height * 7/10, width * 3/10, height * 3/10))
return context
}
async function loadData() {
let url = "https://api.waqi.info/feed/bangkok/?token=" + waqiToken
let req = new Request(url)
try {
return await req.loadJSON()
} catch (error) {
log(error);
return {};
}
}
const { data } = await loadData()
let widget = new ListWidget()
widget.setPadding(0, 0, 0, -8)
let image = circularRange(data.aqi, 0, 200, 175, 175).getImage()
widget.addImage(image)
if (config.runsInAccessoryWidget) {
Script.setWidget(widget)
} else {
widget.presentSmall()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment