みなさんこんにちは、フロントエンドのスイカ兄弟です。今回はグラフィックエディタのアレンジ機能を実装してみます。
まずは効果を見てみましょう。
移動には次の 4 つの方法があります。
- Front: 指定されたグラフィックスを一番上に移動します。
- Back (Back): 指定したグラフィックを一番下に移動します。
- 進む: 指定された要素を 1 レイヤー上に移動します。
- 1 レベル下に移動 (後方): 最上位の要素を 1 レベル下に移動します。
移動したグラフィックを維持し、元の相対順序を維持するように注意する必要があります。
編集者の github アドレス:
https://github.com/F-star/suika
オンライン体験:
https://blog.fstars.wang/app/suika/
フロントトップ
トップは、グラフィックを一番上の位置に配置することで、
グラフ木に対応する配列グラフを想定すると、移動する要素の集合はmovedGraphSet(集合型)です。すべきことは、それらの要素を配列の最後に移動することです。
グラフィックスは配列の順序で描画され、後で描画されるグラフィックスは前のグラフィックスをカバーするため、最初ではなく最後に移動されます。これには注意が必要です。
グラフを再帰し、movedGraphSet にない要素を新しい配列に移動し、movedGraphSet の要素を tailGraphs 配列に移動するだけです。
const front = (graphs: Graph[], movedGraphSet: Set<Graph>) => {
const newGraphs: Graph[] = [];
const tailGraphs: Graph[] = [];
for (let i = 0; i < graphs.length; i++) {
const graph = graphs[i];
if (movedGraphSet.has(graph)) {
tailGraphs.push(graph);
} else {
newGraphs.push(graph);
}
}
newGraphs.push(...tailGraphs);
return newGraphs;
};
グラフ ツリーは、リンクされたリストである場合もあれば、グループの概念を持っている場合もあります。実装コードは異なる場合がありますが、考え方は同じです。
戻る
底上げも同様です。
今度は右から左へトラバース。さらに、配列を移動する操作を減らすために、配列に対して追加の逆順を実行する必要があります。
配列の先頭に新しい要素を挿入することは、元の配列全体を 1 スペース分戻すことであり、時間計算量は 1 ですが、O(n)
最後に追加することは必要ありません。
const back = (graphs: Graph[], movedGraphSet: Set<Graph>) => {
const newGraphs: Graph[] = [];
const tailGraphs: Graph[] = [];
for (let i = graphs.length - 1; i >= 0; i--) {
const graph = graphs[i];
if (movedGraphSet.has(graph)) {
tailGraphs.push(graph);
} else {
newGraphs.push(graph);
}
}
newGraphs.push(...tailGraphs);
return newGraphs.reverse(); // 反向
};
進む 1 レベル上に移動
movedGraphSet 内のグラフを 1 つ後方に移動します。移動する必要のある複数のグラフィックスが互いに隣接している場合、それらは全体として、それらの背後にある最初の移動していないグラフィックスの背後に配置する必要があることに注意してください。
たとえば、操作される配列は であり[0, 1, 2, 3, 4, 5, 6, 7]
、指定された配列要素は であり[1, 2, 6]
、 return です[0, 3, 1, 2, 4, 5, 7, 6]
。
最初は、複数のポインタを使用して連続的に移動する必要があるグラフィックスを記録し、左から右にトラバースすることを考えていましたが、実装が複雑すぎることがわかりました。ポインターを維持するには、いつポインターを移動するかなどを決定する必要もあります。
その後、気が変わって右から左へのトラバースに変更。現在の要素が移動対象の要素である場合は、次の要素と交換されます。
このようにして、移動する必要のない要素は、移動中の要素のクラスターを押し進めることができます。
const forward = (graphs: Graph[], movedGraphs: Set<Graph>) => {
const newGraphs = [...graphs];
for (let i = newGraphs.length - 2; i >= 0; i--) {
if (movedGraphs.has(newGraphs[i])) {
// 交换
[newGraphs[i], newGraphs[i + 1]] = [newGraphs[i + 1], newGraphs[i]];
}
}
return newGraphs;
};
戻る 1 つ下のレイヤーに移動
同じ方法。
反対に行きなさい。
const backward = (graphs: Graph[], movedGraphs: Set<Graph>) => {
const newGraphs = [...graphs];
for (let i = 1; i < newGraphs.length; i++) {
if (movedGraphs.has(newGraphs[i])) {
[newGraphs[i], newGraphs[i - 1]] = [newGraphs[i - 1], newGraphs[i]];
}
}
return newGraphs;
};
終わり
私はフロントエンドのスイカの兄弟です。私をフォローして、フロントエンドのグラフィックスの知識を学んでください。