TextItem.vue 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. <template>
  2. <div>
  3. <el-row>
  4. <el-input v-model="input" @keyup.native="handleKeyup" style="width:200px;" placeholder="请输入内容"></el-input>
  5. <el-button @click="undo">Undo</el-button>
  6. <el-button @click="redo">Redo</el-button>
  7. </el-row>
  8. <canvas id="TextItem1" width="400" height="400" />
  9. </div>
  10. </template>
  11. <script lang="ts">
  12. import { SMouseEvent, SUndoStack } from "@saga-web/base";
  13. import { SColor, SPainter, SRect, SFont, SSize, STextBaseLine } from "@saga-web/draw";
  14. import { SObjectItem } from "@saga-web/big/lib/items/SObjectItem";
  15. import { SGraphItem, SGraphScene, SGraphView } from "@saga-web/graph";
  16. import { SGraphCommand } from "@saga-web/graph/lib";
  17. import { SUndoCommand } from "@saga-web/base/lib";
  18. import { SPoint } from "@saga-web/draw/lib";
  19. class TextItem extends SObjectItem {
  20. /** 文本内容 */
  21. private _text: string = "";
  22. get text(): string {
  23. return this._text;
  24. }
  25. set text(v: string) {
  26. this._text = v;
  27. this.update();
  28. }
  29. /** 文本颜色 */
  30. private _color: string ="#333333";
  31. get color():string {
  32. return this._color;
  33. }
  34. set color(v: string) {
  35. this._color = v;
  36. this.update();
  37. }
  38. /** 字体 */
  39. private _font: SFont;
  40. get font():SFont {
  41. return this._font;
  42. }
  43. set font(v: SFont) {
  44. this._font = v;
  45. this.update();
  46. }
  47. /** 文本绘制最大宽 */
  48. maxWidth: number | undefined = undefined;
  49. /**
  50. * 构造函数
  51. *
  52. * @param parent 指向父Item
  53. * @param str 文本内容
  54. */
  55. constructor(parent: SGraphItem | null = null, str: string = "") {
  56. super(parent);
  57. this._text = str;
  58. this._font = new SFont();
  59. this.moveable = true;
  60. this.selectable = true;
  61. this.selected = true;
  62. }
  63. /**
  64. * 对象边界区域
  65. *
  66. * @return 边界区域
  67. */
  68. boundingRect(): SRect {
  69. return new SRect(this.x, this.y, this.width, this.height);
  70. }
  71. protected onResize(oldSize: SSize, newSize: SSize) {
  72. console.log("resize",oldSize,newSize)
  73. }
  74. /**
  75. * Item绘制操作
  76. *
  77. * @param canvas 画布
  78. */
  79. onDraw(canvas: SPainter): void {
  80. // this.width = canvas.toPx(canvas.textWidth(this.text));
  81. // this.height = canvas.toPx(this.font.size);
  82. // canvas.font.textBaseLine = this.font.textBaseLine;
  83. // canvas.font.textDirection = this.font.textDirection;
  84. // canvas.font.textAlign = this.font.textAlign;
  85. // canvas.font.name = this.font.name;
  86. // canvas.font.size = canvas.toPx(this.font.size);
  87. // canvas.brush.color = new SColor(this.color);
  88. // canvas.drawText(this.text, 0, 0, this.maxWidth);
  89. canvas.brush.color = SColor.White;
  90. canvas.drawRect(this.x, this.y, this.width, this.height);
  91. //绘制文本
  92. canvas.brush.color = new SColor(this.color);
  93. canvas.font = this.font;
  94. canvas.drawText(this.text, this.x, this.y , this.maxWidth);
  95. }
  96. }
  97. class SScene extends SGraphScene {
  98. undoStack = new SUndoStack();
  99. textItem: SGraphItem = new TextItem(null);
  100. constructor() {
  101. super();
  102. this.addItem(this.textItem);
  103. this.textItem.connect("onMove", this, this.onItemMove.bind(this));
  104. }
  105. updateText(str: string): void {
  106. if(this.textItem.text !== str) {
  107. let old = this.textItem.text;
  108. this.textItem.text = str;
  109. this.undoStack.push(new SGraphPropertyCommand(this, this.textItem, "text", old, str));
  110. }
  111. }
  112. onItemMove(item: SGraphItem, ...arg: any): void {
  113. this.undoStack.push(new SGraphMoveCommand(this, item, arg[0][0] as SPoint, arg[0][1] as SPoint));
  114. }
  115. }
  116. class TestView extends SGraphView {
  117. constructor() {
  118. super("TextItem1");
  119. }
  120. }
  121. /**
  122. * 属性修改命令类
  123. *
  124. * @author 张宇(taohuzy@163.com)
  125. */
  126. class SGraphPropertyCommand<T> extends SGraphCommand {
  127. /** 指向item对象 */
  128. item: SGraphItem;
  129. /** 属性名称 */
  130. propName: string;
  131. /** 属性旧值 */
  132. oldProp: T;
  133. /** 属性新值 */
  134. newProp: T;
  135. /**
  136. * 构造函数
  137. *
  138. * @param scene 命令所属的场景类
  139. * @param item 命令所属的item类
  140. * @param propName 修改的属性名称
  141. * @param oldProp 修改前的属性值
  142. * @param newProp 修改后的属性值
  143. */
  144. constructor(scene: SGraphScene, item: SGraphItem, propName: string, oldProp: T, newProp: T) {
  145. super(scene);
  146. this.item = item;
  147. this.propName = propName;
  148. this.oldProp = oldProp;
  149. this.newProp = newProp;
  150. } // Constructor
  151. /**
  152. * redo操作
  153. */
  154. redo(): void {
  155. this.item[this.propName] = this.newProp;
  156. this.item.update();
  157. } // Function redo()
  158. /**
  159. * undo操作
  160. */
  161. undo(): void {
  162. this.item[this.propName] = this.oldProp;
  163. this.item.update();
  164. } // Function undo()
  165. }
  166. class SGraphMoveCommand extends SGraphCommand {
  167. item: SGraphItem;
  168. old: SPoint;
  169. pos: SPoint;
  170. constructor(scene: SGraphScene, item: SGraphItem, old: SPoint, pos: SPoint) {
  171. super(scene);
  172. this.item = item;
  173. this.old = old;
  174. this.pos = pos;
  175. }
  176. mergeWith(command: SUndoCommand): boolean {
  177. if (command instanceof SGraphMoveCommand && command.item == this.item) {
  178. command.pos = this.pos;
  179. return true;
  180. }
  181. return false;
  182. }
  183. redo(): void {
  184. this.item.pos = new SPoint(this.pos.x, this.pos.y);
  185. this.item.update();
  186. }
  187. undo(): void {
  188. this.item.pos = new SPoint(this.old.x, this.old.y);
  189. this.item.update();
  190. }
  191. }
  192. export default {
  193. mounted(): void {
  194. let view = new TestView();
  195. this.scene.updateText(this.input);
  196. view.scene = this.scene;
  197. },
  198. data() {
  199. return {
  200. scene: new SScene(),
  201. input: '测试文本',
  202. }
  203. },
  204. methods: {
  205. handleKeyup(value): void {
  206. this.scene.updateText(this.input);
  207. },
  208. undo(): void {
  209. this.scene.undoStack.undo();
  210. },
  211. redo(): void {
  212. this.scene.undoStack.redo();
  213. }
  214. },
  215. }
  216. </script>
  217. <style scoped>
  218. </style>