Semi-transparant background for widget

Hi,

I wrote (more like cherry-picked from dozens of other examples) a small script to retrieve a daily comic from GoComics (e.g. Get Fuzzy or Garfield) and display it in a widget.

It works, and while I’m sure there are a ton of things I could improve in my code (I’m not used to writing JS), the main thing bothering me is that the background of the widget is white. If possible, I’d prefer a semi-transparent, kind of “frosted” look like e.g. the iOS’s battery widget.

I’ve been trying to pass a Color with an alpha value to the backgroundColor property, but that doesn’t seem to do anything. I’ve also tried using ListGradient, but again, no dice.

Would anyone be able to offer a hand in this? Below is my code (again, not a JS coder by far). Thank you!

let imgUrl = await getUrl(args.widgetParameter)
let img = await getImg(imgUrl)
let widget = await createWidget(img, imgUrl)

// If the script isn't running as a Widget, 
// show a debugging preview of the widget, 
// in Scriptable itself
if ( ! config.runsInWidget) {
    await widget.presentMedium()
}

Script.setWidget(widget)
Script.complete()

async function createWidget(img, url) {
    let w = new ListWidget()

	w.backgroundColor = new Color("#ffffff", 0.1)
    w.url = url
    w.setPadding(0, 0, 0, 0)
    let wimg = w.addImage(img)
    wimg.centerAlignImage()
    return w
}

async function getUrl(comicName) {
    // Retrieve today's date formatted as YYYY/MM/DD to append to the URL
    const nowDt = new Date()
    const datepart = nowDt.toISOString().split('T',1)[0].replace(/-/g,'/')
    
    const url='https://www.gocomics.com/' + (comicName ?? 'getfuzzy') + '/' + datepart
    let wv = new WebView()
    await wv.loadURL(url)
    
    // Retrieve the image URL from the metadata
    const comicJS = `
    document.querySelector("meta[property='og:image']")['content']
    `
    const imgUrl = await wv.evaluateJavaScript(comicJS)
    return imgUrl
}

async function getImg(url) {
    const imgReq = await new Request(imgUrl)
    const img = await imgReq.loadImage()
    return img
}

Widgets cannot actually be transparent, or semi-transparent for that matter. But you can trick it by setting a background image that is the same as the “slice” of your wallpaper where the widget is located.

shameless plug, I have the no-background module for that

To make it semi-transparent, add a gradient background with a small alpha value.

Sample code here.


const nobg = importModule('no-background.js')
async function createWidget() {
   
  const widget = new ListWidget();

  widget.backgroundImage = await nobg.getSlice('small-middle-right')
  
  widget.backgroundGradient = newLinearGradient(['#00000022','#00000022'], [0,1])
  
  widget.addSpacer()

  let text = widget.addText('semi-transparent')
  text.textColor = Color.white()
  text.centerAlignText()
  

  widget.addSpacer()

  return widget
} //createWidget


//---[ main ]-------------------------------------
if (config.runsInWidget) {
  let widget = await createWidget()
  Script.setWidget(widget)
  Script.complete()
} else {
  let widget = await createWidget()
  await widget.presentSmall()
}

//------------------------------------------------
function newLinearGradient(hexcolors, locations) {
  let gradient = new LinearGradient()
  gradient.locations = locations
  gradient.colors = hexcolors
                     .map(color=>new Color(color))
  return gradient
}

Thank you very much for the explanation And looking at your repository, I see that you had a go at GoComics yourself too :slight_smile:.

I’ve been using your code to try and make a widget transparent. If you have the time could you take a look at my code in this discussion and tell me what I am doing wrong. Thanks in advance.