edittext.vue 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. <template>
  2. <div class="edit-line">
  3. <!-- 所有按钮 -->
  4. <div class="btn-list">
  5. </div>
  6. <div class="content">
  7. <div class="left" id="left">
  8. <!-- <textarea name="" class="text" cols="30" rows="10"></textarea> -->
  9. <canvas id="edit_polygon" width="700" height="460" tabindex="0" />
  10. </div>
  11. <div class="line-property">
  12. <el-card shadow="always">
  13. <div slot="header" class="clearfix">
  14. <span>属性修改</span>
  15. </div>
  16. <div class="always-item">
  17. <span>字号:</span>
  18. <el-input-number size="small" v-model="size" @change="updateSize" :min="1" :max="50"></el-input-number>
  19. </div>
  20. <div class="always-item">
  21. <span>文本框:</span>
  22. <el-input
  23. v-model="text"
  24. @change="handleChangeText"
  25. type="textarea"
  26. :autosize="{ minRows: 1, maxRows: 1}"
  27. placeholder="请输入内容"
  28. style="width:200px;"
  29. ></el-input>
  30. </div>
  31. <div class="always-item">
  32. <span>线颜色:</span>
  33. <el-color-picker v-model="color" @change="changeColor" show-alpha></el-color-picker>
  34. </div>
  35. </el-card>
  36. </div>
  37. </div>
  38. </div>
  39. </template>
  40. <script>
  41. import {
  42. SGraphScene,
  43. SGraphView,
  44. SGraphPropertyCommand,
  45. SGraphMoveCommand
  46. } from "@persagy-web/graph/";
  47. import { SUndoStack } from "@persagy-web/base/lib";
  48. import { SFont } from "@persagy-web/draw/lib";
  49. import { SPoint, SColor } from "@persagy-web/draw/";
  50. //注: 开发者引入 SImageItem 包为: import {SImageItem} from "@persagy-web/edit/";
  51. import { EditText } from "./../../../../../guides/edit/items/src/EditText";
  52. import { hexify } from "./../../../../public/until/rgbaUtil";
  53. class SScene extends SGraphScene {
  54. undoStack = new SUndoStack();
  55. textItem = new EditText(null);
  56. constructor() {
  57. super();
  58. this.textItem.moveable = true;
  59. this.textItem.x = 100;
  60. this.textItem.y = 100;
  61. this.addItem(this.textItem);
  62. this.textItem.connect("onMove", this, this.onItemMove.bind(this));
  63. }
  64. updateText(str) {
  65. if (this.textItem.text !== str) {
  66. let old = this.textItem.text;
  67. this.textItem.text = str;
  68. this.undoStack.push(
  69. new SGraphPropertyCommand(this, this.textItem, "text", old, str)
  70. );
  71. }
  72. }
  73. updateColor(color) {
  74. if (this.textItem.color !== color) {
  75. let old = this.textItem.color;
  76. this.textItem.color = color;
  77. this.undoStack.push(
  78. new SGraphPropertyCommand(this, this.textItem, "color", old, color)
  79. );
  80. }
  81. }
  82. updateSize(size) {
  83. if (this.textItem.font.size !== size) {
  84. let old = new SFont(this.textItem.font);
  85. let font = new SFont(this.textItem.font);
  86. font.size = size;
  87. this.textItem.font = font;
  88. this.undoStack.push(
  89. new SGraphPropertyCommand(this, this.textItem, "font", old, font)
  90. );
  91. }
  92. }
  93. onItemMove(item, ...arg) {
  94. this.undoStack.push(
  95. new SGraphMoveCommand(this, item, arg[0][0], arg[0][1])
  96. );
  97. }
  98. }
  99. class TestView extends SGraphView {
  100. constructor() {
  101. super("edit_polygon");
  102. }
  103. }
  104. export default {
  105. name: "edittext",
  106. data() {
  107. return {
  108. scene: new SScene(),
  109. text: "测试文本",
  110. size: 20,
  111. color: "#333333"
  112. };
  113. },
  114. mounted() {
  115. let view = new TestView();
  116. this.scene.updateText(this.text);
  117. this.scene.updateColor(this.color);
  118. this.scene.updateSize(this.size);
  119. view.scene = this.scene;
  120. // this.scene.onMouseUp = this.onMouseUp;
  121. },
  122. methods: {
  123. handleChangeText(text) {
  124. this.scene.updateText(text);
  125. },
  126. handleChangeColor(color) {
  127. this.scene.updateColor(color);
  128. },
  129. updateSize(size) {
  130. this.scene.updateSize(size);
  131. },
  132. undo() {
  133. this.scene.undoStack.undo();
  134. },
  135. redo() {
  136. this.scene.undoStack.redo();
  137. },
  138. reset() {
  139. this.text = "测试文本";
  140. this.size = 20;
  141. this.color = "#333333";
  142. this.scene.updateText(this.text);
  143. this.scene.updateColor(this.color);
  144. this.scene.updateSize(this.size);
  145. },
  146. // 改变颜色
  147. changeColor(val) {
  148. this.scene.updateColor(hexify(val));
  149. },
  150. ///////////////////////////////////
  151. //// 以下为测试代码,请忽略
  152. // 设置tooltip位置
  153. /**
  154. * raduis 灵敏范围
  155. * e 鼠标事件对象
  156. * tipDom 浮动得dom
  157. * boxDom 最外层盒子
  158. * offset 偏移量
  159. */
  160. toolTipPosition(radius, e, tipDom, offset = 0) {
  161. // 滚动高度
  162. const screenTop =
  163. document.documentElement.scrollTop || document.body.scrollTop;
  164. const screenLeft =
  165. document.documentElement.scrollLeft || document.body.scrollLeft;
  166. radius = radius + offset;
  167. const mapBox = document.getElementById("edit_polygon");
  168. // 测试边界mousePosition = 1(右下) 2 (右上)3 (左上) 4 (左下)
  169. const mousePosition = this.Boxboundary(radius, e, mapBox);
  170. const absPosition = this.offsetTL(mapBox);
  171. const absPositionLeft = absPosition.left;
  172. const absPositionTop = absPosition.top;
  173. const mClientY = e.clientY + screenTop;
  174. const mClientX = e.clientX + screenLeft;
  175. const fuzzy_model_width = tipDom.offsetWidth;
  176. const fuzzy_model_height = tipDom.offsetHeight;
  177. // let offsetTL
  178. if (mousePosition == 2) {
  179. tipDom.style.left = `${mClientX - absPositionLeft + offset}px`;
  180. tipDom.style.top = `${mClientY -
  181. fuzzy_model_height -
  182. absPositionTop -
  183. offset}px`;
  184. } else if (mousePosition == 3) {
  185. tipDom.style.left = `${mClientX -
  186. fuzzy_model_width -
  187. absPositionLeft -
  188. offset}px`;
  189. tipDom.style.top = `${mClientY -
  190. fuzzy_model_height -
  191. absPositionTop -
  192. offset}px`;
  193. } else if (mousePosition == 4) {
  194. tipDom.style.left = `${mClientX -
  195. fuzzy_model_width -
  196. absPositionLeft -
  197. offset}px`;
  198. tipDom.style.top = `${mClientY - absPositionTop + offset}px`;
  199. } else {
  200. tipDom.style.left = `${mClientX - absPositionLeft + offset}px`;
  201. tipDom.style.top = `${mClientY - absPositionTop + offset}px`;
  202. }
  203. },
  204. Boxboundary(radius, event, box) {
  205. const screenTop =
  206. document.documentElement.scrollTop || document.body.scrollTop;
  207. const boxWidth = Number(box.style.width.slice(0, -2));
  208. const boxHeight = Number(box.style.height.slice(0, -2));
  209. const absPosition = this.offsetTL(box);
  210. const boxClientX = absPosition.left;
  211. const boxClientY = absPosition.top;
  212. const mouseX = event.clientX;
  213. const mouseY = event.clientY + screenTop;
  214. if (mouseY >= boxClientY + boxHeight - radius) {
  215. if (mouseX <= radius + boxClientX) {
  216. return 2;
  217. } else if (mouseX >= boxClientX + boxWidth - radius) {
  218. return 3;
  219. } else {
  220. return 2;
  221. }
  222. } else if (mouseX >= boxClientX + boxWidth - radius) {
  223. return 4;
  224. } else {
  225. return 1;
  226. }
  227. },
  228. offsetTL(obj) {
  229. //获取到body的offsetTop和offsetLeft
  230. var t = 0,
  231. l = 0;
  232. while (obj) {
  233. t = t + obj.offsetTop;
  234. l = l + obj.offsetLeft;
  235. obj = obj.offsetParent;
  236. }
  237. return {
  238. top: t,
  239. left: l
  240. };
  241. },
  242. onMouseUp(event) {
  243. const dom = "<textarea autofocus ref='textarea' class='text'></textarea>";
  244. let parentDom = document.getElementById("left");
  245. parentDom.innerHTML = parentDom.innerHTML + dom;
  246. const textareaDom = this.$refs.textarea;
  247. // console.log('textareaDom',parentDom.children[0])
  248. this.toolTipPosition(1, event, textareaDom, 0);
  249. }
  250. },
  251. watch: {
  252. // cmdStatus(val) {
  253. // this.scene.cmdStatus = val;
  254. // }
  255. }
  256. };
  257. </script>
  258. <style scoped lang="less">
  259. .text {
  260. overflow: auto;
  261. word-break: break-all;
  262. outline: none;
  263. // background: #409eff;
  264. position: absolute;
  265. left: 0;
  266. top: 0;
  267. }
  268. .edit-line {
  269. width: 100%;
  270. height: 500px;
  271. position: relative;
  272. .content {
  273. display: flex;
  274. justify-content: flex-start;
  275. .left {
  276. margin-right: 20px;
  277. }
  278. .line-property {
  279. width: 300px;
  280. margin-top: 20px;
  281. .always {
  282. width: 100%;
  283. height: 100%;
  284. }
  285. .always-item {
  286. display: flex;
  287. margin-top: 10px;
  288. justify-content: space-between;
  289. }
  290. }
  291. }
  292. .heightLight {
  293. color: #409eff;
  294. border-color: #c6e2ff;
  295. background-color: #ecf5ff;
  296. }
  297. }
  298. </style>