Parcourir la source

增加undo实例。

sybotan il y a 4 ans
Parent
commit
f996db32c7

+ 218 - 0
docs/.vuepress/components/example/web/graph/scene/Undo1.vue

@@ -0,0 +1,218 @@
+<template>
+    <div>
+        <el-button @click="addCircle">Circle</el-button>
+        <el-button @click="addRect">Rect</el-button>
+        <el-button @click="deleteItem">Delete</el-button>
+        <el-button @click="undo">Undo</el-button>
+        <el-button @click="redo">Redo</el-button>
+        <canvas id="undoFrame" width="800" height="400" />
+    </div>
+</template>
+
+<script lang="ts">
+    import Vue from "vue";
+    import ElementUI from "element-ui";
+    import { SMouseEvent, SUndoStack } from "@saga-web/base";
+    import { SColor, SPainter, SRect } from "@saga-web/draw";
+    import { SGraphyItem, SGraphyScene, SGraphyView } from "@saga-web/graphy";
+    import {SGraphyCommand} from "@saga-web/graphy/lib";
+    import {SUndoCommand} from "@saga-web/base/lib";
+    import {SPoint} from "@saga-web/draw/lib";
+
+    Vue.use(ElementUI);
+
+    class RectItem extends SGraphyItem {
+        width = 100;
+        height = 100;
+
+        constructor(parent: SGraphyItem | null) {
+            super(parent);
+            this.moveable = true;
+            this.selectable = true;
+            this.selected = true;
+        }
+
+        boundingRect(): SRect {
+            return new SRect(0, 0, this.width, this.height);
+        }
+
+        onDraw(canvas: SPainter): void {
+            canvas.pen.color = SColor.Blue;
+            canvas.pen.lineWidth = 5;
+            canvas.brush.color = this.selected ? SColor.Red : SColor.Green;
+            canvas.drawRect(0, 0, this.width, this.height)
+        }
+    }
+
+    class CircleItem extends SGraphyItem {
+        r = 50;
+
+        constructor(parent: SGraphyItem | null) {
+            super(parent);
+            this.moveable = true;
+            this.selectable = true;
+        }
+
+        boundingRect(): SRect {
+            return new SRect(0, 0, this.r * 2, this.r * 2);
+        }
+
+        onDraw(canvas: SPainter): void {
+            canvas.pen.color = SColor.Blue;
+            canvas.pen.lineWidth = 5;
+            canvas.brush.color = this.selected ? SColor.Red : SColor.Green;
+            canvas.drawCircle(this.r, this.r, this.r);
+        }
+    }
+
+    class SScene extends SGraphyScene {
+        undoStack = new SUndoStack();
+        /** 定义命令 */
+        cmd = 0;
+
+        constructor() {
+            super();
+        }
+
+
+        onMouseUp(event: SMouseEvent): void {
+            switch(this.cmd) {
+                case 1:
+                    this.addCircle(event.x, event.y);
+                    break;
+                case 2:
+                    this.addRect(event.x, event.y);
+                    break;
+                default:
+                    super.onMouseUp(event);
+            }
+            this.cmd = 0;
+        }
+
+        private addCircle(x: number, y: number): void {
+            let item = new CircleItem();
+            item.moveTo(x - 50, y - 50);
+            this.addItem(item);
+            this.undoStack.push(new SGraphyAddCommand(this, item));
+            item.connect("onMove", this, this.onItemMove.bind(this));
+        }
+
+        private addRect(x: number, y: number): void {
+            let item = new RectItem();
+            item.moveTo(x - 50, y - 50);
+            this.addItem(item);
+            this.undoStack.push(new SGraphyAddCommand(this, item));
+            item.connect("onMove", this, this.onItemMove.bind(this));
+        }
+
+        onItemMove(item: SGraphyItem, ...arg: any): void {
+            this.undoStack.push(new SGraphyMoveCommand(this, item, arg[0][0] as SPoint, arg[0][1] as SPoint));
+        }
+    }
+
+    class TestView extends SGraphyView {
+        constructor() {
+            super("undoFrame");
+        }
+    }
+
+    class SGraphyAddCommand extends SGraphyCommand {
+        item: SGraphyItem;
+        parent: SGraphyItem | null;
+
+        constructor(scene: SGraphyScene, item: SGraphyItem) {
+            super(scene);
+            this.item = item;
+            this.parent = item.parent;
+        }
+        mergeWith(command: SUndoCommand): boolean {
+            return false;
+        }
+
+        redo(): void {
+            this.item.parent = this.parent;
+            this.parent.update();
+        }
+
+        undo(): void {
+            this.item.parent = null;
+            this.parent.update();
+        }
+    }
+
+    class SGraphyDeleteCommand extends SGraphyCommand {
+        mergeWith(command: SUndoCommand): boolean {
+            return false;
+        }
+
+        redo(): void {
+        }
+
+        undo(): void {
+        }
+    }
+
+    class SGraphyMoveCommand extends SGraphyCommand {
+        item: SGraphyItem;
+        old: SPoint;
+        pos: SPoint;
+
+        constructor(scene: SGraphyScene, item: SGraphyItem, old: SPoint, pos: SPoint) {
+            super(scene);
+            this.item = item;
+            this.old = old;
+            this.pos = pos;
+        }
+        mergeWith(command: SUndoCommand): boolean {
+            if (command instanceof  SGraphyMoveCommand && command.item == this.item) {
+                command.pos = this.pos;
+                return true;
+            }
+            return false;
+        }
+
+        redo(): void {
+            this.item.pos = new SPoint(this.pos.x, this.pos.y);
+            this.item.update();
+        }
+
+        undo(): void {
+            this.item.pos = new SPoint(this.old.x, this.old.y);
+            this.item.update();
+        }
+    }
+
+    export default {
+        data() {
+            return {
+                scene: new SScene();
+            }
+        },
+        mounted(): void {
+            let view = new TestView();
+            view.scene = this.scene;//new SScene(); //this.data.scene;
+        },
+        methods: {
+            addCircle() {
+                this.scene.cmd = 1;
+            },
+            addRect() {
+                this.scene.cmd = 2;
+            },
+            deleteItem() {
+
+            },
+            undo() {
+                console.log("undo");
+                this.scene.undoStack.undo();
+            },
+            redo() {
+                this.scene.undoStack.redo();
+            }
+        }
+    }
+</script>
+
+<style scoped>
+
+</style>

+ 2 - 1
docs/dev/saga-graphy/index.js

@@ -24,7 +24,8 @@ const content = [
                 children: [
                     ["/dev/saga-graphy/scene-manage/items/clock", "时钟"],
                 ]
-            }
+            },
+            ["/dev/saga-graphy/scene-manage/undo", "Undo示例"]
         ]
     },
     {

+ 10 - 0
docs/dev/saga-graphy/scene-manage/undo.md

@@ -0,0 +1,10 @@
+# Undo/Redo 框架
+::: details 目录
+[[toc]]
+:::
+
+<example-web-graph-scene-Undo1 />
+
+::: details 查看代码
+<<< @/docs/.vuepress/components/example/web/graph/scene/Undo1.vue
+:::

+ 3 - 3
package.json

@@ -12,9 +12,9 @@
     "publish": "node publish.js"
   },
   "dependencies": {
-    "@saga-web/base": "^2.1.9",
-    "@saga-web/draw": "^2.1.82",
-    "@saga-web/graphy": "^2.1.52",
+    "@saga-web/base": "^2.1.14",
+    "@saga-web/draw": "^2.1.83",
+    "@saga-web/graphy": "^2.1.58",
     "axios": "^0.18.1",
     "element-ui": "^2.12.0",
     "vue": "^2.6.10",