独自の小さなフローベースのレイアウト エンジンを実装しようとしています。HTML レイアウトの動作を模倣する必要がありますが、DOM 部分ではなくレンダリング ツリーのみを模倣する必要があります。render-tree の要素の基本クラスは Node
class です。それは持っています:
- DOM 内の要素へのリンク (そのライブラリでレンダリング ツリーを構築するもの用)
- その親への参照 (
ContainerNode
インスタンスまたは None です。後述) - layouting-options への参照
- X、Y、幅、高さ ( で
layout()
サイズが計算された後、で位置が計算されcompute_size()
ます。位置はlayout()
親のメソッドで定義されますが、サイズはオプション リファレンスで定義されます)。
その方法は次のとおりです。
reflow()
呼び出しcompute_size()
とlayout()
compute_size()
これは、ノードの幅と高さを計算するためのものです。layout()
これは、ノード自体ではなく、ノードのサブノードを配置するためのものです。paint()
これは、ライブラリのユーザーが上書きするためにあります。
このContainerNode
クラスは、サブノードの処理を実装しています。add_node()
これは、渡されたノードをコンテナの子に追加する という新しいメソッドを提供します。forceが True に設定されている場合を除いて、コンテナは渡されたノードを拒否できるため、関数はデフォルトで False に設定されているパラメータforceも受け入れます。
これら 2 つのクラスは、レイアウト アルゴリズムを実装していません。私の目的は、さまざまなタイプのレイアウト用にさまざまなクラスを作成することでした (CSS では、主にdisplay
属性によって定義されます)。昨夜、テキスト レイアウトでいくつかのテストを行いました。私のコードは、pastebin.com (pygame が必要) で見つけることができます。これを Python スクリプト ファイルに保存して、次のように呼び出すことができます。
python text_test block -c -f "Georgia" -s 15
注: コードは本当にくだらないものです。嘘の深い誤解についてのコメントに感謝します。
上記のコードのクラスInlineNodeRow
は、属性に似たレイアウトのノードをdisplay:inline
( と組み合わせてNodeBox
) 実装する方法についての私の考えを実際に表しています。
問題 1 - インライン テキストのマージンとパディング
ライブラリでの現在のアプローチに戻ると、テキストの 1 つの単語も 1 つのノードとして表されます (上記のコードのように)。<span>
しかし、タグのマージンとパディングについて 2 つのことに気付きました。
- マージンが設定されている場合、水平マージンのみが考慮され、垂直マージンは無視されます。
- パディングが親コンテナーをオーバーフローしており、スパン ノードを「移動」していません。
http://jsfiddle.net/CeRkT/1/を参照してください。
ここに問題があります。 のサイズを計算したい場合InlineNodeBox
、テキストノードにそのサイズを尋ね、それをノードのサイズに追加します。ただし、テキストノードのサイズにはマージンとパディングが含まれており、HTML レンダラーの配置には含まれていません。したがって、次のコードは正しくありません。
def compute_size(self):
# Propagates the computation to the child-nodes.
super(InlineNodeBox, self).compute_size()
self.w = 0
self.h = 0
for node in self.nodes:
self.w += node.w
if self.h < node.h:
self.h = node.h
node.w
マージンとパディングが含まれます。TextNode
私が目にする次の問題は、テキストノードを正しくレイアウトするために、単語ごとに単一の s に分割したかったのですが、マージンとパディングはこれらすべてのノードに適用され、HTML のマージンとパディングは<span>
タグのみです。
各単語を個別のノードに入れるという現在の考えは理想的ではないと思います。ブラウザがレンダーツリーを構築する方法、またはより良いアイデアはありますか?
問題 2 - 単語が長すぎます。次の行に入れます。
このクラスは現在、1 行InlineNodeBox
のみを編成しています。上記のコード例では、前者がノードの受け入れを拒否した (つまり、収まらなかった) ときに、新しいfromを作成しました。レンダー ツリーを最初から再構築したくないので、現在のアプローチではこれを行うことはできません。ノードが一度受け入れられたが、次のリフローで超えた場合、次の行に単語を適切に配置するにはどうすればよいですか (クラスがノードの単一行のみを編成するという考えを保持していると仮定します)。InlineNodeBox
NodeBox
InlineNodeBox
InlineNodeBox
これがすべて理にかなっていることを本当に願っています。私のコンセプトがわからない場合は、お気軽にお尋ねください。また、他の概念、リソースへのリンク、ドキュメント、出版物などに対する批判やアイデアにも非常にオープンです。