shape.js 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. import { getTextByPathList } from './utils'
  2. export function shapeArc (cX, cY, rX, rY, stAng, endAng, isClose) {
  3. let dData
  4. let angle = stAng
  5. if (endAng >= stAng) {
  6. while (angle <= endAng) {
  7. const radians = angle * (Math.PI / 180)
  8. const x = cX + Math.cos(radians) * rX
  9. const y = cY + Math.sin(radians) * rY
  10. if (angle === stAng) {
  11. dData = ' M' + x + ' ' + y
  12. }
  13. dData += ' L' + x + ' ' + y
  14. angle++
  15. }
  16. } else {
  17. while (angle > endAng) {
  18. const radians = angle * (Math.PI / 180)
  19. const x = cX + Math.cos(radians) * rX
  20. const y = cY + Math.sin(radians) * rY
  21. if (angle === stAng) {
  22. dData = ' M ' + x + ' ' + y
  23. }
  24. dData += ' L ' + x + ' ' + y
  25. angle--
  26. }
  27. }
  28. dData += (isClose ? ' z' : '')
  29. return dData
  30. }
  31. export function getCustomShapePath (custShapType, w, h) {
  32. const pathLstNode = getTextByPathList(custShapType, ['a:pathLst'])
  33. let pathNodes = getTextByPathList(pathLstNode, ['a:path'])
  34. if (Array.isArray(pathNodes)) pathNodes = pathNodes.shift()
  35. const maxX = parseInt(pathNodes['attrs']['w'])
  36. const maxY = parseInt(pathNodes['attrs']['h'])
  37. const cX = maxX === 0 ? 0 : (1 / maxX) * w
  38. const cY = maxY === 0 ? 0 : (1 / maxY) * h
  39. let d = ''
  40. let moveToNode = getTextByPathList(pathNodes, ['a:moveTo'])
  41. const lnToNodes = pathNodes['a:lnTo']
  42. let cubicBezToNodes = pathNodes['a:cubicBezTo']
  43. const arcToNodes = pathNodes['a:arcTo']
  44. let closeNode = getTextByPathList(pathNodes, ['a:close'])
  45. if (!Array.isArray(moveToNode)) moveToNode = [moveToNode]
  46. const multiSapeAry = []
  47. if (moveToNode.length > 0) {
  48. Object.keys(moveToNode).forEach(key => {
  49. const moveToPtNode = moveToNode[key]['a:pt']
  50. if (moveToPtNode) {
  51. Object.keys(moveToPtNode).forEach(key => {
  52. const moveToNoPt = moveToPtNode[key]
  53. const spX = moveToNoPt['attrs', 'x']
  54. const spY = moveToNoPt['attrs', 'y']
  55. const order = moveToNoPt['attrs', 'order']
  56. multiSapeAry.push({
  57. type: 'movto',
  58. x: spX,
  59. y: spY,
  60. order
  61. })
  62. })
  63. }
  64. })
  65. if (lnToNodes) {
  66. Object.keys(lnToNodes).forEach(key => {
  67. const lnToPtNode = lnToNodes[key]['a:pt']
  68. if (lnToPtNode) {
  69. Object.keys(lnToPtNode).forEach(key => {
  70. const lnToNoPt = lnToPtNode[key]
  71. const ptX = lnToNoPt['attrs', 'x']
  72. const ptY = lnToNoPt['attrs', 'y']
  73. const order = lnToNoPt['attrs', 'order']
  74. multiSapeAry.push({
  75. type: 'lnto',
  76. x: ptX,
  77. y: ptY,
  78. order
  79. })
  80. })
  81. }
  82. })
  83. }
  84. if (cubicBezToNodes) {
  85. const cubicBezToPtNodesAry = []
  86. if (!Array.isArray(cubicBezToNodes)) {
  87. cubicBezToNodes = [cubicBezToNodes]
  88. }
  89. Object.keys(cubicBezToNodes).forEach(key => {
  90. cubicBezToPtNodesAry.push(cubicBezToNodes[key]['a:pt'])
  91. })
  92. cubicBezToPtNodesAry.forEach(key => {
  93. const pts_ary = []
  94. key.forEach(pt => {
  95. const pt_obj = {
  96. x: pt['attrs']['x'],
  97. y: pt['attrs']['y']
  98. }
  99. pts_ary.push(pt_obj)
  100. })
  101. const order = key[0]['attrs']['order']
  102. multiSapeAry.push({
  103. type: 'cubicBezTo',
  104. cubBzPt: pts_ary,
  105. order
  106. })
  107. })
  108. }
  109. if (arcToNodes) {
  110. const arcToNodesAttrs = arcToNodes['attrs']
  111. const order = arcToNodesAttrs['order']
  112. const hR = arcToNodesAttrs['hR']
  113. const wR = arcToNodesAttrs['wR']
  114. const stAng = arcToNodesAttrs['stAng']
  115. const swAng = arcToNodesAttrs['swAng']
  116. let shftX = 0
  117. let shftY = 0
  118. const arcToPtNode = getTextByPathList(arcToNodes, ['a:pt', 'attrs'])
  119. if (arcToPtNode) {
  120. shftX = arcToPtNode['x']
  121. shftY = arcToPtNode['y']
  122. }
  123. multiSapeAry.push({
  124. type: 'arcTo',
  125. hR: hR,
  126. wR: wR,
  127. stAng: stAng,
  128. swAng: swAng,
  129. shftX: shftX,
  130. shftY: shftY,
  131. order
  132. })
  133. }
  134. if (closeNode) {
  135. if (!Array.isArray(closeNode)) closeNode = [closeNode]
  136. Object.keys(closeNode).forEach(() => {
  137. multiSapeAry.push({
  138. type: 'close',
  139. order: Infinity
  140. })
  141. })
  142. }
  143. multiSapeAry.sort((a, b) => a.order - b.order)
  144. let k = 0
  145. while (k < multiSapeAry.length) {
  146. if (multiSapeAry[k].type === 'movto') {
  147. const spX = parseInt(multiSapeAry[k].x) * cX
  148. const spY = parseInt(multiSapeAry[k].y) * cY
  149. d += ' M' + spX + ',' + spY
  150. } else if (multiSapeAry[k].type === 'lnto') {
  151. const Lx = parseInt(multiSapeAry[k].x) * cX
  152. const Ly = parseInt(multiSapeAry[k].y) * cY
  153. d += ' L' + Lx + ',' + Ly
  154. } else if (multiSapeAry[k].type === 'cubicBezTo') {
  155. const Cx1 = parseInt(multiSapeAry[k].cubBzPt[0].x) * cX
  156. const Cy1 = parseInt(multiSapeAry[k].cubBzPt[0].y) * cY
  157. const Cx2 = parseInt(multiSapeAry[k].cubBzPt[1].x) * cX
  158. const Cy2 = parseInt(multiSapeAry[k].cubBzPt[1].y) * cY
  159. const Cx3 = parseInt(multiSapeAry[k].cubBzPt[2].x) * cX
  160. const Cy3 = parseInt(multiSapeAry[k].cubBzPt[2].y) * cY
  161. d += ' C' + Cx1 + ',' + Cy1 + ' ' + Cx2 + ',' + Cy2 + ' ' + Cx3 + ',' + Cy3
  162. } else if (multiSapeAry[k].type === 'arcTo') {
  163. const hR = parseInt(multiSapeAry[k].hR) * cX
  164. const wR = parseInt(multiSapeAry[k].wR) * cY
  165. const stAng = parseInt(multiSapeAry[k].stAng) / 60000
  166. const swAng = parseInt(multiSapeAry[k].swAng) / 60000
  167. const endAng = stAng + swAng
  168. d += shapeArc(wR, hR, wR, hR, stAng, endAng, false)
  169. } else if (multiSapeAry[k].type === 'close') d += 'z'
  170. k++
  171. }
  172. }
  173. return d
  174. }