You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Element.js 3.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. import { bbox, rbox, inside } from '../types/Box.js'
  2. import { ctm, screenCTM } from '../types/Matrix.js'
  3. import {
  4. extend,
  5. getClass,
  6. makeInstance,
  7. register,
  8. root
  9. } from '../utils/adopter.js'
  10. import { globals } from '../utils/window.js'
  11. import { point } from '../types/Point.js'
  12. import { proportionalSize, writeDataToDom } from '../utils/utils.js'
  13. import { reference } from '../modules/core/regex.js'
  14. import Dom from './Dom.js'
  15. import List from '../types/List.js'
  16. import SVGNumber from '../types/SVGNumber.js'
  17. export default class Element extends Dom {
  18. constructor(node, attrs) {
  19. super(node, attrs)
  20. // initialize data object
  21. this.dom = {}
  22. // create circular reference
  23. this.node.instance = this
  24. if (node.hasAttribute('data-svgjs') || node.hasAttribute('svgjs:data')) {
  25. // pull svgjs data from the dom (getAttributeNS doesn't work in html5)
  26. this.setData(
  27. JSON.parse(node.getAttribute('data-svgjs')) ??
  28. JSON.parse(node.getAttribute('svgjs:data')) ??
  29. {}
  30. )
  31. }
  32. }
  33. // Move element by its center
  34. center(x, y) {
  35. return this.cx(x).cy(y)
  36. }
  37. // Move by center over x-axis
  38. cx(x) {
  39. return x == null
  40. ? this.x() + this.width() / 2
  41. : this.x(x - this.width() / 2)
  42. }
  43. // Move by center over y-axis
  44. cy(y) {
  45. return y == null
  46. ? this.y() + this.height() / 2
  47. : this.y(y - this.height() / 2)
  48. }
  49. // Get defs
  50. defs() {
  51. const root = this.root()
  52. return root && root.defs()
  53. }
  54. // Relative move over x and y axes
  55. dmove(x, y) {
  56. return this.dx(x).dy(y)
  57. }
  58. // Relative move over x axis
  59. dx(x = 0) {
  60. return this.x(new SVGNumber(x).plus(this.x()))
  61. }
  62. // Relative move over y axis
  63. dy(y = 0) {
  64. return this.y(new SVGNumber(y).plus(this.y()))
  65. }
  66. getEventHolder() {
  67. return this
  68. }
  69. // Set height of element
  70. height(height) {
  71. return this.attr('height', height)
  72. }
  73. // Move element to given x and y values
  74. move(x, y) {
  75. return this.x(x).y(y)
  76. }
  77. // return array of all ancestors of given type up to the root svg
  78. parents(until = this.root()) {
  79. const isSelector = typeof until === 'string'
  80. if (!isSelector) {
  81. until = makeInstance(until)
  82. }
  83. const parents = new List()
  84. let parent = this
  85. while (
  86. (parent = parent.parent()) &&
  87. parent.node !== globals.document &&
  88. parent.nodeName !== '#document-fragment'
  89. ) {
  90. parents.push(parent)
  91. if (!isSelector && parent.node === until.node) {
  92. break
  93. }
  94. if (isSelector && parent.matches(until)) {
  95. break
  96. }
  97. if (parent.node === this.root().node) {
  98. // We worked our way to the root and didn't match `until`
  99. return null
  100. }
  101. }
  102. return parents
  103. }
  104. // Get referenced element form attribute value
  105. reference(attr) {
  106. attr = this.attr(attr)
  107. if (!attr) return null
  108. const m = (attr + '').match(reference)
  109. return m ? makeInstance(m[1]) : null
  110. }
  111. // Get parent document
  112. root() {
  113. const p = this.parent(getClass(root))
  114. return p && p.root()
  115. }
  116. // set given data to the elements data property
  117. setData(o) {
  118. this.dom = o
  119. return this
  120. }
  121. // Set element size to given width and height
  122. size(width, height) {
  123. const p = proportionalSize(this, width, height)
  124. return this.width(new SVGNumber(p.width)).height(new SVGNumber(p.height))
  125. }
  126. // Set width of element
  127. width(width) {
  128. return this.attr('width', width)
  129. }
  130. // write svgjs data to the dom
  131. writeDataToDom() {
  132. writeDataToDom(this, this.dom)
  133. return super.writeDataToDom()
  134. }
  135. // Move over x-axis
  136. x(x) {
  137. return this.attr('x', x)
  138. }
  139. // Move over y-axis
  140. y(y) {
  141. return this.attr('y', y)
  142. }
  143. }
  144. extend(Element, {
  145. bbox,
  146. rbox,
  147. inside,
  148. point,
  149. ctm,
  150. screenCTM
  151. })
  152. register(Element, 'Element')