QS-SharePoster.js 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322
  1. import _app from './app.js';
  2. import QRCodeAlg from './QRCodeAlg.js';
  3. import { base64ToPath } from './image-tools.js';
  4. const ShreUserPosterBackgroundKey = 'ShrePosterBackground_'; // 背景图片缓存名称前缀
  5. const idKey = 'QSSHAREPOSTER_IDKEY'; //drawArray自动生成的idkey
  6. var isMp = false;
  7. // #ifdef MP
  8. isMp = true;
  9. // #endif
  10. var nbgScale = 1;
  11. // export default
  12. function getSharePoster(obj) {
  13. return new Promise(async (resolve, reject) => {
  14. try {
  15. const result1 = await returnPromise(obj);
  16. resolve(result1);
  17. } catch (e) {
  18. //TODO handle the exception
  19. try {
  20. if(obj.bgScale) {
  21. obj.bgScale = Number(obj.bgScale) - 0.1
  22. }else{
  23. nbgScale = nbgScale - 0.1
  24. }
  25. console.log('------------清除缓存后, 开始第二次尝试------------');
  26. const result2 = await returnPromise(obj);
  27. resolve(result2);
  28. } catch (e) {
  29. //TODO handle the exception
  30. reject(e);
  31. }
  32. }
  33. })
  34. }
  35. function returnPromise(obj) {
  36. let {
  37. type,
  38. formData,
  39. background,
  40. posterCanvasId,
  41. backgroundImage,
  42. reserve,
  43. textArray,
  44. drawArray,
  45. qrCodeArray,
  46. imagesArray,
  47. setCanvasWH,
  48. setCanvasToTempFilePath,
  49. setDraw,
  50. bgScale,
  51. Context,
  52. _this,
  53. delayTimeScale,
  54. drawDelayTime
  55. } = obj;
  56. return new Promise(async (rs, rj) => {
  57. try {
  58. _app.showLoading('正在准备海报数据');
  59. if (!Context) {
  60. _app.log('没有画布对象,创建画布对象');
  61. Context = uni.createCanvasContext(posterCanvasId, (_this || null));
  62. }
  63. let bgObj;
  64. if (background && background.width && background.height) {
  65. bgObj = background;
  66. } else {
  67. bgObj = await getShreUserPosterBackground({
  68. backgroundImage,
  69. type,
  70. formData
  71. });
  72. }
  73. bgScale = bgScale || nbgScale;
  74. bgObj.width = bgObj.width * bgScale;
  75. bgObj.height = bgObj.height * bgScale;
  76. _app.log('获取背景图信息对象成功:' + JSON.stringify(bgObj));
  77. const params = {
  78. bgObj,
  79. type,
  80. bgScale,
  81. getBgObj: function() {
  82. return params.bgObj;
  83. },
  84. setBgObj: function(newBgObj){
  85. const n = {...params.bgObj, ...newBgObj};
  86. params.bgObj = n;
  87. bgObj = n;
  88. }
  89. };
  90. if (imagesArray) {
  91. if (typeof(imagesArray) == 'function')
  92. imagesArray = imagesArray(params);
  93. _app.showLoading('正在生成需绘制图片的临时路径');
  94. _app.log('准备设置图片');
  95. imagesArray = await setImage(imagesArray);
  96. _app.hideLoading();
  97. }
  98. if (textArray) {
  99. if (typeof(textArray) == 'function')
  100. textArray = textArray(params);
  101. textArray = setText(Context, textArray);
  102. }
  103. if (qrCodeArray) {
  104. if (typeof(qrCodeArray) == 'function')
  105. qrCodeArray = qrCodeArray(params);
  106. _app.showLoading('正在生成需绘制图片的临时路径');
  107. for (let i = 0; i < qrCodeArray.length; i++) {
  108. _app.log(i);
  109. if (qrCodeArray[i].image)
  110. qrCodeArray[i].image = await _app.downloadFile_PromiseFc(qrCodeArray[i].image);
  111. }
  112. _app.hideLoading();
  113. }
  114. if (drawArray) {
  115. if (typeof(drawArray) == 'function') {
  116. drawArray = drawArray(params);
  117. }
  118. if (_app.isPromise(drawArray)) {
  119. drawArray = await drawArray;
  120. }
  121. if (_app.isArray(drawArray) && drawArray.length > 0) {
  122. let hasAllInfoCallback = false;
  123. for (let i = 0; i < drawArray.length; i++) {
  124. const drawArrayItem = drawArray[i];
  125. if (_app.isFn(drawArrayItem.allInfoCallback) && !hasAllInfoCallback) hasAllInfoCallback = true;
  126. drawArrayItem[idKey] = i;
  127. let newData;
  128. switch (drawArrayItem.type) {
  129. case 'image':
  130. newData = await setImage(drawArrayItem);
  131. break;
  132. case 'text':
  133. newData = setText(Context, drawArrayItem);
  134. break;
  135. case 'qrcode':
  136. if (drawArrayItem.image)
  137. newData = {
  138. image: await _app.downloadFile_PromiseFc(drawArrayItem.image)
  139. };
  140. break;
  141. case 'custom':
  142. break;
  143. case 'fillrect':
  144. break;
  145. case 'strokeRect':
  146. break;
  147. case 'roundStrokeRect':
  148. break;
  149. case 'roundFillRect':
  150. break;
  151. default:
  152. _app.log('未识别的类型');
  153. break;
  154. }
  155. if (newData && _app.isObject(newData)) {
  156. drawArray[i] = { ...drawArrayItem,
  157. ...newData
  158. }
  159. };
  160. }
  161. if (hasAllInfoCallback) {
  162. _app.log('----------------hasAllInfoCallback----------------');
  163. const drawArray_copy = [...drawArray];
  164. drawArray_copy.sort((a, b) => {
  165. const a_serialNum = !_app.isUndef(a.serialNum) && !_app.isNull(a.serialNum) ? Number(a.serialNum) : Number.NEGATIVE_INFINITY;
  166. const b_serialNum = !_app.isUndef(b.serialNum) && !_app.isNull(b.serialNum) ? Number(b.serialNum) : Number.NEGATIVE_INFINITY;
  167. return a_serialNum - b_serialNum;
  168. })
  169. _app.log('开始for循环');
  170. for (let i = 0; i < drawArray_copy.length; i++) {
  171. const item = { ...drawArray_copy[i]
  172. };
  173. if (_app.isFn(item.allInfoCallback)) {
  174. let newData = item.allInfoCallback({
  175. drawArray
  176. });
  177. if (_app.isPromise(newData)) newData = await newData;
  178. const item_idKey = item[idKey];
  179. if (!_app.isUndef(item_idKey)) {
  180. drawArray[item[idKey]] = { ...item,
  181. ...newData
  182. };
  183. } else {
  184. console.log('程序错误 找不到idKey!!! ...这不应该啊');
  185. }
  186. }
  187. }
  188. _app.log('for循环结束');
  189. }
  190. }
  191. }
  192. console.log('params:' + JSON.stringify(params))
  193. if (setCanvasWH && typeof(setCanvasWH) == 'function') {
  194. await new Promise((resolve, reject)=>{
  195. setCanvasWH(params);
  196. setTimeout(()=>{
  197. resolve();
  198. }, 50)
  199. })
  200. }
  201. const poster = await drawShareImage({
  202. Context,
  203. type,
  204. posterCanvasId,
  205. reserve,
  206. drawArray,
  207. textArray,
  208. imagesArray,
  209. bgObj,
  210. qrCodeArray,
  211. setCanvasToTempFilePath,
  212. setDraw,
  213. bgScale,
  214. _this,
  215. delayTimeScale,
  216. drawDelayTime
  217. });
  218. _app.hideLoading();
  219. rs({
  220. bgObj,
  221. poster,
  222. type
  223. });
  224. } catch (e) {
  225. //TODO handle the exception
  226. rj(e);
  227. }
  228. });
  229. }
  230. function drawShareImage(obj) { //绘制海报方法
  231. let {
  232. Context,
  233. type,
  234. posterCanvasId,
  235. reserve,
  236. bgObj,
  237. drawArray,
  238. textArray,
  239. qrCodeArray,
  240. imagesArray,
  241. setCanvasToTempFilePath,
  242. setDraw,
  243. bgScale,
  244. _this,
  245. delayTimeScale,
  246. drawDelayTime
  247. } = obj;
  248. const params = {
  249. Context,
  250. bgObj,
  251. type,
  252. bgScale
  253. };
  254. delayTimeScale = delayTimeScale !== undefined ? delayTimeScale : 15;
  255. drawDelayTime = drawDelayTime !== undefined ? drawDelayTime : 100;
  256. return new Promise((rs, rj) => {
  257. try {
  258. _app.showLoading('正在绘制海报');
  259. _app.log('背景对象:' + JSON.stringify(bgObj));
  260. if (bgObj && bgObj.path) {
  261. _app.log('背景有图片路径');
  262. Context.drawImage(bgObj.path, 0, 0, bgObj.width, bgObj.height);
  263. } else {
  264. _app.log('背景没有图片路径');
  265. if (bgObj.backgroundColor) {
  266. _app.log('背景有背景颜色:' + bgObj.backgroundColor);
  267. Context.setFillStyle(bgObj.backgroundColor);
  268. Context.fillRect(0, 0, bgObj.width, bgObj.height);
  269. } else {
  270. _app.log('背景没有背景颜色');
  271. }
  272. }
  273. _app.showLoading('绘制图片');
  274. if (imagesArray && imagesArray.length > 0)
  275. drawImage(Context, imagesArray);
  276. _app.showLoading('绘制自定义内容');
  277. if (setDraw && typeof(setDraw) == 'function') setDraw(params);
  278. _app.showLoading('绘制文本');
  279. if (textArray && textArray.length > 0)
  280. drawText(Context, textArray, bgObj);
  281. _app.showLoading('绘制二维码');
  282. if (qrCodeArray && qrCodeArray.length > 0) {
  283. for (let i = 0; i < qrCodeArray.length; i++) {
  284. drawQrCode(Context, qrCodeArray[i]);
  285. }
  286. }
  287. _app.showLoading('绘制可控层级序列');
  288. if (drawArray && drawArray.length > 0) {
  289. for (let i = 0; i < drawArray.length; i++) {
  290. const drawArrayItem = drawArray[i];
  291. _app.log('绘制可控层级序列, drawArrayItem:' + JSON.stringify(drawArrayItem));
  292. switch (drawArrayItem.type) {
  293. case 'image':
  294. _app.log('绘制可控层级序列, 绘制图片');
  295. drawImage(Context, drawArrayItem);
  296. break;
  297. case 'text':
  298. _app.log('绘制可控层级序列, 绘制文本');
  299. drawText(Context, drawArrayItem, bgObj);
  300. break;
  301. case 'qrcode':
  302. _app.log('绘制可控层级序列, 绘制二维码');
  303. drawQrCode(Context, drawArrayItem);
  304. break;
  305. case 'custom':
  306. _app.log('绘制可控层级序列, 绘制自定义内容');
  307. if (drawArrayItem.setDraw && typeof drawArrayItem.setDraw === 'function')
  308. drawArrayItem.setDraw(Context);
  309. break;drawRoundStrokeRect, drawStrokeRect
  310. case 'fillRect':
  311. _app.log('绘制可控层级序列, 绘制填充直角矩形');
  312. drawFillRect(Context, drawArrayItem);
  313. break;
  314. case 'strokeRect':
  315. _app.log('绘制可控层级序列, 绘制线条直角矩形');
  316. drawStrokeRect(Context, drawArrayItem);
  317. break;
  318. case 'roundStrokeRect':
  319. _app.log('绘制可控层级序列, 绘制线条圆角矩形');
  320. drawRoundStrokeRect(Context, drawArrayItem);
  321. break;
  322. case 'roundFillRect':
  323. _app.log('绘制可控层级序列, 绘制填充圆角矩形');
  324. drawRoundFillRect(Context, drawArrayItem);
  325. break;
  326. default:
  327. _app.log('未识别的类型');
  328. break;
  329. }
  330. }
  331. }
  332. _app.showLoading('绘制中')
  333. setTimeout(() => {
  334. _app.log('准备执行draw方法')
  335. _app.log('Context:' + Context);
  336. const fn = function(){
  337. _app.showLoading('正在输出图片');
  338. let setObj = setCanvasToTempFilePath || {};
  339. if (setObj && typeof(setObj) == 'function')
  340. setObj = setCanvasToTempFilePath(bgObj, type);
  341. let canvasToTempFilePathFn;
  342. const data = {
  343. x: 0,
  344. y: 0,
  345. width: Number(bgObj.width),
  346. height: Number(bgObj.height),
  347. destWidth: Number(bgObj.width), // 若H5使用这里请不要乘以二
  348. destHeight: Number(bgObj.height), // 若H5使用这里请不要乘以二
  349. quality: .8,
  350. fileType: 'jpg',
  351. ...setObj
  352. };
  353. console.log('canvasToTempFilePath的data对象:' + JSON.stringify(data));
  354. canvasToTempFilePathFn = function() {
  355. const toTempFilePathObj = { //输出为图片
  356. ...data,
  357. canvasId: posterCanvasId,
  358. success(res) {
  359. _app.hideLoading();
  360. rs(res);
  361. },
  362. fail(err) {
  363. _app.hideLoading();
  364. console.log('输出图片失败');
  365. _app.log('输出图片失败:' + JSON.stringify(err));
  366. rj('输出图片失败:' + JSON.stringify(err))
  367. }
  368. }
  369. uni.canvasToTempFilePath(toTempFilePathObj, _this || null);
  370. }
  371. let delayTime = 0;
  372. if (qrCodeArray) {
  373. qrCodeArray.forEach(item => {
  374. if (item.text) {
  375. delayTime += Number(item.text.length);
  376. }
  377. })
  378. }
  379. if (imagesArray) {
  380. imagesArray.forEach(() => {
  381. delayTime += delayTimeScale;
  382. })
  383. }
  384. if (textArray) {
  385. textArray.forEach(() => {
  386. delayTime += delayTimeScale;
  387. })
  388. }
  389. if (drawArray) {
  390. drawArray.forEach(item => {
  391. switch (item.type) {
  392. case 'text':
  393. if (item.text) {
  394. delayTime += item.text.length;
  395. }
  396. break;
  397. default:
  398. delayTime += delayTimeScale;
  399. break;
  400. }
  401. })
  402. }
  403. _app.log('延时系数:' + delayTimeScale);
  404. _app.log('总计延时:' + delayTime);
  405. setTimeout(canvasToTempFilePathFn, delayTime);
  406. }
  407. Context.draw((typeof(reserve) == 'boolean' ? reserve : false), fn);
  408. }, drawDelayTime);
  409. } catch (e) {
  410. //TODO handle the exception
  411. _app.hideLoading();
  412. rj(e);
  413. }
  414. });
  415. }
  416. // export
  417. function drawFillRect(Context, drawArrayItem = {}) { //填充矩形
  418. _app.log('进入绘制填充直角矩形方法, drawArrayItem:' + JSON.stringify(drawArrayItem));
  419. Context.setFillStyle(drawArrayItem.backgroundColor || 'black');
  420. Context.setGlobalAlpha(drawArrayItem.alpha || 1);
  421. Context.fillRect(drawArrayItem.dx || 0, drawArrayItem.dy || 0, drawArrayItem.width || 0, drawArrayItem.height || 0);
  422. Context.setGlobalAlpha(1);
  423. }
  424. // export
  425. function drawStrokeRect(Context, drawArrayItem = {}) { //线条矩形
  426. Context.setStrokeStyle(drawArrayItem.color||'black');
  427. Context.setLineWidth(drawArrayItem.lineWidth || 1);
  428. Context.strokeRect(drawArrayItem.dx, drawArrayItem.dy, drawArrayItem.width, drawArrayItem.height);
  429. }
  430. // export
  431. function drawRoundStrokeRect(Context, drawArrayItem = {}) {
  432. let { dx, dy, width, height, r, lineWidth, color } = drawArrayItem;
  433. r = r || width * .1;
  434. if (width < 2 * r) {
  435. r = width / 2;
  436. }
  437. if (width < 2 * r) {
  438. r = width / 2;
  439. }
  440. Context.beginPath();
  441. Context.moveTo(dx + r, dy);
  442. Context.arcTo(dx + width, dy, dx + width, dy + height, r);
  443. Context.arcTo(dx + width, dy + height, dx, dy + height, r);
  444. Context.arcTo(dx, dy + height, dx, dy, r);
  445. Context.arcTo(dx, dy, dx + width, dy, r);
  446. Context.closePath();
  447. Context.setLineWidth(lineWidth || 1);
  448. Context.setStrokeStyle(color || 'black');
  449. Context.stroke();
  450. }
  451. // export
  452. function drawRoundFillRect(Context, drawArrayItem = {}) {
  453. let { dx, dy, width, height, r, backgroundColor } = drawArrayItem;
  454. r = r || width * .1;
  455. if (width < 2 * r) {
  456. r = width / 2;
  457. }
  458. if (width < 2 * r) {
  459. r = width / 2;
  460. }
  461. Context.beginPath();
  462. Context.moveTo(dx + r, dy);
  463. Context.arcTo(dx + width, dy, dx + width, dy + height, r);
  464. Context.arcTo(dx + width, dy + height, dx, dy + height, r);
  465. Context.arcTo(dx, dy + height, dx, dy, r);
  466. Context.arcTo(dx, dy, dx + width, dy, r);
  467. Context.closePath();
  468. Context.setFillStyle(backgroundColor);
  469. Context.fill();
  470. }
  471. // export
  472. function setText(Context, texts) { // 设置文本数据
  473. _app.log('进入设置文字方法, texts:' + JSON.stringify(texts));
  474. if (texts && _app.isArray(texts)) {
  475. _app.log('texts是数组');
  476. if (texts.length > 0) {
  477. for (let i = 0; i < texts.length; i++) {
  478. _app.log('字符串信息-初始化之前:' + JSON.stringify(texts[i]));
  479. texts[i] = setTextFn(Context, texts[i]);
  480. }
  481. }
  482. } else {
  483. _app.log('texts是对象');
  484. texts = setTextFn(Context, texts);
  485. }
  486. _app.log('返回texts:' + JSON.stringify(texts));
  487. return texts;
  488. }
  489. function setTextFn(Context, textItem) {
  490. _app.log('进入设置文字方法, textItem:' + JSON.stringify(textItem));
  491. if (_app.isNotNull_string(textItem.text)) {
  492. textItem.text = String(textItem.text);
  493. textItem.alpha = textItem.alpha !== undefined ? Number(textItem.alpha) : 1;
  494. textItem.color = textItem.color || 'black';
  495. textItem.size = textItem.size !== undefined ? Number(textItem.size) : 10;
  496. textItem.textAlign = textItem.textAlign || 'left';
  497. textItem.textBaseline = textItem.textBaseline || 'middle';
  498. textItem.dx = Number(textItem.dx) || 0;
  499. textItem.dy = Number(textItem.dy) || 0;
  500. textItem.size = Math.ceil(Number(textItem.size));
  501. _app.log('字符串信息-初始化默认值后:' + JSON.stringify(textItem));
  502. const textLength = countTextLength(Context, {
  503. text: textItem.text,
  504. size: textItem.size
  505. });
  506. _app.log('字符串信息-初始化时的文本长度:' + textLength);
  507. let infoCallBackObj = {};
  508. if (textItem.infoCallBack && typeof(textItem.infoCallBack) === 'function') {
  509. infoCallBackObj = textItem.infoCallBack(textLength);
  510. }
  511. textItem = {
  512. ...textItem,
  513. textLength,
  514. ...infoCallBackObj
  515. }
  516. _app.log('字符串信息-infoCallBack后:' + JSON.stringify(textItem));
  517. }
  518. return textItem;
  519. }
  520. function countTextLength(Context, obj) {
  521. _app.log('计算文字长度, obj:' + JSON.stringify(obj));
  522. const {
  523. text,
  524. size
  525. } = obj;
  526. Context.setFontSize(size);
  527. let textLength;
  528. try{
  529. textLength = Context.measureText(text); // 官方文档说 App端自定义组件编译模式暂时不可用measureText方法
  530. }catch(e){
  531. //TODO handle the exception
  532. textLength = {};
  533. }
  534. textLength = {};
  535. _app.log('measureText计算文字长度, textLength:' + JSON.stringify(textLength));
  536. textLength = textLength && textLength.width ? textLength.width : 0;
  537. if (!textLength) {
  538. let l = 0;
  539. for (let j = 0; j < text.length; j++) {
  540. let t = text.substr(j, 1);
  541. const countL = countStrLength(t);
  542. _app.log('计算文字宽度系数:' + countL);
  543. l += countL;
  544. }
  545. _app.log('文字宽度总系数:' + l);
  546. textLength = l * size;
  547. }
  548. return textLength;
  549. }
  550. //计算字符长度系数
  551. function countStrLength(t) {
  552. let l;
  553. if (/a/.test(t)) {
  554. l = 0.552734375
  555. } else if (/b/.test(t)) {
  556. l = 0.638671875
  557. } else if (/c/.test(t)) {
  558. l = 0.50146484375
  559. } else if (/d/.test(t)) {
  560. l = 0.6396484375
  561. } else if (/e/.test(t)) {
  562. l = 0.5673828125
  563. } else if (/f/.test(t)) {
  564. l = 0.3466796875
  565. } else if (/g/.test(t)) {
  566. l = 0.6396484375
  567. } else if (/h/.test(t)) {
  568. l = 0.61572265625
  569. } else if (/i/.test(t)) {
  570. l = 0.26611328125
  571. } else if (/j/.test(t)) {
  572. l = 0.26708984375
  573. } else if (/k/.test(t)) {
  574. l = 0.54443359375
  575. } else if (/l/.test(t)) {
  576. l = 0.26611328125
  577. } else if (/m/.test(t)) {
  578. l = 0.93701171875
  579. } else if (/n/.test(t)) {
  580. l = 0.6162109375
  581. } else if (/o/.test(t)) {
  582. l = 0.6357421875
  583. } else if (/p/.test(t)) {
  584. l = 0.638671875
  585. } else if (/q/.test(t)) {
  586. l = 0.6396484375
  587. } else if (/r/.test(t)) {
  588. l = 0.3818359375
  589. } else if (/s/.test(t)) {
  590. l = 0.462890625
  591. } else if (/t/.test(t)) {
  592. l = 0.37255859375
  593. } else if (/u/.test(t)) {
  594. l = 0.6162109375
  595. } else if (/v/.test(t)) {
  596. l = 0.52490234375
  597. } else if (/w/.test(t)) {
  598. l = 0.78955078125
  599. } else if (/x/.test(t)) {
  600. l = 0.5068359375
  601. } else if (/y/.test(t)) {
  602. l = 0.529296875
  603. } else if (/z/.test(t)) {
  604. l = 0.49169921875
  605. } else if (/A/.test(t)) {
  606. l = 0.70361328125
  607. } else if (/B/.test(t)) {
  608. l = 0.62744140625
  609. } else if (/C/.test(t)) {
  610. l = 0.6689453125
  611. } else if (/D/.test(t)) {
  612. l = 0.76171875
  613. } else if (/E/.test(t)) {
  614. l = 0.5498046875
  615. } else if (/F/.test(t)) {
  616. l = 0.53125
  617. } else if (/G/.test(t)) {
  618. l = 0.74365234375
  619. } else if (/H/.test(t)) {
  620. l = 0.7734375
  621. } else if (/I/.test(t)) {
  622. l = 0.2939453125
  623. } else if (/J/.test(t)) {
  624. l = 0.39599609375
  625. } else if (/K/.test(t)) {
  626. l = 0.634765625
  627. } else if (/L/.test(t)) {
  628. l = 0.51318359375
  629. } else if (/M/.test(t)) {
  630. l = 0.97705078125
  631. } else if (/N/.test(t)) {
  632. l = 0.81298828125
  633. } else if (/O/.test(t)) {
  634. l = 0.81494140625
  635. } else if (/P/.test(t)) {
  636. l = 0.61181640625
  637. } else if (/Q/.test(t)) {
  638. l = 0.81494140625
  639. } else if (/R/.test(t)) {
  640. l = 0.65283203125
  641. } else if (/S/.test(t)) {
  642. l = 0.5771484375
  643. } else if (/T/.test(t)) {
  644. l = 0.5732421875
  645. } else if (/U/.test(t)) {
  646. l = 0.74658203125
  647. } else if (/V/.test(t)) {
  648. l = 0.67626953125
  649. } else if (/W/.test(t)) {
  650. l = 1.017578125
  651. } else if (/X/.test(t)) {
  652. l = 0.64501953125
  653. } else if (/Y/.test(t)) {
  654. l = 0.603515625
  655. } else if (/Z/.test(t)) {
  656. l = 0.6201171875
  657. } else if (/[0-9]/.test(t)) {
  658. l = 0.58642578125
  659. } else if (/[\u4e00-\u9fa5]/.test(t)) {
  660. l = 1
  661. } else if (/ /.test(t)) {
  662. l = 0.2958984375
  663. } else if (/\`/.test(t)) {
  664. l = 0.294921875
  665. } else if (/\~/.test(t)) {
  666. l = 0.74169921875
  667. } else if (/\!/.test(t)) {
  668. l = 0.3125
  669. } else if (/\@/.test(t)) {
  670. l = 1.03125
  671. } else if (/\#/.test(t)) {
  672. l = 0.63818359375
  673. } else if (/\$/.test(t)) {
  674. l = 0.58642578125
  675. } else if (/\%/.test(t)) {
  676. l = 0.8896484375
  677. } else if (/\^/.test(t)) {
  678. l = 0.74169921875
  679. } else if (/\&/.test(t)) {
  680. l = 0.8701171875
  681. } else if (/\*/.test(t)) {
  682. l = 0.455078125
  683. } else if (/\(/.test(t)) {
  684. l = 0.333984375
  685. } else if (/\)/.test(t)) {
  686. l = 0.333984375
  687. } else if (/\_/.test(t)) {
  688. l = 0.4482421875
  689. } else if (/\-/.test(t)) {
  690. l = 0.4326171875
  691. } else if (/\+/.test(t)) {
  692. l = 0.74169921875
  693. } else if (/\=/.test(t)) {
  694. l = 0.74169921875
  695. } else if (/\|/.test(t)) {
  696. l = 0.26904296875
  697. } else if (/\\/.test(t)) {
  698. l = 0.416015625
  699. } else if (/\[/.test(t)) {
  700. l = 0.333984375
  701. } else if (/\]/.test(t)) {
  702. l = 0.333984375
  703. } else if (/\;/.test(t)) {
  704. l = 0.24072265625
  705. } else if (/\'/.test(t)) {
  706. l = 0.25634765625
  707. } else if (/\,/.test(t)) {
  708. l = 0.24072265625
  709. } else if (/\./.test(t)) {
  710. l = 0.24072265625
  711. } else if (/\//.test(t)) {
  712. l = 0.42724609375
  713. } else if (/\{/.test(t)) {
  714. l = 0.333984375
  715. } else if (/\}/.test(t)) {
  716. l = 0.333984375
  717. } else if (/\:/.test(t)) {
  718. l = 0.24072265625
  719. } else if (/\"/.test(t)) {
  720. l = 0.435546875
  721. } else if (/\</.test(t)) {
  722. l = 0.74169921875
  723. } else if (/\>/.test(t)) {
  724. l = 0.74169921875
  725. } else if (/\?/.test(t)) {
  726. l = 0.48291015625
  727. } else {
  728. l = 1
  729. }
  730. return l;
  731. }
  732. // export
  733. function setImage(images) { // 设置图片数据
  734. _app.log('进入设置图片数据方法');
  735. return new Promise(async (resolve, rejcet) => {
  736. try {
  737. if (images && _app.isArray(images)) {
  738. _app.log('images是一个数组');
  739. for (let i = 0; i < images.length; i++) {
  740. _app.log('设置图片数据循环中:' + i);
  741. images[i] = await setImageFn(images[i]);
  742. }
  743. } else {
  744. _app.log('images是一个对象');
  745. images = await setImageFn(images);
  746. }
  747. resolve(images);
  748. } catch (e) {
  749. //TODO handle the exception
  750. rejcet(e);
  751. }
  752. })
  753. }
  754. function base64ToPathFn(path) {
  755. var reg = /^\s*data:([a-z]+\/[a-z0-9-+.]+(;[a-z-]+=[a-z0-9-]+)?)?(;base64)?,([a-z0-9!$&',()*+;=\-._~:@\/?%\s]*?)\s*$/i;
  756. if(!reg.test(path)){
  757. return Promise.resolve(path);
  758. }
  759. return base64ToPath(path);
  760. }
  761. function setImageFn(image) {
  762. return new Promise(async (resolve, reject) => {
  763. if (image.url) {
  764. image.url = (await base64ToPathFn(image.url));
  765. let imgUrl = image.url;
  766. imgUrl = await _app.downloadFile_PromiseFc(imgUrl);
  767. image.url = imgUrl;
  768. const hasinfoCallBack = image.infoCallBack && typeof(image.infoCallBack) === 'function';
  769. let imageInfo = {};
  770. imageInfo = await _app.getImageInfo_PromiseFc(imgUrl);
  771. if (hasinfoCallBack) {
  772. image = {
  773. ...image,
  774. ...image.infoCallBack(imageInfo)
  775. };
  776. }
  777. image.dx = Number(image.dx) || 0;
  778. image.dy = Number(image.dy) || 0;
  779. image.dWidth = Number(image.dWidth || imageInfo.width);
  780. image.dHeight = Number(image.dHeight || imageInfo.height);
  781. image = {
  782. ...image,
  783. imageInfo
  784. }
  785. }
  786. resolve(image);
  787. })
  788. }
  789. // export
  790. function drawText(Context, textArray, bgObj) { // 先遍历换行再绘制
  791. if (!_app.isArray(textArray)) {
  792. _app.log('遍历文本方法, 不是数组');
  793. textArray = [textArray];
  794. } else {
  795. _app.log('遍历文本方法, 是数组');
  796. }
  797. _app.log('遍历文本方法, textArray:' + JSON.stringify(textArray));
  798. const newArr = [];
  799. if (textArray && textArray.length > 0) {
  800. for (let j = 0; j < textArray.length; j++) {
  801. const textItem = textArray[j];
  802. if (textItem.text && textItem.lineFeed) {
  803. let lineNum = -1,
  804. maxWidth = bgObj.width,
  805. lineHeight = textItem.size,
  806. dx = textItem.dx;
  807. if (_app.isObject(textItem.lineFeed)) {
  808. const lineFeed = textItem.lineFeed;
  809. lineNum = (lineFeed.lineNum !== undefined && typeof(lineFeed.lineNum) === 'number') && lineFeed.lineNum >= 0 ?
  810. lineFeed.lineNum : lineNum;
  811. maxWidth = (lineFeed.maxWidth !== undefined && typeof(lineFeed.maxWidth) === 'number') ? lineFeed.maxWidth :
  812. maxWidth;
  813. lineHeight = (lineFeed.lineHeight !== undefined && typeof(lineFeed.lineHeight) === 'number') ? lineFeed.lineHeight :
  814. lineHeight;
  815. dx = (lineFeed.dx !== undefined && typeof(lineFeed.dx) === 'number') ? lineFeed.dx : dx;
  816. }
  817. const chr = (textItem.text).split("");
  818. let temp = "";
  819. const row = [];
  820. //循环出几行文字组成数组
  821. for (let a = 0, len = chr.length; a < len; a++) {
  822. if (countTextLength(Context, {
  823. text: temp,
  824. size: textItem.size
  825. }) <= maxWidth && countTextLength(Context, {
  826. text: (temp + chr[a]),
  827. size: textItem.size
  828. }) <= maxWidth) {
  829. temp += chr[a];
  830. if (a == (chr.length - 1)) {
  831. row.push(temp);
  832. }
  833. } else {
  834. row.push(temp);
  835. temp = chr[a];
  836. }
  837. }
  838. _app.log('循环出的文本数组:' + JSON.stringify(row));
  839. //只显示几行 变量间距lineHeight 变量行数lineNum
  840. let allNum = (lineNum >= 0 && lineNum < row.length) ? lineNum : row.length;
  841. for (let i = 0; i < allNum; i++) {
  842. let str = row[i];
  843. if (i == (allNum - 1) && allNum < row.length) {
  844. str = str.substring(0, str.length - 1) + '...';
  845. }
  846. const obj = { ...textItem,
  847. text: str,
  848. dx: i === 0 ? textItem.dx : (dx >= 0 ? dx : textItem.dx),
  849. dy: textItem.dy + (i * lineHeight),
  850. textLength: countTextLength(Context, {
  851. text: str,
  852. size: textItem.size
  853. })
  854. };
  855. _app.log('重新组成的文本对象:' + JSON.stringify(obj));
  856. newArr.push(obj);
  857. }
  858. } else {
  859. newArr.push(textItem);
  860. }
  861. }
  862. }
  863. _app.log('绘制文本新数组:' + JSON.stringify(newArr));
  864. drawTexts(Context, newArr);
  865. }
  866. function setFont(textItem = {}) {
  867. if (textItem.font && typeof(textItem.font) === 'string') {
  868. _app.log(textItem.font)
  869. return textItem.font;
  870. } else {
  871. let fontStyle = 'normal';
  872. let fontVariant = 'normal';
  873. let fontWeight = 'normal';
  874. let fontSize = textItem.size || 10;
  875. let fontFamily = 'sans-serif';
  876. fontSize = Math.ceil(Number(fontSize));
  877. if (textItem.fontStyle && typeof(textItem.fontStyle) === 'string')
  878. fontStyle = textItem.fontStyle.trim();
  879. if (textItem.fontVariant && typeof(textItem.fontVariant) === 'string')
  880. fontVariant = textItem.fontVariant.trim();
  881. if (textItem.fontWeight && (typeof(textItem.fontWeight) === 'string' || typeof(textItem.fontWeight) === 'number'))
  882. fontWeight = textItem.fontWeight.trim();
  883. if (textItem.fontFamily && typeof(textItem.fontFamily) === 'string')
  884. fontFamily = textItem.fontFamily.trim();
  885. return fontStyle + ' ' +
  886. fontVariant + ' ' +
  887. fontWeight + ' ' +
  888. fontSize + 'px' + ' ' +
  889. fontFamily;
  890. }
  891. }
  892. function drawTexts(Context, texts) { // 绘制文本
  893. _app.log('准备绘制文本方法, texts:' + JSON.stringify(texts));
  894. if (texts && _app.isArray(texts)) {
  895. _app.log('准备绘制文本方法, 是数组');
  896. if (texts.length > 0) {
  897. for (let i = 0; i < texts.length; i++) {
  898. drawTextFn(Context, texts[i]);
  899. }
  900. }
  901. } else {
  902. _app.log('准备绘制文本方法, 不是数组');
  903. drawTextFn(Context, texts);
  904. }
  905. }
  906. function drawTextFn(Context, textItem) {
  907. _app.log('进入绘制文本方法, textItem:' + JSON.stringify(textItem));
  908. if (textItem && _app.isObject(textItem) && textItem.text) {
  909. Context.font = setFont(textItem);
  910. Context.setFillStyle(textItem.color);
  911. Context.setGlobalAlpha(textItem.alpha);
  912. Context.setTextAlign(textItem.textAlign);
  913. Context.setTextBaseline(textItem.textBaseline);
  914. Context.fillText(textItem.text, textItem.dx, textItem.dy);
  915. if (textItem.lineThrough && _app.isObject(textItem.lineThrough)) {
  916. _app.log('有删除线');
  917. let lineThrough = textItem.lineThrough;
  918. lineThrough.alpha = lineThrough.alpha !== undefined ? lineThrough.alpha : textItem.alpha;
  919. lineThrough.style = lineThrough.style || textItem.color;
  920. lineThrough.width = lineThrough.width !== undefined ? lineThrough.width : textItem.size / 10;
  921. lineThrough.cap = lineThrough.cap !== undefined ? lineThrough.cap : 'butt';
  922. _app.log('删除线对象:' + JSON.stringify(lineThrough));
  923. Context.setGlobalAlpha(lineThrough.alpha);
  924. Context.setStrokeStyle(lineThrough.style);
  925. Context.setLineWidth(lineThrough.width);
  926. Context.setLineCap(lineThrough.cap);
  927. let mx, my;
  928. switch (textItem.textAlign) {
  929. case 'left':
  930. mx = textItem.dx;
  931. break;
  932. case 'center':
  933. mx = textItem.dx - (textItem.textLength) / 2;
  934. break;
  935. default:
  936. mx = textItem.dx - (textItem.textLength);
  937. break;
  938. }
  939. switch (textItem.textBaseline) {
  940. case 'top':
  941. my = textItem.dy + (textItem.size * .5);
  942. break;
  943. case 'middle':
  944. my = textItem.dy;
  945. break;
  946. default:
  947. my = textItem.dy - (textItem.size * .5);
  948. break;
  949. }
  950. Context.beginPath();
  951. Context.moveTo(mx, my);
  952. Context.lineTo(mx + textItem.textLength, my);
  953. Context.stroke();
  954. Context.closePath();
  955. _app.log('删除线完毕');
  956. }
  957. Context.setGlobalAlpha(1);
  958. Context.font = '10px sans-serif';
  959. }
  960. }
  961. // export
  962. function drawImage(Context, images) { // 绘制图片
  963. _app.log('判断图片数据类型:' + JSON.stringify(images))
  964. if (images && _app.isArray(images)) {
  965. if (images.length > 0) {
  966. for (let i = 0; i < images.length; i++) {
  967. readyDrawImageFn(Context, images[i]);
  968. }
  969. }
  970. } else {
  971. readyDrawImageFn(Context, images);
  972. }
  973. }
  974. function readyDrawImageFn(Context, img) {
  975. _app.log('判断绘制图片形状, img:' + JSON.stringify(img));
  976. if (img.url) {
  977. if (img.circleSet) {
  978. drawCircleImage(Context, img);
  979. } else if (img.roundRectSet) {
  980. drawRoundRectImage(Context, img);
  981. } else {
  982. drawImageFn(Context, img);
  983. }
  984. }
  985. }
  986. function drawImageFn(Context, img) {
  987. _app.log('进入绘制默认图片方法, img:' + JSON.stringify(img));
  988. if (img.url) {
  989. const hasAlpha = !_app.isUndef(img.alpha);
  990. img.alpha = Number(!_app.isUndef(img.alpha) ? img.alpha : 1);
  991. Context.setGlobalAlpha(img.alpha);
  992. _app.log('绘制默认图片方法, 有url');
  993. if (img.dWidth && img.dHeight && img.sx && img.sy && img.sWidth && img.sHeight) {
  994. _app.log('绘制默认图片方法, 绘制第一种方案');
  995. Context.drawImage(img.url,
  996. Number(img.sx) || false, Number(img.sy) || false,
  997. Number(img.sWidth) || false, Number(img.sHeight) || false,
  998. Number(img.dx || 0), Number(img.dy || 0),
  999. Number(img.dWidth) || false, Number(img.dHeight) || false,);
  1000. } else if (img.dWidth && img.dHeight) {
  1001. _app.log('绘制默认图片方法, 绘制第二种方案');
  1002. Context.drawImage(img.url, Number(img.dx || 0), Number(img.dy || 0),
  1003. Number(img.dWidth) || false, Number(img.dHeight) || false);
  1004. } else {
  1005. _app.log('绘制默认图片方法, 绘制第三种方案');
  1006. Context.drawImage(img.url, Number(img.dx || 0), Number(img.dy || 0));
  1007. }
  1008. if (hasAlpha) {
  1009. Context.setGlobalAlpha(1);
  1010. }
  1011. }
  1012. _app.log('绘制默认图片方法, 绘制完毕');
  1013. }
  1014. function drawCircleImage(Context, obj) {
  1015. _app.log('进入绘制圆形图片方法, obj:' + JSON.stringify(obj));
  1016. let {
  1017. dx,
  1018. dy,
  1019. dWidth,
  1020. dHeight,
  1021. circleSet,
  1022. imageInfo
  1023. } = obj;
  1024. let x, y, r;
  1025. if (typeof circleSet === 'object') {
  1026. x = circleSet.x;
  1027. y = circleSet.y;
  1028. r = circleSet.r;
  1029. }
  1030. if (!r) {
  1031. let d;
  1032. d = dWidth > dHeight ? dHeight : dWidth;
  1033. r = d / 2;
  1034. }
  1035. x = x ? dx + x : (dx || 0) + r;
  1036. y = y ? dy + y : (dy || 0) + r;
  1037. Context.save();
  1038. Context.beginPath();
  1039. Context.arc(x, y, r, 0, 2 * Math.PI, false);
  1040. Context.closePath();
  1041. Context.setGlobalAlpha(0);
  1042. Context.fillStyle = '#FFFFFF';
  1043. Context.fill();
  1044. Context.setGlobalAlpha(1);
  1045. Context.clip();
  1046. drawImageFn(Context, obj);
  1047. _app.log('默认图片绘制完毕');
  1048. Context.restore();
  1049. }
  1050. function drawRoundRectImage(Context, obj) { // 绘制矩形
  1051. _app.log('进入绘制矩形图片方法, obj:' + JSON.stringify(obj));
  1052. Context.save();
  1053. let {
  1054. dx,
  1055. dy,
  1056. dWidth,
  1057. dHeight,
  1058. roundRectSet,
  1059. imageInfo
  1060. } = obj;
  1061. let r;
  1062. if (typeof roundRectSet === 'object') {
  1063. r = roundRectSet.r;
  1064. }
  1065. r = r || dWidth * .1;
  1066. if (dWidth < 2 * r) {
  1067. r = dWidth / 2;
  1068. }
  1069. if (dHeight < 2 * r) {
  1070. r = dHeight / 2;
  1071. }
  1072. Context.beginPath();
  1073. Context.moveTo(dx + r, dy);
  1074. Context.arcTo(dx + dWidth, dy, dx + dWidth, dy + dHeight, r);
  1075. Context.arcTo(dx + dWidth, dy + dHeight, dx, dy + dHeight, r);
  1076. Context.arcTo(dx, dy + dHeight, dx, dy, r);
  1077. Context.arcTo(dx, dy, dx + dWidth, dy, r);
  1078. Context.closePath();
  1079. Context.setGlobalAlpha(0);
  1080. Context.fillStyle = '#FFFFFF';
  1081. Context.fill();
  1082. Context.setGlobalAlpha(1);
  1083. Context.clip();
  1084. drawImageFn(Context, obj);
  1085. Context.restore();
  1086. _app.log('进入绘制矩形图片方法, 绘制完毕');
  1087. }
  1088. // export
  1089. function drawQrCode(Context, qrCodeObj) { //生成二维码方法, 参考了 诗小柒 的二维码生成器代码
  1090. _app.log('进入绘制二维码方法')
  1091. _app.showLoading('正在生成二维码');
  1092. let qrcodeAlgObjCache = [];
  1093. let options = {
  1094. text: String(qrCodeObj.text || '') || '', // 生成内容
  1095. size: Number(qrCodeObj.size || 0) || 200, // 二维码大小
  1096. background: String(qrCodeObj.background || '') || '#ffffff', // 背景色
  1097. foreground: String(qrCodeObj.foreground || '') || '#000000', // 前景色
  1098. pdground: String(qrCodeObj.pdground || '') || '#000000', // 定位角点颜色
  1099. correctLevel: Number(qrCodeObj.correctLevel || 0) || 3, // 容错级别
  1100. image: String(qrCodeObj.image || '') || '', // 二维码图标
  1101. imageSize: Number(qrCodeObj.imageSize || 0) || 40, // 二维码图标大小
  1102. dx: Number(qrCodeObj.dx || 0) || 0, // x轴距离
  1103. dy: Number(qrCodeObj.dy || 0) || 0 // y轴距离
  1104. }
  1105. let qrCodeAlg = null;
  1106. let d = 0;
  1107. for (var i = 0, l = qrcodeAlgObjCache.length; i < l; i++) {
  1108. d = i;
  1109. if (qrcodeAlgObjCache[i].text == options.text && qrcodeAlgObjCache[i].text.correctLevel == options.correctLevel) {
  1110. qrCodeAlg = qrcodeAlgObjCache[i].obj;
  1111. break;
  1112. }
  1113. }
  1114. if (d == l) {
  1115. qrCodeAlg = new QRCodeAlg(options.text, options.correctLevel);
  1116. qrcodeAlgObjCache.push({
  1117. text: options.text,
  1118. correctLevel: options.correctLevel,
  1119. obj: qrCodeAlg
  1120. });
  1121. }
  1122. let getForeGround = function(config) {
  1123. let options = config.options;
  1124. if (options.pdground && (
  1125. (config.row > 1 && config.row < 5 && config.col > 1 && config.col < 5) ||
  1126. (config.row > (config.count - 6) && config.row < (config.count - 2) && config.col > 1 && config.col < 5) ||
  1127. (config.row > 1 && config.row < 5 && config.col > (config.count - 6) && config.col < (config.count - 2))
  1128. )) {
  1129. return options.pdground;
  1130. }
  1131. return options.foreground;
  1132. }
  1133. let count = qrCodeAlg.getModuleCount();
  1134. let ratioSize = options.size;
  1135. let ratioImgSize = options.imageSize;
  1136. //计算每个点的长宽
  1137. let tileW = (ratioSize / count).toPrecision(4);
  1138. let tileH = (ratioSize / count).toPrecision(4);
  1139. //绘制
  1140. for (let row = 0; row < count; row++) {
  1141. for (let col = 0; col < count; col++) {
  1142. let w = (Math.ceil((col + 1) * tileW) - Math.floor(col * tileW));
  1143. let h = (Math.ceil((row + 1) * tileW) - Math.floor(row * tileW));
  1144. let foreground = getForeGround({
  1145. row: row,
  1146. col: col,
  1147. count: count,
  1148. options: options
  1149. });
  1150. Context.setFillStyle(qrCodeAlg.modules[row][col] ? foreground : options.background);
  1151. Context.fillRect(options.dx + Math.round(col * tileW), options.dy + Math.round(row * tileH), w, h);
  1152. }
  1153. }
  1154. if (options.image) {
  1155. let x = options.dx + Number(((ratioSize - ratioImgSize) / 2).toFixed(2));
  1156. let y = options.dy + Number(((ratioSize - ratioImgSize) / 2).toFixed(2));
  1157. drawRoundedRect(Context, x, y, ratioImgSize, ratioImgSize, 2, 6, true, true)
  1158. Context.drawImage(options.image, x, y, ratioImgSize, ratioImgSize);
  1159. // 画圆角矩形
  1160. function drawRoundedRect(ctxi, x, y, width, height, r, lineWidth, fill, stroke) {
  1161. ctxi.setLineWidth(lineWidth);
  1162. ctxi.setFillStyle(options.background);
  1163. ctxi.setStrokeStyle(options.background);
  1164. ctxi.beginPath(); // draw top and top right corner
  1165. ctxi.moveTo(x + r, y);
  1166. ctxi.arcTo(x + width, y, x + width, y + r, r); // draw right side and bottom right corner
  1167. ctxi.arcTo(x + width, y + height, x + width - r, y + height, r); // draw bottom and bottom left corner
  1168. ctxi.arcTo(x, y + height, x, y + height - r, r); // draw left and top left corner
  1169. ctxi.arcTo(x, y, x + r, y, r);
  1170. ctxi.closePath();
  1171. if (fill) {
  1172. ctxi.fill();
  1173. }
  1174. if (stroke) {
  1175. ctxi.stroke();
  1176. }
  1177. }
  1178. }
  1179. _app.log('进入绘制二维码方法完毕')
  1180. _app.hideLoading();
  1181. }
  1182. function getShreUserPosterBackground(objs) { //检查背景图是否存在于本地, 若存在直接返回, 否则调用getShreUserPosterBackgroundFc方法
  1183. let {
  1184. backgroundImage,
  1185. type
  1186. } = objs;
  1187. return new Promise(async (resolve, reject) => {
  1188. try {
  1189. _app.showLoading('正在获取海报背景图');
  1190. const savedFilePath = await getShreUserPosterBackgroundFc(objs)
  1191. _app.hideLoading();
  1192. resolve(savedFilePath);
  1193. } catch (e) {
  1194. _app.hideLoading();
  1195. _app.showToast('获取分享用户背景图失败:' + JSON.stringify(e));
  1196. _app.log(JSON.stringify(e));
  1197. reject(e);
  1198. }
  1199. })
  1200. }
  1201. function getPosterStorage(type) {
  1202. return _app.getStorageSync(getStorageKey(type));
  1203. }
  1204. function removePosterStorage(type) {
  1205. const ShreUserPosterBackgroundKey = getStorageKey(type);
  1206. const pbg = _app.getStorageSync(ShreUserPosterBackgroundKey);
  1207. if (pbg && pbg.path) {
  1208. _app.removeStorageSync(ShreUserPosterBackgroundKey);
  1209. }
  1210. }
  1211. function setPosterStorage(type, data) {
  1212. _app.setStorage(getStorageKey(type), data);
  1213. }
  1214. function getStorageKey(type) {
  1215. return ShreUserPosterBackgroundKey + (type || 'default');
  1216. }
  1217. function getShreUserPosterBackgroundFc(objs, upimage) { //下载并保存背景图方法
  1218. let {
  1219. backgroundImage,
  1220. type
  1221. } = objs;
  1222. _app.log('获取分享背景图, 尝试清空本地数据');
  1223. return new Promise(async (resolve, reject) => {
  1224. try {
  1225. _app.showLoading('正在下载海报背景图');
  1226. _app.log('没有从后端获取的背景图片路径, 尝试从后端获取背景图片路径');
  1227. let image = backgroundImage?backgroundImage:(await _app.getPosterUrl(objs));
  1228. image = (await base64ToPathFn(image));
  1229. _app.log('尝试下载并保存背景图:' + image);
  1230. const savedFilePath = await _app.downLoadAndSaveFile_PromiseFc(image);
  1231. if (savedFilePath) {
  1232. _app.log('下载并保存背景图成功:' + savedFilePath);
  1233. const imageObj = await _app.getImageInfo_PromiseFc(savedFilePath);
  1234. _app.log('获取图片信息成功');
  1235. const returnObj = {
  1236. path: savedFilePath,
  1237. width: imageObj.width,
  1238. height: imageObj.height,
  1239. name: _app.fileNameInPath(image)
  1240. }
  1241. _app.log('拼接背景图信息对象成功:' + JSON.stringify(returnObj));
  1242. // #ifndef H5
  1243. setPosterStorage(type, { ...returnObj
  1244. });
  1245. // #endif
  1246. _app.hideLoading();
  1247. _app.log('返回背景图信息对象');
  1248. resolve({ ...returnObj
  1249. });
  1250. } else {
  1251. _app.hideLoading();
  1252. reject('not find savedFilePath');
  1253. }
  1254. } catch (e) {
  1255. //TODO handle the exception
  1256. reject(e);
  1257. }
  1258. });
  1259. }
  1260. module.exports = {
  1261. getSharePoster,
  1262. setText,
  1263. setImage,
  1264. drawText,
  1265. drawImage,
  1266. drawQrCode,
  1267. drawFillRect,
  1268. drawStrokeRect,
  1269. drawRoundStrokeRect,
  1270. drawRoundFillRect
  1271. }