SSvgPaintEngine.ts 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. /*
  2. * *********************************************************************************************************************
  3. *
  4. * !!
  5. * .F88X
  6. * X8888Y
  7. * .}888888N;
  8. * i888888N; .:! .I$WI:
  9. * R888888I .'N88~ i8}+8Y&8"l8i$8>8W~'>W8}8]KW+8IIN"8&
  10. * .R888888I .;N8888~ .X8' "8I.!,/8" !%NY8`"8I8~~8>,88I
  11. * +888888N; .8888888Y "&&8Y.}8,
  12. * ./888888N; .R888888Y .'}~ .>}'.`+> i}! "i' +/' .'i~ !11,.:">, .~]! .i}i
  13. * ~888888%: .I888888l .]88~`1/iY88Ii+1'.R$8$8]"888888888> Y8$ W8E X8E W8888'188Il}Y88$*
  14. * 18888888 E8888881 .]W%8$`R8X'&8%++N8i,8N%N8+l8%` .}8N:.R$RE%N88N%N$K$R 188,FE$8%~Y88I
  15. * .E888888I .i8888888' .:$8I;88+`E8R:/8N,.>881.`$8E/1/]N8X.Y8N`"KF&&FK!'88*."88K./$88%RN888+~
  16. * 8888888I .,N888888~ ~88i"8W,!N8*.I88.}888%F,i$88"F88" 888:E8X.>88!i88>`888*.}Fl1]*}1YKi'
  17. * i888888N' I888Y ]88;/EX*IFKFK88X K8R .l8W 88Y ~88}'88E&%8W.X8N``]88!.$8K .:W8I
  18. * .i888888N; I8Y .&8$ .X88! i881.:%888>I88 ;88] +88+.';;;;:.Y88X 18N.,88l .+88/
  19. * .:R888888I
  20. * .&888888I Copyright (c) 2009-2020. 博锐尚格科技股份有限公司
  21. * ~8888'
  22. * .!88~ All rights reserved.
  23. *
  24. * *********************************************************************************************************************
  25. */
  26. import { SStringBuilder } from "@persagy-web/base";
  27. import {
  28. SFont,
  29. SLine,
  30. SPaintEngine,
  31. SPaintEngineType,
  32. SPoint,
  33. SRect
  34. } from "..";
  35. import { SPath } from "../SPath";
  36. /**
  37. * Canvas 绘制引擎基类
  38. *
  39. * @author 庞利祥 <sybotan@126.com>
  40. */
  41. export class SSvgPaintEngine extends SPaintEngine {
  42. /** 字符串 builder */
  43. private _builder = new SStringBuilder();
  44. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  45. // 属性定义
  46. /** svg 版本号(1.1) */
  47. version = "1.1";
  48. /** 宽度 */
  49. width: number = 0;
  50. /** 高度 */
  51. height: number = 0;
  52. /**
  53. * 绘制引擎类型
  54. *
  55. * @return 返回 SVG 绘制引擎类型
  56. */
  57. get type(): SPaintEngineType {
  58. return SPaintEngineType.SVG;
  59. } // Get type
  60. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  61. // 构造函数
  62. /**
  63. * 构造函数
  64. *
  65. * @param w 宽度
  66. * @param h 高度
  67. */
  68. constructor(w: number, h: number) {
  69. super();
  70. this.width = w;
  71. this.height = h;
  72. this._builder.append(`<?xml version='1.0' standalone='no'?>`);
  73. this._builder.append(`<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"`);
  74. this._builder.append(
  75. ` "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">`
  76. );
  77. this._builder.append(
  78. `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"`
  79. );
  80. this._builder.append(
  81. `version="${this.version}" width="${w}" height="${h}">`
  82. );
  83. } // Constructor
  84. /**
  85. * 转 svg 图像
  86. *
  87. * @return svg图像
  88. */
  89. toSvg(): string {
  90. return this._builder.toString("\n") + "</svg>\n";
  91. } // Function toSvg()
  92. // =================================================================================================================
  93. // 绘制图形
  94. /**
  95. * 清空矩形区域
  96. *
  97. * @param rect 矩形
  98. */
  99. clearRect(rect: SRect): void {} // Function clearRect()
  100. /**
  101. * 绘制空心矩形
  102. *
  103. * @param rect 矩形
  104. */
  105. drawRect(rect: SRect): void {
  106. this._builder.append(
  107. // eslint-disable-next-line max-len
  108. `<rect x="${rect.x}" y="${rect.y}" width="${rect.width}" height="${
  109. rect.height
  110. }" ${this.getStyle(true, true, false)} ${this.getSvgMatrix()}/>`
  111. );
  112. } // Function drawRects()
  113. /**
  114. * 绘制圆形
  115. *
  116. * @param cx 圆心 X 坐标
  117. * @param cy 圆心 Y 坐标
  118. * @param r 圆半径
  119. */
  120. drawCircle(cx: number, cy: number, r: number): void {
  121. this._builder.append(
  122. `<circle cx="${cx}" cy="${cy}" r="${r}" ${this.getStyle(
  123. true,
  124. true,
  125. false
  126. )} ${this.getSvgMatrix()}/>`
  127. );
  128. } // Function drawCircle()
  129. /**
  130. * 绘制椭圆
  131. *
  132. * @param cx 圆点 X 坐标
  133. * @param cy 圆点 Y 坐标
  134. * @param rx 水平半径
  135. * @param ry 垂直半径
  136. */
  137. drawEllipse(cx: number, cy: number, rx: number, ry: number): void {
  138. this._builder.append(
  139. `<ellipse cx="${cx}" cy="${cy}" rx="${rx}" ry="${ry}" ${this.getStyle(
  140. true,
  141. true,
  142. false
  143. )} ${this.getSvgMatrix()}/>`
  144. );
  145. } // Function drawEllipse()
  146. /**
  147. * 绘制线段
  148. *
  149. * @param line 线段
  150. */
  151. drawLine(line: SLine): void {
  152. this._builder.append(
  153. `<line x1="${line.x1}" y1="${line.y1}" x2="${line.x2}" y2="${
  154. line.y2
  155. }" ${this.getStyle(false, true, false)} ${this.getSvgMatrix()}/>`
  156. );
  157. } // Function drawLine()
  158. /**
  159. * 绘制折线
  160. *
  161. * @param points 折线折点
  162. */
  163. drawPolyline(points: SPoint[]): void {
  164. this._builder.append(
  165. `<polyline points="${SSvgPaintEngine.pointsToStr(
  166. points
  167. )}" ${this.getStyle(false, true, false)} ${this.getSvgMatrix()}/>`
  168. );
  169. } // Function drawPolyline()
  170. /**
  171. * 绘制多边形
  172. *
  173. * @param points 多边形顶点
  174. */
  175. drawPolygon(points: SPoint[]): void {
  176. this._builder.append(
  177. `<polygon points="${SSvgPaintEngine.pointsToStr(
  178. points
  179. )}" ${this.getStyle(true, true, false)} ${this.getSvgMatrix()}/>`
  180. );
  181. } // Function drawPolyline()
  182. /**
  183. * 绘制路径
  184. *
  185. * @param path 路径
  186. */
  187. drawPath(path: SPath): void {
  188. // this._builder.append(
  189. // `<path d="${path.svgPath()}" ${this.getStyle(
  190. // true,
  191. // true,
  192. // false
  193. // )} ${this.getSvgMatrix()}/>`
  194. // );
  195. } // Function drawPath()
  196. /**
  197. * 绘制文本
  198. *
  199. * @param text 文本内容
  200. * @param x X 坐标
  201. * @param y Y 坐标
  202. * @param maxWidth 最大宽度
  203. */
  204. drawText(text: string, x: number, y: number, maxWidth?: number): void {
  205. this._builder.append(
  206. `<text x="${x}" y="${y}" ${this.getStyle(
  207. true,
  208. false,
  209. true
  210. )} ${this.getSvgMatrix()}>${text}</text>>`
  211. );
  212. } // Function drawText()
  213. /**
  214. * 绘制图片
  215. *
  216. * @param img 图片
  217. * @param x X 坐标
  218. * @param y Y 坐标
  219. * @param width 宽度
  220. * @param height 高度
  221. */
  222. drawImage(
  223. img: CanvasImageSource,
  224. x: number,
  225. y: number,
  226. width?: number,
  227. height?: number
  228. ): void {
  229. // TODO: 未完成
  230. } // Function drawImage()
  231. /**
  232. * 预测量文本宽度
  233. *
  234. * @param text 预测的文本
  235. * @return 文本长度像素
  236. */
  237. textWidth(text: string): number {
  238. return 0;
  239. } // Function textWidth()
  240. /**
  241. * 设置字体
  242. *
  243. * @param font 字体
  244. */
  245. changeFont(font: SFont): void {} // Function changeFont()
  246. /**
  247. * 获得svg需要的变形信息
  248. *
  249. * @return 变换信息
  250. */
  251. private getSvgMatrix(): string {
  252. // eslint-disable-next-line max-len
  253. return `transform="matrix(${this.state.matrix.a}, ${this.state.matrix.b}, ${this.state.matrix.c}, ${this.state.matrix.d}, ${this.state.matrix.e}, ${this.state.matrix.f})"`;
  254. } // Function getMatrix()
  255. /**
  256. * 将点列表转换为字符串表达形式
  257. *
  258. * @param points 被转换的点
  259. * @return 点列表字符串
  260. */
  261. private static pointsToStr(points: SPoint[]): string {
  262. let strBuilder = new SStringBuilder();
  263. for (let p of points) {
  264. strBuilder.append(`${p.x},${p.y}`);
  265. }
  266. return strBuilder.toString(" ");
  267. } // Function pointsToStr()
  268. /** 获得风格 */
  269. private getStyle(
  270. brush: boolean = false,
  271. pen: boolean = false,
  272. font: boolean = false
  273. ): string {
  274. let builder = new SStringBuilder();
  275. builder.append('style="');
  276. if (pen) {
  277. // 画笔
  278. // eslint-disable-next-line max-len
  279. builder.append(
  280. `stroke:rgba(${this.state.pen.color.red}, ${
  281. this.state.pen.color.green
  282. }, ${this.state.pen.color.blue}, ${this.state.pen.color.alpha /
  283. 255.0});`
  284. );
  285. builder.append(`stroke-width:${this.state.pen.lineWidth};`);
  286. } else {
  287. builder.append(`stroke-width:0;`);
  288. }
  289. if (brush) {
  290. // 画刷
  291. builder.append(
  292. `fill:rgba(${this.state.brush.color.red}, ${
  293. this.state.brush.color.green
  294. }, ${this.state.brush.color.blue}, ${this.state.brush.color
  295. .alpha / 255.0});`
  296. );
  297. } else {
  298. builder.append(`fill:rgba(0,0,0,0);`);
  299. }
  300. if (font) {
  301. // 字体
  302. // builder.append(`font-family:"${this.state.font.name}";`);
  303. builder.append(`font-size:${this.state.font.size}px;`);
  304. // builder.append(`text-align:${this.state.font.textAlign};`);
  305. }
  306. builder.append('"');
  307. return builder.toString("");
  308. } // Get penStyle
  309. /**
  310. * 绘制圆角矩形
  311. */
  312. drawRoundRect(): void {} // Function drawRoundRect()
  313. } // Class SSvgPaintEngine