Kami mempunyai banyak jenis carta yang terkenal: bar, donat, garis, pai, anda namakannya. Semua perpustakaan carta popular menyokong ini. Kemudian ada jenis carta yang tidak mempunyai nama. Lihat carta Dreamt-up ini dengan dataran yang disusun (bersarang) yang dapat membantu menggambarkan saiz relatif, atau bagaimana nilai yang berbeza dibandingkan dengan satu sama lain:
Apa yang kita buat
Tanpa sebarang interaktiviti, mewujudkan reka bentuk ini agak mudah. Salah satu cara untuk melakukannya adalah untuk menyusun unsur-unsur (misalnya SVG unsur-unsur, atau bahkan HTML Divs) dalam saiz penurunan, di mana semua sudut bawah kiri mereka menyentuh titik yang sama.
Tetapi perkara menjadi lebih rumit apabila kita memperkenalkan beberapa interaktiviti. Inilah caranya: Apabila kita menggerakkan tetikus kita ke atas salah satu bentuk, kita mahu yang lain memudar dan bergerak.
Kami akan mencipta bentuk yang tidak teratur ini menggunakan segi empat tepat dan topeng - literal dengan dan elemen. Jika anda sama sekali baru dengan topeng, anda berada di tempat yang betul. Ini adalah artikel peringkat pengenalan. Sekiranya anda lebih berpengalaman, maka mungkin kesan pemotongan ini adalah silap mata yang boleh anda ambil dengan anda.
Sekarang, sebelum kita mula, anda mungkin tertanya -tanya jika alternatif yang lebih baik untuk SVG menggunakan bentuk tersuai. Itu pasti kemungkinan! Tetapi melukis bentuk dengan boleh menakutkan, atau bahkan menjadi kemas. Jadi, kami bekerja dengan elemen "lebih mudah" untuk mendapatkan bentuk dan kesan yang sama.
Sebagai contoh, inilah caranya kita perlu mewakili bentuk biru terbesar menggunakan .
<svg viewbox="0 0 320 320" width="320" height="320">
<path d="M320 0H0V56H264V320H320V0Z" fill="#264653"></path>
</svg>
Jika 0H0V56 ... tidak masuk akal kepada anda, lihat "Sintaks Laluan SVG: Panduan Illustrated" untuk penjelasan yang menyeluruh mengenai sintaks.
Asas -asas carta
Memandangkan set data seperti ini:
Taipkan DataseTeNtry = {
Label: String;
Nilai: Nombor;
};
taip dataset = dataseTentry [];
const rawdataset: dataset = [
{label: 'buruk', nilai: 1231},
{label: 'permulaan', nilai: 6321},
{label: 'membangun', nilai: 10028},
{label: 'dicapai', nilai: 12123},
{label: 'contoh', nilai: 2120}
];
... Kami mahu berakhir dengan SVG seperti ini:
<svg viewbox="0 0 320 320" width="320" height="320">
<rect width="320" ketinggian="320" y="0" fill="..."> </rect>
<rect width="264" ketinggian="264" y="56" fill="..."> </rect>
<rect width="167" ketinggian="167" y="153" fill="..."> </rect>
<rect width="56" ketinggian="56" y="264" fill="..."> </rect>
<rect width="32" ketinggian="32" y="288" fill="..."> </rect>
</svg>
Menentukan nilai tertinggi
Ia akan menjadi jelas dalam seketika mengapa kita memerlukan nilai tertinggi. Kita boleh menggunakan math.max () untuk mendapatkannya. Ia menerima sejumlah argumen dan mengembalikan nilai tertinggi dalam satu set.
const datasethighestvalue: nombor = math.max (
... rawDataset.map ((entri: dataseTentry) => entry.value)
);
Oleh kerana kita mempunyai dataset kecil, kita hanya dapat memberitahu bahawa kita akan mendapat 12123.
Mengira dimensi segi empat tepat
Jika kita melihat reka bentuk, segi empat tepat yang mewakili nilai tertinggi (12123) merangkumi seluruh kawasan carta.
Kami sewenang -wenangnya memilih 320 untuk dimensi SVG. Oleh kerana segi empat tepat kami adalah dataran, lebar dan ketinggian adalah sama. Bagaimana kita boleh membuat 12123 sama dengan 320? Bagaimana dengan nilai "istimewa" yang kurang? Berapa besar segi empat tepat 6321?
Ditanya cara lain, bagaimana kita memetakan nombor dari satu julat ([0, 12123]) kepada yang lain ([0, 320])? Atau, dalam istilah matematik yang lebih banyak, bagaimanakah kita skala pembolehubah kepada selang [A, B]?
Untuk tujuan kami, kami akan melaksanakan fungsi seperti ini:
const remapvalue = (
Nilai: Nombor,
Frommin: Nombor,
Frommax: Nombor,
Tomin: Nombor,
Tomax: Nombor
): nombor => {
pulangan ((nilai - darimin) / (dariMax - Frommin)) * (Tomax - Tomin) Tomin;
};
remapvalue (1231, 0, 12123, 0, 320); // 32
remapvalue (6321, 0, 12123, 0, 320); // 167
remapvalue (12123, 0, 12123, 0, 320); // 320
Oleh kerana kami memetakan nilai ke julat yang sama dalam kod kami, bukannya lulus minimum dan maksimum berulang kali, kami boleh membuat fungsi pembungkus:
const valueremapper = (
Frommin: Nombor,
Frommax: Nombor,
Tomin: Nombor,
Tomax: Nombor
) => {
kembali (nilai: nombor): nombor => {
kembali remapvalue (nilai, darimin, darimax, tomin, tomax);
};
};
const remapdatasetvaluetosvgdimension = valueremapper (
0,
DataSethestValue,
0,
svgdimension
);
Kita boleh menggunakannya seperti ini:
remapdatasetvaluetosvgdimension (1231); // 32
remapdatasetvaluetosvgdimension (6321); // 167
remapdatasetvaluetosvgdimension (12123); // 320
Membuat dan memasukkan elemen DOM
Apa yang tersisa berkaitan dengan manipulasi DOM. Kita perlu membuat dan lima elemen Perhatikan bahawa kami menggunakan createelementns dan bukannya createelement yang lebih biasa. Ini kerana kami bekerja dengan SVG. Elemen HTML dan SVG mempunyai spesifikasi yang berbeza, jadi mereka berada di bawah ruang nama yang berbeza. Ia hanya berlaku bahawa createelement dengan mudah menggunakan ruang nama HTML! Jadi, untuk membuat SVG, kita harus menjadi verbose ini:
document.createelementns ('http://www.w3.org/2000/svg', 'svg') sebagai svgsvgelement;
Tentunya, kita boleh membuat fungsi penolong lain:
const createsVgnSelement = (elemen: string): svgelement => {
kembali document.createelementns ('http://www.w3.org/2000/svg', elemen);
};
Apabila kita melaksanakan segi empat tepat ke DOM, kita perlu memberi perhatian kepada pesanan mereka. Jika tidak, kita perlu menentukan indeks Z secara eksplisit. Rectangle pertama harus menjadi yang terbesar, dan segi empat tepat terakhir harus menjadi yang terkecil. Terbaik untuk menyusun data sebelum gelung.
const data = rawdataset.sort (
(A: DatasetEntry, B: DatasetEntry) => B.Value - A.Value
);
data.Foreach ((D: DatasetEntry, Index: Number) => {
const rect: svgrectElement = createsvgnSelement ('rect') sebagai svgrectelement;
const rectDimension: nombor = remapdatasetValueToSvgDimension (d.Value);
rect.setAttribute ('width', `$ {rectDimension}`);
rect.setAttribute ('ketinggian', `$ {rectDimension}`);
rect.setAttribute ('y', `$ {svgdimension - rectDimension}`);
svg.appendchild (rect);
});
Sistem koordinat bermula dari kiri atas; Di sinilah [0, 0] adalah. Kami sentiasa akan menarik segi empat tepat dari sebelah kiri. Atribut X, yang mengawal kedudukan mendatar, mungkir kepada 0, jadi kita tidak perlu menetapkannya. Atribut Y mengawal kedudukan menegak.
Untuk memberikan kesan visual bahawa semua segi empat tepat berasal dari titik yang sama yang menyentuh sudut bawah kiri mereka, kita perlu menolak segi empat tepat untuk bercakap. Dengan berapa? Jumlah yang tepat yang tidak diisi oleh segi empat tepat. Dan nilai itu adalah perbezaan antara dimensi carta dan segi empat tepat tertentu. Jika kita meletakkan semua bit bersama -sama, kita berakhir dengan ini:
Kami telah menambah kod untuk animasi ke demo ini menggunakan CSS.
Cutout Rectangles
Kita perlu mengubah segi empat tepat kita menjadi bentuk yang tidak teratur yang kelihatan seperti nombor tujuh, atau huruf l berputar 180 darjah.
Sekiranya kita memberi tumpuan kepada "bahagian yang hilang" maka kita dapat melihat mereka memotong segi empat tepat yang sama yang sudah kita bekerjasama.
Kami mahu menyembunyikan cutouts tersebut. Begitulah cara kita akan berakhir dengan bentuk L yang kita mahukan.
Masking 101
Topeng adalah sesuatu yang anda tentukan dan kemudian memohon kepada elemen. Biasanya, topeng digariskan dalam elemen yang dimilikinya. Dan, secara amnya, ia sepatutnya mempunyai ID yang unik kerana kita perlu merujuknya untuk memohon topeng ke elemen.
<svg>
<kop>
</kop></svg>
Dalam tag , kami meletakkan bentuk yang berfungsi sebagai topeng sebenar. Kami juga menggunakan atribut topeng kepada unsur -unsur.
<svg>
<kop>
<rect mask="url (#mycleverlynamedmask)"> </rect>
</kop></svg>
Itu bukan satu -satunya cara untuk menentukan atau memohon topeng, tetapi ia adalah cara yang paling mudah untuk demo ini. Mari kita lakukan sedikit percubaan sebelum menulis sebarang kod untuk menghasilkan topeng.
Kami berkata bahawa kami mahu menutup kawasan cutout yang sepadan dengan saiz segi empat tepat yang ada. Jika kita mengambil elemen terbesar dan kita menggunakan segi empat tepat sebelumnya sebagai topeng, kita berakhir dengan kod ini:
<svg viewbox="0 0 320 320" width="320" height="320">
<kop>
<rect width="264" ketinggian="264" y="56" fill=""> </rect>
<rect width="320" height="320" y="0" fill="#264653" mask="url (#themask)"> </rect>
</kop></svg>
Unsur di dalam topeng memerlukan nilai mengisi. Apa yang sepatutnya? Kami akan melihat hasil yang sama sekali berbeza berdasarkan nilai mengisi (warna) yang kami pilih.
Mengisi putih
Jika kita menggunakan nilai putih untuk mengisi, maka kita dapat ini:
Sekarang, segi empat tepat kami adalah dimensi yang sama seperti segi empat tepat. Tidak betul -betul apa yang kita mahu.
Pengisian hitam
Jika kita menggunakan nilai hitam sebaliknya, maka ia kelihatan seperti ini:
Kami tidak melihat apa -apa. Itu kerana apa yang dipenuhi dengan hitam adalah apa yang menjadi tidak kelihatan. Kami mengawal keterlihatan topeng menggunakan mengisi putih dan hitam. Garis putus -putus ada di sana sebagai bantuan visual untuk merujuk dimensi kawasan yang tidak kelihatan.
Pengisian kelabu
Sekarang mari kita gunakan sesuatu di antara putih dan hitam, katakan kelabu:
Ia bukan legap sepenuhnya atau pepejal; ia telus. Jadi, sekarang kita tahu kita dapat mengawal "tahap penglihatan" di sini dengan menggunakan sesuatu yang berbeza daripada nilai putih dan hitam yang merupakan helah yang baik untuk menyimpan poket belakang kita.
Bit terakhir
Inilah yang telah kami sampaikan dan belajar mengenai topeng setakat ini:
Unsur di dalam mengawal dimensi kawasan bertopeng.
Kita boleh membuat kandungan kawasan bertopeng kelihatan, tidak kelihatan, atau telus.
Kami hanya menggunakan satu bentuk untuk topeng, tetapi seperti mana -mana tag HTML tujuan umum, kita boleh bersarang banyak elemen kanak -kanak di sana seperti yang kita mahu. Malah, helah untuk mencapai apa yang kita mahukan adalah menggunakan dua elemen SVG . Kita perlu menyusunnya satu di atas yang lain:
<svg viewbox="0 0 320 320" width="320" height="320">
<kop>
<rect width="320" height="320" y="0" fill="???"> </rect>
<rect width="264" ketinggian="264" y="56" fill="???"> </rect>
<rect width="320" ketinggian="320" y="0" fill="#264653" mask="url (#maskw320)"> </rect>
</kop></svg>
Salah satu segi empat tepat kami dipenuhi dengan putih; Yang lain dipenuhi dengan hitam. Walaupun kita tahu peraturan, mari kita cuba kemungkinan.
<kop>
<rect width="320" height="320" y="0" fill="Black"> </rect>
<rect width="264" ketinggian="264" y="56" fill="white"> </rect>
</kop>
adalah dimensi elemen terbesar dan elemen terbesar diisi dengan hitam. Ini bermakna segala -galanya di bawah kawasan itu tidak dapat dilihat. Dan segala -galanya di bawah segi empat tepat yang lebih kecil dapat dilihat.
Sekarang mari kita lakukan perkara -perkara di mana segi empat tepat hitam berada di atas:
<kop>
<rect width="320" ketinggian="320" y="0" fill="white"> </rect>
<rect width="264" ketinggian="264" y="56" fill="Black"> </rect>
</kop>
Inilah yang kita mahukan!
Segala-galanya di bawah segi empat tepat putih yang terbesar dapat dilihat, tetapi segi empat hitam yang lebih kecil berada di atasnya (lebih dekat dengan kami pada paksi z), memasangkan bahagian itu.
Menjana topeng
Sekarang kita tahu apa yang perlu kita lakukan, kita boleh membuat topeng dengan mudah. Ia sama dengan bagaimana kami menjana segi empat tepat berwarna di tempat pertama - kami membuat gelung sekunder di mana kami membuat topeng dan dua rektum.
Kali ini, bukannya memasuki Rect terus ke SVG, kami menambahkannya ke topeng:
data.Foreach ((D: DatasetEntry, Index: Number) => {
Const Mask: svgmaskeLement = createSvgnSelement ('Mask') sebagai svgmaskelement;
const rectDimension: nombor = remapdatasetValueToSvgDimension (d.Value);
const rect: svgrectElement = createsvgnSelement ('rect') sebagai svgrectelement;
rect.setAttribute ('width', `$ {rectDimension}`);
// ... menetapkan selebihnya atribut ...
mask.setAttribute ('id', `maskw $ {rectDimension.tofixed ()}`);
Mask.AppendChild (Rect);
// ... mencipta dan menetapkan atribut untuk segi empat tepat yang lebih kecil ...
svg.appendchild (topeng);
});
data.Foreach ((D: DatasetEntry, Index: Number) => {
// ... kod kami untuk menghasilkan segi empat tepat berwarna ...
});
Kita boleh menggunakan indeks sebagai ID topeng, tetapi ini nampaknya pilihan yang lebih mudah dibaca, sekurang -kurangnya kepada saya:
mask.setAttribute ('id', `maskw $ {rectDimension.tofixed ()}`); // maskw320, masw240, ...
Bagi menambah segi empat tepat yang lebih kecil dalam topeng, kami mempunyai akses mudah nilai yang kami perlukan kerana kami sebelum ini mengarahkan nilai segi empat tepat dari yang tertinggi hingga terendah. Ini bermakna elemen seterusnya dalam gelung adalah segi empat tepat yang lebih kecil, yang harus kita rujuk. Dan kita boleh melakukannya dengan indeksnya.
// ... bahagian sebelumnya di mana kita membuat topeng dan segi empat tepat ...
constRectindex = indeks 1;
// Tidak ada yang seterusnya ketika kita berada di yang paling kecil
jika (data [smallerrectindex]! == undefined) {
consterrectdimension: nombor = remapdatasetvaluetosvgdimension (
data [SmallerrectIndex] .value
);
consterrect: svgrectelement = createsvgnSelement (
'rect'
) sebagai svgrectelement;
// ... menetapkan atribut segi empat tepat ...
Mask.AppendChild (Smallerrect);
}
svg.appendchild (topeng);
Apa yang tersisa adalah untuk menambah atribut topeng ke segi empat tepat berwarna dalam gelung asal kami. Ia sepadan dengan format yang kita pilih:
rect.setAttribute ('topeng', `url (#maskw $ {rectDimension.tofixed ()})`); // maskw320, maskw240, ...
Hasil akhir
Dan kita sudah selesai! Kami telah berjaya membuat carta yang dibuat daripada dataran bersarang. Ia juga terpisah pada hover tetikus. Dan semua yang diperlukan adalah beberapa SVG menggunakan elemen untuk menarik kawasan cutout setiap persegi.
Atas ialah kandungan terperinci Cara membuat carta animasi dataran bersarang menggunakan topeng. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!