Ruang komputer 3D yang dirender dengan WebGL bukanlah hal baru saat ini. Tujuan utama artikel ini adalah untuk menjelaskan masalah mata dan pusat pada ruang komputer 3D yang kebetulan digunakan dalam proyek tersebut merasa bahwa contoh ini paling memenuhi persyaratan saya, jadi saya menggunakannya sebagai catatan.
renderingDemo ruang komputer 3D ini cukup bagus, cantik, dan interaksi dasarnya memuaskan. Mari kita lihat cara mengimplementasikannya.
pembuatan kode Tentukan kelasPertama, buka js yang sesuai satu per satu dari jalur js yang disebut di index.html. Kelas Editor.Server dikustomisasi di server.js dan dibuat oleh fungsi ht.Default.def yang dienkapsulasi oleh HT (perhatikan bahwa kelas yang dibuat namanya Editor Editor di depan .Server tidak bisa diganti dengan E):
ht.Default.def('Editor.Server', Object, {//Parameter pertama adalah nama kelas. Jika berupa string, maka akan otomatis terdaftar di classMap HT; parameter kedua adalah kelas induk yang akan diwarisi oleh kelas ini. ; Parameter ketiga adalah deklarasi metode dan variabel addToDataModel: function(dm) { //Tambahkan node ke wadah data dm.add(this._node); simpul melalui add Metode ditambahkan ke wadah data}, setHost: function() { //Setel adsorpsi this._node.setHost.apply(this._node, argument }, s3: function() {//Setel ukuran node this._node .s3.apply(this._node, argumen }, setElevation: function() {//Kontrol posisi sumbu y dari sistem koordinat 3D tempat posisi tengah primitif Node berada this._node.setElevation.apply(this._node, argument }});
Buat kelas Editor.Server
Kelas ini dapat membuat node ht.Node dan mengatur warna dan tekstur depan node:
var S = E.Server = function(obj) {//Komponen server var color = obj.color, frontImg = obj.frontImg var node = this._node = new ht.Node();//Buat node node.s; ({//Atur gaya simpul ke singkatan setStyle 'all.color': color,//Atur warna keenam sisi simpul 'front.image': frontImg //Mengatur gambar di depan node});};
Dengan cara ini, saya bisa langsung membuat objek komponen server baru di mana saya perlu membuat komponen server, dan saya bisa langsung memanggil setHost dan fungsi lain yang kami nyatakan di atas, yang akan segera kami gunakan.
Selanjutnya buat kelas kabinet Editor.Cabinet Caranya mirip dengan metode definisi kelas Editor.Server di atas:
ht.Default.def('Editor.Cabinet', Objek, { addToDataModel: function(dm) { dm.add(this._door); dm.add(this._node); this._serverList.forEach(function(s) { s.addToDataModel(dm } }, p3: fungsi() { this._node.p3.apply(this._node, argument);//Tetapkan koordinat 3d dari node}});
Buat kelas Editor.Cabinet
Kelas ini relatif lebih kompleks dibandingkan kelas komponen server Editor.Server sebelumnya. Kelas ini membuat badan kabinet, pintu kabinet, dan komponen server di dalam kabinet:
var C = E.Cabinet = fungsi(obj) { var color = obj.color, doorFrontImg = obj.doorFrontImg, doorBackImg = obj.doorBackImg, s3 = obj.s3; ; // Kabinet node.s3(s3); //Atur ukuran node ke setSize3d node.a('cabinet', this);//Sesuaikan properti kabinet node.s({//Atur gaya node ke setStyle 'all.color': color,//Atur warna keenam sisi node 'front.visible ': false//Setel apakah bagian depan node terlihat}); if (Math.random() > 0.5) { node.addStyleIcon('alarm', {//Tambahkan nama ikon ke node: ['ikon termometer'], //Array yang berisi beberapa string, setiap string berhubungan dengan gambar atau vektor (didaftarkan melalui ht.Default.setImage) wajah: 'atas', //Nilai defaultnya adalah depan, ikon Orientasi dalam 3D , nilai yang tersedia adalah kiri|kanan|atas|bawah|depan|belakang|posisi tengah: 17, //Tentukan posisi ikon putar otomatis: 'y', //Nilai defaultnya salah, apakah ikon otomatis menghadap ke arah mata dalam 3D t3: [0, 16, 0], //Nilai defaultnya tidak ditentukan, offset ikon dalam 3D, formatnya adalah [x ,y,z] lebar: 37,//Tentukan lebar setiap ikon, defaultnya berdasarkan lebar saat mendaftarkan tinggi gambar: 32,//Tentukan tinggi setiap ikon, defaultnya adalah berdasarkan tinggi saat mendaftarkan gambar textureScale: 4, //Nilai defaultnya adalah 2. Nilai ini mewakili kelipatan dari peta sebenarnya yang dihasilkan oleh memori. Nilai ini tidak boleh disetel terlalu besar karena akan mempengaruhi kinerja yang terlihat: { func: function() { return !!. E.alarmVisible; }}//Menunjukkan grup gambar. Apakah akan ditampilkan } } var door = this._door = new ht.DoorWindow();//Pintu kabinet door.setWidth(s3[0]);//Atur panjang elemen grafis dalam arah sumbu x pada topologi 3D door.setHeight(1);//Atur elemen grafis dalam topologi 3D sumbu z di Panjang door.setTall(s3[1]);//Kontrol panjang Node primitif pada sumbu y door.setElevation(0);//Atur koordinat y dari pusat primitif dalam sistem koordinat 3D pintu .setY(s3[2 ] * 0,5);//Atur posisi simpul pada sumbu y door.setHost(node);//Atur pintu adsorpsi.s({//Atur gaya simpul setStyle 'all.color': color,/ /Mengatur warna keenam sisi node 'front.image': doorFrontImg, //Mengatur gambar depan node 'front.transparent': true, //Mengatur apakah wajah depan node transparan 'back .image': doorBackImg, //Atur gambar di belakang node 'back.uv': [1,0, 1,1, 0,1, 0,0],//Sesuaikan peta uv di belakang node. Jika kosong, nilai defaultnya adalah [0,0, 0,1, 1,1, 1 ,0] ' dw.axis': 'right'//Setel sumbu rotasi untuk operasi perluasan dan penutupan elemen DoorWindow, nilai yang mungkin adalah left|right|top|bottom|v|h }); ._serverList = []; max = 6, list = E.randomList(max, Math.floor(Math.random() * (max - 2)) + 2 //Fungsi untuk mendapatkan angka acak yang dideklarasikan di server var global.js, h = s3 [0] / 4; list.forEach(function(r) { var server = new E.Server({ //Warna komponen server: 'rgb(51,49,49)', frontImg: 'Komponen server baik-baik saja' }); server.s3(s3[0] - 2, h, s3[2] - 4);//Setel ukuran node server.setElevation((r - max * 0.5) * (h + 2 ));//Atur koordinat titik pusat node pada sumbu y server.setHost(node);//Atur adsorpsi node serverList.push(server);//Ke serverList Tambahkan node server di });};
Satu-satunya hal yang tidak disebutkan dalam kode di atas adalah fungsi Editor.randomList. Fungsi ini dideklarasikan dalam file global.js dan dideklarasikan sebagai berikut:
var E = window.Editor = { leftWidth: 0, topHeight: 40, randomList: function(max, size) { var list = [], berlari while (list.length < size) { ran = Math.floor(Matematika. random() * max); if (list.indexOf(ran) >= 0) lanjutkan; list.push(ran);
Oke, sekarang kelas untuk setiap bagian adegan telah dibuat, kita harus membuat adegan dan kemudian menumpuk primitif ini ke dalamnya!
Penciptaan adeganSiswa yang sudah familiar dengan hal ini harus mengetahui bahwa menggunakan HT untuk membuat adegan 3D hanya memerlukan komponen 3D baru, dan kemudian menambahkan adegan ke badan melalui fungsi addToDOM:
var g3d = E.main = ht.graph3d.Graph3dView(); //adegan 3d baru
File main.js terutama mengerjakan beberapa elemen penting dalam adegan 3D, seperti dinding, lantai, pintu, AC, dan posisi pembangkitan dan pelepasan semua kabinet, serta bagian interaktif yang sangat penting.
Saya tidak akan memposting kode untuk pembuatan dinding, lantai, pintu, AC dan lemari. Jika Anda tertarik, silakan periksa sendiri kodenya. Di sini kita terutama berbicara tentang mengklik dua kali kabinet dan benda apa pun yang berhubungan dengan kabinet ( pintu lemari, peralatan server) untuk membuat 3D Bagian tengah garis pandang kamera akan berpindah ke posisi tertentu di depan lemari yang diklik dua kali, dan gerakan ini sangat mulus tentang bagian ini sejak lama, dan akhirnya merujuk pada metode implementasi Demo ini.
Agar dapat mengatur mata dan pusat berulang kali, konten yang terkait dengan pengaturan kedua parameter ini dienkapsulasi ke dalam metode setEye dan setCenter. Metode setCenter mirip dengan metode setEye dan tidak akan diulangi di sini:
//Atur posisi mata var setEye = function(eye, finish) { if (!eye) return; var e = g3d.getEye().slice(0),//Dapatkan nilai mata saat ini dx = eye[0] - e[0], dy = eye[1] - e[1], dz = eye[2] - e[2]; // Memulai transisi animasi 500 milidetik ht.Default.startAnim({ durasi: 500, easing: easing,//Fungsi easing animasi finishFunc: finish || function() {}, //Fungsi dipanggil setelah animasi berakhir tindakan: function(v, t) {//Setel animasi v untuk merepresentasikan passing easing (t) Nilai setelah operasi fungsi, t mewakili kemajuan animasi saat ini [0~1], perubahan atribut umum didasarkan pada parameter v g3d.setEye([ //Atur mata dalam adegan 3D Nilai mata adalah larik, sesuai dengan nilai sumbu x, y, dan z masing-masing e[0] + dx * v, e[1] + dy * v, e[2] + dz * v ]);
Fakta bahwa saya tidak berulang kali mendeklarasikan fungsi setCenter tidak berarti bahwa fungsi ini tidak penting. Sebaliknya, fungsi ini memainkan peran yang menentukan dalam proses pergerakan garis pandang di atas setara dengan yang saya inginkan untuk berjalan di depan posisi target saya (setidaknya saya tentukan digunakan untuk tujuan ini), sambil sCenter Yang dimaksud dengan menggerakkan pandanganku ke posisi sasaran (misalnya aku bisa berdiri di posisiku saat ini dan melihat objek di belakangku ke kanan, atau aku bisa ke belakang ke kanan dan berdiri di depan objek untuk melihatnya). Ini sangat penting, silakan nikmati.
Acara klik dua kali itu sederhana. Cukup dengarkan acara yang diringkas oleh HT, tentukan jenis acara, dan ambil tindakan yang sesuai:
g3d.mi(function(e) {//addInteractorListener fungsi mendengarkan acara if (e.kind !== 'doubleClickData') //Tentukan jenis acara menjadi simpul klik dua kali kembali; var data = e.data, p3 ; if (data.a('cabinet')) //Body p3 = data.p3(); else { host = data.getHost(); host.a('cabinet')) {//Jika objek adsorpsi adalah kabinet p3 = host.p3(); } } if (!p3) return; setCenter(p3); posisi kabinet setEye([p3[0], 211, p3[2] + 247]); //Mengatur posisi dimana mata akan bergerak});bilah navigasi atas
Ketika saya pertama kali melihat contoh ini, saya berpikir, orang ini sangat mengagumkan. Saya telah menggunakan HT begitu lama, tetapi saya masih belum dapat membuat efek yang begitu indah menggunakan ht.widget.Toolbar HT saat itu, saya menyadari bahwa ini sebenarnya menggunakan HT. Itu dibuat dengan bentuk, luar biasa, saya sangat bodoh.
var form = E.top = ht.widget.FormPane(); //Komponen formulir teratas form.setRowHeight(E.topHeight);//Atur tinggi baris form.setVGap(-E.topHeight);//Atur jarak horizontal komponen formulir ke nilai negatif dari tinggi baris yang akan dipertahankan beberapa baris di posisi yang sama Baris form.setVPadding(0);//Mengatur bagian atas formulir dan jarak antara bagian atas dan konten komponen form.addRow([null, {//Tambahkan baris komponen ke formulir. Parameter pertama adalah array elemen. Elemen dapat berupa string, informasi parameter komponen yang dijelaskan dalam format json, elemen html, atau gambar null: { icon: './symbols/ inputBG.json ', regangan: 'centerUniform' }}], [40, 260]);//Parameter kedua adalah array informasi lebar untuk setiap elemen. Nilai lebar lebih besar dari 1 mewakili nilai absolut tetap, dan nilai lebar kurang dari atau sama dengan 1 mewakili nilai relatif kombinasi 80+0.3 form.addRow([null, null , { id: 'searchInput', textField: {}}, { elemen: 'Sistem manajemen visual ruang komputer', warna: 'putih', font: '18px arial , sans-serif'}, batal, { tombol: { // label: 'ViewChange', ikon: './symbols/viewChange.json', latar belakang: null, selectBackground: 'rgb(128,128,128)', borderColor: 'rgba(0, 0, 0, 0 ) ', diklik: function() { E.focusTo(); './symbols/alarm.json', dapat diubah: true, dipilih: false, latar belakang: null, selectBackground: 'rgb(128,128,128)', borderColor: 'rgba(0, 0, 0, 0)', onClicked: function( e) { E.setAlarmVisible(ini.isSelected()); 42, 218, 300, 0,1, 50, 10, 50, 10]);
Hal di atas hanya mungkin, tetapi sebenarnya tidak ditambahkan ke tag html, yang berarti tidak ada apa pun di antarmuka sekarang! Jangan lupa untuk menambahkan adegan 3D ke badan saat halaman dimuat, dan jangan lupa untuk menambahkan formulir ke badan. Saat mengatur acara perubahan ukuran jendela, formulir juga perlu diperbarui secara real time:
window.addEventListener('load', function() { g3d.addToDOM(); //Tambahkan adegan 3D ke badan document.body.appendChild(E.top.getView()); //Tambahkan div yang mendasarinya komponen formulir Tambahkan ke badan window.addEventListener('resize', function() {//Dengarkan peristiwa perubahan ukuran jendela E.top.iv();//Perbarui div yang mendasari formulir formulir });});
Berikut penjelasan fungsi addToDOM yang sangat penting untuk memahami mekanisme HT. Komponen HT umumnya tertanam dalam wadah seperti BorderPane, SplitView dan TabView. Komponen HT terluar mengharuskan pengguna untuk secara manual menambahkan elemen div dasar yang dikembalikan oleh getView() ke elemen DOM halaman , Ketika ukuran penampung induk berubah, jika penampung induk adalah komponen penampung HT yang telah ditentukan sebelumnya seperti BorderPane dan SplitView, penampung HT akan secara otomatis memanggil fungsi tidak valid dari komponen anak secara rekursif untuk memberi tahu pembaruan. Tetapi jika wadah induk adalah elemen html asli, komponen HT tidak dapat mengetahui bahwa ia perlu diperbarui. Oleh karena itu, komponen HT terluar umumnya perlu mendengarkan peristiwa perubahan ukuran jendela dan memanggil fungsi tidak valid dari jendela terluar. komponen yang akan diperbarui.
Untuk memudahkan pemuatan komponen terluar untuk mengisi jendela, semua komponen HT memiliki fungsi addToDOM, dan logika implementasinya adalah sebagai berikut, dimana iv adalah singkatan dari invalidate:
addToDOM = function(){ var self = this, view = self.getView(), style = view.style; document.body.appendChild(view); ' 0';//HT menyetel posisi div yang mendasari semua komponen ke absolute style.right = '0'; style.top = '0'; window.addEventListener('resize', function () { self.iv(); }, false); //Mendengarkan kejadian untuk perubahan ukuran jendela dan memberitahukan perubahan dan pembaruan komponen}
Dengan cara ini, semua kode sudah selesai. Anda dapat mengklik kanan untuk memeriksanya sendiri, dan file json yang sesuai dapat diperoleh dari jaringan.
Di atas adalah keseluruhan isi artikel ini, saya harap dapat bermanfaat untuk pembelajaran semua orang. Saya juga berharap semua orang mendukung VeVb Wulin Network.