Sunday, April 7, 2013
Note: the demos in this blog post require IE 9+ (preferably 10), Firefox, or any WebKit browser. If you’re on a mobile device, you might need to click the open in new page button to view the demos properly.
Kreatif Media Solution
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <div id="ac-wrapper" class="ac-wrapper"> <h2>Weatherous <span>Concept & UI Design</span></h2> <div class="ac-device"> <a href="#"><img src="images/screen1.jpg"/></a> <h3 class="ac-title">Gentrify small batch umami retro vegan</h3> </div> <div class="ac-grid"> <a href="#"><img src="images/screen1.jpg"/><span>Gentrify small batch umami retro vegan</span></a> <a href="#"><img src="images/screen2.jpg"/><span>Chambray squid semiotics</span></a> <a href="#"><img src="images/screen3.jpg"/><span>Fashion axe blue bottle</span></a> <a href="#"><img src="images/screen4.jpg"/><span>Photo booth single-origin coffee</span></a> <a href="#"><img src="images/screen5.jpg"/><span>Flexitarian synth keytar blog master</span></a> <a href="#"><img src="images/screen6.jpg"/><span>Next level retro flexitarian freegan</span></a> <a href="#"><img src="images/screen7.jpg"/><span>Pour-over superious meggings terry</span></a> <a href="#"><img src="images/screen8.jpg"/><span>Seitan william vinyl chillwave</span></a> </div></div> |
1 2 3 4 5 6 | .ac-wrapper { width: 100%; position: relative; perspective: 1000px; perspective-origin: 50% 25%;} |
1 2 3 4 5 6 7 8 9 | .ac-wrapper h2 { top: 20%; width: 50%; position: absolute; font-weight: 300; font-size: 4em; text-align: right; padding: 0 180px 0 50px;} |
1 2 3 4 5 | .ac-wrapper h2 span { display: block; font-size: 60%; color: #c0c0c0;} |
1 2 3 4 5 6 7 8 9 | .ac-device { background: url(../images/iPhone.png) no-repeat; width: 288px; height: 611px; margin: 0 auto; position: relative; transition: all 0.3s ease; transform-style: preserve-3d;} |
1 2 3 4 5 6 7 8 9 10 | .ac-device a { height: 440px; width: 249px; display: inline-block; margin: 85px 0 0 20px;}.ac-device a img { display: block;} |
1 2 3 4 5 6 7 8 9 10 | .ac-device h3 { position: absolute; font-size: 2.5em; left: 100%; width: 100%; top: 60%; margin-left: 30px; font-weight: 300; color: #888;} |
none so that we can’t click on it when it’s invisible. We’ll also add a transition and translate it -350px on the Z axis:1 2 3 4 5 6 7 8 9 10 11 12 13 14 | .ac-grid { position: absolute; width: 620px; left: 50%; margin-left: -310px; height: 100%; z-index: 1000; top: 0; opacity: 0; pointer-events: none; transform-style: preserve-3d; transition: all 0.3s ease; transform: translateZ(-350px);} |
1 2 3 4 5 6 7 8 9 10 11 12 13 | .ac-grid a { width: 145px; display: block; position: relative; float: left; margin: 10px 5px; cursor: pointer;}.ac-grid a img { display: block; width: 100%;} |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | .ac-grid a span { position: absolute; height: 100%; width: 100%; left: 0; top: 0; text-transform: uppercase; padding: 3em 1em 0; z-index: 100; color: #ddd; background: rgba(0,0,0,0.4); font-weight: 700; opacity: 0; transform: translateY(-5px); transition: all 0.2s ease;}.ac-grid a:hover span { opacity: 1; transform: translateY(0);} |
1 2 3 4 5 6 7 8 9 10 | .ac-wrapper.ac-gridview .ac-device { transform: translateZ(-350px); opacity: 0.6;}.ac-wrapper.ac-gridview .ac-grid { transform: translateZ(0px); opacity: 1; pointer-events: auto;} |
auto again.1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | @media screen and (max-width: 63.875em) { .ac-wrapper { font-size: 60%; width: 100%; padding: 0 20px; } .ac-device { margin: 0; width: 100%; } .ac-device h3 { width: 50%; left: 290px; } .ac-wrapper h2 { left: 308px; padding: 0; text-align: left; margin-left: 30px; }}@media screen and (max-width: 39.8125em) { .ac-grid { width: 90%; left: 5%; margin-left: 0; padding-top: 150px; } .ac-grid a { width: 22%; }}@media screen and (max-width: 35.6875em) { .ac-wrapper { padding: 0 20px 100px; } .ac-wrapper h2 { width: 100%; text-align: center; margin: 0 0 1em; top: 0; left: auto; position: relative; } .ac-device { margin: 0 auto; width: 288px; } .ac-device h3 { position: relative; margin: 0; left: auto; width: 100%; top: 100px; display: block; text-align: center; }} |
1 2 3 4 5 6 7 8 9 10 11 12 13 | var $el = $( '#ac-wrapper' ), // device element $device = $el.find( '.ac-device' ), // the device image wrapper $trigger = $device.children( 'a:first' ), // the screens $screens = $el.find( '.ac-grid > a' ), // the device screen image $screenImg = $device.find( 'img' ), // the device screen title $screenTitle = $device.find( '.ac-title' ), // HTML Body element $body = $( 'body' ); |
1 2 3 4 5 6 7 8 9 | function init() { // show grid $trigger.on( 'click', showGrid ); // when a grid´s screen is clicked, show the respective image on the device $screens.on( 'click', function() { showScreen( $( this ) ); return false; } );} |
1 2 3 4 5 6 | function showGrid() { $el.addClass( 'ac-gridview' ); // clicking somewhere else on the page closes the grid view $body.off( 'click' ).on( 'click', function() { showScreen(); } ); return false;} |
1 2 3 4 5 6 7 8 | function showScreen( $screen ) { $el.removeClass( 'ac-gridview' ); if( $screen ) { // update image and title on the device $screenImg.attr( 'src', $screen.find( 'img' ).attr( 'src' ) ); $screenTitle.text( $screen.find( 'span' ).text() ); }} |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | function navigate( direction ) { // if currently animating return if( animating ) { return false; } animating = true; // update current if( direction === 'next' ) { current = current < screensCount - 1 ? ++current : 0; } else if( direction === 'prev' ) { current = current > 0 ? --current : screensCount - 1; } // next screen to show var $nextScreen = $screens.eq( current ); // if css transitions support: if( support ) { // append new image to the device and set the transition and initial style var $nextScreenImg = $( '<img src="' + $nextScreen.find( 'img' ).attr( 'src' ) + '">' ).css( { transition : 'all 0.5s ease', opacity : 0, transform : direction === 'next' ? 'scale(0.9)' : 'translateY(100px)' } ).insertBefore( $screenImg ); // update title $screenTitle.text( $nextScreen.find( 'span' ).text() ); setTimeout( function() { // current image fades out / new image fades in $screenImg.css( { opacity : 0, transform : direction === 'next' ? 'translateY(100px)' : 'scale(0.9)' } ).on( transEndEventName, function() { $( this ).remove(); } ); $nextScreenImg.css( { opacity : 1, transform : direction === 'next' ? 'scale(1)' : 'translateY(0px)' } ).on( transEndEventName, function() { $screenImg = $( this ).off( transEndEventName ); animating = false; } ); }, 25 ); } else { // update image and title on the device $screenImg.attr( 'src', $nextScreen.find( 'img' ).attr( 'src' ) ); $screenTitle.text( $nextScreen.find( 'span' ).text() ); animating = false; }} |
1 | # The title of the blog post |
2 |
3 | Body of the blog post. | | |
1 | { |
2 | "require": { |
3 | "dflydev/markdown": "v1.0.2", |
4 | "suin/php-rss-writer": ">=1.0" |
5 | } |
6 | } |
1 | require 'vendor/autoload.php'; |
01 | ; The URL of your blog |
03 |
04 | ; Blog info |
05 |
06 | blog.title = "Tutorialzine Demo Blog" |
07 | blog.description = "This is a lightweight and responsive blogging system.." |
08 | blog.authorbio = "Created by ..." |
09 |
10 | posts.perpage = 5 |
11 |
12 | ; Framework config. No need to edit. |
13 | views.root = app/views |
14 | views.layout = layout |
01 | // This is the composer autoloader. Used by |
02 | // the markdown parser and RSS feed builder. |
03 | require 'vendor/autoload.php'; |
04 |
05 | // Explicitly including the dispatch framework, |
06 | // and our functions.php file |
07 | require 'app/includes/dispatch.php'; |
08 | require 'app/includes/functions.php'; |
09 |
10 | // Load the configuration file |
11 | config('source', 'app/config.ini'); |
12 |
13 | // The front page of the blog. |
14 | // This will match the root url |
15 | get('/index', function () { |
16 |
17 | $page = from($_GET, 'page'); |
18 | $page = $page ? (int)$page : 1; |
19 |
20 | $posts = get_posts($page); |
21 |
22 | if(empty($posts) || $page < 1){ |
23 | // a non-existing page |
24 | not_found(); |
25 | } |
26 |
27 | render('main',array( |
28 | 'page' => $page, |
29 | 'posts' => $posts, |
30 | 'has_pagination' => has_pagination($page) |
31 | )); |
32 | }); |
33 |
34 | // The post page |
35 | get('/:year/:month/:name',function($year, $month, $name){ |
36 |
37 | $post = find_post($year, $month, $name); |
38 |
39 | if(!$post){ |
40 | not_found(); |
41 | } |
42 |
43 | render('post', array( |
44 | 'title' => $post->title .' ⋅ ' . config('blog.title'), |
45 | 'p' => $post |
46 | )); |
47 | }); |
48 |
49 | // The JSON API |
50 | get('/api/json',function(){ |
51 |
52 | header('Content-type: application/json'); |
53 |
54 | // Print the 10 latest posts as JSON |
55 | echo generate_json(get_posts(1, 10)); |
56 | }); |
57 |
58 | // Show the RSS feed |
59 | get('/rss',function(){ |
60 |
61 | header('Content-Type: application/rss+xml'); |
62 |
63 | // Show an RSS feed with the 30 latest posts |
64 | echo generate_rss(get_posts(1, 30)); |
65 | }); |
66 |
67 | // If we get here, it means that |
68 | // nothing has been matched above |
69 |
70 | get('.*',function(){ |
71 | not_found(); |
72 | }); |
73 |
74 | // Serve the blog |
75 | dispatch(); |
001 | use dflydev\markdown\MarkdownParser; |
002 | use \Suin\RSSWriter\Feed; |
003 | use \Suin\RSSWriter\Channel; |
004 | use \Suin\RSSWriter\Item; |
005 |
006 | /* General Blog Functions */ |
007 |
008 | function get_post_names(){ |
009 |
010 | static $_cache = array(); |
011 |
012 | if(empty($_cache)){ |
013 |
014 | // Get the names of all the |
015 | // posts (newest first): |
016 |
017 | $_cache = array_reverse(glob('posts/*.md')); |
018 | } |
019 |
020 | return $_cache; |
021 | } |
022 |
023 | // Return an array of posts. |
024 | // Can return a subset of the results |
025 | function get_posts($page = 1, $perpage = 0){ |
026 |
027 | if($perpage == 0){ |
028 | $perpage = config('posts.perpage'); |
029 | } |
030 |
031 | $posts = get_post_names(); |
032 |
033 | // Extract a specific page with results |
034 | $posts = array_slice($posts, ($page-1) * $perpage, $perpage); |
035 |
036 | $tmp = array(); |
037 |
038 | // Create a new instance of the markdown parser |
039 | $md = new MarkdownParser(); |
040 |
041 | foreach($posts as $k=>$v){ |
042 |
043 | $post = new stdClass; |
044 |
045 | // Extract the date |
046 | $arr = explode('_', $v); |
047 | $post->date = strtotime(str_replace('posts/','',$arr[0])); |
048 |
049 | // The post URL |
050 | $post->url = site_url().date('Y/m', $post->date).'/'.str_replace('.md','',$arr[1]); |
051 |
052 | // Get the contents and convert it to HTML |
053 | $content = $md->transformMarkdown(file_get_contents($v)); |
054 |
055 | // Extract the title and body |
056 | $arr = explode('</h1>', $content); |
057 | $post->title = str_replace('<h1>','',$arr[0]); |
058 | $post->body = $arr[1]; |
059 |
060 | $tmp[] = $post; |
061 | } |
062 |
063 | return $tmp; |
064 | } |
065 |
066 | // Find post by year, month and name |
067 | function find_post($year, $month, $name){ |
068 |
069 | foreach(get_post_names() as $index => $v){ |
070 | if( strpos($v, "$year-$month") !== false && strpos($v, $name.'.md') !== false){ |
071 |
072 | // Use the get_posts method to return |
073 | // a properly parsed object |
074 |
075 | $arr = get_posts($index+1,1); |
076 | return $arr[0]; |
077 | } |
078 | } |
079 |
080 | return false; |
081 | } |
082 |
083 | // Helper function to determine whether |
084 | // to show the pagination buttons |
085 | function has_pagination($page = 1){ |
086 | $total = count(get_post_names()); |
087 |
088 | return array( |
089 | 'prev'=> $page > 1, |
090 | 'next'=> $total > $page*config('posts.perpage') |
091 | ); |
092 | } |
093 |
094 | // The not found error |
095 | function not_found(){ |
096 | error(404, render('404', null, false)); |
097 | } |
098 |
099 | // Turn an array of posts into an RSS feed |
100 | function generate_rss($posts){ |
101 |
102 | $feed = new Feed(); |
103 | $channel = new Channel(); |
104 |
105 | $channel |
106 | ->title(config('blog.title')) |
107 | ->description(config('blog.description')) |
108 | ->url(site_url()) |
109 | ->appendTo($feed); |
110 |
111 | foreach($posts as $p){ |
112 |
113 | $item = new Item(); |
114 | $item |
115 | ->title($p->title) |
116 | ->description($p->body) |
117 | ->url($p->url) |
118 | ->appendTo($channel); |
119 | } |
120 |
121 | echo $feed; |
122 | } |
123 |
124 | // Turn an array of posts into a JSON |
125 | function generate_json($posts){ |
126 | return json_encode($posts); |
127 | } |
1 | RewriteEngine On |
2 |
3 | RewriteCond %{REQUEST_FILENAME} !-f |
4 | RewriteCond %{REQUEST_FILENAME} !-d |
5 |
6 | RewriteCond $1 !^(index\.php) |
7 | RewriteRule ^(.*)$ index.php/$1 [L] |