Maison > interface Web > Tutoriel H5 > Désérialisation par pression 3D de Canvas en HTML5

Désérialisation par pression 3D de Canvas en HTML5

小云云
Libérer: 2017-12-18 15:58:58
original
1995 Les gens l'ont consulté

Dans cet article nous partagerons avec vous la désérialisation pressurisée 3D de Canvas en HTML5. Dans les applications pratiques, je pense qu'il est très pratique de pouvoir opérer des changements de scène 3D en exploitant des fichiers JSON, notamment lorsque l'éditeur glisse et. supprime les éléments graphiques et produit une série de modifications sur les éléments graphiques, les données peuvent nous être reflétées de manière très intuitive. Ici, nous avons simplement fait un exemple de base pour votre référence.

Reproduction de scène de pratique :

Désérialisation par pression 3D de Canvas en HTML5

Tout d'abord, installons la scène de cet exemple que des amis familiers ont peut-être déjà vue. ceci. La scène est divisée en trois parties : gauche, supérieure droite et inférieure droite. HT peut facilement diviser la scène via ht.widget.SplitView pour obtenir une bonne mise en page. Enfin, ajoutez ce composant divisé au corps du code HTML :

//场景搭建
dataModel = new ht.DataModel();//数据容器
                
g3d = new ht.graph3d.Graph3dView(dataModel);//3D 组件
propertyView = new ht.widget.PropertyView(dataModel);// 属性组件
formPane = new ht.widget.FormPane();//表单组件
rightSplit = new ht.widget.SplitView(propertyView, formPane, 'v', 100);//分割组件
                        
new ht.widget.SplitView(g3d, rightSplit, 'h', 0.65).addToDOM();
Copier après la connexion

L'étape suivante consiste à l'ajouter au corps du code HTML. scène Élément graphique et ajouter l'élément graphique à la scène 3D. À ce stade, nous pouvons ajouter divers attributs, styles et étiquettes à l'élément graphique en tant que balises. L'élément graphique utilisé dans cet exemple est un modèle 3D, en utilisant ht.Default. parseObj La fonction analyse les fichiers obj et mtl :

//添加模型
var params = {center: true};//JSON格式控制参数 传入 ht.Default.parseObj 函数中
var modelMap = ht.Default.parseObj(meter_obj, meter_mtl, params);//解析obj和mtl文件, 解析后返回的map结构json对象中,每个材质名对应一个模型信息
Copier après la connexion

Bien sûr, le principe est que les deux fichiers Meter_obj et Meter_mtl ont été déclarés ici, nous mettons respectivement ces deux parties dans le fichier js, et Header. appel.

Nous pouvons voir dans l'animation ci-dessus que les seules parties du modèle qui doivent être modifiées dans cet exemple sont le "pointeur" et le "commutateur" ci-dessous, nous obtenons donc ces deux parties obj via le modèle de traversée partie et enregistrer le modèle 3D :

var array = [];
for(var name in modelMap){
    var model = modelMap[name];//modelMap 中的模型
    array.push(model);
                    
    if(name === 'pointer'){//obj 文件中的一个模型 名称为 pointer
        model.mat = {//矩阵变化参数,可对模型进行矩阵变化后导入 
            func: function(data){
                var start = Math.PI * 0.736,
                range = Math.PI * 1.49,   
                angle = start - range * data.a('meter.value') / 4;//动态获取了 meter.value 的值
                return ht.Default.createMatrix([//将一组JSON描述的缩放、移动和旋转等操作转换成对应的变化矩阵
                    { t3: [0, -82.5, 0] },
                    { r3: [0, 0, angle] },
                    { t3: [0, 82.5, 0]  }
                ]);
            }
        };                         
    }
    if(name === 'switch'){//obj 文件中的一个模型 名称为 switch
        model.mat = {
            func: function(data){
                return ht.Default.createMatrix([
                    { t3: [0, 48.5, 0] },
                    { r3: [0, 0, data.a('meter.angle')] },
                    { t3: [0, -48.5, 0]  }
                ]);
            }
        }; 
        model.color = {
            func: function(data){
                if(data.a('meter.angle')){
                    return 'rgb(186, 0, 0)';
                }else{
                    return 'black';
                }
            }
        };
    }
}
ht.Default.setShape3dModel('meter', array);//注册3D模型,请参考modeling建模手册 第一参数为模型名称,第二参数为 JSON 类型对象
Copier après la connexion

Ensuite, l'utilisateur peut définir directement l'attribut shape3d si nécessaire pour l'utiliser comme nom du modèle 3D enregistré ici. Nous allons créer 3 nœuds ci-dessous, et définir le modèle 3D. nœud à ce modèle 3D :

for(var i=0; i<3; i++){//创建3个节点 meter
    var node = new ht.Node();
    node.setTag(i);//设置 tag 标签
    node.setName('Meter - 00' + (i+1));//设置图元名称一般显示在图元的下方
    node.s({
        'label.color': 'white',
        'label.background': '#5271B8',
        'label.face': 'center',
        'label.position': 23,
        'label.scale': 2,
        'label.reverse.flip': true, 
                        
        'note.scale': 1.5,//设置字体大小,这种方式不会碰到浏览器最小字体的问题
        'note.t3': [-30, -5, -90], 
                        
        'note2.scale': 1.2,
        'note2.position': 17,
        'note2.t3': [0, -20, -30],
        'note2.color': 'black',
        'note2.background': 'yellow', 
                        
        'shape3d': 'meter',//设置为前面注册的 meter 3D 模型
        'shape3d.scaleable': false,
        'wf.visible': 'selected',//选中图元时显示线框
        'select.brightness': 1
    });
    node.a({//自定义属性 下面会利用这些自定义属性进行数据绑定
        'meter.value': i+1,
        'meter.angle': i * Math.PI / 3
    });
    node.p3(i*200-200, params.rawS3[1]/2, i===1?100:-100);                    
    node.r3(0, -Math.PI/6*(i-1), 0);
    node.s3(params.rawS3);//设置图元的大小为 rawS3 模型的原始尺寸
    dataModel.add(node); //向数据模型中添加节点           
}
dataModel.sm().ss(dataModel.getDataByTag(1));//设置默认选中 tag 标签为1的图元
Copier après la connexion

Nous ajoutons ici deux annotations au nœud sous forme d'invites de texte. Vous pouvez surcharger getNote/getNote2 (un nœud dans HT prend en charge les doubles annotations, fournissez donc la deuxième annotation de note2). La fonction surcharge la méthode de dénomination de la note. Bien entendu, d'autres invites de texte similaires dans HT peuvent également modifier les informations d'affichage du texte de cette manière, nous obtenons ici meter.value et meter.angle via la liaison de données dynamiques de deux attributs. :

g3d.getNote = function(data){//重载 getNote 方法
    return 'Value:' + data.a('meter.value').toFixed(2);
};
g3d.getNote2 = function(data){
    var value = Math.round(data.a('meter.angle') / Math.PI * 180);//获取了 meter.angle 属性,数据实时变化                 
    return value ? 'Angle:' + value : 'Switch is off';
};
Copier après la connexion

Nous avons également fait preuve d'un peu de prudence dans la partie affichage de la scène~en modifiant les valeurs de l'œil et du centre pour obtenir l'effet de vue de loin vers de près :

var oldEye = g3d.getEye().slice(0),
oldCenter = g3d.getCenter().slice(0),
newEye = [200, 300, 650],
newCenter = [0, params.rawS3[1]/2, 0];

ht.Default.startAnim({//动画              
    duration: 1000,//持续时间
    easing: function(t){ //动画缓动函数,默认采用 ht.Default.animEasing
        return (t *= 2) < 1 ? 0.5 * t * t : 0.5 * (1 - (--t) * (t - 2));                      
    },
    action: function(k){//action 函数必须提供,实现动画过程中的属性变化 参数 k 代表通过 easing(t) 函数运算后的值
        g3d.setEye(
            oldEye[0] + (newEye[0] - oldEye[0]) * k,
            oldEye[1] + (newEye[1] - oldEye[1]) * k,
            oldEye[2] + (newEye[2] - oldEye[2]) * k
        );
        g3d.setCenter(
            oldCenter[0] + (newCenter[0] - oldCenter[0]) * k,
            oldCenter[1] + (newCenter[1] - oldCenter[1]) * k,
            oldCenter[2] + (newCenter[2] - oldCenter[2]) * k
        );    
    }                  
});
Copier après la connexion

L'implémentation entière de gauche est terminée ~ Ensuite, la partie supérieure droite est implémentée, l'affichage et le contrôle des valeurs d'attribut. Nous avons ajouté un total de quatre attributs : nom, mètre.valeur, mètre.angle et rotation, via des opérations de liaison de données Utilisez la valeur dans la barre de propriétés pour modifier l'état d'affichage dans le modèle 3D. Pour la liaison de données, nous appelons cette propriété en obtenant la valeur dans accessType et le nom :

propertyView.addProperties([//用 json 的数组参数方式批量添加属性信息
    {
        name: 'name',//属性名 这里不用设置 accessType,因为 accessType 默认的值为 setName/getName 这种格式 
        editable: true//设置为可编辑状态
    },
    {
        name: 'meter.value',//用于存取name属性,该属性结合accessType属性最终实现对Data属性的存取
        accessType: 'attr',//通过 getAttr/setAttr 获取或设置属性值
        editable: true,
        slider: {
            min: 0,
            max: 4
        }
    },
    {
        name: 'meter.angle',
        accessType: 'attr',
        editable: true,
        formatValue: function(value){//一般用于将数字转换更易读的文本格式
            return Math.round(value / Math.PI * 180);
        },
        slider: {
            min: 0,
            max: Math.PI,
            step: Math.PI/180*5,//每移动一下滑动的步进
            getToolTip: function(){//设置鼠标放在图元上的文字提示
                return Math.round(this.getValue() / Math.PI * 180);
            }
        }
    },
    {
        name: 'rotation',
        editable: true,
        formatValue: function(value){
            return Math.round(value / Math.PI * 180);
        },
        slider: {
            min: -Math.PI,
            max: Math.PI,
            step: Math.PI/180*5,
            getToolTip: function(){
                return Math.round(this.getValue() / Math.PI * 180);
            }
        }
    }                    
]);
Copier après la connexion

Enfin, continuez. dans la partie inférieure droite du panneau du formulaire formPane. Pour l'analyse, formPane ajoute des lignes au formulaire via la fonction addRow. Il y a deux lignes dans ce formulaire, et la première ligne comporte deux parties :

formPane.addRow([//向表单组件中添加行
    {
        id: 'export',
        button: {//按钮                              
            label: 'Export JSON',
            onClicked: function(){//点击时触发的函数
                var json = dataModel.serialize();
                formPane.v('textArea', json);
            }
        }
    },
    {
        button: {                            
            label: 'Import JSON',
            onClicked: function(){
                dataModel.clear();//清空数据模型
                dataModel.deserialize(formPane.v('textArea'));//将获取到的 textArea 中的数据反序列化,是下面一行的 id 值
            }
        }
    }
],
[0.1, 0.1]);  //最后的参数是这行的宽度分配比例 小于1的值为比例,大于1为实际值                             
formPane.addRow([
    {
        id: 'textArea',
        textArea: {
        }
    }
],
[0.1], 0.1);
Copier après la connexion

. De cette façon, nous pouvons modifier la barre de propriétés ou le fichier JSON, vous pouvez voir directement l'effet de notre modification en 3D~ Et si ? N'est-ce pas cool et rapide ?

Recommandations associées :

Le canevas JavaScript implémente une animation de rotation

Réalisation de la surveillance des stations de métro basée sur HTML5 Canvas

Exemple de comment dessiner des cœurs sur une toile html5


Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal