Advertisement
  1. Web Design
  2. Web Development

Canvas dari awal: Transformasi dan gradien

Scroll to top
Read Time: 11 min
This post is part of a series called Canvas From Scratch.
Canvas From Scratch: Advanced Drawing
Canvas From Scratch: Pixel Manipulation

() translation by (you can also view the original English article)

Dalam artikel ini, saya akan memandu Anda melalui transformasi di canvas, serta bayangan dengan gradien. Transformasi set metode yang memungkinkan Anda untuk mulai menjadi kreatif dengan cara Anda menggambar objek pada canvas yang sangat berharga. Mari kita mulai!


Menyiapkan

Anda akan menggunakan template HTML yang sama dari artikel sebelumnya, sehingga membuka editor favorit Anda dan paste kode berikut:

1
<!DOCTYPE html>
2
3
<html>
4
    <head>
5
        <title>Canvas from scratch</title>
6
        <meta charset="utf-8">
7
8
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
9
10
        <script>
11
            $(document).ready(function() {
12
                var canvas = document.getElementById("myCanvas");
13
                var ctx = canvas.getContext("2d");
14
            });
15
        </script>
16
    </head>
17
18
    <body>
19
        <canvas id="myCanvas" width="500" height="500">
20
            <!-- Insert fallback content here -->
21
        </canvas>
22
    </body>
23
</html>

Di sini kami memiliki tidak lebih dari halaman HTML dasar dengan canvas elemen dan beberapa JavaScript yang berjalan setelah DOM dimuat. Tidak ada yang gila.


Translation di Praktekan

Translate pada dasarny menggeser seluruh sistem koordinat.

Salah satu yang paling sederhana transformasi di canvas adalah translate. Hal ini memungkinkan Anda untuk memindahkan titik asal konteks rendering 2d; (0, 0) posisi di canvas. Biarkan saya menunjukkan kepada Anda apa artinya.

Pertama, tempatkan persegi di canvas di posisi (0, 0):

1
ctx.fillRect(0, 0, 100, 100);

Itu akan menarik sendiri di tepi kiri atas canvas. Masih - tidak ada yang luar biasa sini.

A simple squareA simple squareA simple square

Sekarang, coba menerjemahkan konteks rendering 2d dan menggambar persegi lain di posisi yang sama:

1
ctx.save();
2
ctx.translate(100, 100);
3
ctx.fillStyle = "rgb(0, 0, 255)";
4
ctx.fillRect(0, 0, 100, 100);
5
ctx.restore();

Apa yang Anda pikir akan terjadi? Memiliki bintang emas jika Anda menduga bahwa alun-alun baru akan ditarik pada posisi (100, 100). Tidak ada waktu bermain bagi mereka yang menduga salah. Maaf!

Translating a squareTranslating a squareTranslating a square

Jadi apa yang terjadi di sini kemudian? Sejauh sebagai kode untuk menggambar persegi kedua yang bersangkutan, Anda menarik di tempat yang sama sebagai kotak pertama. Alasan untuk ini adalah bahwa Anda pada dasarnya bergeser seluruh sistem koordinat canvas sehingga yang (0, 0) posisi adalah sekarang di tempat (100, 100).

How translation worksHow translation worksHow translation works

Apakah itu membuat sedikit lebih paham sekarang? Aku harap begitu. Ini dapat mengambil sedikit sementara untuk mendapatkan kepala Anda di sekitar, tapi itu adalah konsep yang sederhana sekali Anda mengerti.

Anda mungkin tidak menggunakan transformasi ini terlalu banyak pada sendiri, seperti yang Anda hanya bisa menggambar persegi kedua di (100, 100) untuk mendapatkan efek yang sama. Keindahan dari translate, meskipun, adalah bahwa Anda dapat menggabungkan dengan transformasi lain untuk melakukan beberapa hal yang keren.

Mari kita lihat pada transformasi berikutnya dalam daftar.


Scaling visual Anda

Seperti yang Anda mungkin sudah menebak, transformasi scale digunakan untuk mengubah ukuran. Lebih khusus lagi, transformasi skala digunakan untuk skala konteks rendering 2d.

Menghapus kode yang Anda bekerja pada dengan contoh translate, dan tambahkan kode berikut:

1
ctx.fillRect(100, 100, 100, 100);

Ini akan menggambar persegi standar pada posisi (100, 100), dengan lebar dan tinggi 100 piksel. Jadi bagaimana kita melakukan skala ini?

A simple squareA simple squareA simple square

Properti dalam skala adalah pengganda untuk x dan y dimensi.

Transformasi scale digunakan dalam cara yang sama untuk translate, yang dipanggil sebelum Anda menggambar objek yang Anda inginkan harus diterapkan. Hal ini penting untuk menunjukkan bahwa sifat dalam scale adalah pengganda untuk x dan y dimensi. Ini berarti bahwa scale (1, 1) akan menggandakan ukuran konteks rendering 2d dengan satu, meninggalkan itu ukuran yang sama sebelumnya. scale (5, 5) akan menggandakan ukuran konteks rendering 2d oleh lima, menjadikannya lima kali lebih besar daripada sebelumnya. Sederhana.

Dalam kasus Anda ingin dua kali lipat persegi, sehingga Anda menerapkan scale (2, 2):

1
ctx.save();
2
ctx.scale(2, 2);
3
ctx.fillRect(100, 100, 100, 100);
4
ctx.restore();

Yang menghasilkan sebuah persegi yang dua kali ukuran:

Scaling a squareScaling a squareScaling a square

Namun, perhatikan bagaimana persegi sekarang digambar dalam posisi yang berbeda daripada itu sedang ditarik sebelum Anda menerapkan scale. Alasan untuk ini adalah bahwa scale mengalikan ukuran dari segala sesuatu dalam konteks rendering 2d, termasuk koordinat. Dalam kasus Anda, posisi (100, 100) sekarang menjadi (200, 200); Koordinat yang dua kali ukuran bahwa mereka akan tanpa menjadi skala.

Untuk menyiasati hal ini, kita dapat melakukan translate yang menggerakan asal-usul konteks rendering 2d ke posisi yang Anda inginkan untuk menggambar persegi. Jika Anda kemudian menerapkan scale dan menggambar persegi di posisi (0, 0), posisinya tidak bergeser:

1
ctx.save();
2
ctx.translate(100, 100);
3
ctx.scale(2, 2);
4
ctx.fillRect(0, 0, 100, 100);
5
ctx.restore();

Yang menghasilkan persegi itu dua kali besar seperti yang asli, tapi yang diambil pada posisi yang sama seperti aslinya:

Scaling and translating squareScaling and translating squareScaling and translating square

Ini menjadi sadar kebiasaan ini sedikit dalam transformasi yang benar-benar membantu dengan menggunakan mereka. Sebagian besar masalah yang umum dengan transformasi tampaknya menjadi akibat dari tidak sepenuhnya memahami bagaimana mereka bekerja.


Elemen berputar

Sejauh ini, Semua transformasi yang Anda sudah berurusan dengan telah cukup tanpa kegirangan. Untungnya, rotate transformasi adalah di sini untuk menyelamatkan hari, dan mudah menjadi favorit saya.

Saya yakin rotasi tidah butuh pengenalan, jadi mari kita melompat tepat di dan rotate sebuah persegi 45 derajat (ingat bahwa derajat perlu di radian):

1
ctx.save();
2
ctx.rotate(Math.PI/4); // Rotate 45 degrees (in radians)

3
ctx.fillRect(100, 100, 100, 100);
4
ctx.restore();

Yang posisi persegi di (100, 100) dan berputar... woah, tunggu! Ini tidak terlihat benar:

Rotating a squareRotating a squareRotating a square

Lihat apa yang terjadi? persegi tampaknya mencoba untuk melarikan diri jendela browser, daripada berputar di tempat pada posisi (100, 100). Ini karena rotate, seperti semua transformasi, mempengaruhi seluruh 2d render konteks, dan bukan objek secara individual.

Berikut ini merupakan ilustrasi dari apa yang terjadi pada sistem koordinat ketika Anda melakukan 45 derajat memutar:

How rotation worksHow rotation worksHow rotation works

Perhatikan bagaimana seluruh sistem koordinat telah berputar 45 derajat dari titik asal (0, 0)? Ini adalah apa yang menyebabkan persegi yang terlihat seperti itu adalah melarikan diri jendela browser, hanya karena posisi (100, 100) telah diputar menampar bang di tepi browser.

Cara sederhana untuk mendapatkan sekitar masalah ini adalah untuk menggabungkan rotate dengan translate, seperti:

1
ctx.save();
2
ctx.translate(150, 150); // Translate to centre of square

3
ctx.rotate(Math.PI/4); // Rotate 45 degrees

4
ctx.fillRect(-50, -50, 100, 100); // Centre at the rotation point

5
ctx.restore();

Melakukan translate bergerak titik asal konteks rendering 2d (0, 0) untuk apa yang harus menjadi titik sentral dari persegi (150, 150). Ini berarti bahwa setiap rotasi akan sekarang didasarkan di sekitar posisi (150, 150). Jika Anda kemudian menggambar persegi dengan negatif x dan y posisi, setengah dari persegi yang lebar dan tinggi, Anda akan berakhir menggambar persegi yang terlihat seperti itu telah diputar di sekitar titik tengah:

Rotating and translating a squareRotating and translating a squareRotating and translating a square

Transformasi rotate adalah mungkin yang paling sulit dari mereka semua untuk memahami sepenuhnya. Penting untuk diingat bahwa transformasi dilakukan pada seluruh konteks rendering 2d, dan, jika Anda ingin memutar bentuk di sekitar titik pusat, Anda akan perlu untuk menggabungkan rotate dengan translate.

Mari kita beralih ke sesuatu yang sedikit lebih visual mengesankan.


Menambahkan bayangan

Menambahkan bayangan objek sangat sederhana.

Canvas datang disertakan dengan beberapa properti untuk memanipulasi tampilan objek yang tertarik di atasnya, dan satu set properti ini memungkinkan Anda untuk menambahkan bayangan.

Menambahkan bayangan pada objek sangat sederhana. Hal ini hanya membutuhkan properti shadowColor diatur pada konteks rendering 2d untuk warna yang tidak transparan hitam, dan salah satu properti shadowBlur, shadowOffsetX, atau shadowOffsetY untuk diatur ke nilai selain 0.

Mencoba kode berikut:

1
ctx.save();
2
ctx.shadowBlur = 15;
3
ctx.shadowColor = "rgb(0, 0, 0)";
4
ctx.fillRect(100, 100, 100, 100);
5
ctx.restore();

Ini akan memberikan bayangan kabur sebuah pixel lima belas, dan akan menetapkan warna ke hitam solid:

Adding a blurred shadowAdding a blurred shadowAdding a blurred shadow

Sesuatu yang standar sejauh ini

Jika Anda menetapkan shadowBlur 0, mengubah shadowColor untuk warna abu-abu, dan memberikan positif shadowOffsetX dan shadowOffsetY:

1
ctx.save();
2
ctx.shadowBlur = 0;
3
ctx.shadowOffsetX = 6;
4
ctx.shadowOffsetY = 6;
5
ctx.shadowColor = "rgba(125, 125, 125, 0.5)"; // Transparent grey

6
ctx.fillRect(300, 100, 100, 100);
7
ctx.restore();

Anda akan berakhir dengan bayangan padat yang muncul sedikit ke kanan, dan obyek yang telah digambar di bawah ini:

Adding a solid shadowAdding a solid shadowAdding a solid shadow

Sebagai keren seperti bayangan, mereka dapat menjadi sedikit memonopoli resource.

Hal ini penting untuk diingat bahwa bayangan mempengaruhi segala sesuatu yang diambil setelah mereka didefinisikan, sehingga sangat berguna untuk menggunakan save dan restore metode untuk menyimpan Anda dari keharusan untuk me-reset properti bayangan setelah Anda telah menggunakan mereka.

Perlu diingat bahwa kinerja dapat menderita bila Anda menerapkan bayangan untuk banyak dan banyak objek pada waktu yang sama. Dalam beberapa kasus, mungkin layak menggunakan gambar PNG dengan bayangan menggambar objek secara manual dan menerapkan bayangan dinamis menggunakan kode. Kita akan membahas bagaimana menggunakan gambar dengan canvas dalam bagian berikutnya dari seri ini.


Membuat gradien

Anda dapat membuat dua jenis gradien di canvas - linear dan radial.

Fitur terakhir yang saya inginkan untuk dibahas dengan Anda dalam tutorial ini adalah gradien. Ada dua jenis gradien dalam kanvas, yang pertama linear (lurus) gradien. Anda dapat membuat gradien linier menggunakan metode createLinearGradient (cukup mengejutkan), yang tampak seperti ini dalam pseudo kode:

1
ctx.createLinearGradient(startX, startY, endX, endY);

Set pertama dua argumen x dan y posisi awal gradien, dan set kedua argumen x dan y posisi akhir gradien. Hal ini juga penting untuk menunjukkan bahwa gradien di canvas adalah sebenarnya jenis nilai warna, sehingga Anda menerapkan properti fillStyle dan strokeStyle.

Berikut adalah contoh bagaimana membuat gradien linier yang berjalan di atas canvas, semua jalan ke bawah:

1
var gradient = ctx.createLinearGradient(0, 0, 0, canvas.height);
2
gradient.addColorStop(0, "rgb(255, 255, 255)");
3
gradient.addColorStop(1, "rgb(0, 0, 0)");
4
5
ctx.save();
6
ctx.fillStyle = gradient;
7
ctx.fillRect(0, 0, canvas.width, canvas.height);
8
ctx.restore();

Perhatikan bagaimana Anda menetapkan gradien ke variabel, kemudian gunakan variabel untuk memanggil metode addColorStop. Metode ini memungkinkan Anda untuk mengatur warna pada titik-titik tertentu sepanjang gradien. Sebagai contoh, posisi 0 akan mewakili awal gradien (pertama x dan y posisi), dan 1 akan mewakili penghujung gradien (kedua x dan y posisi). Anda juga dapat menggunakan titik desimal antara 0 dan 1 untuk menetapkan warna pada titik berbeda sepanjang gradien, seperti 0,5 akan setengah jalan.

Dengan menerapkan variabel gradien fillStyle properti, Anda berakhir dengan gradien bagus yang berlangsung dari putih (di posisi 0 di atas canvas), menjadi hitam (pada posisi 1 di bawah kanvas):

Creating a linear gradientCreating a linear gradientCreating a linear gradient

Tapi Anda tidak selalu harus menggunakan gradien linear; Anda juga dapat membuat gradien radial!

Gradien radial tidaklah diciptakan dengan createRadialGradient metode, yang terlihat seperti ini dalam pseudo kode:

1
ctx.createRadialGradient(startX, startY, startRadius, endX, endY, endRadius);

Set pertama tiga argumen yang x dan y posisi serta radius lingkaran pada awal gradien, dengan tiga argumen terakhir mewakili x dan y posisi serta radius lingkaran pada akhir gradien.

Terdengar membingungkan, kan? Itu sedikit, jadi mari kita melompat dan membuat gradien radial untuk melihat apa yang terjadi:

1
var gradient = ctx.createRadialGradient(350, 350, 0, 50, 50, 100);
2
gradient.addColorStop(0, "rgb(0, 0, 0)");
3
gradient.addColorStop(1, "rgb(125, 125, 125)");
4
5
ctx.save();
6
ctx.fillStyle = gradient;
7
ctx.fillRect(0, 0, canvas.width, canvas.height);
8
ctx.restore();

Anda telah membuat gradien radial yang memiliki titik awal di (350, 350) dengan radius 0, dan titik akhir di (50, 50) dengan radius 100. Dapatkah kamu menebak apa yang ini akan terlihat seperti? 20 poin jika Anda menebak itu akan terlihat seperti ini:

Creating a radial gradientCreating a radial gradientCreating a radial gradient

Jika Anda seperti saya, itulah tidak apa yang saya harapkan untuk melihat. Saya telah menggunakan gradien radial tidaklah sebelum di aplikasi seperti Adobe Photoshop, dan mereka terlihat tidak seperti itu! Jadi mengapa tidak itu terlihat seperti ini maka? Yah, itulah apa ini dimaksudkan untuk terlihat aneh.

Memeriksa ini diagram yang menggambarkan persis bagaimana gradien radial bekerja di canvas:

How radial gradients workHow radial gradients workHow radial gradients work

Menarik, bukan? Pada dasarnya memungkinkan Anda untuk membuat bentuk kerucut, tetapi bagaimana jika Anda ingin membuat gradien radial tepat seperti yang ada di Photoshop? Untungnya, ini sederhana.

Membuat gradien radial tepat hanya mengharuskan Anda untuk menempatkan dua lingkaran gradiasi persis sama x dan y posisi, pastikan bahwa salah satu lingkaran gradien lebih besar daripada yang lain:

1
var canvasCentreX = canvas.width/2;
2
var canvasCentreY = canvas.height/2;
3
4
var gradient = ctx.createRadialGradient(canvasCentreX, canvasCentreY, 250, canvasCentreX, canvasCentreY, 0);
5
gradient.addColorStop(0, "rgb(0, 0, 0)");
6
gradient.addColorStop(1, "rgb(125, 125, 125)");
7
8
ctx.save();
9
ctx.fillStyle = gradient;
10
ctx.fillRect(0, 0, canvas.width, canvas.height);
11
ctx.restore();

Kode di atas menciptakan gradien radial yang berada di tengah canvas. Salah satu lingkaran di gradien memiliki radius 0, sementara yang lain memiliki radius 250. Hasilnya adalah gradien radial tradisional bahwa perjalanan dari pusat hingga keluar canvas, seperti:

Creating a radial gradientCreating a radial gradientCreating a radial gradient

Itu terlihat lebih baik! Saya jujur kagum ketika aku melihat bagaimana radial gradien diimplementasi di canvas. Aku yakin itu telah tersandung banyak orang ketika mereka melihat yang membentuk kerucut. Oh well, setidaknya Anda tahu bagaimana membuat yang tepat sekarang.

Itu harus ditunjukan bahwa gradien di canvas juga cukup intensif operasi. Jika Anda ingin untuk menggunakan seluruh canvas di gradien, saya akan mempertimbangkan pertama menerapkan latar gradien CSS3 canvas elemen itu sendiri.


Kesimpulan

Dalam artikel ini, kami memeriksa bagaimana melakukan dasar transformasi di canvas, termasuk translation, scaling dan rotasi. Anda juga belajar bagaimana menambahkan bayangan objek, dan bagaimana membuat gradien. Tidak terdengar seperti banyak, tetapi transformasi, khususnya, membentuk tulang punggung dari beberapa hal keren yang dapat dicapai di canvas.

Dalam entri berikutnya di "Canvas dari awal", kita akan melepaskan diri dari menggambar objek dan Lihatlah bagaimana memanipulasi gambar dan video di canvas. Ini dimaan hal-hal mulai benar-benar menjadi menarik! Nantikan!

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Web Design tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.