Jadual Kandungan
Tetapi pertama, pelajaran bagaimana audio digital berfungsi
Bagaimana laman web boleh membaca mp3?
Menapis data
Menggambarkan data
Nota mengenai prestasi
Beberapa pemikiran penutup
Rumah hujung hadapan web tutorial css Membuat Visualisasi Gelombang Audio dengan Vanila JavaScript

Membuat Visualisasi Gelombang Audio dengan Vanila JavaScript

Apr 14, 2025 am 09:42 AM

Membuat visualisasi gelombang audio dengan vanila javascript

Sebagai pereka UI, saya sentiasa diingatkan akan nilai mengetahui cara kod. Saya bangga memikirkan pemaju dalam pasukan saya semasa merancang antara muka pengguna. Tetapi kadang -kadang, saya melangkah ke darat teknikal.

Beberapa tahun yang lalu, sebagai pengarah reka bentuk WSJ.com, saya membantu merancang semula direktori podcast Wall Street Journal. Salah satu pereka dalam projek itu sedang mengusahakan pemain podcast, dan saya datang kepada pemain tertanam Megaphone.

Saya sebelum ini bekerja di SoundCloud dan tahu bahawa jenis visualisasi ini berguna untuk pengguna yang melangkaui audio. Saya tertanya -tanya jika kita dapat mencapai penampilan yang sama untuk pemain di laman web Wall Street Journal.

Jawapan dari Kejuruteraan: Pasti tidak. Memandangkan garis masa dan sekatan, ia bukan kemungkinan untuk projek itu. Kami akhirnya menghantar halaman yang direka bentuk semula dengan pemain podcast yang lebih mudah.

Tetapi saya terpikat pada masalah ini. Lebih malam dan hujung minggu, saya menggodam cuba mencapai kesan ini. Saya belajar banyak tentang bagaimana audio berfungsi di web, dan akhirnya dapat mencapai rupa dengan kurang daripada 100 baris JavaScript!

Ternyata contoh ini adalah cara yang sempurna untuk mengenali API Audio Web, dan bagaimana untuk memvisualisasikan data audio menggunakan API Kanvas.

Tetapi pertama, pelajaran bagaimana audio digital berfungsi

Dalam dunia sebenar, analog, bunyi adalah gelombang. Sebagai bunyi perjalanan dari sumber (seperti penceramah) ke telinga anda, ia memampatkan dan menguraikan udara dalam corak yang telinga dan otak anda mendengar sebagai muzik, atau ucapan, atau kulit anjing, dll.

Tetapi dalam dunia isyarat elektronik, bunyi bukan gelombang. Untuk menjadikan gelombang yang lancar, berterusan ke dalam data yang dapat disimpan, komputer melakukan sesuatu yang dipanggil persampelan . Pensampelan bermaksud mengukur gelombang bunyi yang memukul mikrofon beribu -ribu kali setiap saat, kemudian menyimpan titik data tersebut. Apabila memainkan audio, komputer anda membalikkan proses: ia mencipta semula bunyi, satu pecahan kecil audio pada satu masa.

Bilangan titik data dalam fail bunyi bergantung pada kadar sampelnya . Anda mungkin pernah melihat nombor ini sebelum ini; Kadar sampel biasa untuk fail MP3 ialah 44.1 kHz. Ini bermakna, untuk setiap detik audio, terdapat 44,100 titik data individu. Untuk fail stereo, terdapat 88,200 setiap saat - 44,100 untuk saluran kiri, dan 44,100 untuk hak. Ini bermakna podcast 30 minit mempunyai 158,760,000 titik data individu yang menggambarkan audio!

Bagaimana laman web boleh membaca mp3?

Sepanjang sembilan tahun yang lalu, W3C (orang yang membantu mengekalkan piawaian web) telah membangunkan API Audio Web untuk membantu pemaju web bekerja dengan audio. API Audio Web adalah topik yang sangat mendalam; Kami tidak akan memecahkan permukaan dalam esei ini. Tetapi semuanya bermula dengan sesuatu yang dipanggil audiocontext.

Fikirkan audiocontext seperti kotak pasir untuk bekerja dengan audio. Kita boleh memulakannya dengan beberapa baris JavaScript:

 // Sediakan konteks audio
window.AudiOContext = window.AudiOContext || window.webkitaudiocontext;
const audiocontext = audiOcontext baru ();
Biarkan CurrentBuffer = NULL;

Baris pertama selepas komen adalah perlu kerana Safari telah melaksanakan AudioContext sebagai WebKitaudiContext.

Seterusnya, kita perlu memberikan audiocontext baru kami fail MP3 yang ingin kami bayangkan. Mari ambilnya menggunakan ... ambil ()!

 const visualizeaudio = url => {
  Ambil (URL)
    .then (response => response.arraybuffer ())
    .then (arrayBuffer => audiocontext.decodeaudiodata (arraybuffer))
    .THEN (AudioBuffer => Visualisasikan (AudioBuffer));
};

Fungsi ini mengambil URL, mengambilnya, kemudian mengubah objek tindak balas beberapa kali.

  • Pertama, ia memanggil kaedah ArrayBuffer (), yang kembali - anda meneka - arraybuffer! Arraybuffer hanyalah bekas untuk data binari; Ini cara yang cekap untuk memindahkan banyak data di JavaScript.
  • Kami kemudian menghantar arraybuffer ke audioContext kami melalui kaedah decodeaudiodata (). Decodeaudiodata () mengambil arraybuffer dan mengembalikan audioBuffer, yang merupakan arraybuffer khusus untuk membaca data audio. Adakah anda tahu bahawa penyemak imbas datang dengan semua objek mudah ini? Saya pasti tidak apabila saya memulakan projek ini.
  • Akhirnya, kami menghantar AudioBuffer kami untuk digambarkan.

Menapis data

Untuk memvisualisasikan audioBuffer kami, kami perlu mengurangkan jumlah data yang kami bekerjasama. Seperti yang saya nyatakan sebelum ini, kami bermula dengan berjuta -juta mata data, tetapi kami akan jauh lebih sedikit dalam visualisasi akhir kami.

Pertama, mari kita hadkan saluran yang kami bekerjasama. Saluran mewakili audio yang dihantar kepada penceramah individu. Dalam bunyi stereo, terdapat dua saluran; Dalam 5.1 bunyi sekeliling, terdapat enam. AudioBuffer mempunyai kaedah terbina dalam untuk melakukan ini: getChanneldata (). Hubungi AudioBuffer.GetChanNeldata (0), dan kami akan ditinggalkan dengan data bernilai satu saluran.

Seterusnya, bahagian yang sukar: gelung melalui data saluran, dan pilih satu set mata data yang lebih kecil. Terdapat beberapa cara yang boleh kita lakukan. Katakan saya mahu visualisasi terakhir saya mempunyai 70 bar; Saya boleh membahagikan data audio ke dalam 70 bahagian yang sama, dan melihat titik data dari setiap satu.

 const filterData = audioBuffer => {
  const rawData = audioBuffer.getChanNeldata (0); // kita hanya perlu bekerja dengan satu saluran data
  sampel const = 70; // bilangan sampel yang kami mahu ada dalam set data akhir kami
  const blockSize = Math.floor (RawData.Length / Samples); // bilangan sampel dalam setiap subdivisi
  const filteredData = [];
  untuk (biarkan i = 0; i <samples i filtereddata.push blocksize kembali filtereddata><p> Output menangkap saya dari pengawal! Ia tidak kelihatan seperti visualisasi yang kita tetapkan sama sekali. Terdapat banyak titik data yang dekat dengan, atau pada sifar. Tetapi itu membuat banyak akal: Dalam podcast, terdapat banyak kesunyian antara kata -kata dan ayat. Dengan hanya melihat sampel pertama di setiap blok kami, kemungkinan besar kami akan menangkap momen yang sangat tenang.</p>
<p> Mari kita ubah algoritma untuk mencari <em>purata</em> sampel. Dan semasa kita berada di sana, kita harus mengambil nilai mutlak data kita, supaya semuanya positif.</p>
<pre rel="JavaScript" data-line=""> const filterData = audioBuffer => {
  const rawData = audioBuffer.getChanNeldata (0); // kita hanya perlu bekerja dengan satu saluran data
  sampel const = 70; // bilangan sampel yang kami mahu ada dalam set data akhir kami
  const blockSize = Math.floor (RawData.Length / Samples); // bilangan sampel dalam setiap bahagian
  const filteredData = [];
  untuk (biarkan i = 0; i <samples i biarkan blockstart="blockSize" lokasi sampel pertama di blok jumlah="0;" untuk j="0;" sum="sum" math.abs cari semua filtereddata.push blocksize bahagikan jumlahnya dengan saiz mendapatkan purata kembali filtereddata><p> Mari lihat bagaimana data itu kelihatan.</p>
<p> Ini hebat. Hanya ada satu perkara yang perlu dilakukan: Kerana kita mempunyai banyak kesunyian dalam fail audio, purata titik data yang dihasilkan sangat kecil. Untuk memastikan visualisasi ini berfungsi untuk semua fail audio, kita perlu <em>menormalkan</em> data; iaitu, ubah skala data supaya sampel paling kuat mengukur sebagai 1.</p>
<pre rel="JavaScript" data-line=""> const normalizedata = filteredData => {
  const multiplier = Math.pow (Math.Max ​​(... FilteredData), -1);
  kembali filteredData.map (n => n * multiplier);
}

Fungsi ini mendapati titik data terbesar dalam array dengan math.max (), mengambil songsang dengan math.pow (n, -1), dan mengumpulkan setiap nilai dalam array oleh nombor itu. Ini menjamin bahawa titik data terbesar akan ditetapkan kepada 1, dan seluruh data akan berskala secara proporsional.

Sekarang kita mempunyai data yang betul, mari kita tulis fungsi yang akan menggambarkannya.

Menggambarkan data

Untuk membuat visualisasi, kami akan menggunakan API Kanvas JavaScript. API ini menarik grafik ke HTML elemen. Langkah pertama untuk menggunakan API kanvas adalah serupa dengan API Audio Web.

 const draw = normalisedData => {
  // Sediakan kanvas
  const canvas = document.QuerySelector ("Canvas");
  const dpr = window.devicepixelratio || 1;
  const padding = 20;
  kanvas.width = canvas.offsetWidth * dpr;
  kanvas.height = (canvas.OffSetheight padding * 2) * dpr;
  const ctx = canvas.getContext ("2d");
  ctx.scale (DPR, DPR);
  ctx.translate (0, canvas.offsetheight / 2 padding); // set y = 0 berada di tengah kanvas
};

Kod ini mendapati elemen pada halaman, dan memeriksa nisbah piksel penyemak imbas (pada dasarnya resolusi skrin) untuk memastikan grafik kami akan ditarik pada saiz yang betul. Kami kemudian mendapatkan konteks kanvas (set kaedah dan nilai masing -masing). Kami mengira dimensi piksel kanvas, pemfaktoran dalam nisbah piksel dan menambah beberapa padding. Akhir sekali, kita menukar sistem koordinat , secara lalai (0,0) berada di bahagian atas kotak, tetapi kita dapat menyelamatkan diri kita banyak matematik dengan menetapkan (0, 0) berada di tengah-tengah tepi kiri.

Sekarang mari kita lukis beberapa baris! Pertama, kami akan membuat fungsi yang akan menarik segmen individu.

 const drawlinSegment = (ctx, x, y, width, isEven) => {
  ctx.lineWidth = 1; // betapa tebalnya garisnya
  ctx.strokeStyle = "#fff"; // Apa warna garis kita
  ctx.beginpath ();
  y = iseven? y: -y;
  ctx.moveto (x, 0);
  ctx.Lineto (x, y);
  ctx.arc (x lebar / 2, y, lebar / 2, math.pi, 0, iseven);
  ctx.Lineto (x lebar, 0);
  ctx.stroke ();
};

API kanvas menggunakan konsep yang disebut "Grafik Penyu." Bayangkan bahawa kod itu adalah satu set arahan yang diberikan kepada penyu dengan penanda. Secara asasnya, fungsi drawLinesegment () berfungsi seperti berikut:

  1. Mulakan di garis tengah, x = 0.
  2. Lukis garis menegak. Buat ketinggian garis relatif terhadap data.
  3. Lukis separuh bulatan lebar segmen.
  4. Lukis garis menegak kembali ke garis tengah.

Kebanyakan arahan adalah mudah: ctx.moveto () dan ctx.lieto () memindahkan penyu ke koordinat yang ditentukan, tanpa lukisan atau semasa lukisan, masing -masing.

Baris 5, y = iseven? -Y: Y, memberitahu penyu kami sama ada untuk menurunkan atau naik dari garis tengah. Segmen bergantian antara berada di atas dan di bawah garis tengah supaya mereka membentuk gelombang yang lancar. Di dunia API kanvas, nilai y negatif lebih jauh daripada yang positif. Ini agak intuitif, jadi ingatlah sebagai sumber pepijat yang mungkin.

Pada baris 8, kami melukis separuh bulatan. ctx.arc () mengambil enam parameter:

  • Koordinat X dan Y Pusat Lingkaran
  • Jejari bulatan
  • Tempat dalam bulatan untuk memulakan lukisan (math.pi atau π adalah lokasi, pada radian, pukul 9)
  • Tempat dalam bulatan untuk menyelesaikan lukisan (0 di radian mewakili jam 3)
  • Nilai Boolean yang memberitahu penyu kami untuk menarik sama ada lawan jam (jika benar) atau mengikut arah jam (jika palsu). Menggunakan ISEVEN dalam hujah terakhir ini bermakna kita akan menarik bahagian atas bulatan-mengikut arah jam dari jam 9 hingga 3 jam-untuk segmen yang bernombor, dan separuh bahagian bawah untuk segmen ganjil.

Ok, kembali ke fungsi seri ().

 const draw = normalisedData => {
  // Sediakan kanvas
  const canvas = document.QuerySelector ("Canvas");
  const dpr = window.devicepixelratio || 1;
  const padding = 20;
  kanvas.width = canvas.offsetWidth * dpr;
  kanvas.height = (canvas.OffSetheight padding * 2) * dpr;
  const ctx = canvas.getContext ("2d");
  ctx.scale (DPR, DPR);
  ctx.translate (0, canvas.offsetheight / 2 padding); // set y = 0 berada di tengah kanvas

  // Lukis segmen garis
  const width = canvas.offsetWidth / normalizedData.length;
  untuk (biarkan i = 0; i <normalizeddata.length i const x="lebar" biarkan ketinggian="normalisedData" canvas.offsetheight padding jika else if> canvas.offsetheight / 2) {
        ketinggian = ketinggian> canvas.offsetheight / 2;
    }
    DrawlinSegment (CTX, X, ketinggian, lebar, (i 1) % 2);
  }
};</normalizeddata.length>

Selepas kod persediaan sebelumnya, kami perlu mengira lebar piksel setiap segmen baris. Ini adalah lebar pada skrin kanvas, dibahagikan dengan bilangan segmen yang ingin kami paparkan.

Kemudian, gelung melalui setiap entri dalam array dan menarik segmen garis menggunakan fungsi yang kami tentukan sebelumnya. Kami menetapkan nilai X ke indeks lelaran semasa, kali lebar segmen. Ketinggian, ketinggian segmen yang dikehendaki datang dari mendarabkan data normal kami dengan ketinggian kanvas, tolak padding yang kami tetapkan sebelumnya. Kami menyemak beberapa kes: Mengurangkan padding mungkin telah mendorong ketinggian ke dalam negatif, jadi kami menetapkan semula kepada sifar. Sekiranya ketinggian segmen akan menghasilkan garis yang ditarik dari atas kanvas, kami menetapkan semula ketinggian ke nilai maksimum.

Kami melewati lebar segmen, dan untuk nilai iseven, kami menggunakan helah yang kemas: (i 1) % 2 bermaksud "Cari selebihnya i 1 dibahagikan dengan 2." Kami periksa saya 1 kerana kaunter kami bermula pada 0. Jika saya 1 adalah walaupun, selebihnya akan menjadi sifar (atau palsu). Sekiranya saya ganjil, baki akan menjadi 1 atau benar.

Dan itu sahaja yang dia tulis. Mari kita buat bersama -sama. Inilah keseluruhan skrip, dalam semua kemuliaannya.

Dalam fungsi Drawaudio (), kami telah menambah beberapa fungsi untuk panggilan akhir: Draw (normalizedata (FilterData (AudioBuffer))). Penapis rantai ini, menormalkan, dan akhirnya menarik audio yang kami dapat kembali dari pelayan.

Sekiranya semuanya telah mengikut pelan, halaman anda sepatutnya kelihatan seperti ini:

Nota mengenai prestasi

Walaupun dengan pengoptimuman, skrip ini masih mungkin menjalankan beratus -ratus ribu operasi dalam penyemak imbas. Bergantung pada pelaksanaan penyemak imbas, ini boleh mengambil masa beberapa saat untuk diselesaikan, dan akan memberi kesan negatif terhadap pengiraan lain yang berlaku pada halaman. Ia juga memuat turun fail audio sebelum melukis visualisasi, yang menggunakan banyak data. Terdapat beberapa cara yang dapat kita dapati skrip untuk menyelesaikan isu -isu ini:

  1. Menganalisis audio di sebelah pelayan. Oleh kerana fail audio tidak sering berubah, kita boleh memanfaatkan sumber pengkomputeran sisi pelayan untuk menapis dan menormalkan data. Kemudian, kita hanya perlu menghantar set data yang lebih kecil; Tidak perlu memuat turun mp3 untuk menarik visualisasi!
  2. Hanya lukis visualisasi apabila pengguna memerlukannya. Tidak kira bagaimana kita menganalisis audio, masuk akal untuk menangguhkan proses sehingga selepas beban halaman. Kita boleh menunggu sehingga elemen itu dilihat menggunakan pemerhati persimpangan, atau melambatkan lebih lama sehingga pengguna berinteraksi dengan pemain podcast.
  3. Peningkatan progresif. Semasa meneroka pemain podcast Megaphone, saya mendapati bahawa visualisasi mereka hanya fasad - ia adalah bentuk gelombang yang sama untuk setiap podcast. Ini boleh menjadi lalai yang besar kepada reka bentuk kami (jauh lebih unggul). Menggunakan prinsip peningkatan progresif, kita boleh memuat imej lalai sebagai pemegang tempat. Kemudian, kita boleh menyemak untuk melihat sama ada masuk akal untuk memuat bentuk gelombang sebenar sebelum memulakan skrip kami. Jika pengguna mempunyai JavaScript dilumpuhkan, penyemak imbas mereka tidak menyokong API Audio Web, atau mereka mempunyai set header Save-Data, tiada apa yang dipecahkan.

Saya suka mendengar apa -apa pemikiran yang ada pada pengoptimuman juga.

Beberapa pemikiran penutup

Ini adalah cara yang sangat tidak praktikal untuk menggambarkan audio. Ia berjalan di sisi klien, memproses berjuta -juta titik data ke dalam visualisasi yang agak mudah.

Tetapi ia sejuk ! Saya banyak belajar menulis kod ini, dan lebih banyak lagi menulis artikel ini. Saya refactor banyak projek asal dan memangkas semuanya dengan separuh. Projek -projek seperti ini mungkin tidak pernah melihat asas kod pengeluaran, tetapi mereka adalah peluang yang unik untuk membangunkan kemahiran baru dan pemahaman yang lebih mendalam tentang beberapa penyemak imbas moden API yang kemas.

Saya harap ini adalah tutorial yang berguna. Jika anda mempunyai idea bagaimana untuk memperbaikinya, atau sebarang variasi yang sejuk pada tema, sila hubungi! Saya @ilikescience di twitter.

Atas ialah kandungan terperinci Membuat Visualisasi Gelombang Audio dengan Vanila JavaScript. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn

Alat AI Hot

Undress AI Tool

Undress AI Tool

Gambar buka pakaian secara percuma

Undresser.AI Undress

Undresser.AI Undress

Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover

AI Clothes Remover

Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Stock Market GPT

Stock Market GPT

Penyelidikan pelaburan dikuasakan AI untuk keputusan yang lebih bijak

Alat panas

Notepad++7.3.1

Notepad++7.3.1

Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina

SublimeText3 versi Cina

Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1

Hantar Studio 13.0.1

Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6

Dreamweaver CS6

Alat pembangunan web visual

SublimeText3 versi Mac

SublimeText3 versi Mac

Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas

Cara Membuat Menu Dropdown Dengan CSS Murni Cara Membuat Menu Dropdown Dengan CSS Murni Sep 20, 2025 am 02:19 AM

Gunakan HTML dan CSS untuk membuat menu drop-down tanpa JavaScript. 2. Memicu paparan submenu melalui: hover pseudo-class. 3. Gunakan senarai bersarang untuk membina struktur, dan tetapkan kesan paparan tersembunyi dan digantung dalam CSS. 4. Animasi peralihan boleh ditambah untuk meningkatkan pengalaman visual.

Cara Mencegah Imej Dari Regangan atau Mengecam Dengan CSS Cara Mencegah Imej Dari Regangan atau Mengecam Dengan CSS Sep 21, 2025 am 12:04 AM

UseObject-Fitormax-Widthwithheight: AutotopreventimagedIstion; Object-FitControlShowimagesfillConterswhilePreservingaseSpectratios, andmax-width: 100%; Height: AutoensureSressiveSsiveScalingWithoutStretching.

Cara Menggunakan Harta Penunjuk-Titik di CSS Cara Menggunakan Harta Penunjuk-Titik di CSS Sep 17, 2025 am 07:30 AM

ThePointer-EventsPropertyIncScontrolswhetheranelementCanBethetargetOfPointerevents.1.usepointer-Events: nonetodisableIntionsLikeClicksorhoversWheLeepingTheelementVisibleVisible.2.applyoverlaystoundlowlickeWough

Cara Menambah Kesan Bayangan Kotak Dengan CSS Cara Menambah Kesan Bayangan Kotak Dengan CSS Sep 20, 2025 am 12:23 AM

Usethebox-shadowpropertytoadddropshadows.Definehorizontalandverticaloffsets,blur,spread,color,andoptionalinsetforinnershadows.Multipleshadowsarecomma-separated.Example:box-shadow:5px10px8pxrgba(0,0,0,0.3);createsasoftblackshadow.

Cara memohon penapis pada gambar dengan css Cara memohon penapis pada gambar dengan css Sep 21, 2025 am 02:27 AM

Thecssfilterpropertyallowseasymagestylingwitheffectslebur, kecerahan, andgrayscale.usefilter: fungsi penapis (nilai) onimagesorbackgroundimages.commonfunctionsincludeblur (px), kecerahan (%)

Cara menambah latar belakang kecerunan dalam css Cara menambah latar belakang kecerunan dalam css Sep 16, 2025 am 05:30 AM

Untuk menambah latar belakang kecerunan CSS, gunakan latar belakang atau atribut imej latar belakang untuk bekerjasama dengan fungsi seperti linear-gradient (), radial-gradient (); Mula-mula pilih jenis kecerunan, tetapkan arah dan warna, dan anda boleh mengawalnya dengan halus melalui titik dok, bentuk, saiz dan parameter lain, seperti gradien linear (toright,#ff7e5f,#feb47b)

Bagaimana untuk membuat jurang dalam susun atur grid CSS? Bagaimana untuk membuat jurang dalam susun atur grid CSS? Sep 22, 2025 am 05:15 AM

Gunakan jurang, jurang atau atribut jurang lajur untuk membuat jarak antara item grid dalam susun atur cssgrid. GAP adalah atribut singkatan untuk menetapkan jarak baris lajur, yang boleh menerima satu atau dua nilai panjang. Gap baris dan jurang lajur secara individu mengawal jarak antara baris dan lajur, dan unit sokongan seperti PX, REM, dan %.

Cara menggunakan fungsi pengapit () untuk tipografi responsif dalam CSS Cara menggunakan fungsi pengapit () untuk tipografi responsif dalam CSS Sep 23, 2025 am 01:24 AM

Fungsi pengapit () menyedari fon responsif skala melalui nilai minimum, pilihan dan maksimum; 2. Sintaks adalah pengapit (nilai minimum, nilai pilihan, nilai maksimum), dan unit REM dan VW yang biasa digunakan; 3. Fon mengambil nilai minimum pada skrin kecil, dan skala mengikut VW apabila skrin meningkat, dan tidak melebihi nilai maksimum; 4. Mendapat memilih nilai berangka untuk memastikan kebolehbacaan dan elakkan terlalu besar atau terlalu kecil; 5. Menggabungkan perkadaran jenis REM untuk meningkatkan konsistensi reka bentuk.

See all articles