edittext.vue 11 KB

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