問題の原因
サブピクセル形状は、ピクセル内でアルファブレンディングを使用します。残念ながら、隣接したときに長方形がシームレスにブレンドされるアルファブレンドアルゴリズムはありません。
たとえば、次の場合:
- 背景色は白です
- 前景色は黒で、
- 2つの長方形があり、それぞれが1つのピクセルの半分をカバーしています。
各長方形は、不透明度50%の黒でペイントされます。1つ目は、白いピクセルを灰色に変換します。2つ目は、それをより暗い灰色に変換しますが、黒には変換しません。これらの長方形が隣接するピクセルで黒く続く場合は、黒の中に濃い灰色のピクセルが表示されます。
2種類のソリューション
この問題を解決するには、2つの一般的な方法があります。
- 単一のジオメトリを使用してすべての長方形を定義する、または
- ユーザーに問題が発生しないように、初期レンダリングを十分に高い解像度にする必要があります。
単一のジオメトリの使用方法
長方形のセットがある場合は、結合された形状を含む単一のPathGeometryを使用して、長方形のセット全体をペイントする単純なコントロールを作成できます。アイデアを説明するために、次のように、高さが異なる2つの長方形が隣り合っている場合:
<Rectangle Canvas.Left="0" Canvas.Top="0" Width="1.5" Height="2" Fill="Red" />
<Rectangle Canvas.Left="1.5" Canvas.Top="0" Width="1.5" Height="4" Fill="Red" />
次のような単一のPathGeometryでレンダリングできます。
<Path Data="M0,0 L0,2 L1.5,2 L1.5,4 L3,4 L3,0 Z" Fill="Red" />
これを実装する実際的な方法は次のとおりです。
- クリック可能であるが見えないように、透明なブラシで長方形をペイントします
- Zオーダーの長方形の下にパスコントロールを追加します
Data
ジオメトリを構築するコンバーターを使用して、パスコントロールのプロパティをデータソースにバインドするデータ。
レイアウトシステムを使用して長方形を配置している場合は、代わりに、長方形ごとにAdornerを作成してAdornerLayerを使用し、レンダリング時に最初のパスの結合パスを計算して、残りを非表示にすることができます。
上記は、ソースデータからPathGeometryを簡単に生成できることを前提としています。より複雑なシナリオでは、パスコントロールをサブクラス化して、親のビジュアルツリーで指定された形状を検索し、一般的な幾何学的アルゴリズムを使用して、余分なエッジのないそれらの結合を表すPathGeometryを計算できます。
長方形に複数の色がある場合は、色ごとに1つずつ複数のパスコントロールを使用するか、Drawingオブジェクトを作成してそれを表示できます。
PathGeometryを構築するためのコードの構造は次のとおりです。
var geo = new PathGeometry();
var figure = new PathFigure();
var segment = new PolyLineSegment();
segment.Points.Add(...);
segment.Points.Add(...);
segment.Points.Add(...);
segment.Points.Add(...);
segment.Points.Add(...);
figure.Segments.Add(segment);
geo.Figures.Add(figure);
初期レンダリングを強制的に高解像度にする方法
より高い解像度でレンダリングを強制するには:
- グラフを表示する数倍の大きさで内部的に作成します。たとえば、ViewBoxでグラフをラップします。
- VisualBrushまたはRenderTargetBitmapを使用して、グラフを個別にレンダリングするように強制します
- そのVisualBrushでペイントされた長方形をUIに追加します
通常、WPFは、ViewBrushを使用するときに必要な実際の解像度でレンダリングするのが賢明ですが、実際のグラフを実際に大きなサイズで画面に表示することでだまされる可能性がありますが、親コントロールによってクリップされるため、大きすぎるバージョンは実際には表示されません。
もちろん、必要な解像度を指定しているため、この問題はRenderTargetBitmapには存在しませんが、ビットマップをいつ再レンダリングするかを知るのは難しい場合があります。データの変更のみを再レンダリングする場合はイベントを使用できますが、視覚的な変更によって再レンダリングをトリガーする場合は、より困難です。