Undo1.vue 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. <template>
  2. <div>
  3. <el-button @click="addCircle">Circle</el-button>
  4. <el-button @click="addRect">Rect</el-button>
  5. <el-button @click="deleteItem">Delete</el-button>
  6. <el-button @click="undo">Undo</el-button>
  7. <el-button @click="redo">Redo</el-button>
  8. <canvas id="undoFrame" width="800" height="400" />
  9. </div>
  10. </template>
  11. <script lang="ts">
  12. import Vue from "vue";
  13. import ElementUI from "element-ui";
  14. import { SMouseEvent, SUndoStack } from "@saga-web/base";
  15. import { SColor, SPainter, SRect } from "@saga-web/draw";
  16. import { SGraphyItem, SGraphyScene, SGraphyView } from "@saga-web/graphy";
  17. import {SGraphyCommand} from "@saga-web/graphy/lib";
  18. import {SUndoCommand} from "@saga-web/base/lib";
  19. import {SPoint} from "@saga-web/draw/lib";
  20. Vue.use(ElementUI);
  21. class RectItem extends SGraphyItem {
  22. width = 100;
  23. height = 100;
  24. constructor(parent: SGraphyItem | null) {
  25. super(parent);
  26. this.moveable = true;
  27. this.selectable = true;
  28. this.selected = true;
  29. }
  30. boundingRect(): SRect {
  31. return new SRect(0, 0, this.width, this.height);
  32. }
  33. onDraw(canvas: SPainter): void {
  34. canvas.pen.color = SColor.Blue;
  35. canvas.pen.lineWidth = 5;
  36. canvas.brush.color = this.selected ? SColor.Red : SColor.Green;
  37. canvas.drawRect(0, 0, this.width, this.height)
  38. }
  39. }
  40. class CircleItem extends SGraphyItem {
  41. r = 50;
  42. constructor(parent: SGraphyItem | null) {
  43. super(parent);
  44. this.moveable = true;
  45. this.selectable = true;
  46. }
  47. boundingRect(): SRect {
  48. return new SRect(0, 0, this.r * 2, this.r * 2);
  49. }
  50. onDraw(canvas: SPainter): void {
  51. canvas.pen.color = SColor.Blue;
  52. canvas.pen.lineWidth = 5;
  53. canvas.brush.color = this.selected ? SColor.Red : SColor.Green;
  54. canvas.drawCircle(this.r, this.r, this.r);
  55. }
  56. }
  57. class SScene extends SGraphyScene {
  58. undoStack = new SUndoStack();
  59. /** 定义命令 */
  60. cmd = 0;
  61. constructor() {
  62. super();
  63. }
  64. onMouseUp(event: SMouseEvent): void {
  65. switch(this.cmd) {
  66. case 1:
  67. this.addCircle(event.x, event.y);
  68. break;
  69. case 2:
  70. this.addRect(event.x, event.y);
  71. break;
  72. default:
  73. super.onMouseUp(event);
  74. }
  75. this.cmd = 0;
  76. }
  77. private addCircle(x: number, y: number): void {
  78. let item = new CircleItem();
  79. item.moveTo(x - 50, y - 50);
  80. this.addItem(item);
  81. this.undoStack.push(new SGraphyAddCommand(this, item));
  82. item.connect("onMove", this, this.onItemMove.bind(this));
  83. }
  84. private addRect(x: number, y: number): void {
  85. let item = new RectItem();
  86. item.moveTo(x - 50, y - 50);
  87. this.addItem(item);
  88. this.undoStack.push(new SGraphyAddCommand(this, item));
  89. item.connect("onMove", this, this.onItemMove.bind(this));
  90. }
  91. onItemMove(item: SGraphyItem, ...arg: any): void {
  92. this.undoStack.push(new SGraphyMoveCommand(this, item, arg[0][0] as SPoint, arg[0][1] as SPoint));
  93. }
  94. }
  95. class TestView extends SGraphyView {
  96. constructor() {
  97. super("undoFrame");
  98. }
  99. }
  100. class SGraphyAddCommand extends SGraphyCommand {
  101. item: SGraphyItem;
  102. parent: SGraphyItem | null;
  103. constructor(scene: SGraphyScene, item: SGraphyItem) {
  104. super(scene);
  105. this.item = item;
  106. this.parent = item.parent;
  107. }
  108. mergeWith(command: SUndoCommand): boolean {
  109. return false;
  110. }
  111. redo(): void {
  112. this.item.parent = this.parent;
  113. this.parent.update();
  114. }
  115. undo(): void {
  116. this.item.parent = null;
  117. this.parent.update();
  118. }
  119. }
  120. class SGraphyDeleteCommand extends SGraphyCommand {
  121. mergeWith(command: SUndoCommand): boolean {
  122. return false;
  123. }
  124. redo(): void {
  125. }
  126. undo(): void {
  127. }
  128. }
  129. class SGraphyMoveCommand extends SGraphyCommand {
  130. item: SGraphyItem;
  131. old: SPoint;
  132. pos: SPoint;
  133. constructor(scene: SGraphyScene, item: SGraphyItem, old: SPoint, pos: SPoint) {
  134. super(scene);
  135. this.item = item;
  136. this.old = old;
  137. this.pos = pos;
  138. }
  139. mergeWith(command: SUndoCommand): boolean {
  140. if (command instanceof SGraphyMoveCommand && command.item == this.item) {
  141. command.pos = this.pos;
  142. return true;
  143. }
  144. return false;
  145. }
  146. redo(): void {
  147. this.item.pos = new SPoint(this.pos.x, this.pos.y);
  148. this.item.update();
  149. }
  150. undo(): void {
  151. this.item.pos = new SPoint(this.old.x, this.old.y);
  152. this.item.update();
  153. }
  154. }
  155. export default {
  156. data() {
  157. return {
  158. scene: new SScene();
  159. }
  160. },
  161. mounted(): void {
  162. let view = new TestView();
  163. view.scene = this.scene;//new SScene(); //this.data.scene;
  164. },
  165. methods: {
  166. addCircle() {
  167. this.scene.cmd = 1;
  168. },
  169. addRect() {
  170. this.scene.cmd = 2;
  171. },
  172. deleteItem() {
  173. },
  174. undo() {
  175. console.log("undo");
  176. this.scene.undoStack.undo();
  177. },
  178. redo() {
  179. this.scene.undoStack.redo();
  180. }
  181. }
  182. }
  183. </script>
  184. <style scoped>
  185. </style>