Zpět

Vue.js & X3Dom

Ukázka #1 - Data-binding do 3D scény

  • 
    <div class="fixed-ratio">
        <!-- X3Dom scéna -->
        <x3d>
            <scene>
                <shape>
                    <appearance>
                        <material :diffusecolor="diffuseColor" :specularcolor="specularColor"></material>
                    </appearance>
                    <text solid="false" :string="text">
                        <fontstyle family="TYPEWRITER" justify="MIDDLE" size="2"></fontstyle>
                    </text>
                </shape>
            </scene>
        </x3d>
    </div>
    <div>
        <!-- Formulář pro ovládání scény -->
        <form>
    	    <div>
    		    <label>Text</label>
                <!-- Vstup pro text s obousměrným data-bindingem v-model -->
    		    <input type="text" v-model="text" />
    	    </div>
    	        <div class="grid">
    		    <div>
    			    <label>Základní barva</label>
    			    <div>
    				    <input type="color" v-model="diffuseColor" />
    				    <span :style="'color: ' + diffuseColor"> {{ diffuseColor }} </span>
    			    </div>
    		    </div>
    		    <div>
    			    <label>Barva lesku</label>
    			    <div>
    				    <input type="color" v-model="specularColor" />
    				    <span :style="'color: ' + specularColor"> {{ specularColor }} </span>
    			    </div>
    		    </div>
    	    </div>
        </form>
    </div>
    
  • // Vue aplikace
    var app1 = new Vue({
        el: '#app1',
        data: {
            text: 'Hello world!',
            diffuseColor: '#dd3300',
            specularColor: '#ee9966'
        }
    });
    
{{ diffuseColor }}
{{ specularColor }}

Ukázka #2 - Práce s polem

  • 
    <div class="fixed-ratio">
        <!-- X3Dom scéna -->
        <x3d>
            <scene>
                <!-- Cyklus s využitím directivy v-for pro vykreslení všech kostek -->
                <group v-for="(item, index) in items">
                    <transform :translation="((index - ((items.length - 1) / 2)) * 2) + ' 0 0'">
                        <transform :translation="item.position.x + ' ' + item.position.y + ' ' + item.position.z">
                            <shape>
                                <appearance>
                                    <material :diffuseColor="item.color"></material>
                                </appearance>
                                <box :size="item.size.x + ' ' + item.size.y + ' ' + item.size.z" useGeoCache="false">
                                </box>
                            </shape>
                        </transform>
                    </transform>
                </group>
            </scene>
        </x3d>
    </div>
    <div>
        <!-- Formulář pro ovládání scény -->
        <form>
            <ul>
                <!-- Cyklus s využitím directivy v-for pro ovládací panely ke všem kostkám -->
                <li v-for="(item, index) in items">
                    <div class="grid">
                        <div>
                            <label>Objekt #{{index + 1}}</label>
                            <div>
                                <input type="color" v-model="item.color" />
                                <span :style="'color: ' + item.color"> {{ item.color }} </span>
                            </div>
                        </div>
                        <div>
                            <label>Šířka {{ Math.floor(item.size.x * 100) }}%</label>
                            <input type="range" v-model="item.size.x" min="0.1" max="2" step="0.1" />
                        </div>
                        <div>
                            <label>Výška {{ Math.floor(item.size.y * 100) }}%</label>
                            <input type="range" v-model="item.size.y" min="0.1" max="2" step="0.1" />
                        </div>
                        <div>
                            <label>Délka {{ Math.floor(item.size.z * 100) }}%</label>
                            <input type="range" v-model="item.size.z" min="0.1" max="2" step="0.1" />
                        </div>
                        <div>
                            <label>X {{ item.position.x }}</label>
                            <input type="range" v-model="item.position.x" min="-1" max="1" step="0.1" />
                        </div>
                        <div>
                            <label>Y {{ item.position.y }}</label>
                            <input type="range" v-model="item.position.y" min="-1" max="1" step="0.1" />
                        </div>
                        <div>
                            <label>Z {{ item.position.z }}</label>
                            <input type="range" v-model="item.position.z" min="-1" max="1" step="0.1" />
                        </div>
                        <div>
                            <!-- Tlačítko napojené na metodu pro smazání kostky -->
                            <a v-on:click="remove(index)">Smazat</a>
                        </div>
                    </div>
                </li>
            </ul>
            <!-- Tlačítko napojené na metodu pro přidání kostky -->
            <a v-on:click="add()" > Přidat nový objekt</a>
        </form>
    </div>
    
  • // Vue aplikace
    var app2 = new Vue({
        el: '#app2',
        data: {
            items: [],
        },
        methods: {
            // metoda pro přidání kostky
            add: function () {
                this.items.push({
                    size: { x: 1, y: 1, z: 1 },
                    position: { x: 0, y: 0, z: 0 },
                    color: getRandomColor()
                });
            },
            // metoda pro smazání kostky
            remove: function (index) {
                this.items.splice(index, 1);
            }
        },
        // metoda volaná při inicializaci
        created: function () {
            this.add();
            this.add();
        }
    });
    
  • {{ item.color }}
Přidat nový objekt

Ukázka #3 - Pokročilejší scéna

  • 
    <x3d>
    	<scene>
    		<navigationinfo headlight="false"></navigationinfo>
    		<viewpoint position="0 0 14" set_bind="true"></viewpoint>
    		<transform rotation="1 0 0 1.0471975511965976">
    			<DirectionalLight direction="0.5 -1 0" on="true" intensity="0.6" shadowIntensity="0.2"></DirectionalLight>
    			<transform translation="0 -0.05 0">
    				<shape>
    					<appearance>
    						<material diffuseColor="0.05 0.4 0.05"></material>
    					</appearance>
    					<box size="16 0.1 6"></box>
    				</shape>
    			</transform>
    			<transform rotation="1 0 0 -1.5707963267948966" translation="0 0.01 -1.6">
    				<gold-text text="LED diody (8 bitů)" size="1"></gold-text>
    			</transform>
    			<group v-for="(led, index) in leds">
    				<transform :translation="((((leds.length - index) - (leds.length / 2)) * 2) - 1) + ' 0 0'">
    					<group def="ledSwitch">
    						<transform translation="0 0.01 1" rotation="1 0 0 -1.5707963267948966">
    							<gold-text :text="Math.pow(2, index)" size="0.5"></gold-text>
    						</transform>
    						<transform translation="0 0.15 -0.25">
    							<transform translation="0 0.95 0">
    								<PointLight :on="led.state" :intensity="led.state ? 4 : 0.2" :color="color" radius="3" shadowIntensity="0"></PointLight>
    								<shape>
    									<led-material :state="led.state" :color="color"></led-material>
    									<sphere radius="0.6"></sphere>
    								</shape>
    							</transform>
    							<transform translation="0 0.55 0">
    								<shape>
    									<led-material :state="led.state" :color="color"></led-material>
    									<cylinder height="0.8" radius="0.6"></cylinder>
    								</shape>
    							</transform>
    							<shape>
    								<led-material :state="led.state" :color="color"></led-material>
    								<cylinder height="0.3" radius="0.66"></cylinder>
    							</shape>
    						</transform>
    						<transform translation="0 0.25 2">
    							<transform translation="0 0.35 0">
    								<shape :onclick="'app3.lightSwitch(' + index + ')'">
    									<appearance>
    										<material diffuseColor="0.5 0.5 0.8"></material>
    									</appearance>
    									<cylinder :height="led.state ? 0.2 : 0.6" radius="0.4"></cylinder>
    								</shape>
    							</transform>
    							<shape>
    								<appearance>
    									<material diffuseColor="0.1 0.1 0.1"></material>
    								</appearance>
    								<box size="1.4 0.5 1.4"></box>
    							</shape>
    						</transform>
    					</group>
    				</transform>
    			</group>
    		</transform>
    	</scene>
    </x3d>
    
  • // Vue komponent pro materiál LED diody
    Vue.component('led-material', Vue.extend({
        props: ['state', 'color'],
        template: '<appearance><material :diffuseColor="state ? color : \'0.4 0.4 0.4\'" :emissiveColor="state ? color : \'0.6 0.6 0.6\'" transparency="0.2" :shininess="state ? 25 : 0.2"></material></appearance>'
    }));
    
    // Vue komponent pro zlatý text
    Vue.component('gold-text', Vue.extend({
        props: ['text', 'size'],
        template: '<shape><appearance><material ambientintensity="0.1" diffusecolor="1 0.6 0" shininess="0.5" specularcolor="0.8 0.4 0" emissivecolor="0 0 0"></material></appearance><text :string="text" solid="false" ccw="true" usegeocache="true" lit="true"><fontstyle family="TYPEWRITER" style="NORMAL" :size="size" justify="MIDDLE" quality="4"></fontstyle></text></shape>'
    }));
    
    // Vue aplikace
    var app3 = new Vue({
        el: '#app3',
        data: {
            leds: [
                { state: false },
                { state: true },
                { state: false },
                { state: false },
                { state: true },
                { state: true },
                { state: false },
                { state: false },
            ],
            color: '#ff0000',
        },
        // dopočítáváné vlastnosti pro hexadecimální a binární zápis
        computed: {
            int: {
                get: function () {
                    var r = 0;
                    for (var i = 0; i < this.leds.length; i++) {
                        r += this.leds[i].state ? Math.pow(2, i) : 0;
                    }
                    return r;
                },
                set: function (v) {
                    var bin = toBin(v);
                    for (var i = 0; i < this.leds.length; i++) {
                        this.leds[this.leds.length - i - 1].state = bin[i] == "1";
                    }
                }
            },
            hex: {
                get: function () { return toHex(this.int); },
                set: function (v) { this.int = parseInt(v, 16); }
            },
            bin: {
                get: function () { return toBin(this.int); },
                set: function (v) { this.int = parseInt(v, 2); }
            }
        },
        methods: {
            // metoda pro přepnutí LED diody
            lightSwitch: function (index) {
                this.leds[index].state = !this.leds[index].state;
            }
        }
    });
    
  • 
    <form>
    	<div>
    		<label>
    			<span class="left">0</span>
    			<span class="right">255</span>
    		</label>
    		<div>
    			<input type="range" v-model="int" min="0" max="255" step="1" />
    		</div>
    	</div>
    	<div>
    		<div class="grid">
    			<div>
    				<label>Číslo</label>
    				<input type="text" v-model="int" />
    			</div>
    			<div>
    				<label>Binární zápis</label>
    				<input type="text" v-model="bin" />
    			</div>
    			<div>
    				<label>Hexadecimální zápis</label>
    				<input type="text" v-model="hex" />
    			</div>
    			<div>
    				<label>Barva světla</label>
    				<input type="color" v-model="color" />
    				<span :style="'color: ' + color"> {{ color }} </span>
    			</div>
    		</div>
    	</div>
    </form>
    
{{ color }}