モチベーション:
最初に二分木を作ろうと思ったのは、会社の構造図を作る必要があったからです。 以前のアプローチは、グラフィック ソフトウェアを使用して直接絵を描くことでした。見た目は素晴らしいですが、変更があるたびに新しいものをペイントする必要があります。 一方、Web ページ上の行の表示とレイアウトはかなり制限されています。動的に生成されたデータに基づいて植字や配置を行うのは非常に難しく、美観も満足のいくものではありません。 いろいろ試した結果、データ操作にはXML+XSLを使用し、行の美化にはVMLを使用し、オブジェクトの配置にはJAVASCRIPTを使用することにしました。
材料:
XML ボリュームの構造ツリー図には、flow2.xml と flow2.xsl の 2 つのファイルがあります。
効果:
ここを参照してください
説明する:
バイナリ ツリーのアイデア (1)
<html xmlns:v="urn:schemas-microsoft-com:vml">
<スタイル>
v:* { 動作: url(#default#VML) }
</スタイル>
<v:group id="group1" name="group1" coordsize = "100,100">
…
</v:グループ>
これらは VML の基本的な形式ですので、詳細な説明は省略します。
XML はツリー構造になっており、各データを読み取る必要があります。
XML データ ツリーが走査されます。再帰操作は XSL の利点の 1 つです。
また、トラバーサル操作を実行するために他のさまざまな方法を使用して失敗した後、XSL を使用することにしました。
<フロールート>
<vcTitle>バイナリ ツリー -- 構造図</vcTitle>
<著者>帆走</著者>
<電子メール>[email protected]</電子メール>
<フローノード>
<iプロセス>1</iプロセス>
<vcCourse>最初のノード</vcCourse>
<i次はい>
<フローノード>
<iプロセス>2</iプロセス>
<vcCourse>2 番目のノード</vcCourse>
<i次はい>…</i次はい>
<iNextNo>…</iNextNo>
</フローノード>
</i次はい>
<iNextNo>
<フローノード>
<iプロセス>3</iプロセス>
<vcCourse>3 番目のノード</vcCourse>
<i次はい>…</i次はい>
<iNextNo>…</iNextNo>
</フローノード>
</i次いいえ>
</フローノード>
</フロールート>
ロジックは非常に単純です。現在のノード (1) の下に 2 つの子ノード (2、3) があります。
ノード 2 とノード 3 をノード 1 の左下と右下に配置するだけです。
ここでは、表示しやすいように、左側と右側のノードの接続線にそれぞれ緑と赤を使用しています。
XSL の再帰関数については前に説明しましたが、各詳細な表示ステップをより明確に確認するには、次のコードを模倣してアラート ステートメントを追加するだけです。
<xsl:template match="FlowNode">
…
<SCRIPT言語="JavaScript1.2">
…
alert('段階的に表示');
…
</スクリプト>
…
</xsl:テンプレート>
上のスローモーションを見て、私の考えが理解できるでしょうか?
二分木のアイデア (2)
私のアイデアは非常にシンプルです。
(1) 現在のノードのデータを読み込み、VML を使用して新しいオブジェクトを生成します。
オブジェクトに初期値を割り当てます (名前、ID、スタイルなど)。
(2) スクリプト コントロールを使用して、現在のオブジェクトを配置します。 (3) 現在のノードとその親ノードの間に矢印と線を追加します。
(4) 現在のノードの子ノードを探し続け、最後までループします。
つまり、すべてのノードが走査され、ツリーが生成されました。
<xsl:template match="FlowNode">
…
<xsl:apply-templates />
…
</xsl:テンプレート>
<xsl:template match="iNextYes">
<xsl:apply-templates select="./FlowNode" />
</xsl:template>
<xsl:template match="iNextNo">
<xsl:apply-templates select="./FlowNode" />
</xsl:テンプレート>
再帰的なプロセス全体は、上記の 3 つのモジュール (テンプレート) によって完了します。
最初のテンプレートは、現在のノードの各子ノードのテンプレートと一致するときに次の 2 つのテンプレートを呼び出し、後の 2 つのテンプレートは特定の実行中に最初のテンプレートを呼び出します。これは再帰関数と同等です。
文法:
現在のノード内の各子ノードのテンプレートを順に照合するには、要素の基本形式 <xsl:apply-templates /> を使用します。
それ以外の場合、一致するノードは、<xsl:apply-templates select="./FlowNode" /> などの選択パラメーターの XPath 式の値によって決定されます。
(1) と (2) の機能は、select パラメータで指定された式の文字列値を返すことです。
検索条件が同じなので、戻り値も同じになります。
ただ、使われる場面によって書き方が違うだけです。
(1) <xsl:value-of select="./iProcess/text()" />
(2) {./iProcess/text()}
ここではいくつかの変数が定義されており、これらの変数に基づいてノードの配置が計算式を呼び出します。
root_left //ルートの左マージン = すべてのリーフの割り当てられた幅 (y*10) + すべてのリーフの幅 (y*50) + 左マージンの基本値 (10)
root_top //ルートの上マージン = 上マージンの基本値(10)
objOval //現在のオブジェクトはオブジェクトです
objOval_iProcess //現在のオブジェクトのステップ値
objParentOval //現在のオブジェクトの親ノードはオブジェクトです
objParentOval_iProcess //現在のオブジェクトの親ノードのステップ値
objParent_name //現在のオブジェクトの親ノードの名前
Leaf_left //現在のオブジェクトのすべての子ノードの左側のリーフの数
Leaf_right //現在のオブジェクトのすべての子ノードの右側の葉の数
Leaf_sum //現在のオブジェクトのすべての子ノードの葉の数
: 子ノードを持たない現在のノードを指します。
ノードの位置決め式:
(1) 現在のノードがルート ノードです
//ルートの位置
SobjOval.style.left=parseInt(root_left);
SobjOval.style.top=parseInt(root_top);
//parseInt() 関数の機能は整数値を取得することですが、そうでない場合は NAN になります
// isNaN() 関数の機能は、parseInt で取得した値が整数であるかどうかを判断することです。
(2) 現在のノードは親ノードの左側の子ノードです
1) 判定条件は、現在のオブジェクトの親ノード名='iNextYes'です。
…
2) 右の子リーフがある場合、式は次のようになります。
現在のノードの左 = 親ノードの左 - 現在のノードの右の子リーフの幅の合計 - 現在のノードの幅
3) 右の子リーフがないが、左の子リーフがある場合、式は次のとおりです。
現在のノードの左 = 親ノードの左 - 現在のノードの左の子リーフの合計幅
4) 現在のノード自体がリーフの場合、式は次のようになります。
現在のノードの左 = 親ノードの左 - 現在のノードの幅...
(3) 現在のノードが親ノードの右の子ノードである
1) 判定条件は、現在のオブジェクトの親ノード名='iNextNo'です。
…
2) 左側の子リーフがある場合、式は次のようになります。
現在のノードの左 = 親ノードの左 + 現在のノードの左の子リーフの幅の合計 + 現在のノードの幅
3) 左の子リーフがなく、右の子リーフがある場合、式は次のとおりです。
現在のノードの左側 = 親ノードの左側 + 現在のノードの右側の子リーフの合計幅
4) 現在のノード自体がリーフの場合、式は次のようになります。
現在のノードの左 = 親ノードの左 + 現在のノードの幅...
式 (2) と (3) はどちらも現在のノードの左側を取得しますが、現在のノードの上部も取得する必要があります。
非常に単純な式: 現在のノードの上部 = 親ノードの上部 + オフセット (80)
二分木のアイデア (3)
接続線の配置に関するアイデア:
(1) 現在のノードと親ノードの位置を調べる (2) 現在のノードが親ノードの左の子ノードであるか右の子ノードであるかを判断する (3) 線を引く
いくつかの変数がここで定義されています。
objOval //現在のノードはオブジェクトです
objParentOval //現在のオブジェクトの親ノードはオブジェクトです
objLine // 現在の行はオブジェクトです
ラインの位置決め式:
from="x1,y1" to="x2,y2" は VML で行を配置する方法であり、
現在のノードが親ノードの左側の子ノードである場合、式は次のようになります。
from = 親ノードの左 + オフセット (15)、親ノードの上 + オフセット (32)
to = left + 親ノードのオフセット (30)、top - 親ノードのオフセット (2)
現在のノードが親ノードの右側の子ノードである場合、式は次のようになります。
from = 親ノードの左 + オフセット (35)、親ノードの上 + オフセット (32)
to = 親ノードの左 + オフセット (20)、親ノードの上 - オフセット (2)
私が思いつくのはそれだけです。
会社の構造図を作成するだけであれば、はるかに簡単になります。
以下はサイ・ヤングのアイデアであり、私は彼のベースに基づいてもう少し詳しく説明します。
まず最下位レベルのノード数を計算して幅を取得します。
次に、ノードの上位ノードの位置をその所属に基づいて再帰的に計算する必要があります。
各レベルのノードは、所属に従ってソートする必要があります。まず、「基本値」を設定します。つまり、子ノードを含む各ノードの左の値は、そのノードの幅の半分に等しくなります。基本値に加えて所有します。
追記:
なぜか最近ネットの調子が悪いです。オンラインよりもオフラインで多くの時間を費やします。
したがって、コードはまだ簡素化されていません。実際には、次のような改善が必要な機能がまだ多くあります。
右クリック メニューを追加する必要があります。右クリック メニューには、新しいノードの作成、ノード名の変更、関連付けの変更などの機能が含まれています。各ノードを右クリックして、このノードの右クリック メニューを開くことができます。 。
説明する:
1) flow2.xml はデータ ファイルです。誰でも問題ないと思います。
2) flow2.xsl はフォーマット ファイルです。注意すべき点がいくつかあります。
(1) スクリプト内:
(1) <xsl:value-of select="./iProcess/text()" />;
(2) {./iProcess/text()}
(1) と (2) の関数は、select パラメータで指定された式の文字列値を返します。
検索条件が同じなので、戻り値も同じになります。
ただ、使われる場面によって書き方が違うだけです。
<xsl:apply-templates select="team" order-by="blue_ID"/>
たとえば、次のコードを生成したいとします。
<div name="パラメータ値">内容</div>
名前は「name」、パラメータ値は XML データの現在のノードの下にある子ノード ブックの値であると仮定します。
最初の記述方法は、最初に属性名を追加し、次にパラメーター値を追加することです。
<div>
<xsl:属性名="名前">
<xsl:value-of select="./book/text()"/> </xsl:attribute>
コンテンツ
</div>
2 番目の書き方は、属性名とパラメータ値を直接追加する方法です。
<div name="{./book/text()}">内容</div>
具体的な使用方法については、私が作成したコード内の例を参照してください。
XSL は公式標準に含まれています xmlns:xsl=" http://www.w3.org/1999/XSL/Transform "
<xsl:value-of select="./book/text()"/>
機能は次のとおりです。テキスト値を書き出すだけです。
<xsl:value-of select="./book"/>
テキスト値とそのすべての子ノードの内容が表示されます。
試してみて、子ノードのあるものと子ノードのないものを出力して、表示される結果が同じかどうかを確認できます。
(2) 注:
IE5 は <tag att="{xpath}"> をサポートしていません。
使いたい
<tag><xsl:attribute name="att"><xsl:value-of select="xpath"></xsl:attribute>
名前空間を使用する必要があります
xmlns:xsl=" http://www.w3.org/TR/WD-xsl "
<?xml version="1.0" encoding="gb2312" ?>
もう一つ:
Encoding="gb2312" が、ほとんどの XML 教科書に示されているコードに追加されることはほとんどありません。
したがって、XML で中国語を使用すると、この宣言が記述されていないためにエラーが報告されます。
追記:
ここで私が話しているのは考え方です。たとえ話をすれば、自然と役に立ちます。