Maison  >  Article  >  interface Web  >  Exemple de code pour implémenter la rotation de la turbine du ventilateur de contrôle industriel vectoriel basé sur HTML5 Canvas

Exemple de code pour implémenter la rotation de la turbine du ventilateur de contrôle industriel vectoriel basé sur HTML5 Canvas

黄舟
黄舟original
2017-03-27 15:50:021552parcourir

Les applications précédentes sur la topologie étaient toutes statique primitive, aujourd'hui nous allons concevoir une primitive mobile sur la topologie - rotation de la turbine

Jetons un coup d'œil à l'effet final que nous avons obtenu :

Voyons d'abord à quoi ressemble cemodèle de turbine

En regardant le modèle, ce modèle de turbine a trois pales, chaque pale a une forme irrégulière, évidemment elle ne peut pas être utilisée par notre HT pour Web graphiques de base, alors que devons-nous faire ? C'est très simple. HT for Web fournit une solution pour les graphiques personnalisés Nous pouvons utiliser des graphiques personnalisés comme des feuilles <.>

Avant de dessiner des feuilles, nous devons d'abord comprendre les connaissances de base du dessin graphique personnalisé en HT pour le Web :

Pour dessiner des graphiques personnalisés, vous devez spécifier le

vecteur tapez comme forme et spécifiez les informations de chaque point via le tableau de points Array. Les points sont représentés par [x1, y1, x2, y2, x3, y3, ...] pour stocker les coordonnées du point. la courbe peut être décrite par le tableau de segments Array, et le segment décrit chaque segment de ligne sous la forme de [1, 2, 1, 3...] :

1 : moveTo, occupe 1 point d'information, représentant le point de départ d'un nouveau chemin

2 : lineTo, occupe 1 point d'information, représentant la connexion du dernier point à ce point

3 : quadraticCurveTo, occupe 2 informations de point, le premier point est utilisé comme point de contrôle de la courbe et le deuxième point est utilisé comme point d'arrivée de la courbe

4 : bezierCurveTo, occupe 3 informations de points, les premier et deuxième points sont utilisés comme points de contrôle de courbe et le troisième point est utilisé comme point d'arrivée de la courbe

5 : closePath, n'occupe pas d'informations de point, représente la fin de ce dessin de chemin, et se ferme au point de départ du chemin

En plus de définir le paramètre segments, vous pouvez également définir l'attribut closePath pour comparer les polygones fermés : * closePath obtient et définit si le polygone est fermé. La valeur par défaut est false. Cette méthode est utilisée pour les lignes droites fermées. pas besoin de définir le paramètre des segments. 🎜>

D'accord, alors commençons à concevoir les lames

Nous avons défini 4 sommets dans le
vecteur

, et avons utilisé ces 4 sommets pour tracer la forme générale de la lame à travers des lignes droites. un peu abstrait, ce qui suit Cette feuille se transformera en ajoutant des points de contrôle et en modifiant les paramètres du segment.
ht.Default.setImage(&#39;vane&#39;, {
    width: 97,
    height: 106,
    comps: [
        {
            type: &#39;shape&#39;,
            points: [
                92, 67,
                62, 7,
                0, 70,
                60, 98
            ],
            segments: [
                1, 2, 2, 2
            ],
            background : &#39;red&#39;
        }
    ]
});

Nous ajoutons d'abord deux points de contrôle au segment de ligne entre le premier et le deuxième sommet via la méthode bezierCurveTo pour dessiner la courbe. Voici les attributs des points et des segments :

points: [
    92, 67,
    93, 35, 78, 0, 62, 7,
    0, 70,
    60, 98
],
segments: [
    1, 4, 2, 2
]
À ce stade, par rapport à la photo précédente, un bord est un peu courbé, parlons donc ensuite du deuxième bord et du troisième côté.

                                                                                                       Maintenant que les pales sont là, la prochaine chose à faire est d'utiliser trois de ces pales pour les assembler dans une turbine.

Pour assembler des ressources existantes, vous devez utiliser la classe de type d'image dans vecteur pour définir un nouveau vecteur. La méthode d'utilisation spécifique est la suivante :

points: [
    92, 67,
    93, 35, 78, 0, 62, 7,
    29, 13, 4, 46, 0, 70,
    28, 53, 68, 60, 60, 98
],
segments: [
    1, 4, 4, 4
]

在代码中,我们定义了三个叶片,并且对第二个和第三个叶片做了旋转和定位的处理,让这三个叶片排布组合成一个叶轮来,但是怎么能让叶轮中间空出一个三角形呢,这个问题解决起来不难,我们只需要在叶片的points属性上再多加一个顶点,就可以填充这个三角形了,代码如下:


points: [
    92, 67,
    93, 35, 78, 0, 62, 7,
    29, 13, 4, 46, 0, 70,
    28, 53, 68, 60, 60, 98,
    97, 106
],
segments: [
    1, 4, 4, 4, 2
]

在points属性上添加了一个顶点后,别忘了在segments数组的最后面添加一个描述,再来看看最终的效果:

到这个叶轮的资源就做好了,那么接下来就是要让这个叶轮旋转起来了,我们先来分析下:

要让叶轮旋转起来,其实原理很简单,我们只需要设置rotation属性就可以实现了,但是这个rotation属性只有在不断的变化中,才会让叶轮旋转起来,所以这个时候就需要用到定时器了,通过定时器来不断地设置rotation属性,让叶轮动起来。

恩,好像就是这样子的,那么我们来实现一下:

首先是创建一个节点,并设置其引用的image为impeller,再将其添加到DataModel,令节点在拓扑中显示出来:

var node = new ht.Node();
node.setSize(166, 181);
node.setPosition(400, 400);
node.setImage(&#39;impeller&#39;);
dataModel.add(node);

接下来就是添加一个定时器了:

window.setInterval(function() {
    var rotation = node.getRotation() + Math.PI / 10;
    if (rotation > Math.PI * 2) {
        rotation -= Math.PI * 2;
    }
    node.setRotation(rotation);
}, 40);

OK了,好像就是这个效果,但是当你选中这个节点的时候,你会发现这个节点的边框在不停的闪动,看起来并不是那么的舒服,为什么会出现这种情况呢?原因很简单,当设置了节点的rotation属性后,节点的显示区域就会发生变化,这个时候节点的宽高自然就发生的变化,其边框也自然跟着改变。

还有,在很多情况下,节点的rotation属性及宽高属性会被当成业务属性来处理,不太适合被实时改变,那么我们该如何处理,才能在不不改变节点的rotation属性的前提下令叶轮转动起来呢?

矢量中,好像有数据绑定的功能,在手册中是这么介绍的:

绑定的格式很简单,只需将以前的参数值用一个带func属性的对象替换即可,func的内容有以下几种类型:

1. function类型,直接调用该函数,并传入相关Data和view对象,由函数返回值决定参数值,即func(data, view);调用。

2. string类型:

    2.1 style@***开头,则返回data.getStyle(***)值,其中***代表style的属性名。

    2.2 attr@***开头,则返回data.getAttr(***)值,其中***代表attr的属性名。

    2.3 field@***开头,则返回data.***值,其中***代表data的属性名。

    2.4 如果不匹配以上情况,则直接将string类型作为data对象的函数名调用data.***(view),返回值作为参数值。

除了func属性外,还可设置value属性作为默认值,如果对应的func取得的值为undefined或null时,则会采用value属性定义的默认值。 例如以下代码,如果对应的Data对象的attr属性stateColor为undefined或null时,则会采用yellow颜色:

color: {
    func: &#39;attr@stateColor&#39;,
    value: &#39;yellow&#39;
}

数据绑定的用法已经介绍得很清楚了,我们不妨先试试绑定叶片的背景色吧,看下好不好使。在矢量vane中的background属性设置成数据绑定的形式,代码如下:

background : {
    value : &#39;red&#39;,
    func : &#39;attr@vane_background&#39;
}

在没有设置vane_background属性的时候,令其去red为默认值,那么接下来我们来定义下vane_background属性为blue,看看叶轮会不会变成蓝色:

node.setAttr(&#39;vane_background&#39;, ‘blue&#39;);

看下效果:

果然生效了,这下好了,我们就可以让叶轮旋转变得更加完美了,来看看具体该这么做。

首先,我们先在节点上定义一个自定义属性,名字为:impeller_rotation

node.setAttr(&#39;impeller_rotation&#39;, 0);

然后再定义一个名字为rotate_impeller的矢量,并将rotation属性绑定到节点的impeller_rotation上:

ht.Default.setImage(&#39;rotate_impeller&#39;, {
    width : 220,
    height : 220,
    comps : [
        {
            type : &#39;image&#39;,
            name : &#39;impeller&#39;,
            rect : [27, 20, 166, 180.666],
            rotation : {
                func : function(data) { 
                    return data.getAttr(&#39;impeller_rotation&#39;); 
                }
            }
        }
    ]
});

这时候我们在定时器中修改节点的rotation属性改成修改自定义属性impeller_rotation就可以让节点中的叶轮旋转起来,并且不会影响到节点自身的属性,这就是我们想要的效果。

在2D上可以实现,在3D上一样可以实现,下一章我们就来讲讲叶轮旋转在3D上的应用,今天就先到这里,下面附上今天Demo的源码,有什么问题欢迎大家咨询。


ht.Default.setImage('vane', {
    width : 97,
    height : 106,
    comps : [
        {
            type : 'shape',
            points : [
                92, 67,
                93, 35, 78, 0, 62, 7,
                29, 13, 4, 46, 0, 70,
                28, 53, 68, 60, 60, 98,
                97, 106
            ],
            segments : [
                1, 4, 4, 4, 2
            ],
            background : {
                value : 'red',
                func : 'attr@vane_background'
            }
        }
    ]
});

ht.Default.setImage('impeller', {
    width : 166,
    height : 180.666,
    comps : [
        {
            type : 'image',
            name : 'vane',
            rect : [0, 0, 97, 106]
        },
        {
            type : 'image',
            name : 'vane',
            rect : [87.45, 26.95, 97, 106],
            rotation : 2 * Math.PI / 3
        },
        {
            type : 'image',
            name : 'vane',
            rect : [20.45, 89.2, 97, 106],
            rotation : 2 * Math.PI / 3 * 2
        }
    ]
});

ht.Default.setImage('rotate_impeller', {
    width : 220,
    height : 220,
    comps : [
        {
            type : 'image',
            name : 'impeller',
            rect : [27, 20, 166, 180.666],
            rotation : {
                func : function(data) {
                    return data.getAttr('impeller_rotation');
                }
            }
        }
    ]
});

function init() {
    var dataModel = new ht.DataModel();

    var graphView = new ht.graph.GraphView(dataModel);
    var view = graphView.getView();
    view.className = "view";
    document.body.appendChild(view);

    var node = new ht.Node();
    node.setSize(220, 220);
    node.setPosition(200, 400);
    node.setImage('rotate_impeller');
    node.setAttr(&#39;impeller_rotation&#39;, 0);
    node.setAttr('vane_background', 'blue');
    dataModel.add(node);

    var node1 = new ht.Node();
    node1.setSize(166, 181);
    node1.setPosition(500, 400);
    node1.setImage('impeller');
    dataModel.add(node1);

    window.setInterval(function() {
        var rotation = node.a('impeller_rotation') + Math.PI / 10;
        if (rotation > Math.PI * 2) {
            rotation -= Math.PI * 2;
        }
        node.a('impeller_rotation', rotation);
        node1.setRotation(rotation);

    }, 40);
}

 

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!

Déclaration:
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