Let It Snow

I wanted to make the Carpenter series of posts look ridiculously romantic, so I got the swashiest font I could find.  But it’s not enough: I wanted to make it snow, too.

Now, this blog is on WordPress.com, which adds limitations to what is easy or even possible to do.  I wanted a CSS-only snowing solution that didn’t involve adding any new HTML elements, and that turns out not to be the common thing to do?  There are approximately five hundred thousand blog articles out there about making web pages snow, but they are either snowing in the background, or is a mess of <div> <div> <div>s to make it snow in front of an image.

Looking at this pretty snowing effect, I wanted to do the same, but by just adding a class: snow to the <a> element already surrounding the <img>s in this blog.

Presto:

This, as anybody who’s done CSS knows, took way too long and went down many blind alleys before I got it to work properly.  (So it’s a good thing I did it while I was on holiday.)  Here’s the CSS I ended up with:

.snow {
  display: inline-block;
  position: relative;
}
.snow::after {
  content: '';
  position: absolute;
  display: block;
  top: 0; left: 0;
  width: 100%;
  height: 100%;
  background-image: url('https://larsmagne23.files.wordpress.com/2017/11/pl2.png'), url('https://larsmagne23.files.wordpress.com/2017/11/pm2.png'), url('https://larsmagne23.files.wordpress.com/2017/11/pm2.png'), url('https://larsmagne23.files.wordpress.com/2017/11/ps2.png'), url('https://larsmagne23.files.wordpress.com/2017/11/ps2.png');
  animation: snow-fall 5s linear infinite;
}
@keyframes snow-fall {
  0% { background-position: 0 0, 0 0, 30px 40px, 0 0, 10px 0;}
  33% { background-position: 0 137px, 0 70px, 45px 100px, 0 30px, 20px 30px; }
  66% { background-position: 0 274px, 0 140px, 35px 200px, 0 60px, 20px 60px; }
  100% { background-position: 0 413px, 0 200px, 30px 240px, 0 100px, 10px 100px; }
}

So: What’s going on here is that I’m adding an :after element to the <a> element, and that element has en empty content, but several background images.  (Five of them, to be precise.)  These images are mostly transparent, but has snowflakes of various sizes and blurrinesses.  In the original version, all these “layers” are of the same size but animated in different speeds so that the closest layer is fastest.  That’s not possible with the :after thing, because there can only be one :after, and therefore only one animation speed.

So instead I chopped the different layer images into different sizes, and then I can animate one from 0px to 100px while I animate a closer, faster layer from 0px to 200px, and so on.  The important thing is that the animations have to be the same sizes as the images, because otherwise you’ll get a shuddering effect when the animations restart.

And then you can do any number of things, like adding some slight wobble and windiness to the scene.

The more layers you add, the more CPU intensive the result will be.  Depending on whether the user’s browser uses hardware acceleration for the CSS animation, of course.  But think of it this way: It makes the computer nice and toasty warm: Perfect for winter.

(One complication to getting this to work on this blog is that I had called the animation “snow”, so the CSS read “animation: snow 5s linear infinite”.  WordPress.com helpfully auto-translated this to “animation: #fffafa 5s linear infinite”.  Presumably because “snow” is a colour name.  And that doesn’t work.  Thank you, WordPress.com.)

So when I grow up, my job is definitely going to be for restaurants that specialise in weddings in December.  I’ve already got the CSS and the font!

Responsive Comics

The other month I was staring at the Diamonds Previews interface that I hacked up last year. Its main purpose is to allow me (and anybody else) to go through the monthly listings rapidly, without all that clicking and stuff.

I was wondering: Has CSS Flexbox technology progressed to the point where the interface could be transformed “responsively” (i.e., via CSS selectors) from the wide design above to something that fits on a cell phone. It would require a completely different layout; shifting from the three column layout with many sub-boxes into a single column where some of the boxes would move up and some down and some become a line of buttons here and and and…

The answer seems to be: Nope. While googling for this stuff, everybody seemed to be saying “just add a div outside the other div and then div it up and then you can sort of move some bits around. If that div is placed before that div”.

CSS still, after 20 years, sucks at layout.

*sigh*

But once I had started tinkering with this, I couldn’t just give up, so I just wrote a bunch of JS to transform the layout, and presto:

So purdy! So UX!

And so I started wondering whether this might make sense as an app, so I wrapped it up in Cordova and shipped it over to Google…

Who rejected it outright because of copyright violations. “But,” I said, “this is like a sales catalogue and isn’t it fair use to show covers in a sales catalogue, man? Man?” And they said “nope; go away”.

While waiting for them to reject the app, I started thinking about… sharing… “Wouldn’t it be nice to make it possible for people to ‘curate’ lists and share these with others?”, so I read up on Firebase and presto: “Curate” button.

Firebase is surprisingly nice, and has a lot of documentation. The main problem is that Firebase covers so many, many use cases that trying to find the correct approach for Goshenite entailed scratching my head for a few hours.

But when the app rejection arrived I just thought, “eh, whatevs”, so it’s a bit lacking in features that are probably not going to be implemented, so it’s more of a toy than anything.

The source code can be found on Github, as usual.

“Concerts in Oslo” App Updated

I took a short holiday to sit in the garden and update the Concerts in Oslo app.  I mainly wanted to make navigation more intuitive by having the “back” button do what you’d expect it to do, but I also wanted to play with the Google Map API and see whether that’s any fun.
And it is.  Results to the right.  I’ve also added a method to list concerts in descending proximity.  You know.  For those days when you’re thinking “I want to go to a concert; I don’t care which one, but it has to be close.  Because I’m too tired to walk far.”
THIS MAKES SENSE!
The Android version is out now; the IOS version will follow once I’ve tested it on the phone I forgot to bring with me.  So a couple of days plus the nine weeks Apple will use to approve the update.
But one can’t post a blog post like this without bitching about Google, can one?  I don’t think so.  First of all, the Google Play Console defaults to the dominant language of the IP address you’re connecting from, which relegates all developers from non-English-speaking countries to third class status: We’re presented with awkwardly translated tech speak that barely made sense in English in the first place.  And it’s impossible to google for any of these messages and errors you’re inevitably presented with to find out what they mean, because all those questions and answers are in English.
And there’s no way to switch to English…  until you notice that the URL itself has a parameter that says “hl=no”, and you can edit that to “hl=en”, and then the interface will behave and become marginally more understandable.
Not very, though: I seem to have pushed an API version of 23, which excludes all pre-version-5 Android users from using the app.  And there seems to be no way to go back to API version 14, SDK 23, which I was using.  Play Console gives me errors, at least, when I try.
*sigh*
I’ll just leave you all with this unrelated screen that Android displays when I plug my phone into the laptop:
If you press “Cancel” here…  is it going to cancel the charging?  Or not?  I’ll leave that as an exercise for the class.

Face Your Problems

I maintain a web site (and a gaggle of apps) that scrape event lists of all the clubs and concert venues in Oslo.  The other day, I was told that it missed a bob hund concert and I was all whaaa?

It turned out that the reason was that Facebook is now blocking all non-logged-in access to their event lists.

Because nobody who has a venue wants anybody but people on Facebook to show up when they have a concert.  I guess that’s what you get when you’re gardening in a walled garden.

This made about a dozen sites disappear off of CSID, so I had to get real and figure out how to deal with the Facebook “Graph” API.  And it turned out to be really easy to work with.  After I read “howto” web sites for half an hour, implementing it was just a matter of connecting app secrets with app IDs with client tokens with access tokens with long-lived access tokens.

It all makes sense.

It’s all on github as usual, but it’s trivial, really.  And I guess it’ll work until Facebook feels like they should cut off more access to the data, whenever they feel like that’ll make more sense for their quarterly outlook.

Blackest Night

Previously: I bought an HDMI OLED screen and determined that its black pixels emitted light.

This made me start wondering: Do all OLED screens emit light from “black” pixels?

So I did the simplest thing possible to test this: I made a little app that displays a black screen. It’s on Google Play and everything. It’s called “Blacker Than Black” if you just want to search for it on your phone.

So I loaded it up on my Blackberry Priv AMOLED (that’s short for “armored led”, I think), and went into the unmentionable room, and took a picture:

OK, that’s kinda… black… let me twiddle the camera settings… er… f2.8… ISO6400… two second exposure…

That’s still very black! Although now the camera can see my fingers in the very, very dim room. Very dim.

OK, let’s test another phone. That’s a Samsung Galaxy S6…  (Which is also AMMO LED.) Very black indeed.

OK, I’m convinced. That SmallHD AC7 OLED screen sucks, but other black OLED screens are blacker than very black.

For kicks, I loaded the app onto my Sony Xperia z4 tablet, which has an IPS screen. And dialed the exposure settings waaaay down.

Yeah. It’s not very black.

Galaxy S6 in front to compare.

So there you have it: The OLED blackness myth… IS CONFIRMED!

Shocking. But that just means that I have to find a different 7″ OLED screen from somebody that makes a better screen, and things will be perfect!

Unfortunately, after googling for an hour or two, that doesn’t seem to exist. There are other OLED screens, and a couple of them even have HDMI, but they’re all really, really ugly, and isn’t really something that I want in my bedroom.

Oh, well. I’ll have to wait a few more years for perfection…

More Fun With Google Geocharts

I’ve been using Google Geocharts to create nice world maps for my World of Films and Cocktail blogging project. It’s a pretty good service, but it doesn’t really have all the bells and whistles I need to customize the interactive version the way I want.

But today I’m hung over, and I got down to the nitty gritty undocumented interfaces. Behold!

But click over here to experience the much awesome.

Here’s the longer story for other people who are interested in doing something similar. Note that this is likely to stop working at any point since I’m using non-public features that just happen to work now with the version of Google Geocharts right now, on January 1st 2017.

So: I wanted to have stuff happen on a “hover” action, so that people don’t need to click to make things happen. Much more fun. But there is no “hover” callback in Google Geocharts. Instead I piggy-back on the tooltips and use them to root out the data I need to determine what country the user is hovering over.

First of all, make the tooltip be HTML instead of the default SVG text elements:

var options = { 
  ... 
  tooltip: { trigger: "focus", isHtml: true } 
};

Then hide the oh-so-ugly tooltip:

.google-visualization-tooltip { 
  visibility: hidden; 
}

Then do something like the following to have something happen when you hover over a country. Each country is a separate SVG path element, so:

$("path").each(function() { 
  $(this).hover(function() { 
   $(".google-visualization-tooltip")
     .find("span")
     .first()
     .each(function() { 
             var html = this.innerHTML; 
             if (html.length == 2) { 
               $.map(films, function(film) { 
                if (film[0] == html) 
                 displayFilm(film); 
               }); 
             } 
           });

Obviously this won’t work directly for you, but what I’m doing here is rooting out the data from the displayed tooltip (here it’s the two-character country code), and then using that to figure out what country I’m over. And from there you can just do whatever you want.

What I wanted was to display a random image from the film from the country under the cursor, so I used a weird cross-origin Google script service, which just reads the HTML from the blog post, finds all the images, and displays one of them at random.

Useful, huh? HUH??!?!

Oh, well.

Here’s the source code.

“Muting” Pictures With Pure CSS

I’ve been somewhat wary about posting some of the images from some of the more extreme Fantagraphics comics I’ve written about (I’m thinking of you, Grit Bath).  Not everybody appreciates being flashed images of bitten-off ears or penises while scrolling down a blog.

On the other hand, I want to represent these comics honestly, so I thought it might be nice to “hide” images from more sensitive readers without making a big deal about it.  That is, I wanted them still to be accessible without the reader having to go to a new page, and I wanted to make this possible without adding a lot of redundant HTML to the articles.

Presto!

shot0028 png

The solution is pure CSS: I only have to add the “redact” class to the <a> link that surrounds the image.  It took me several hours of googling around to put all the pieces together, but the end result looks quite “d’oh, that’s simple”.  All the other solutions I found involved adding <div>s around and <p>s inside, which is yucky.

I’ve put the solution on Github for people interested in adapting it to their own needs.