Behind The Scenes: Our The Unfinished Swan Review

Yesterday, at 10am, the embargo for The Unfinished Swan lifted. A little earlier than normal (apparently due to certain US sites going live early), perhaps, but due to a very late night the day before, we were more than ready. What we weren’t quite ready for was the almost universal praise that the layout and design of the piece attracted, something that we hadn’t actually thought that highly about until it landed.

I had the idea a couple of days before the review code landed a week or two back, but hadn’t started to figure out how I’d actually do it until about 9pm on Sunday night. As it happens, and something that seems to have bypassed a fair chunk of the people letting us know that they liked it, it was pretty easy. If anyone’s interested, I’d like to explain how it was done.

unfinished swan

Web development, at this level, is reasonably trivial. We use WordPress, so a massive portion of the hard work is already done in terms of delivering the content to the reader and tying everything together – you just need to coax what you want out of it. Coupled with jQuery, one of the best Javascript libraries, there wasn’t actually a huge amount to create from scratch.

The first thing I wanted was a brand new page template. Because of the modular way I’ve built this latest theme, the templates are actually driven by categories. That is, if we want to use a wide format page (for a big review or a video interview, perhaps) it’s just a case of picking the relevant category from WordPress’ back end. I created the category required, got its ID, and added it to our modified single.php, which just checks the ID of the category used in the post, and pulls the relevant page.

if (in_category(‘X’)) { include (TEMPLATEPATH . ‘/wide-templatesingle.php’); }
elseif (in_category(‘Y’)) { include (TEMPLATEPATH . ‘/tusreview-templatesingle.php’); }
else { include (TEMPLATEPATH . ‘/normal-templatesingle.php’); }

There’re three main page layouts for single posts – the wide one (ID ‘X’), the new one for the Unfinished Swan review (ID ‘Y’) and the regular one, used on most posts (including this one). Obviously I’ve replaced the actual IDs with X and Y. Those template pages actually replace the standard WordPress single.php, and pull in everything the page needs, from the header section, the background, the side bar, the comments and the story itself.

In this case, and it was a decision I made quite early, I didn’t want any comments. The idea was that people would read and like the review, and then share it over Twitter. One of the things I’ve found about TSA is that if our readers like a story they’ll comment (which is always lovely to see) but it rarely spreads much further unless we get lucky. In this case, sharing on social networks is something we pushed quite hard, and that seems to have worked.

Back to the code, then, and the PHP is remarkably simple. It does our basic user security stuff, loads the WordPress header, loads another page that contains the layout, and then renders the footer section, and the basic Javascript that the site normally loads. In hindsight this latter load wasn’t needed, but there’s little point changing it now. The actual page itself, the one that loads the story and displays it, is where the real stuff happens anyway.

It starts with the usual WordPress check:

if (have_posts()) : while (have_posts()) : the_post();

And then jumps straight into some hugely ugly and W3C invalid inline style sheets. These should have been loaded in the head section, but that would have meant further lower level changes and didn’t seem necessary for the scope of the project (and the limited development time we had) – remember, I still had to actually review the game after all this, at the moment the post in WordPress is (literally) just Lorem Ipsum.

The CSS consists of a few wrappers (to keep the text neat and centred) and a body class that adds a subtle inset shadow (to create a gentle vignette look). Some other basic styling set the font types, sizes and so on:

body {margin:0;padding:0;
-webkit-box-shadow: inset 0px 0px 80px rgba(0,0,0,0.1);
-moz-box-shadow: inset 0px 0px 80px rgba(0,0,0,0.1);
box-shadow: inset 0px 0px 80px rgba(0,0,0,0.1);}
.wrapper {width:960px;margin:auto;height:auto;overflow:hidden;}
.tus {width:560px;margin:auto;color:#000;padding-top:80px;height:auto;overflow:hidden;font-family: ‘Rosarivo’, serif;position:relative;z-index:5;}
.tus p {clear:both;margin-bottom:20px;cursor:default;text-align:justify;text-justify:inter-word;font-family: ‘Rosarivo’, serif;line-height:1.8;opacity:0;}
.tus h1 {width:560px;float:right;margin-bottom:20px;font-size:36px;letter-spacing:-1px;font-weight:700;font-family: ‘Rosarivo’, serif;}

The font, Rosarivo, is a Google Web Font and is loaded just above the CSS – I wanted the page to have a very distinct, un-TSA look about it, and a fresh, serif typeface seemed to do just that (and fit with the game’s storybook look and feel). I then needed CSS to control the positioning of the images and the header tags:

.tusleft {float:left;padding-right:10px;padding-bottom:10px;margin-right:10px;border-right:1px solid #aaa;}
.tusright {float:right;padding-left:10px;padding-bottom:10px;margin-left:10px;border-left:1px solid #aaa;}
.tusmid {margin:10px 40px 10px;border-top:1px solid #aaa;border-bottom:1px solid #aaa;padding:10px 0;}
.tusfooter {margin:20px auto 0px;padding-bottom:80px;border-top:1px solid #000;font-size:12px;color:#444;width:560px;padding-top:20px;font-style:italic;font-family: ‘Rosarivo’, serif;}
.tusfooter h2 {color:#888;margin-bottom:20px;font-size:12px;font-style:italic;font-family: ‘Rosarivo’, serif;}
.tusfooter h2 a {color:#444;font-size:12px;font-style:italic;font-family: ‘Rosarivo’, serif;text-decoration:none;}
.tusfooter h2 a:hover {color:#888;font-size:12px;font-style:italic;font-family: ‘Rosarivo’, serif;text-decoration:underline;}

There’ll be people looking at this and weeping. But time was short, and it seemed to do the job across every device I could test it on, and the browser support should be fine on anything above (and including) IE9. The PHP then renders the content, which again, is standard WordPress stuff.

the_content(‘

Read the rest of this entry »

‘);

At this point, the page was working. It was obviously dummy text, but it was displaying as I wanted it to. Obviously, mind, it was invisible, due to the opacity:0 in the CSS for the paragraph tags. Then I rendered the footer, which was a few Twitter links (that had to be inserted after the post went live so we could grab the Twitter IDs) and a simple credit link. Twitter’s ‘web intent‘ links are quite nice – if you’re logged in they automatically do the hard work for the end user.

So, now, the jQuery that would let the page come alive.

Bear in mind that I’m absolutely not a JavaScript expert by any stretch, but hopefully this is all easy to follow. I started with the usual: a ‘script’ tag and this:

jQuery(document).ready(function ($) {

That tells the browser to do the following once the page is ready. Immediately after that, I added a ‘notclicked’ class to everything (which was defined in the CSS as ‘opacity:0;’), thus:

$(“p”).addClass(‘notclicked’);
$(“h2”).addClass(‘notclicked’);
$(“.tus img”).addClass(‘notclicked’);
$(“tusleft”).addClass(‘notclicked’);
$(“tusright”).addClass(‘notclicked’);

Then it was a case of asking jQuery to wait for a click on any of the paragraph or image tags, and change the opacity of that particular tag to 1.

$(“p”).click(function () {
$(this).stop().animate({
opacity: 1
}, 250, function() {
});
$(this).removeClass(‘notclicked’);
});

$(“img”).click(function () {
$(this).stop().animate({
opacity: 1,
}, 250, function() {
});
$(this).removeClass(‘notclicked’);
});

The change from transparent to solid takes 250 milliseconds, and the jQuery also removes the ‘notclicked’ CSS class. A couple of other things I wanted to happen was a cue that the page wasn’t dead (although at least one high profile game developer immediately thought it was) by slowly revealing the Unfinished Swan logo, and then the footer in case the reader quickly scrolled down. Again, fairly trivial:

$(“h1 img”).delay(5000).animate({
opacity: 1
}, 3000, function() {
});

$(“h2”).delay(10000).animate({
opacity: 1
}, 3000, function() {
});

The logo appears after 5 seconds, the footer after 10. This probably needed a bit more balancing, but I thought the payoff for those that stuck with the page was probably greater this way than if we’d have given too much signposting. The only other thing to happen was the paint splat, something that really brought the page to life. I tried for a while to recreate the ball of paint flying to the cursor, but it wasn’t getting anywhere. Instead, we just used some Photoshop brushes to make a transparent .png and loaded that at the top of the page, albeit transparent, with an ID and a class we could manipulate later.

The jQuery for this took the longest, although that’s mainly because I’d messed up with the making of the img tags transparent earlier, meaning you had to double click first to make the paint appear, a bug that took about 90 minutes to figure out.

$(“.wrapper”).live(“click”, function(e){

var rNum = (Math.random()*360)-2;
$(“#paintsplat”).css({
‘-webkit-transform’: ‘rotate(‘+rNum+’deg)’,
‘-moz-transform’: ‘rotate(‘+rNum+’deg)’
} );

$(“#paintsplat”).css({
top: (e.pageY -150) + “px”,
left: (e.pageX -150) + “px”
});

$(“#paintsplat”).stop(true,true).fadeIn(5).delay(250).fadeOut(250);

});

This just looks for a click on the main wrapper div, picks a random number (which translates to a degree of rotation) and then rotates the div accordingly. It then places it at the co-ords of the mouse (offset by half the .png’s size, so it’s centred) and then quickly fades it in, waits 250 milliseconds, then fades it out again. The code to reveal the text is already underway, so the two just work nicely together, after a little bit of tweaking.

That’s literally all there is to it. It’s hugely simple, really, but seemed to have a fairly wideranging appeal. We’ve seen tweets from developers, publishers, journalists and – thankfully – our readers, and for the first time (to my knowledge) we got a nod from the main @playstationeu account. That wasn’t really the aim – and nor was it anything to do with Sony as one site suggested – it was just a fun experiment for a game I really liked and wanted to present a little bit differently.

Oh, and the review. I had to write the actual review, too.

Was it a success? Depends on how you measure success, I guess. It was interesting to see how a fairly standard bit of writing was so widely distributed solely because of the way it was delivered. It just goes to show that with a little bit of effort you can completely transform an article, something that we’d expect the bigger outlets to be doing on a much more regular basis.

28 Comments

  1. I was smiling to myself when I was reading the review, very nicely done.

  2. I was looking at it and weeping, but only because to me all that code looked like inscriptions you’d find on the side of an alien spacecraft.

    Was a great review too ;-)

  3. Lovely insight into the making of the review. I loved it, both the review itself and the way it was presented. Being a web designer/developer, I really loved the way it was presented, I thought it was so clever. This behind the scenes look is obviously interesting to me too, it helps that it all makes sense to me :) As you’ve said, all pretty simple, but it creates a wonderful effect. Great work :)

  4. Well done Alex.
    It really was a fantastic idea expertly executed. It turned an enjoyable review into a really engaging experience. Having that interactivity which perfectly fitted with the game being reviewed really created something great.
    Things like those show what a fantastic site TSA is and how the writers are willing to go above and beyond the call of duty for no pay, just the love of games and the community.
    I really hope this level of creativity rears its head again from time to time and hope that it shows some sites how things really should be done.
    Again, well done.

  5. I’ll admit the first thing I did when I opened the article was refresh, but then I figured it out and a smile grew on my face. Very well done!

  6. I thought it was a wonderfully fitting and clever way to do the review, this article is a bit scary though ;)

    • It was a lovely way to present it, just frustrating not being able to comment on it. However, the internet took to it like an animal of the avian variety to water.

      • An unfinished avian variety at that! ;)

      • Yes although i suspected comments might spoil the whole look of the review, so this bird took to tweeting! :)

      • Oh my

  7. Kudos, Alex.

    We here at the office poured over it and marvelled at what is essentially ingenuity, relevance and simplicity all conjoined together to present a singular conceit.

    Well done.

    (Have I qualified for a blue background yet? /jk!)

  8. At first, i just thought the site was actually a bit broken by it, as i was just seeing a lot of text & a couple of pictures on a white background. Nothing more.

    Turns out that this was due to my browser in work though, as it appeared as it should have when i looked on my phone on the bus home!

    Really clever idea & very fitting for the subject matter.

  9. *Copies and pastes for everything I write this week!*

    Very cool stuff, Al. Can’t wait for the Wonderbook: Book of Spells review. :P

    • Playstation Move required for that one i reckon. :)

  10. I keep clicking on this page but much of the text still remains gibberish to me…

    Loved the review yesterday, a nice surprise after I figured out why it was blank…

Comments are now closed for this post.