Print Logo Rumah Coding [Programming Quiz #2]

Berikut adalah Programming Quiz #2:

Tulis kode program untuk menampilkan output logo “Rumah Coding” menggunakan karakter asterik (*). Anda dapat menggunakan bahasa pemrograman apa saja.

Penjelasan:

Buatlah sebuah kode program lengkap (bisa diekesekusi) untuk menghasilkan output sederhana berupa versi teks dari logo Rumah Coding berikut.

Program yang dibuat tidak menggunakan library graphics apapun, hanya menggunakan karakter asterik (*). Jika diberikan input sebuah bilangan bulat n, maka program harus mengeluarkan output logo Rumah Coding dengan tinggi n dengan ketentuan sebagai berikut:

  • Jika n genap, maka tinggi atap dan tinggi dinding adalah n/2
  • Jika n ganjil, maka atap lebih tinggi satu satuan dari dinding.

Sedangkan lebar dinding memiliki ketentuan sebagai berikut:

  • Jika n adalah kelipatan 3, maka lebar dinding adalah n/3
  • Jika n bukan kelipatan 3, maka lebar dinding adalah ceil(n/3)

Berikut adalah contoh output yang benar:

  1. Jika n=8, maka hasilnya adalah seperti berikut:
            *
          * * *
        * * * * *
      * * * * * * *
    * * *       * * *
    * * *       * * *
    * * *       * * *
    * * *       * * *
    
  2. Jika n=9, maka hasilnya adalah seperti berikut:
            *
          * * *
        * * * * *
      * * * * * * *
    * * * * * * * * *
    * * *       * * *
    * * *       * * *
    * * *       * * *
    * * *       * * *
    

Untuk membantu anda memahami, anda bisa mencoba program yang sudah kami buat melalui link ini

https://apps.rumahcoding.co.id/rc.php?tinggi=8

Program tersebut dibuat menggunakan bahasa pemrograman PHP. Anda bisa mengganti parameter tinggi sesuai keinginan anda.

Nah, bisakah anda membuat kode programnya?

Ayo submit jawaban anda paling lambat tanggal 6 Mei 2017. Satu orang peserta yang beruntung akan mendapatkan 1 buah T-Shirt Ekslusive dari Rumah Coding.

 

Catatan:

  • Jawaban harus dikirim paling lambat tanggal  6 Mei 2017.
  • Penilaian jawaban berdasarkan keakuratan jawaban dan penjelasan logisnya.
  • Keputusan pemenang sepenuhnya menjadi hak Rumah Coding.
  • Pemenang akan diumumkan pada halaman ini, facebook dan twitter Rumah Coding pada tanggal 8 Mei 2017

Pemenang Programming Quiz #2

Setelah menelaah beberapa jawaban yang masuk, kami putuskan untuk memilih Prasasto Adi Wismoyo sebagai pemenang Programming Quiz #2.

Menukar Nilai Dua Variabel Menggunakan Operator XOR

Kebanyakan programmer ketika menukar nilai dua buah variabel, misal variabel x dan y membutuhkan bantuan variabel ketiga, seperti contoh berikut:

tmp = x
x = y
y = tmp

Akan tetapi ada sebuah trik yang sangat jitu. Trik ini memungkinkan anda menukar nilai dua buah variabel tanpa menggunakan variabel ketiga, yaitu dengan menggunkan operator XOR.

x = x ^ y
y = x ^ y
x = x ^ y

Anda bisa langsung mencobanya menggunakan bahasa pemrograman apa saja. Cara ini bisa digunakan untuk menukar nilai variabel yang bertipe integer ataupun string. Kode tersebut bekerja hampir seperti sihir. Dua buah nilai secara ajaib tertukar, tanpa anda tahu apa yang sebenarnya terjadi. Baiklah saya akan bahas cara kerja operator XOR hingga bisa menukar nilai dua variabel.

Cara Kerja

Untuk membantu memahami trik ini, saya gunakan variabel lain untuk menampung hasil dari operasi XOR

x1 = x ^ y
y1 = x1 ^ y
x2 = x1 ^ y1

Berdasarkan kode sebelumnya, x2 memiliki nilai yang sama dengan y. Mari kita buktikan:

x2 = x1 ^ y1
x2 = x1 ^ (x1 ^ y)   // subtitusi y1
x2 = (x1 ^ x1) ^ y   // operasi xor bersifat asosiatif
x2 = 0 ^ y         // a ^ a hasilnya adalah 0
x2 = y           // 0 ^ a hasilnya a, sehingga nilai x2 sama dengan nilai y

Terbukti bahwa nilai x2 sama dengan nilai y. Itu artinya proses penukaran nilai berhasil. Sekarang kita buktikan juga untuk variabel y1. Berdasarkan kode sebelumnya, nilai y1 seharusnya sama dengan nilai x.

y1 = x1 ^ y
y1 = (x ^ y) ^ y
y1 = x ^ (y ^ y)
y1 = x ^ 0
y1 = x                  // y1 sama dengan nilai x

Terbukti bahwa nilai y1 sama dengan nilai x. Selamat mencoba

Workshop#6: Membuat Aplikasi Android Untuk Pemula

Setiap bulan, Rumah Coding mengadakan workshop untuk umum. Pada workshop ke-6 kali ini, Rumah Coding mengadakan workshop bertema “Membuat Aplikasi Android Untuk Pemula”.

Tertarik membuat aplikasi android tapi tidak tau harus memulai dari mana? Jangan khawatir, Rumah Coding kembali akan mengadakan pelatihan/workshop android bertema “Membuat Aplikasi Android Untuk Pemula”. Pada pelatihan ini teman-teman akan diajarkan dasar-dasar pembuatan aplikasi android.

Materi yang akan di bahas, antara lain:
– Activity
– Layout dan View
– Resource
– Menu
– List View
– Custom List Adapter
– SqLite

Hari: Minggu,
Tanggal: 30 April 2017
Waktu: 09:00 – 17:00
Tempat: DILo (Digital Innovation Longue ) Depok
Jl. Margonda Raya No. 23 (Rukan Sebelah BPJS Kesehatan Kota Depok),
Kel. Depok, Kec. Pancoran MAS, Depok, Pancoran MAS, Kota Depok, Jawa Barat 16431
https://goo.gl/maps/2cb1AZBRGZQ2

Biaya Workshop: Gratis

Persyaratan:
1. Memiliki laptop sendiri (Windows/Linux/Mac 4GB RAM)

Persyaratan Software:
1. JDK 7
2. Android Studio
3. Geny Motion

Tahap pendaftaran:
1. Mengisi formulir di bawah.
2. Peserta akan dihubungi melalui email/whatsapp
3. Workshop.

Catatan:
– Tersedia koneksi internet, tetapi untuk berjaga-jaga, silahkan mempersiapkan koneksi internet masing-masing.

Informasi:
087876335618
[email protected]

Update:

Saat ini, quota peserta sudah full. Anda tetap bisa mengisi form di bawah ini, kami akan mengabarkan via email jika ada workshop berikutnya.

Silahkan lengkapi formulir pendaftaran di bawah ini:

[Case Closed] Tukar Nilai Dua Variabel Tanpa Variabel Ketiga [Programming Quiz #1]

Berikut adalah Programming Quiz #1:

Tulis kode program untuk menukar nilai dua variable tanpa bantuan variabel ketiga. Anda bisa menggunakan bahasa pemrograman apa saja.

Penjelasan:

Misalkan anda memiliki 2 variabel A = 6 dan B = 7. Kemudian anda ingin menukar kedua nilai tersebut, sehingga A = 7 dan B = 6. Normalnya, kita membutuhkan bantuan variabel ketiga, misal variabel C. Berikut adalah potongan kode untuk menukar nilai A dan B dengan bantuan variabel C.

int A = 6;
int B = 7;

int C = A;
A = B;
B = C;

Nah, bagaimana caranya agar bisa menukar nilai A dan B tanpa bantuan variabel tambahan?

Ayo submit jawaban anda paling lambat tanggal 21 April 2017. Peserta yang beruntung akan mendapatkan 1 buah T-Shirt Ekslusive dari Rumah Coding.

Catatan:

  1. Jawaban harus dikirim paling lambat tanggal  21 April 2017.
  2. Penilaian jawaban berdasarkan keakuratan jawaban dan penjelasan logisnya.
  3. Keputusan pemenang sepenuhnya menjadi hak Rumah Coding.
  4. Pemenang akan diumumkan pada halaman ini, facebook dan twitter Rumah Coding pada tanggal 24 April 2017


Pemenang Programming Quiz #1

Setelah menelaah beberapa jawaban yang masuk, kami putuskan untuk memilih Tedi Sanubari sebagai pemenang Programming Quiz #1. Dari jawaban yang masuk, semua berporos pada 3 jawaban berikut:

1. Manipulasi Aljabar

a = a + b;
b = a - b;
a = a - b;

Ini adalah jawaban yang benar, akan tetapi kami tidak memilih jawaban ini dikarenakan hanya dapat digunakan untuk tipe data number (int). Walaupun bisa digunakan untuk menukar tipe data String, akan tetapi mengikutsertakan banyak fungsi built-in seperti length dan substring.

2. Penggunaan fungsi built in untuk menukar

[a,b] = [b,a];

Ini juga jawaban yang benar, akan tetapi kami tidak memilih jawaban ini dikarenakan penggunaan penggunaan fungsi built in pada bahasa pemrograman tertentu, misal python dan javascript. Kode tersebut tidak akan bekerja pada bahasa pemrograman yang lain.

3. Penggunaan Operator XOR
Dan inilah jawaban yang kami pilih, karena keunikannya. Walaupun ada beberapa yang menjawab menggunakan operator XOR, akan tetapi kami memilih penjelasan yang paling lengkap dan logis. Untuk mengetahui jawaban dan penjelasan detail, silahkan baca posting berikut Menukar Nilai Dua Variabel Menggunakan Operator XOR

Menampilkan Data dari MySQL ke Dalam List View Pada Android Menggunakan PHP

Pada tutorial ini, anda akan belajar membuat sebuah aplikasi android sederhana yang menggunakan List View. Data yang akan ditampilkan adalah kumpulan aplikasi android yang populer di Play Store lengkap dengan icon, total download dan data rating dari masing-masing aplikasi. Data total download dan rating yang kita gunakan dalam tutorial ini bukan merupakan data asli, akan tetapi hanya berupa data dumi untuk tujuan demo.

Data dumi tersebut akan disimpan dalam database MySQL. Kemudian anda juga akan membuat script PHP yang akan mengambil data dumi tadi dari database MySQL. Aplikasi android yang anda buat kemudian memanggil script PHP tadi untuk mengambil data dumi dalam format JSON (Javascript Object Notation). Sebelum saya menjelaskan tahap-tahap pembuatan aplikasi tersebut. Saya akan menjelaskan terlebih dahulu konsep-konsep dasar yang perlu anda pahami.

 

Mengenal JSON

JSON (Javascript Object Notation) merupakan format pertukaran data. Sebuah objek JSON merupakan kumpulan dari pasangan key dan value yang diawali dengan tanda “{” dan diakhiri dengan tanda “}”. Berikut ini adalah contoh sebuah objek JSON yang akan anda gunakan dalam tutorial ini.

var json = {
    'title' : 'Facebook',
    'rating' : 5,
    'total_dl' : 10990998,
    'icon' : 'facebook'
};

Sebuah array dari JSON merupakan serangkaian object JSON. Di bawah ini merupakan contoh array dari beberapa objek JSON di atas.

var json = [
    {'title' : 'Facebook',
    'rating' : 5,
    'total_dl' : 10990998,
    'icon' : 'facebook'},
    {'title' : 'Twitter',
    'rating' : 5,
    'total_dl' : 12343487,
    'icon' : 'twitter'},
    {'title' : 'Whatsapp',
    'rating' : 4,
    'total_dl' : 5635989,
    'icon' : 'whatsapp'}
    ];

 

Konsep Dasar

 

As I’ve stated before, we’ll create simple android application that show a list of top application. We use android list view to display the data. The list data come from MySQL server. So this application will have a http connection feature. Communication between server and android application is use JSON based data. In this tutorial we’ll use apached server in localhost that running AVD (Android Virtual Device).
The data that are fetched from server including applicatoin title, rating, total download and icon name. For simplicity of the tutorial, we’ll use an icons that are saved in /res/drawable folder for applications. This will reduce the complexity of downloading the icons from server.
Below is final screenshot of our tutorial

Populate Listview Using JSON
Populate Listview Using JSON

Server Side Task

1. Creating A Database in MySQL

Before creating a database in MySQL, make sure you’ve create a user to login into the MySQL server. In this tutorial, we use a default user root with blank password.
We’ll create a simple database scheme for the application. The database will be used to store application data. Execute the following sql to create such database.

CREATE DATABASE apps;

Now, we have a database apps. We need to create a table in database apps that will store the application title, total download, rating and icon file name. Execute the following sql to create the table.

CREATE TABLE `app_data`(
    `id` int unsigned NOT NULL AUTO_INCREMENT,
    `app_title` varchar(150) NOT NULL,
    `total_dl` int unsigned NOT NULL default 0,
    `rating` int unsigned NOT NULL default 0,
    `icon` varchar(120) NOT NULL,
    primary key(`id`)
);

Now, we must put sample application data into the table. Execute the following sql to create sample application data.

INSERT INTO app_data VALUES(null, "Facebook", 20099099, 5, "facebook");
INSERT INTO app_data VALUES(null, "Twitter", 11342099, 5, "twitter");
INSERT INTO app_data VALUES(null, "Google +", 10123023, 4, "google");
INSERT INTO app_data VALUES(null, "Whatsapp", 10033876, 3, "whatsapp");
INSERT INTO app_data VALUES(null, "Youtube", 10023444, 4, "youtube");
INSERT INTO app_data VALUES(null, "Line", 9023434, 5, "line");
INSERT INTO app_data VALUES(null, "Kakao Talk", 8247836, 3, "kakao");
INSERT INTO app_data VALUES(null, "Linked In", 784736, 4, "linkedin");
INSERT INTO app_data VALUES(null, "Angry Bird", 693847, 2, "angrybird");
INSERT INTO app_data VALUES(null, "Skype", 528374, 3, "skype");

 

2. Create PHP Script to Fetch the Data

The database now ready, we need create a PHP script that connect to MySQL server and get the application data. Then the application data is converted into JSON string that will send into client (android application). This script use user root with blank password to login into MySQL server, you can change them to meet your server account.

<?php
$host = "localhost"; // host of MySQL server
$user = "root"; // MySQL user
$pwd = ""; // MySQL user's password
$db = "apps"; // database name

// Create connection
$con = mysqli_connect($host, $user, $pwd, $db);

// Check connection
if(mysqli_connect_errno($con)) {
    die("Failed to connect to MySQL: " . mysqli_connect_error());
} 

// query the application data
$sql = "SELECT * FROM app_data ORDER By id";
$result = mysqli_query($con, $sql);

// an array to save the application data
$rows = array();

// iterate to query result and add every rows into array
while($row = mysqli_fetch_array($result, MYSQLI_ASSOC)) {
    $rows[] = $row; 
}

// close the database connection
mysqli_close($con);

// echo the application data in json format
echo json_encode($rows);

Save above source as PHP file and give a name apps.php and you must place it in apache document root, for example http://localhost/test/apps.php.

3. Testing PHP Script in A Browser

We must test the PHP script we’ve created to make sure the script works well. Open your browser and goto http://localhost/test/apps.php (the url may depend on your environtment). If the script works well, you’ll see the following result in your browser.

JSON In Browser
JSON In Browser

Client Side Task (Android Application)

After the server side is ready and tested, now we’ll create an android application that will create a http request to PHP script that we’ve created previously to get all application data and display the data in a list view. In order to display all of data like application title, total downloads, rating and icon, we must create a custom adapter for the list view.
Open your Eclipse IDE and create new android application. Use JsonDemo as the project’s name.
Do the following step by step to create the application.

1. Create Main Layout File

This file is an xml layout file that defines the main user interface. It contains a list view that will display all of the application data.
Save below source code as /res/layout/activity_main.xml.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" >

    <ListView android:id="@android:id/list" android:layout_width="match_parent" android:layout_height="wrap_content" >
    </ListView>

</LinearLayout>

 

2. Create Custom List View Layout File

This file is an xml layout file. It responsibles to define a custom view the list view that is contained in the main layout. This file will be used in the custom adapter that will be defined later. The layout contains 3 TextView and 1 ImageView. The image view is used to display the application icon. It is placed on the left. First text view is used to display application’s title. It is placed on the right of the icon. Second text is used to display application’s rating. It is placed on the bottom application’s title. The last text view is used to display the application’ total download.
Save below source code as /res/layout/app_custom_list.xml.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" >

    <ImageView android:id="@+id/appIcon" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:layout_marginLeft="3dp" android:layout_marginTop="3dp" android:src="@drawable/facebook" />
    <TextView android:id="@+id/titleTxt" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignTop="@id/appIcon" android:layout_toRightOf="@id/appIcon" android:layout_marginLeft="3dp" android:text="Application Title" android:textSize="22dp"/>

    <LinearLayout android:id="@+id/ratingCntr" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toRightOf="@id/appIcon" android:layout_below="@id/titleTxt" android:layout_marginLeft="5dp" >
    </LinearLayout>

    <TextView android:id="@+id/dlTxt" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/titleTxt" android:layout_alignParentRight="true" android:layout_marginRight="3dp" android:text="0 dl" />    

</RelativeLayout>

 

3. Create Application Value Object File

This file is a java object class that represents an application value object. It has several properties that are mapped from the app_data table from our database. It has properties such as application name, total downloads, rating and icon. Below is definition of the file. Below is the source code that define application value object. Save it as /src/com/sj/jsondemo/Application.java.

package com.sj.jsondemo;

public class Application {
    private String title;
    private long totalDl;
    private int rating;
    private String icon;
    
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
    public long getTotalDl() {
        return totalDl;
    }
    public void setTotalDl(long totalDl) {
        this.totalDl = totalDl;
    }
    public int getRating() {
        return rating;
    }
    public void setRating(int rating) {
        this.rating = rating;
    }
    public String getIcon() {
        return icon;
    }
    public void setIcon(String icon) {
        this.icon = icon;
    }
}

 

4. Create Custom Adapter File

This file is list view’s custom adapter that will inflate /res/layout/app_custom_list.xml layout file. It’s constructor is defined with 1 parameter. The parameter is an array list of application value object. The adapter will inflates the layout for each application object in the array list and change the application title, rating, total downloads and icons dynamically.
Below is source code that defines the custom adapter. Save it as /src/com/sj/jsondemo/ApplicationAdapter.java.

package com.sj.jsondemo;

import java.text.NumberFormat;
import java.util.List;

import android.content.Context;
import android.content.res.Resources;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

public class ApplicationAdapter extends ArrayAdapter<Application>{
    private List<Application> items;
    
    public ApplicationAdapter(Context context, List<Application> items) {
        super(context, R.layout.app_custom_list, items);
        this.items = items;
    }
    
    @Override
    public int getCount() {
        return items.size();
    }
    
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View v = convertView;
        
        if(v == null) {
            LayoutInflater li = LayoutInflater.from(getContext());
            v = li.inflate(R.layout.app_custom_list, null);            
        }
        
        Application app = items.get(position);
        
        if(app != null) {
            ImageView icon = (ImageView)v.findViewById(R.id.appIcon);
            TextView titleText = (TextView)v.findViewById(R.id.titleTxt);
            LinearLayout ratingCntr = (LinearLayout)v.findViewById(R.id.ratingCntr);
            TextView dlText = (TextView)v.findViewById(R.id.dlTxt);
            
            if(icon != null) {
                Resources res = getContext().getResources();
                String sIcon = "com.sj.jsondemo:drawable/" + app.getIcon();
                icon.setImageDrawable(res.getDrawable(res.getIdentifier(sIcon, null, null)));
            }
            
            if(titleText != null) titleText.setText(app.getTitle());
            
            if(dlText != null) {
                NumberFormat nf = NumberFormat.getNumberInstance();
                dlText.setText(nf.format(app.getTotalDl())+" dl");            
            }
            
            if(ratingCntr != null && ratingCntr.getChildCount() == 0) {        
                /*
                 * max rating: 5
                 */
                for(int i=1; i<=5; i++) {
                    ImageView iv = new ImageView(getContext());
                    
                    if(i <= app.getRating()) {
                        iv.setImageDrawable(getContext().
                        getResources().getDrawable(R.drawable.start_checked));
                    }
                    else {                
                        iv.setImageDrawable(getContext().
                        getResources().getDrawable(R.drawable.start_unchecked));
                    }
                    
                    ratingCntr.addView(iv);
                }
            }
        }
        
        return v;
    }
}

 

5. Create An Async Task File To Get The Data From Server

This file responsibles to get all the application data by creating a http request to PHP script. It is defined by subclassed AsyncTask object class. This means the task will be execute in the background, so it never block the user interface. When the task is executed, a progress bar will be shown to make the interface user friendly. This file communicate to activity via a listener that we’ll create later. This communication is important because we need to notify the activity when all the data has been fetched.
Below is the source code that define the async task. Save it as /src/com/sj/jsondemo/FetchDataTask.java.

package com.sj.jsondemo;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.os.AsyncTask;

public class FetchDataTask extends AsyncTask<String, Void, String>{
    private final FetchDataListener listener;
    private String msg;
    
    public FetchDataTask(FetchDataListener listener) {
        this.listener = listener;
    }
    
    @Override
    protected String doInBackground(String... params) {
        if(params == null) return null;
        
        // get url from params
        String url = params[0];
        
        try {
            // create http connection
            HttpClient client = new DefaultHttpClient();
            HttpGet httpget = new HttpGet(url);
            
            // connect
            HttpResponse response = client.execute(httpget);
            
            // get response
            HttpEntity entity = response.getEntity();
            
            if(entity == null) {
                msg = "No response from server";
                return null;        
            }
         
            // get response content and convert it to json string
            InputStream is = entity.getContent();
            return streamToString(is);
        }
        catch(IOException e){
            msg = "No Network Connection";
        }
        
        return null;
    }
    
    @Override
    protected void onPostExecute(String sJson) {
        if(sJson == null) {
            if(listener != null) listener.onFetchFailure(msg);
            return;
        }        
        
        try {
            // convert json string to json array
            JSONArray aJson = new JSONArray(sJson);
            // create apps list
            List<Application> apps = new ArrayList<Application>();
            
            for(int i=0; i<aJson.length(); i++) {
                JSONObject json = aJson.getJSONObject(i);
                Application app = new Application();
                app.setTitle(json.getString("app_title"));
                app.setTotalDl(Long.parseLong(json.getString("total_dl")));
                app.setRating(Integer.parseInt(json.getString("rating")));  
                app.setIcon(json.getString("icon"));
                
                // add the app to apps list
                apps.add(app);
            }
            
            //notify the activity that fetch data has been complete
            if(listener != null) listener.onFetchComplete(apps);
        } catch (JSONException e) {
            msg = "Invalid response";
            if(listener != null) listener.onFetchFailure(msg);
            return;
        }        
    }
    
    /**
     * This function will convert response stream into json string
     * @param is respons string
     * @return json string
     * @throws IOException
     */
    public String streamToString(final InputStream is) throws IOException{
        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
        StringBuilder sb = new StringBuilder(); 
        String line = null;
        
        try {
            while ((line = reader.readLine()) != null) {
                sb.append(line + "\n");
            }
        } 
        catch (IOException e) {
            throw e;
        } 
        finally {           
            try {
                is.close();
            } 
            catch (IOException e) {
                throw e;
            }
        }
        
        return sb.toString();
    }
}

 

6. Create Fetch Data Listener

This file is simple Java interface. It has two method’s declarations, onFetchCompleted and onFetchFailure. onFetchCompleted method will be called from FetchDataTask when data fetching is complete. onFetchFailure will be called from FetchDataTask when data fetching is failure.
Save below source code as /src/com/sj/jsondemo/FetchDataListener.java.

package com.sj.jsondemo;

import java.util.List;

public interface FetchDataListener {
    public void onFetchComplete(List<Application> data);
    public void onFetchFailure(String msg);
}

 

7. Create Activity

This is main activity that will inflate /res/layout/activity_main.xml to create main user interface. When the activity is created, it’s create new FetchDataTask instance and call execute method of the instance. The task runs and start to get all application data in the background. Before execute the task, the activity show progress bar to the user to indicate that the system is loading the data.
This activity also implements FecthDataListener and overriden onFetchCompleted and onFetchFailure. onFetchFailure is used by activity to hide the progress bar and display failure message to user. onFetchCompleted is used by activity to hide the progress bar and display the application data into the list.
The apache server that we used is localhost which same as host that run AVD(Android Virtual Device), so to refers this host from AVD, we must use IP address 10.0.2.2. For more information please visit Android Developer Site.
Save below source code as /src/com/sj/jsondemo/MainActivity.java.

package com.sj.jsondemo;

import java.util.List;

import android.app.ListActivity;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.widget.Toast;

public class MainActivity extends ListActivity implements FetchDataListener{
    private ProgressDialog dialog;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);        
        setContentView(R.layout.activity_main);        
        initView();   
    }

    private void initView() {
        // show progress dialog
        dialog = ProgressDialog.show(this, "", "Loading...");
        
        String url = "http://10.0.2.2/test/apps.php";
        FetchDataTask task = new FetchDataTask(this);
        task.execute(url);
    }
    
    @Override
    public void onFetchComplete(List<Application> data) {
        // dismiss the progress dialog
        if(dialog != null)  dialog.dismiss();
        // create new adapter
        ApplicationAdapter adapter = new ApplicationAdapter(this, data);
        // set the adapter to list
        setListAdapter(adapter);        
    }

    @Override
    public void onFetchFailure(String msg) {
        // dismiss the progress dialog
        if(dialog != null)  dialog.dismiss();
        // show failure message
        Toast.makeText(this, msg, Toast.LENGTH_LONG).show();        
    }
}

8. Create Manifest File

The application make a http request, so the the manifest file must contains network usage permission. Below is complete manifest file. Save it as Android.Manifest.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.sj.jsondemo" android:versionCode="1" android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="17" />
    <uses-permission android:name="android.permission.INTERNET" />

    <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" >
        <activity android:name="com.sj.jsondemo.MainActivity" android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

Membuat Menu Navigasi Breadcrumb Menggunakan CSS3

Pada tutorial kali ini, kita akan sebuah menu navigasi breadcrumb menggunakan CSS3. Hasil akhir dari menu navigasi tersebut adalah seperti gambar di bawah ini:

Lihat video cara pembuatannya berikut ini:

Source Code

<html>
<head>
    <title>Pure CSS3 Breadcrumb Navigation Menu</title>    
    <style>
        /* Import custom font from google font*/
        @import url(http://fonts.googleapis.com/css?family=Noto+Serif); 

        body {
            font-family: 'Noto Serif', Verdana, Arial;	
            font-size:13px;	
            padding-top: 100px;
            text-align:center;
        }

        .breadcrumb {
            display:inline-block;
            box-shadow: 0 0 15px 1px rgba(0,0,0,0.6);
            border-radius: 5px;
            
            overflow:hidden;
            counter-reset:flag;
        }

        .breadcrumb a {
            display:block;
            float:left;
            
            text-decoration:none;
            padding: 0 10px 0 60px;
            
            line-height:36px;
            
            background: linear-gradient(#5DA6E1,#185282);
            color:white;
            
            position:relative;
        }

        .breadcrumb a.active, .breadcrumb a:hover {
            background: linear-gradient(#64D86A, #1D7521);
        }
                
        .breadcrumb a.active:after, .breadcrumb a:hover:after {
            background: linear-gradient(135deg,#64D86A, #1D7521);
        }

        .breadcrumb a:after {
            content:'';
            width: 36px;
            height:36px;
                            
            background:linear-gradient(135deg,#5DA6E1,#185282);
            
            position:absolute;
            top:0px;
            
            z-index:1;
            right:-18px;
            
            -webkit-transform: scale(0.707) rotate(45deg);
            -moz-transform: scale(0.707) rotate(45deg);
            -o-transform: scale(0.707) rotate(45deg);
            transform: scale(0.707) rotate(45deg);
            
            border-radius: 0 0 0 30px;
            
            box-shadow: 2px -2px 1px 1px rgba(0,0,0,0.5),
                3px -2px 1px 1px rgba(255,255,255,0.6);					
        }

        .breadcrumb a:last-child:after {
            content:none;
        }

        .breadcrumb a:last-child {
            padding-right:20px;
            border-radius: 0 5px 5px 0;
        }

        .breadcrumb a:before {
            content:counter(flag);
            counter-increment:flag;
            
            width: 20px;
            height:20px;
            
            background:#0E2F4A;
            font-weight:bold;
            
            position:absolute;
            top:0px;
            left:30px;
            
            line-height:20px;
            margin:8px 0;
            
            border-radius: 100%;
        }
    </style>
</head>
<body>
<div class="breadcrumb">
	<a href="#" class="active">Choose Product</a>
	<a href="#">Choose Color</a>
	<a href="#">Billing Address</a>
	<a href="#">Checkout</a>
</div>
</body>
</html>

Building Simple Image Slider Using Pure CSS3

CSS is an acronym for Cascading Style Sheets, it is used to format web page look. The latest version of CSS is CSS3. This new version of CSS gives web developers more flexibility when styling the webpage. It comes with a set of new rules that make CSS3 better than the old version. CSS3 provides way to create an animation. In this tutorial, we’ll build simple image slider using pure CSS3.

CSS Overview

Before we start into deep explanation to create the slider, I’ll give some overview of CSS feature that is used to create the slider.

  1. Transform Property
    The transform property applies a 2D or 3D transformation to an element. This property allows you to rotate, scale, move, skew, etc., elements.
  2. :target Selector
  3. URLs with an # followed by an anchor name, link to a certain element within a document. The element being linked to is the target element. The :target selector can be used to style the current active target element.

  4. :before and :after Selector
    The :before selector inserts content before the selected element(s). The :after selector inserts content after the selected element(s).
  5. ~ (Tilde Selector)
  6. Tilde selector also called general sibling combination. The general sibling combinator selector is very similar to the adjacent sibling combinator selector. The difference is that that the element being selected doesn’t need immediately succeed the first element, but can appear anywhere after it.

  7. Vendor Specific Property
    In order to make our slider runs cross browser, we must add vendor specific property by adding the following prefix into several CSS properties:

    • -moz-: Mozila Firefox
    • -webkit-: Safari, Chrome (and other WebKit-based browsers)
    • -ms-: Microsoft
    • -o-: Opera

Prepare the Stage

The stage of the slider is a div HTML tag where the slider takes place. We’ll create the stage which have 640px x 320px dimensions. The following HTML tags define the slider stage. We give id [cci]slider[/cci] to the stage.

<html>
<head>
    <title>CSS3 Image Slider</title>
</head>
<body>
    <div id="slider"></div>
</body>
</html>

Give Style to the Stage

After the stage has been created, now it’s time to give a style to the stage. At this step, we give dimension, margin, background and shadow to the stage.

#slider {
    width: 640px;
    height: 320px;
    margin: 50px auto 0;
    position: relative;
    background: #fff;

    /* give shadow to the stage*/
    box-shadow: 0px 0px 5px 0px rgba(0, 0, 0, 0.2);
    -moz-box-shadow: 0px 0px 5px 0px rgba(0, 0, 0, 0.2);
    -webkit-box-shadow: 0px 0px 5px 0px rgba(0, 0, 0, 0.2);
}

Now, our stage looks like below image.

Stage Preview
Stage Preview

Add Drop Shadow Effect at the Bottom of Stage

We’ll add a drop shadow effect to the stage at the bottom left and bottom right. The drop shadow that we used is simply a blank div element with the following style.

#slider:before, #slider:after {
    content: '';
    position: absolute;
    width: 60%;
    height: 20px;
    
    /* Adding shadow to this content*/
    -webkit-box-shadow: 0 8px 16px rgba(0, 0, 0, 0.5);
    -moz-box-shadow: 0 8px 16px rgba(0, 0, 0, 0.5);
    -ms-box-shadow: 0 8px 16px rgba(0, 0, 0, 0.5);
    -o-box-shadow: 0 8px 16px rgba(0, 0, 0, 0.5);        
    box-shadow: 0 8px 16px rgba(0, 0, 0, 0.5);
    
    /* Transform the content*/
    -webkit-transform: rotate(-4deg) skew(-10deg);
    -moz-transform: rotate(-4deg) skew(-10deg);
    -o-transform: rotate(-4deg) skew(-10deg);
    -ms-transform: rotate(-4deg) skew(-10deg);
    transform: rotate(-4deg) skew(-10deg);
    
    left: 10px;
    bottom: 13px;
    z-index: -1;
}

Move the second drop shadow to the right.

#slider:after {
    left: auto;
    right: 10px;
    
    -webkit-transform: rotate(4deg) skew(10deg);
    -moz-transform: rotate(4deg) skew(10deg);
    -o-transform: rotate(4deg) skew(10deg);
    -ms-transform: rotate(4deg) skew(10deg);
    transform: rotate(4deg) skew(10deg);
}

Now, the stage looks like below image:

Drop Shadow on Stage
Drop Shadow on Stage

Add Control Button

Control buttons is a set of buttons to control the slider. The button is used as a transition trigger for the slider. If user click a button, the slider will change the image on the stage.

<html>
<head>
    <title>CSS3 Image Slider</title>
</head>
<body>
    <div id="slider"></div>
    
    <!-- Control buttons! -->
	<ul>
		<li>
			<a href="#one"></a>
		</li>
		<li>
			<a href="#two"></a>
		</li>
		<li>
			<a href="#three"></a>
		</li>
		<li>
			<a href="#four"></a>
		</li>
		<li>
			<a href="#five"></a>
		</li>
	</ul>
</body>
</html>

Add style to control buttons.

#slider ul {
    width: 140px;
    height: 40px;
    padding: 0 0 0 0;
    position: absolute;
    z-index: 10;
    list-style: none;
    left: 50%;
    margin-left: -70px;
    bottom: -60px;
}

#slider ul li:first-child {
    margin-left: 16px;
}

#slider ul li {
    float: left;
    margin-right: 12px;
    margin-top: 14px;
}

#slider ul li:last-child {
    margin-right: 0;
}

#slider ul li a {
    width: 12px;
    height: 12px;
    display: block;
    outline: none;
    border: none;
    position: relative;
    z-index: 2;
    background: #aaa;
    
    box-shadow: inset 0 1px 1px 0px rgba(0, 0, 0, 0.6), 0px 1px 1px 0px white;
    -moz-box-shadow: inset 0 1px 1px 0px rgba(0, 0, 0, 0.6), 0px 1px 1px 0px white;
    -webkit-box-shadow: inset 0 1px 1px 0px rgba(0, 0, 0, 0.6), 0px 1px 1px 0px white;
    
    -webkit-border-radius: 50%;
    -moz-border-radius: 50%;
    border-radius: 50%;
}

#slider ul li a:hover {
    background: #888;
}

Now, our slider will look like image bellow.

Style Control Button
Style Control Button

Add images

Images is the heart of our slider. You can download the images we used in this tutorial by downloading source code. The donwload button is located on the top.

<html>
<head>
    <title>CSS3 Image Slider</title>
</head>
<body>
    <!-- Images -->
    <img id="one" src="1.jpg" />
	<img id="two" src="2.jpg" />
	<img id="three" src="3.jpg" />
	<img id="four" src="4.jpg" />
	<img id="five" src="5.jpg" />
    
    <div id="slider"></div>
    
    <!-- Control buttons! -->
	<ul>
		<li>
			<a href="#one"></a>
		</li>
		<li>
			<a href="#two"></a>
		</li>
		<li>
			<a href="#three"></a>
		</li>
		<li>
			<a href="#four"></a>
		</li>
		<li>
			<a href="#five"></a>
		</li>
	</ul>
</body>
</html>

Now, we give style to the images.

#slider img {
    position: absolute;
    left: 0;
    top: 0;
    opacity: 0;
    
    /* scale images*/
    -webkit-transform: scale(1.2);
    -moz-transform: scale(1.2);
    -ms-transform: scale(1.2);
    -o-transform: scale(1.2);
    transform: scale(1.2);
    
    /* set transition*/
    -webkit-transition: all .5s ease;
    -moz-transition: all .5s ease;
    -ms-transition: all .5s ease;
    -o-transition: all .5s ease;
    transition: all .5s ease;
}

Make The Image Slidding When Control Button Clicked

We’ll make the slider to change active image by using :target property

#slider img:target {
    opacity: 1;        
    -webkit-transform: scale(1);
    -moz-transform: scale(1);
    -ms-transform: scale(1);
    -o-transform: scale(1);
    transform: scale(1);
}
#slider img:not(:target){
    opacity: 0;
    
    -webkit-transform: scale(1.2);        
    -moz-transform: scale(1.2);        
    -ms-transform: scale(1.2);        
    -o-transform: scale(1.2);        
    transform: scale(1.2);        
}

Make The Control Buttons Selected When The Button Clicked

#one:target ~ ul li a[href="#one"],
#two:target ~ ul li a[href="#two"],
#three:target ~ ul li a[href="#three"],
#four:target ~ ul li a[href="#four"],
#five:target ~ ul li a[href="#five"] {
    background: #777;
}
#two:target ~ ul li a[href="#one"],
#three:target ~ ul li a[href="#one"],
#four:target ~ ul li a[href="#one"],
#one:target ~ ul li a[href="#one"] {
    background: #aaa;
}

Make First Image Appear When Page Loaded

#slider img#one {
    opacity: 1;
    -webkit-transform: scale(1);
    -moz-transform: scale(1);
    -ms-transform: scale(1);
    -o-transform: scale(1);
    transform: scale(1);
}
#slider ul li a[href="#one"] {
    background: #777;
}

Final Image Slider
Final Image Slider

Final Source Codes

Below the final source codes. Save it as HTML file and open it on your favorite browser.

<html>
<head>
    <title>CSS3 Image Slider</title>    
    <style>
    body {
        padding: 0;
        margin: 0;
        background: #ccc;
    }
    
    #slider {
        width: 640px;
        height: 320px;
        margin: 50px auto 0;
        position: relative;
        background: #fff;

        box-shadow: 0px 0px 5px 0px rgba(0, 0, 0, 0.2);
        -moz-box-shadow: 0px 0px 5px 0px rgba(0, 0, 0, 0.2);
        -webkit-box-shadow: 0px 0px 5px 0px rgba(0, 0, 0, 0.2);
    }

    #slider:before, #slider:after {
        content: '';
        position: absolute;
        width: 60%;
        height: 20px;
        
        -webkit-box-shadow: 0 8px 16px rgba(0, 0, 0, 0.5);
        -moz-box-shadow: 0 8px 16px rgba(0, 0, 0, 0.5);
        -ms-box-shadow: 0 8px 16px rgba(0, 0, 0, 0.5);
        -o-box-shadow: 0 8px 16px rgba(0, 0, 0, 0.5);        
        box-shadow: 0 8px 16px rgba(0, 0, 0, 0.5);
        
        -webkit-transform: rotate(-4deg) skew(-10deg);
        -moz-transform: rotate(-4deg) skew(-10deg);
        -o-transform: rotate(-4deg) skew(-10deg);
        -ms-transform: rotate(-4deg) skew(-10deg);
        transform: rotate(-4deg) skew(-10deg);
        
        left: 10px;
        bottom: 13px;
        z-index: -1;
    }

    #slider:after {
        left: auto;
        right: 10px;
        
        -webkit-transform: rotate(4deg) skew(10deg);
        -moz-transform: rotate(4deg) skew(10deg);
        -o-transform: rotate(4deg) skew(10deg);
        -ms-transform: rotate(4deg) skew(10deg);
        transform: rotate(4deg) skew(10deg);
    }

    #slider ul {
        width: 140px;
        height: 40px;
        padding: 0 0 0 0;
        position: absolute;
        z-index: 10;
        list-style: none;
        left: 50%;
        margin-left: -70px;
        bottom: -60px;
    }

    #slider ul li:first-child {
        margin-left: 16px;
    }

    #slider ul li {
        float: left;
        margin-right: 12px;
        margin-top: 14px;
    }

    #slider ul li:last-child {
        margin-right: 0;
    }

    #slider ul li a {
        width: 12px;
        height: 12px;
        display: block;
        outline: none;
        border: none;
        position: relative;
        z-index: 2;
        background: #aaa;
        
        box-shadow: inset 0 1px 1px 0px rgba(0, 0, 0, 0.6), 0px 1px 1px 0px white;
        -moz-box-shadow: inset 0 1px 1px 0px rgba(0, 0, 0, 0.6), 0px 1px 1px 0px white;
        -webkit-box-shadow: inset 0 1px 1px 0px rgba(0, 0, 0, 0.6), 0px 1px 1px 0px white;
        
        -webkit-border-radius: 50%;
        -moz-border-radius: 50%;
        border-radius: 50%;
    }

    #slider ul li a:hover {
        background: #888;
    }

    #slider img {
        position: absolute;
        left: 0;
        top: 0;
        opacity: 0;
        
        -webkit-transform: scale(1.2);
        -moz-transform: scale(1.2);
        -ms-transform: scale(1.2);
        -o-transform: scale(1.2);
        transform: scale(1.2);
        
        -webkit-transition: all .5s ease;
        -moz-transition: all .5s ease;
        -ms-transition: all .5s ease;
        -o-transition: all .5s ease;
        transition: all .5s ease;
    }

    #slider img:target {
        opacity: 1;        
        -webkit-transform: scale(1);
        -moz-transform: scale(1);
        -ms-transform: scale(1);
        -o-transform: scale(1);
        transform: scale(1);
    }
    
    #slider img#one {
        opacity: 1;
        -webkit-transform: scale(1);
        -moz-transform: scale(1);
        -ms-transform: scale(1);
        -o-transform: scale(1);
        transform: scale(1);
    }
    
    #slider img:not(:target){
        opacity: 0;
        
        -webkit-transform: scale(1.2);        
        -moz-transform: scale(1.2);        
        -ms-transform: scale(1.2);        
        -o-transform: scale(1.2);        
        transform: scale(1.2);        
    }

    #slider ul li a[href="#one"] {
        background: #777;
    }

    #one:target ~ ul li a[href="#one"],
    #two:target ~ ul li a[href="#two"],
    #three:target ~ ul li a[href="#three"],
    #four:target ~ ul li a[href="#four"],
    #five:target ~ ul li a[href="#five"] {
        background: #777;
    }

    #two:target ~ ul li a[href="#one"],
    #three:target ~ ul li a[href="#one"],
    #four:target ~ ul li a[href="#one"],
    #five:target ~ ul li a[href="#one"] {
        background: #aaa;
    }
    </style>
</head>
<body>
    <div id="slider">
	
	<!-- Images -->
	<img id="one" src="1.jpg" />
	<img id="two" src="2.jpg" />
	<img id="three" src="3.jpg" />
	<img id="four" src="4.jpg" />
	<img id="five" src="5.jpg" />
	
	<!-- Control buttons! -->
	<ul>
		<li>
			<a href="#one"></a>
		</li>
		<li>
			<a href="#two"></a>
		</li>
		<li>
			<a href="#three"></a>
		</li>
		<li>
			<a href="#four"></a>
		</li>
		<li>
			<a href="#five"></a>
		</li>
	</ul>
</div>
</body>
</html>

Creating Cool Animation Effect Using HTML5 Canvas

HTML5 is new technology that is developed as a replacement for current HTML standard. HTML5 brings so many improvement that not exists in current standard HTML. Canvas is one of the most important element of HTML5. This new element allows us to draw directly and manipulate any pixels on canvas. The canvas has a context that provides us cool high level API to help us when drawing onto canvas.

In this tutorial we’ll try to create a simple animation effect using HTML5 canvas. Although the animation we’ll create is just a simple animation, but it’s pretty cool to see. Here is a screenshot of the final animation. If you want to see it lives, you can see the final animation by clicking Live Preview button above.

Cool Animation Effect
Cool Animation Effect

Basic Idea

When you see the animation, may be you think it’s difficult to create such animation. As I stated before, this is simple and easy to create the animation like that. The idea is creating invisible particles with random location on the canvas then move every particles randomly. As the particles moved, we check the distance between particles, if the distances is less than, say 230 pixels, we create random color line. Then the logic is repeated.

Define Canvas Object

We’ll work on HTML5 canvas, so we must define it first.

<div style="width:800px;padding-top:20px; margin:0 auto;">
    <canvas id="canvas" width="800" height="500"></canvas>
</div>

The context of the canvas can be gotten by invoking [cci]getContext(‘2d’)[/cci] on canvas object. This will give us the 2d context.

// get canvas element
var canvas = document.getElementById('canvas');
if(!canvas.getContext) {
    alert("Your browser doesn't support html5");
    return;
}

// get drawing context
ctx = canvas.getContext("2d");

Define Particle Object

For simplicity and easy to manage the particles, we create a javascript object which represent a particle. Our particle has the following properties:

  1. Position
    Position property define the particle’s location on the canvas. It contains [cci]x[/cci] and [cci]y[/cci] variables which represent the particle’s coordinat on the canvas. The position property will be generated randomly.
  2. Radius
    Radius property defines the particle radius. Because we want to create an invisible particle, we’ll put [cci]0[/cci] as radius value.
  3. Speed
    Speed property determines how fast a particle can move
  4. Color
    Color property determines particle’s color. Because we want to create an invisible particle, this property will be used to color the line that connecting this particle with others. This property will be generated randomly
  5. Steering Angle
    Steering angle determines the particle’s movement direction. Steering angle has range from 0 to 360 and will be generated randomly.

Below is the particle object definition on Javascript:

// Particle object
var Particle = function() {
    // particle position
    this.x = Math.random()*width;
    this.y = Math.random()*height;
    
    // particle radius, 0 means invisible particle
    this.rad = 0;
    
    // particle speed
    this.speed = 4;
    
    // generate random particle color
    var r = Math.round(Math.random()*255);
    var g = Math.round(Math.random()*255);
    var b = Math.round(Math.random()*255);
    var a = Math.random();
    this.color = "rgba("+r+","+g+","+b+","+a+")";

    //particle steering angle, 0 to 360
    this.angle = Math.round(Math.random()*Math.PI*2);
};         

Variables [cci]width[/cci] and [cci]height[/cci] are respectively represent the canvas width and height. It is defined like this:

width = canvas.width;
height = canvas.height;

After the particle object definition is complete, we can populate a random particles by using this way:

// populate particles
for(var i=0; i< NUM_PARTICLES; i++) {
    particles.push(new Particle());
}

Variable [cci]NUM_PARTICLES[/cci] is global variable that defines the number of particle that will be generated.

Render The Particle

Now, we’ll add the rendering method for a particle. This method responsibles to render the particle that respect to the particle’ properties. This method also responsible to check the distance of the particle from another particles. If the distance is less than 230 pixels, the line will drawn connecting this particle to other.

// particle rendering method
this.render = function() {
    // render the particle
    ctx.beginPath();
    ctx.arc(this.x, this.y, this.rad, 0, 2*Math.PI, false);
    ctx.fillStyle = this.color;
    ctx.fill();
    
    // count distance from another particle
    // if the distance less than 230px, connect the particles with line                    
    for(var i=0; i<NUM_PARTICLES; i++) {
        var p2 = particles[i];                        
        var dx =  p2.x - this.x;
        var dy =  p2.y - this.y;
        // count the distance
        var distance = Math.sqrt(dx*dx + dy*dy);
        
        // if distance less than 230px, draw a line to connecting between two particles
        if(distance < 230) {
            ctx.beginPath();
            ctx.lineWidth = 1;
            ctx.moveTo(this.x, this.y);
            ctx.lineTo(p2.x, p2.y);
            ctx.strokeStyle = this.color;
            ctx.stroke();
        }
    }
};

Move The Particle

Our animation will be nonsense if the particles don’t move. We’ll give the particle ability to move by adding a function that handle the movement into particle object. This function uses a simple vector operation to move the particles. The [cci]x[/cci] coordinat property will be increased by the speed multiplied by the cosinus of steering angle. The [cci]y[/cci] coordinat property will be increased by the speed multiplied by the sinus of steering angle. Because the particles is always move, there is a time when the particle reach the canvas border. To avoid the particles moves out of canvas, we’ll move the particles to opposite side when the border is reached.

// particle moving method
this.move = function(){
    this.x += this.speed*Math.cos(this.angle);
    this.y += this.speed*Math.sin(this.angle);
    
    //avoid particle to move out of canvas
    if(this.x < 0) this.x = width;
    if(this.y < 0) this.y = height;
    if(this.x > width) this.x = 0;
    if(this.y > height) this.y = 0;
};

Render The Canvas

We have our particle ready, now it’s time to render the canvas. Rendering the canvas means rendering all of the particles including the canvas background.

var render = function() {
    // render the background
    ctx.fillStyle = "rgba(0,0,0,0.1)";
    ctx.fillRect(0, 0, width, height);

    // render particles
    for(var i=0; i<NUM_PARTICLES; i++){
        var p = particles[i];
        p.render();
        p.move();
    }
};

Render Scheduling

To make the animation life, we must schedule to call [cci]render[/cci] method. We want to set FPS (Frame Per Second) to be 30, so we must set the interval to be [cci]1000/FPS ms[/cci]

// setup FPS = Frame Per Second
// render function will be called every 1000/FPS = 33 ms
setInterval(render, 1000/FPS);

Final Source Code

This is the final source code. Save it as html file and open it in your favorite browser.

<html>
    <head>
        <title>Cool Animation Effect Using HTML5 Canvas</title>
        <script type="text/javascript">
            // define FPS(Frame Per Second)
            var FPS = 30;
            // define number of particles in the system
            var NUM_PARTICLES = 20;
            
            // hold the canvas width and height
            var width, height;
            
            // hold the canvas context
            var ctx;
            
            // array of particles
            var particles = [];
            
            // Particle object
            var Particle = function() {
                // particle position
                this.x = Math.random()*width;
                this.y = Math.random()*height;
                
                // particle radius, 0 means invisible particle
                this.rad = 0;
                
                // particle speed
                this.speed = 4;
                
                // generate random particle color
                var r = Math.round(Math.random()*255);
                var g = Math.round(Math.random()*255);
                var b = Math.round(Math.random()*255);
                var a = Math.random();
                this.color = "rgba("+r+","+g+","+b+","+a+")";
        
                //particle steering angle, 0 to 360
                this.angle = Math.round(Math.random()*Math.PI*2);
                
                // particle rendering method
                this.render = function() {
                    // render the particle
                    ctx.beginPath();
                    ctx.arc(this.x, this.y, this.rad, 0, 2*Math.PI, false);
                    ctx.fillStyle = this.color;
                    ctx.fill();
                    
                    // count distance from another particle
                    // if the distance less than 230px, connect the particles with line                    
                    for(var i=0; i<NUM_PARTICLES; i++) {
                        var p2 = particles[i];                        
                        var dx =  p2.x - this.x;
                        var dy =  p2.y - this.y;
                        // count the distance
                        var distance = Math.sqrt(dx*dx + dy*dy);
                        
                        // if distance less than 230px, draw a line to connecting between two particles
                        if(distance < 230) {
                            ctx.beginPath();
                            ctx.lineWidth = 1;
                            ctx.moveTo(this.x, this.y);
                            ctx.lineTo(p2.x, p2.y);
                            ctx.strokeStyle = this.color;
                            ctx.stroke();
                        }
                    }
                };
                
                // particle moving method
                this.move = function(){
                    this.x += this.speed*Math.cos(this.angle);
                    this.y += this.speed*Math.sin(this.angle);
                    
                    //avoid particle to move out of canvas
                    if(this.x < 0) this.x = width;
                    if(this.y < 0) this.y = height;
                    if(this.x > width) this.x = 0;
                    if(this.y > height) this.y = 0;
                };
            };            
            var render = function() {
                // render the background
                ctx.fillStyle = "rgba(0,0,0,0.1)";
                ctx.fillRect(0, 0, width, height);

                // render particles
                for(var i=0; i<NUM_PARTICLES; i++){
                    var p = particles[i];
                    p.render();
                    p.move();
                }
            };
            window.onload = function() {
                // get canvas element
                var canvas = document.getElementById('canvas');
                if(!canvas.getContext) {
                    alert("Your browser doesn't support html5");
                    return;
                }

                width = canvas.width;
                height = canvas.height;

                // get drawing context
                ctx = canvas.getContext("2d");

                // populate particles
                for(var i=0; i< NUM_PARTICLES; i++) {
                    particles.push(new Particle());
                }

                // setup FPS = Frame Per Second
                // render function will be called every 1000/FPS = 33 ms
                setInterval(render, 1000/FPS);
            };
        </script>
    </head>
    <body>
        <div style="width:800px;padding-top:20px; margin:0 auto;">
             <canvas id="canvas" width="800" height="500"></canvas>
        </div>
    </body>
</html>

Drawing Mandelbrot Set on HTML5 Graphics Canvas

Mandelbrot set is a mathematical set of points whose boundary is a distinctive and easily recognizable two-dimensional fractal shape. The Mandelbrot set is defined over the complex number plane. The definition of the Mandelbrot set is simple but the structure of the set is really complex and beautiful.

Mandelbrot Set Overview

Mandelbrot set is defined mathematically as the set of values of c in the complex plane for which the orbit of 0 under iteration of the complex quadratic polynomial zn+1 = zn2 + c remains bounded. That is, a complex number c is part of the Mandelbrot set if, when starting with z0 = 0 and applying the iteration repeatedly, the absolute value of zn remains bounded however large n gets.

Below is the structure of the Mandelbrot set that is generated using our application.

Mandelbrot Set
Mandelbrot Set

HTML 5 Canvas Overview

HTML5 is the latest version of the standard HTML. It comes with new cool element, Canvas that allows you to draw directly and manipulate every single pixels in the canvas. A canvas is a rectangular area on an HTML page, and it is specified with the [cci][/cci] element. HTML5 currently is under development and not all browser support it yet.

We’ll not cover all the definition of cool function in the canvas. There are documentation of those over the web. We only give an attention to several functions that will be used in our tutorial.

Every canvas element has a graphics context that will be used to modify the pixel on the canvas. We’ll use [cci]2d[/cci] context. To get the context, use [cci]getContext[/cci] function of the canvas object.

var canvas = document.getElementById('thecanvas');
var ctx = canvas.getContext('2d');

The above code assumes that we have defined a canvas element which id [cci]thecanvas[/cci].

<canvas id="thecanvas" width="500" height="500"></canvas>

Our requirement is to get all the pixels data of the canvas and modify the color of the pixels. To get all pixels data, use [cci]getImageData[/cci] function of the context. The function has 4 arguments [cci]x[/cci],[cci]y[/cci],[cci]width[/cci] and [cci]height[/cci]. [cci]x[/cci] and [cci]y[/cci] arguments define the square top left position from which the pixels will be taken. [cci]width[/cci] and [cci]height[/cci] define the dimension of the square.

var imageData = ctx.getImageData(0, 0, 100, 100);
var pixels = imageData.data;

The variable [cci]pixels[/cci] above contains 100×100=10.000 pixels that is save in 1 dimension array. 1 pixels have 4 elements, red,green,blue and alpha component. So [cci]pixels[/cci] variable has 10.000×4 = 40.000 elements. 1 element pixel is an integer from 0 to 255.

We now can modify the pixels data. After the pixels have been modified, we must put the pixels back to canvas in order to our modification takes effect.

ctx.putImageData(imageData, 0, 0);

Drawing Mandelbrot Set on HTML 5 Canvas

Javascript doesn’t provides built in complex number data type. So, we have to define our complex number data type. For simplicity of the tutorial, we will represent any complex number in javascript object with two properties. The [cci]x[/cci] property represents the real part and [cci]y[/cci] property represents the imaginary part.

//define complex data type
var Complex = function(x, y) {
   this.x = x; // real part
   this.y = y; // imaginary part
};

//define new complex number 1+2i
var complex = new Complex(1,2);

We have now a simple complex number data type for our application. Before we start to code, remember from above explanation. The mandelbrot definition requires to use two operation on complex number. We’ll not define all number operations in complex number, but we’ll create only two operations, multiplication and addition that will be used in generating mandelbrot set.

//define two complex number
var a = 1, b = 2, c = 3, d = 4;
var complex1 = new Complex(a,b);
var complex1 = new Complex(c,d);

//add complex1 and complex1 will result
var addition = new Complex(a+c, b+d);

//multiply complex1 and complex 2 will result
var multiplication = new Complex(a*c - b*d, b*c + a*d);

 

The Mandelbrot Set Drawing Algorithm

We’ll use different approach from mandelbrot set definition to visualize the set. Rather than finding all complex numbers [cci]c[/cci] which is bounded, our goal is to colorize all of the pixels in the canvas based on number of iterations. This will result great visualization for mandelbrot set.

Step by Step Mandelbrot Set Drawing

  1. Define user interface. Our application will has simple user interface. It’ll contains color scheme selection box, a button and the canvas.
    Mandelbrot Generator Simple User Interface
    Mandelbrot Generator Simple User Interface

    Below is HTML tags that defines our simple user interface.

<html>
<head>
<title>Drawing Mandelbrot set on HTML5 graphics canvas</title>
</head>
<body onload="setupCanvas();">
    
<div style="margin:0 auto;width:505px;padding-top:10px;">

<div>Color Scheme:
        <select id="scheme">
<option value="1" selected>Color Scheme 1</option>
<option value="2">Color Scheme 2</option>
<option value="3">Color Scheme 3</option>
<option value="4">Color Scheme 4</option>
<option value="5">Color Scheme 5</option>
<option value="6">Color Scheme 6</option>
        </select>
        <input type="button" value="Render" id="render_btn" onclick="render()"/>
        Scroll your mouse on the canvas to zoomin/zoomout
        </div>

        <canvas style="border:1px solid;" id="thecanvas" width="500" height="500"></canvas>
    </div>

</body>
</html>

After the html page is loaded, immediately we call javascript function [cci]setupCanvas[/cci]. This function will checks whether the browser support html5 canvas then get canvas’s drawing context and save it as global variable [cci]ctx[/cci]. We’ll use the context to modify each pixels on the canvas.

  • Define [cci]setupCanvas[/cci] function.
         
    var setupCanvas = function() {
        canvas = document.getElementById('thecanvas');
        setupMouseListener();
    
        if (!canvas.getContext) {
            alert("I'm sorry, seems your browser not support HTML 5, try another browser.");
            return;
        }
           
        // get drawing context
        ctx = canvas.getContext('2d');
    };   
    
  • Define render function.
    In this function we get the selected color scheme in the selection box. Save the canvas size as global variables then define the scaling ratio from canvas coordinats to mandelbrot coordinats.

 

var render = function() {
    if (!canvas.getContext) return;
    
    //get color scheme
    var a = document.getElementById('scheme');
    colorScheme = parseInt((a.value || a.options[a.selectedIndex].value));
    
    //save canvas size into variable
    cw = canvas.width;
    ch = canvas.height;
    
    //define scaling ratio from canvas coordinat to mandlebort coordinat
    scaleX = (mx[1] - mx[0])/cw;
    scaleY = (my[1] - my[0])/ch;
    
    drawMandlebrot();
};
  • Define the [cci]drawMandelbrot[/cci] function.
    In this function, we iterate to each pixels in the canvas and find the iteration for each pixels then color the pixel based on number iterations.

    var drawMandlebrot = function() {
        if(isDrawing) return;
        
        isDrawing = true;
        
        var imageData = ctx.getImageData(0, 0, cw, ch);
        pixels = imageData.data;
        
        for(var x = 0; x < cw; x++) {
            for(var y = 0; y < ch; y++) {
                iteration = 0;
                // scale canvas coordinat to mandlebrot complex coordinat
                var x0 = scaleX*x + mx[0], y0 = scaleY*y + my[0];
                // define complex number c
                var c = new Complex(x0, y0), z = new Complex(0, 0);
                
                while(iteration < maxIteration) { // check if z still inbound if(z.x*z.x + z.y*z.y >= 2*2) {
                        break;
                    }
                    
                    // multiply z and z
                    z = new Complex(z.x*z.x - z.y*z.y, z.y*z.x + z.x*z.y);
                    // add z and c
                    z = new Complex(z.x+c.x, z.y+c.y);
                    // inrease iteration
                    iteration++;
                }
                
                // colorize current pixel
                setPixelColor(x, y, iteration);
            }
        }
        
        ctx.putImageData(imageData, 0, 0);
        isDrawing = false;
    };        
    
  • Define [cci]setPixelColor[/cci]
    This function will color the current pixels and get the color from [cci]getColor[/cci] function. [cci]getColor[/cci] function will generate a color based on number of iteration and selected color scheme.

    var getColor = function(i) {            
        i /= maxIteration;
        var cr = 0.0;
        var cg = 0.0;
        var cb = 0.0;
        
        switch(colorScheme) {
            case 1:
                if (i >= 0.66) cr = i;
                else if (i >= 0.33) cg = i;
                else cb = i;
                break;
            case 2:
                if (i >= 0.66) cr = i;
                else if (i >= 0.33) cb = i;
                else cg = i;
                break;
            case 3:
                if (i >= 0.66) cb = i;
                else if (i >= 0.33) cg = i;
                else cr = i;
                break;
            case 4:
                if (i >= 0.66) cg = i;
                else if (i >= 0.33) cr = i;
                else cb = i;
                break;
            case 5:
                if (i >= 0.66) cg = i;
                else if (i >= 0.33) cb = i;
                else cr = i;
                break;
            case 6:
                if (i >= 0.66) cb = i;
                else if (i >= 0.33) cr = i;
                else cg = i;
                break;
        };            
        
        var r = parseInt(cr * 3 * maxColor);
        var g = parseInt(cg * 3 * maxColor);
        var b = parseInt(cb * 3 * maxColor);
        return [r, g, b];
    };
    var setPixelColor = function(x, y, i) {
        var c = getColor(i);
        var off = 4 * (y * cw + x);
        pixels[off] = c[0]; //red
        pixels[off + 1] = c[1]; //green
        pixels[off + 2] = c[2]; //blue
        pixels[off + 3] = 255; //alpha
    };
    
  • Finally, add the zoom capability.
    var mouseWheelHandler = function(e) {
        // cross-browser wheel delta
        var e = window.event || e; // old IE support
        // get delta scroll
        var delta = Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail)));
        
        //get mouse position
        var mousePos = getMousePos(e);
        
        // scale canvas coordinat to mandlebrot complex coordinat
        var x0 = scaleX*mousePos.x + mx[0], y0 = scaleY*mousePos.y + my[0];
        
        //scale the mandelbrot coordinat size
        var scale = 1 - delta*zoomScale;
        var sizeX = (mx[1]-mx[0])*scale;
        var sizeY = (my[1]-my[0])*scale;
        
        // redefine mandelbrot boundaries
        mx = [x0-sizeX/2, x0+sizeX/2];
        my = [y0-sizeY/2, y0+sizeY/2];
        render();
    };        
    var getMousePos = function(evt) {
        var rect = canvas.getBoundingClientRect();
        return {
            x: evt.clientX - rect.left,
            y: evt.clientY - rect.top
        };
    };
    

Final Source Code

<html>
<head>
    <title>Drawing Mandelbrot set on HTML5 graphics canvas</title>
    <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cscript%20type%3D%22text%2Fjavascript%22%3E%0A%20%20%20%20%20%20%20%20var%20canvas%2C%20ctx%3B%0A%20%20%20%20%20%20%20%20var%20iteration%2C%20maxIteration%20%3D%20100%2C%20maxColor%20%3D%20255%3B%0A%20%20%20%20%20%20%20%20var%20cw%2C%20ch%2C%20scaleX%2C%20scaleY%3B%0A%20%20%20%20%20%20%20%20var%20zoomScale%20%3D%200.3%3B%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%2F%2F%20color%20schemes%0A%20%20%20%20%20%20%20%20var%20colorScheme%20%3D%201%3B%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%2F%2Fdefine%20mandlebort%20boundaries%0A%20%20%20%20%20%20%20%20var%20mx%20%3D%20%5B-2%2C2%5D%2C%20my%20%3D%20%5B-2%2C2%5D%3B%0A%20%20%20%20%20%20%20%20%2F%2F%20hold%20all%20pixels%20image%20data%0A%20%20%20%20%20%20%20%20var%20pixels%3B%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20var%20isDrawing%20%3D%20false%3B%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%2F%2Fdefine%20complex%20data%20type%0A%20%20%20%20%20%20%20%20var%20Complex%20%3D%20function(x%2C%20y)%20%7B%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20this.x%20%3D%20x%3B%20%2F%2F%20real%20part%0A%20%20%20%20%20%20%20%20%20%20%20%20this.y%20%3D%20y%3B%20%2F%2F%20imaginary%20part%0A%20%20%20%20%20%20%20%20%7D%3B%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20var%20setupCanvas%20%3D%20function()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20canvas%20%3D%20document.getElementById('thecanvas')%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20setupMouseListener()%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(!canvas.getContext)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alert(%22I'm%20sorry%2C%20seems%20your%20browser%20not%20support%20HTML%205%2C%20try%20another%20browser.%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20get%20drawing%20context%0A%20%20%20%20%20%20%20%20%20%20%20%20ctx%20%3D%20canvas.getContext('2d')%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20render()%3B%0A%20%20%20%20%20%20%20%20%7D%3B%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20var%20render%20%3D%20function()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(!canvas.getContext)%20return%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2Fget%20color%20scheme%0A%20%20%20%20%20%20%20%20%20%20%20%20var%20a%20%3D%20document.getElementById('scheme')%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20colorScheme%20%3D%20parseInt((a.value%20%7C%7C%20a.options%5Ba.selectedIndex%5D.value))%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2Fsave%20canvas%20size%20into%20variable%0A%20%20%20%20%20%20%20%20%20%20%20%20cw%20%3D%20canvas.width%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20ch%20%3D%20canvas.height%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2Fdefine%20scaling%20ratio%20from%20canvas%20coordinat%20to%20mandlebort%20coordinat%0A%20%20%20%20%20%20%20%20%20%20%20%20scaleX%20%3D%20(mx%5B1%5D%20-%20mx%5B0%5D)%2Fcw%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20scaleY%20%3D%20(my%5B1%5D%20-%20my%5B0%5D)%2Fch%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20drawMandlebrot()%3B%0A%20%20%20%20%20%20%20%20%7D%3B%0A%20%20%20%20%20%20%20%20var%20drawMandlebrot%20%3D%20function()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if(isDrawing)%20return%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20isDrawing%20%3D%20true%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20var%20imageData%20%3D%20ctx.getImageData(0%2C%200%2C%20cw%2C%20ch)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20pixels%20%3D%20imageData.data%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20for(var%20x%20%3D%200%3B%20x%20%3C%20cw%3B%20x%2B%2B)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20for(var%20y%20%3D%200%3B%20y%20%3C%20ch%3B%20y%2B%2B)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20iteration%20%3D%200%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20scale%20canvas%20coordinat%20to%20mandlebrot%20complex%20coordinat%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20var%20x0%20%3D%20scaleX*x%20%2B%20mx%5B0%5D%2C%20y0%20%3D%20scaleY*y%20%2B%20my%5B0%5D%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20define%20complex%20number%20c%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20var%20c%20%3D%20new%20Complex(x0%2C%20y0)%2C%20z%20%3D%20new%20Complex(0%2C%200)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20while(iteration%20%3C%20maxIteration)%20%7B%20%2F%2F%20check%20if%20z%20still%20inbound%20if(z.x*z.x%20%2B%20z.y*z.y%20%3E%3D%202*2)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20break%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20multiply%20z%20and%20z%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20z%20%3D%20new%20Complex(z.x*z.x%20-%20z.y*z.y%2C%20z.y*z.x%20%2B%20z.x*z.y)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20add%20z%20and%20c%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20z%20%3D%20new%20Complex(z.x%2Bc.x%2C%20z.y%2Bc.y)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20inrease%20iteration%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20iteration%2B%2B%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20colorize%20current%20pixel%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20setPixelColor(x%2C%20y%2C%20iteration)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20ctx.putImageData(imageData%2C%200%2C%200)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20isDrawing%20%3D%20false%3B%0A%20%20%20%20%20%20%20%20%7D%3B%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20var%20getColor%20%3D%20function(i)%20%7B%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20i%20%2F%3D%20maxIteration%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20var%20cr%20%3D%200.0%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20var%20cg%20%3D%200.0%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20var%20cb%20%3D%200.0%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20switch(colorScheme)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20case%201%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(i%20%3E%3D%200.66)%20cr%20%3D%20i%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20else%20if%20(i%20%3E%3D%200.33)%20cg%20%3D%20i%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20else%20cb%20%3D%20i%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20break%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20case%202%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(i%20%3E%3D%200.66)%20cr%20%3D%20i%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20else%20if%20(i%20%3E%3D%200.33)%20cb%20%3D%20i%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20else%20cg%20%3D%20i%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20break%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20case%203%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(i%20%3E%3D%200.66)%20cb%20%3D%20i%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20else%20if%20(i%20%3E%3D%200.33)%20cg%20%3D%20i%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20else%20cr%20%3D%20i%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20break%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20case%204%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(i%20%3E%3D%200.66)%20cg%20%3D%20i%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20else%20if%20(i%20%3E%3D%200.33)%20cr%20%3D%20i%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20else%20cb%20%3D%20i%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20break%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20case%205%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(i%20%3E%3D%200.66)%20cg%20%3D%20i%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20else%20if%20(i%20%3E%3D%200.33)%20cb%20%3D%20i%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20else%20cr%20%3D%20i%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20break%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20case%206%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(i%20%3E%3D%200.66)%20cb%20%3D%20i%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20else%20if%20(i%20%3E%3D%200.33)%20cr%20%3D%20i%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20else%20cg%20%3D%20i%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20break%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%3B%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20var%20r%20%3D%20parseInt(cr%20*%203%20*%20maxColor)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20var%20g%20%3D%20parseInt(cg%20*%203%20*%20maxColor)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20var%20b%20%3D%20parseInt(cb%20*%203%20*%20maxColor)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20%5Br%2C%20g%2C%20b%5D%3B%0A%20%20%20%20%20%20%20%20%7D%3B%0A%20%20%20%20%20%20%20%20var%20setPixelColor%20%3D%20function(x%2C%20y%2C%20i)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20var%20c%20%3D%20getColor(i)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20var%20off%20%3D%204%20*%20(y%20*%20cw%20%2B%20x)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20pixels%5Boff%5D%20%3D%20c%5B0%5D%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20pixels%5Boff%20%2B%201%5D%20%3D%20c%5B1%5D%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20pixels%5Boff%20%2B%202%5D%20%3D%20c%5B2%5D%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20pixels%5Boff%20%2B%203%5D%20%3D%20255%3B%0A%20%20%20%20%20%20%20%20%7D%3B%0A%20%20%20%20%20%20%20%20var%20setupMouseListener%20%3D%20function()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(canvas.addEventListener)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20IE9%2C%20Chrome%2C%20Safari%2C%20Opera%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20canvas.addEventListener(%22mousewheel%22%2C%20mouseWheelHandler%2C%20false)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20Firefox%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20canvas.addEventListener(%22DOMMouseScroll%22%2C%20mouseWheelHandler%2C%20false)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20IE%206%2F7%2F8%0A%20%20%20%20%20%20%20%20%20%20%20%20else%20canvas.attachEvent(%22onmousewheel%22%2C%20mouseWheelHandler)%3B%0A%20%20%20%20%20%20%20%20%7D%3B%0A%20%20%20%20%20%20%20%20var%20mouseWheelHandler%20%3D%20function(e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20cross-browser%20wheel%20delta%0A%20%20%20%20%20%20%20%20%20%20%20%20var%20e%20%3D%20window.event%20%7C%7C%20e%3B%20%2F%2F%20old%20IE%20support%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20get%20delta%20scroll%0A%20%20%20%20%20%20%20%20%20%20%20%20var%20delta%20%3D%20Math.max(-1%2C%20Math.min(1%2C%20(e.wheelDelta%20%7C%7C%20-e.detail)))%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2Fget%20mouse%20position%0A%20%20%20%20%20%20%20%20%20%20%20%20var%20mousePos%20%3D%20getMousePos(e)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20scale%20canvas%20coordinat%20to%20mandlebrot%20complex%20coordinat%0A%20%20%20%20%20%20%20%20%20%20%20%20var%20x0%20%3D%20scaleX*mousePos.x%20%2B%20mx%5B0%5D%2C%20y0%20%3D%20scaleY*mousePos.y%20%2B%20my%5B0%5D%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2Fscale%20the%20mandelbrot%20coordinat%20size%0A%20%20%20%20%20%20%20%20%20%20%20%20var%20scale%20%3D%201%20-%20delta*zoomScale%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20var%20sizeX%20%3D%20(mx%5B1%5D-mx%5B0%5D)*scale%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20var%20sizeY%20%3D%20(my%5B1%5D-my%5B0%5D)*scale%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20redefine%20mandelbrot%20boundaries%0A%20%20%20%20%20%20%20%20%20%20%20%20mx%20%3D%20%5Bx0-sizeX%2F2%2C%20x0%2BsizeX%2F2%5D%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20my%20%3D%20%5By0-sizeY%2F2%2C%20y0%2BsizeY%2F2%5D%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20render()%3B%0A%20%20%20%20%20%20%20%20%7D%3B%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20var%20getMousePos%20%3D%20function(evt)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20var%20rect%20%3D%20canvas.getBoundingClientRect()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20x%3A%20evt.clientX%20-%20rect.left%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20y%3A%20evt.clientY%20-%20rect.top%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%3B%0A%20%20%20%20%20%20%20%20%7D%3B%0A%20%20%20%20%3C%2Fscript%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="&lt;script&gt;" title="&lt;script&gt;" />
</head>
<body onload="setupCanvas();">
    
<div style="margin:0 auto;width:505px;padding-top:10px;">

<div>Color Scheme:
        <select id="scheme">
<option value="1" selected>Color Scheme 1</option>
<option value="2">Color Scheme 2</option>
<option value="3">Color Scheme 3</option>
<option value="4">Color Scheme 4</option>
<option value="5">Color Scheme 5</option>
<option value="6">Color Scheme 6</option>
        </select>
        <input type="button" value="Render" id="render_btn" onclick="render()"/>
        Scroll your mouse on the canvas to zoomin/zoomout
        </div>

        <canvas style="border:1px solid;" id="thecanvas" width="500" height="500"></canvas>
    </div>

</body>
</html>