QS-SharePoster.js 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321
  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: bgObj.width,
  346. height: bgObj.height,
  347. destWidth: bgObj.width, // 若H5使用这里请不要乘以二
  348. destHeight: bgObj.height, // 若H5使用这里请不要乘以二
  349. quality: .8,
  350. fileType: 'jpg',
  351. ...setObj
  352. };
  353. _app.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. _app.log('输出图片失败:' + JSON.stringify(err));
  365. rj('输出图片失败:' + JSON.stringify(err))
  366. }
  367. }
  368. uni.canvasToTempFilePath(toTempFilePathObj, _this || null);
  369. }
  370. let delayTime = 0;
  371. if (qrCodeArray) {
  372. qrCodeArray.forEach(item => {
  373. if (item.text) {
  374. delayTime += Number(item.text.length);
  375. }
  376. })
  377. }
  378. if (imagesArray) {
  379. imagesArray.forEach(() => {
  380. delayTime += delayTimeScale;
  381. })
  382. }
  383. if (textArray) {
  384. textArray.forEach(() => {
  385. delayTime += delayTimeScale;
  386. })
  387. }
  388. if (drawArray) {
  389. drawArray.forEach(item => {
  390. switch (item.type) {
  391. case 'text':
  392. if (item.text) {
  393. delayTime += item.text.length;
  394. }
  395. break;
  396. default:
  397. delayTime += delayTimeScale;
  398. break;
  399. }
  400. })
  401. }
  402. _app.log('延时系数:' + delayTimeScale);
  403. _app.log('总计延时:' + delayTime);
  404. setTimeout(canvasToTempFilePathFn, delayTime);
  405. }
  406. Context.draw((typeof(reserve) == 'boolean' ? reserve : false), fn);
  407. }, drawDelayTime);
  408. } catch (e) {
  409. //TODO handle the exception
  410. _app.hideLoading();
  411. rj(e);
  412. }
  413. });
  414. }
  415. // export
  416. function drawFillRect(Context, drawArrayItem = {}) { //填充矩形
  417. _app.log('进入绘制填充直角矩形方法, drawArrayItem:' + JSON.stringify(drawArrayItem));
  418. Context.setFillStyle(drawArrayItem.backgroundColor || 'black');
  419. Context.setGlobalAlpha(drawArrayItem.alpha || 1);
  420. Context.fillRect(drawArrayItem.dx || 0, drawArrayItem.dy || 0, drawArrayItem.width || 0, drawArrayItem.height || 0);
  421. Context.setGlobalAlpha(1);
  422. }
  423. // export
  424. function drawStrokeRect(Context, drawArrayItem = {}) { //线条矩形
  425. Context.setStrokeStyle(drawArrayItem.color||'black');
  426. Context.setLineWidth(drawArrayItem.lineWidth || 1);
  427. Context.strokeRect(drawArrayItem.dx, drawArrayItem.dy, drawArrayItem.width, drawArrayItem.height);
  428. }
  429. // export
  430. function drawRoundStrokeRect(Context, drawArrayItem = {}) {
  431. let { dx, dy, width, height, r, lineWidth, color } = drawArrayItem;
  432. r = r || width * .1;
  433. if (width < 2 * r) {
  434. r = width / 2;
  435. }
  436. if (width < 2 * r) {
  437. r = width / 2;
  438. }
  439. Context.beginPath();
  440. Context.moveTo(dx + r, dy);
  441. Context.arcTo(dx + width, dy, dx + width, dy + height, r);
  442. Context.arcTo(dx + width, dy + height, dx, dy + height, r);
  443. Context.arcTo(dx, dy + height, dx, dy, r);
  444. Context.arcTo(dx, dy, dx + width, dy, r);
  445. Context.closePath();
  446. Context.setLineWidth(lineWidth || 1);
  447. Context.setStrokeStyle(color || 'black');
  448. Context.stroke();
  449. }
  450. // export
  451. function drawRoundFillRect(Context, drawArrayItem = {}) {
  452. let { dx, dy, width, height, r, backgroundColor } = drawArrayItem;
  453. r = r || width * .1;
  454. if (width < 2 * r) {
  455. r = width / 2;
  456. }
  457. if (width < 2 * r) {
  458. r = width / 2;
  459. }
  460. Context.beginPath();
  461. Context.moveTo(dx + r, dy);
  462. Context.arcTo(dx + width, dy, dx + width, dy + height, r);
  463. Context.arcTo(dx + width, dy + height, dx, dy + height, r);
  464. Context.arcTo(dx, dy + height, dx, dy, r);
  465. Context.arcTo(dx, dy, dx + width, dy, r);
  466. Context.closePath();
  467. Context.setFillStyle(backgroundColor);
  468. Context.fill();
  469. }
  470. // export
  471. function setText(Context, texts) { // 设置文本数据
  472. _app.log('进入设置文字方法, texts:' + JSON.stringify(texts));
  473. if (texts && _app.isArray(texts)) {
  474. _app.log('texts是数组');
  475. if (texts.length > 0) {
  476. for (let i = 0; i < texts.length; i++) {
  477. _app.log('字符串信息-初始化之前:' + JSON.stringify(texts[i]));
  478. texts[i] = setTextFn(Context, texts[i]);
  479. }
  480. }
  481. } else {
  482. _app.log('texts是对象');
  483. texts = setTextFn(Context, texts);
  484. }
  485. _app.log('返回texts:' + JSON.stringify(texts));
  486. return texts;
  487. }
  488. function setTextFn(Context, textItem) {
  489. _app.log('进入设置文字方法, textItem:' + JSON.stringify(textItem));
  490. if (_app.isNotNull_string(textItem.text)) {
  491. textItem.text = String(textItem.text);
  492. textItem.alpha = textItem.alpha !== undefined ? Number(textItem.alpha) : 1;
  493. textItem.color = textItem.color || 'black';
  494. textItem.size = textItem.size !== undefined ? Number(textItem.size) : 10;
  495. textItem.textAlign = textItem.textAlign || 'left';
  496. textItem.textBaseline = textItem.textBaseline || 'middle';
  497. textItem.dx = Number(textItem.dx) || 0;
  498. textItem.dy = Number(textItem.dy) || 0;
  499. textItem.size = Math.ceil(Number(textItem.size));
  500. _app.log('字符串信息-初始化默认值后:' + JSON.stringify(textItem));
  501. const textLength = countTextLength(Context, {
  502. text: textItem.text,
  503. size: textItem.size
  504. });
  505. _app.log('字符串信息-初始化时的文本长度:' + textLength);
  506. let infoCallBackObj = {};
  507. if (textItem.infoCallBack && typeof(textItem.infoCallBack) === 'function') {
  508. infoCallBackObj = textItem.infoCallBack(textLength);
  509. }
  510. textItem = {
  511. ...textItem,
  512. textLength,
  513. ...infoCallBackObj
  514. }
  515. _app.log('字符串信息-infoCallBack后:' + JSON.stringify(textItem));
  516. }
  517. return textItem;
  518. }
  519. function countTextLength(Context, obj) {
  520. _app.log('计算文字长度, obj:' + JSON.stringify(obj));
  521. const {
  522. text,
  523. size
  524. } = obj;
  525. Context.setFontSize(size);
  526. let textLength;
  527. try{
  528. textLength = Context.measureText(text); // 官方文档说 App端自定义组件编译模式暂时不可用measureText方法
  529. }catch(e){
  530. //TODO handle the exception
  531. textLength = {};
  532. }
  533. textLength = {};
  534. _app.log('measureText计算文字长度, textLength:' + JSON.stringify(textLength));
  535. textLength = textLength && textLength.width ? textLength.width : 0;
  536. if (!textLength) {
  537. let l = 0;
  538. for (let j = 0; j < text.length; j++) {
  539. let t = text.substr(j, 1);
  540. const countL = countStrLength(t);
  541. _app.log('计算文字宽度系数:' + countL);
  542. l += countL;
  543. }
  544. _app.log('文字宽度总系数:' + l);
  545. textLength = l * size;
  546. }
  547. return textLength;
  548. }
  549. //计算字符长度系数
  550. function countStrLength(t) {
  551. let l;
  552. if (/a/.test(t)) {
  553. l = 0.552734375
  554. } else if (/b/.test(t)) {
  555. l = 0.638671875
  556. } else if (/c/.test(t)) {
  557. l = 0.50146484375
  558. } else if (/d/.test(t)) {
  559. l = 0.6396484375
  560. } else if (/e/.test(t)) {
  561. l = 0.5673828125
  562. } else if (/f/.test(t)) {
  563. l = 0.3466796875
  564. } else if (/g/.test(t)) {
  565. l = 0.6396484375
  566. } else if (/h/.test(t)) {
  567. l = 0.61572265625
  568. } else if (/i/.test(t)) {
  569. l = 0.26611328125
  570. } else if (/j/.test(t)) {
  571. l = 0.26708984375
  572. } else if (/k/.test(t)) {
  573. l = 0.54443359375
  574. } else if (/l/.test(t)) {
  575. l = 0.26611328125
  576. } else if (/m/.test(t)) {
  577. l = 0.93701171875
  578. } else if (/n/.test(t)) {
  579. l = 0.6162109375
  580. } else if (/o/.test(t)) {
  581. l = 0.6357421875
  582. } else if (/p/.test(t)) {
  583. l = 0.638671875
  584. } else if (/q/.test(t)) {
  585. l = 0.6396484375
  586. } else if (/r/.test(t)) {
  587. l = 0.3818359375
  588. } else if (/s/.test(t)) {
  589. l = 0.462890625
  590. } else if (/t/.test(t)) {
  591. l = 0.37255859375
  592. } else if (/u/.test(t)) {
  593. l = 0.6162109375
  594. } else if (/v/.test(t)) {
  595. l = 0.52490234375
  596. } else if (/w/.test(t)) {
  597. l = 0.78955078125
  598. } else if (/x/.test(t)) {
  599. l = 0.5068359375
  600. } else if (/y/.test(t)) {
  601. l = 0.529296875
  602. } else if (/z/.test(t)) {
  603. l = 0.49169921875
  604. } else if (/A/.test(t)) {
  605. l = 0.70361328125
  606. } else if (/B/.test(t)) {
  607. l = 0.62744140625
  608. } else if (/C/.test(t)) {
  609. l = 0.6689453125
  610. } else if (/D/.test(t)) {
  611. l = 0.76171875
  612. } else if (/E/.test(t)) {
  613. l = 0.5498046875
  614. } else if (/F/.test(t)) {
  615. l = 0.53125
  616. } else if (/G/.test(t)) {
  617. l = 0.74365234375
  618. } else if (/H/.test(t)) {
  619. l = 0.7734375
  620. } else if (/I/.test(t)) {
  621. l = 0.2939453125
  622. } else if (/J/.test(t)) {
  623. l = 0.39599609375
  624. } else if (/K/.test(t)) {
  625. l = 0.634765625
  626. } else if (/L/.test(t)) {
  627. l = 0.51318359375
  628. } else if (/M/.test(t)) {
  629. l = 0.97705078125
  630. } else if (/N/.test(t)) {
  631. l = 0.81298828125
  632. } else if (/O/.test(t)) {
  633. l = 0.81494140625
  634. } else if (/P/.test(t)) {
  635. l = 0.61181640625
  636. } else if (/Q/.test(t)) {
  637. l = 0.81494140625
  638. } else if (/R/.test(t)) {
  639. l = 0.65283203125
  640. } else if (/S/.test(t)) {
  641. l = 0.5771484375
  642. } else if (/T/.test(t)) {
  643. l = 0.5732421875
  644. } else if (/U/.test(t)) {
  645. l = 0.74658203125
  646. } else if (/V/.test(t)) {
  647. l = 0.67626953125
  648. } else if (/W/.test(t)) {
  649. l = 1.017578125
  650. } else if (/X/.test(t)) {
  651. l = 0.64501953125
  652. } else if (/Y/.test(t)) {
  653. l = 0.603515625
  654. } else if (/Z/.test(t)) {
  655. l = 0.6201171875
  656. } else if (/[0-9]/.test(t)) {
  657. l = 0.58642578125
  658. } else if (/[\u4e00-\u9fa5]/.test(t)) {
  659. l = 1
  660. } else if (/ /.test(t)) {
  661. l = 0.2958984375
  662. } else if (/\`/.test(t)) {
  663. l = 0.294921875
  664. } else if (/\~/.test(t)) {
  665. l = 0.74169921875
  666. } else if (/\!/.test(t)) {
  667. l = 0.3125
  668. } else if (/\@/.test(t)) {
  669. l = 1.03125
  670. } else if (/\#/.test(t)) {
  671. l = 0.63818359375
  672. } else if (/\$/.test(t)) {
  673. l = 0.58642578125
  674. } else if (/\%/.test(t)) {
  675. l = 0.8896484375
  676. } else if (/\^/.test(t)) {
  677. l = 0.74169921875
  678. } else if (/\&/.test(t)) {
  679. l = 0.8701171875
  680. } else if (/\*/.test(t)) {
  681. l = 0.455078125
  682. } else if (/\(/.test(t)) {
  683. l = 0.333984375
  684. } else if (/\)/.test(t)) {
  685. l = 0.333984375
  686. } else if (/\_/.test(t)) {
  687. l = 0.4482421875
  688. } else if (/\-/.test(t)) {
  689. l = 0.4326171875
  690. } else if (/\+/.test(t)) {
  691. l = 0.74169921875
  692. } else if (/\=/.test(t)) {
  693. l = 0.74169921875
  694. } else if (/\|/.test(t)) {
  695. l = 0.26904296875
  696. } else if (/\\/.test(t)) {
  697. l = 0.416015625
  698. } else if (/\[/.test(t)) {
  699. l = 0.333984375
  700. } else if (/\]/.test(t)) {
  701. l = 0.333984375
  702. } else if (/\;/.test(t)) {
  703. l = 0.24072265625
  704. } else if (/\'/.test(t)) {
  705. l = 0.25634765625
  706. } else if (/\,/.test(t)) {
  707. l = 0.24072265625
  708. } else if (/\./.test(t)) {
  709. l = 0.24072265625
  710. } else if (/\//.test(t)) {
  711. l = 0.42724609375
  712. } else if (/\{/.test(t)) {
  713. l = 0.333984375
  714. } else if (/\}/.test(t)) {
  715. l = 0.333984375
  716. } else if (/\:/.test(t)) {
  717. l = 0.24072265625
  718. } else if (/\"/.test(t)) {
  719. l = 0.435546875
  720. } else if (/\</.test(t)) {
  721. l = 0.74169921875
  722. } else if (/\>/.test(t)) {
  723. l = 0.74169921875
  724. } else if (/\?/.test(t)) {
  725. l = 0.48291015625
  726. } else {
  727. l = 1
  728. }
  729. return l;
  730. }
  731. // export
  732. function setImage(images) { // 设置图片数据
  733. _app.log('进入设置图片数据方法');
  734. return new Promise(async (resolve, rejcet) => {
  735. try {
  736. if (images && _app.isArray(images)) {
  737. _app.log('images是一个数组');
  738. for (let i = 0; i < images.length; i++) {
  739. _app.log('设置图片数据循环中:' + i);
  740. images[i] = await setImageFn(images[i]);
  741. }
  742. } else {
  743. _app.log('images是一个对象');
  744. images = await setImageFn(images);
  745. }
  746. resolve(images);
  747. } catch (e) {
  748. //TODO handle the exception
  749. rejcet(e);
  750. }
  751. })
  752. }
  753. function base64ToPathFn(path) {
  754. var reg = /^\s*data:([a-z]+\/[a-z0-9-+.]+(;[a-z-]+=[a-z0-9-]+)?)?(;base64)?,([a-z0-9!$&',()*+;=\-._~:@\/?%\s]*?)\s*$/i;
  755. if(!reg.test(path)){
  756. return Promise.resolve(path);
  757. }
  758. return base64ToPath(path);
  759. }
  760. function setImageFn(image) {
  761. return new Promise(async (resolve, reject) => {
  762. if (image.url) {
  763. image.url = (await base64ToPathFn(image.url));
  764. let imgUrl = image.url;
  765. imgUrl = await _app.downloadFile_PromiseFc(imgUrl);
  766. image.url = imgUrl;
  767. const hasinfoCallBack = image.infoCallBack && typeof(image.infoCallBack) === 'function';
  768. let imageInfo = {};
  769. imageInfo = await _app.getImageInfo_PromiseFc(imgUrl);
  770. if (hasinfoCallBack) {
  771. image = {
  772. ...image,
  773. ...image.infoCallBack(imageInfo)
  774. };
  775. }
  776. image.dx = Number(image.dx) || 0;
  777. image.dy = Number(image.dy) || 0;
  778. image.dWidth = Number(image.dWidth || imageInfo.width);
  779. image.dHeight = Number(image.dHeight || imageInfo.height);
  780. image = {
  781. ...image,
  782. imageInfo
  783. }
  784. }
  785. resolve(image);
  786. })
  787. }
  788. // export
  789. function drawText(Context, textArray, bgObj) { // 先遍历换行再绘制
  790. if (!_app.isArray(textArray)) {
  791. _app.log('遍历文本方法, 不是数组');
  792. textArray = [textArray];
  793. } else {
  794. _app.log('遍历文本方法, 是数组');
  795. }
  796. _app.log('遍历文本方法, textArray:' + JSON.stringify(textArray));
  797. const newArr = [];
  798. if (textArray && textArray.length > 0) {
  799. for (let j = 0; j < textArray.length; j++) {
  800. const textItem = textArray[j];
  801. if (textItem.text && textItem.lineFeed) {
  802. let lineNum = -1,
  803. maxWidth = bgObj.width,
  804. lineHeight = textItem.size,
  805. dx = textItem.dx;
  806. if (_app.isObject(textItem.lineFeed)) {
  807. const lineFeed = textItem.lineFeed;
  808. lineNum = (lineFeed.lineNum !== undefined && typeof(lineFeed.lineNum) === 'number') && lineFeed.lineNum >= 0 ?
  809. lineFeed.lineNum : lineNum;
  810. maxWidth = (lineFeed.maxWidth !== undefined && typeof(lineFeed.maxWidth) === 'number') ? lineFeed.maxWidth :
  811. maxWidth;
  812. lineHeight = (lineFeed.lineHeight !== undefined && typeof(lineFeed.lineHeight) === 'number') ? lineFeed.lineHeight :
  813. lineHeight;
  814. dx = (lineFeed.dx !== undefined && typeof(lineFeed.dx) === 'number') ? lineFeed.dx : dx;
  815. }
  816. const chr = (textItem.text).split("");
  817. let temp = "";
  818. const row = [];
  819. //循环出几行文字组成数组
  820. for (let a = 0, len = chr.length; a < len; a++) {
  821. if (countTextLength(Context, {
  822. text: temp,
  823. size: textItem.size
  824. }) <= maxWidth && countTextLength(Context, {
  825. text: (temp + chr[a]),
  826. size: textItem.size
  827. }) <= maxWidth) {
  828. temp += chr[a];
  829. if (a == (chr.length - 1)) {
  830. row.push(temp);
  831. }
  832. } else {
  833. row.push(temp);
  834. temp = chr[a];
  835. }
  836. }
  837. _app.log('循环出的文本数组:' + JSON.stringify(row));
  838. //只显示几行 变量间距lineHeight 变量行数lineNum
  839. let allNum = (lineNum >= 0 && lineNum < row.length) ? lineNum : row.length;
  840. for (let i = 0; i < allNum; i++) {
  841. let str = row[i];
  842. if (i == (allNum - 1) && allNum < row.length) {
  843. str = str.substring(0, str.length - 1) + '...';
  844. }
  845. const obj = { ...textItem,
  846. text: str,
  847. dx: i === 0 ? textItem.dx : (dx >= 0 ? dx : textItem.dx),
  848. dy: textItem.dy + (i * lineHeight),
  849. textLength: countTextLength(Context, {
  850. text: str,
  851. size: textItem.size
  852. })
  853. };
  854. _app.log('重新组成的文本对象:' + JSON.stringify(obj));
  855. newArr.push(obj);
  856. }
  857. } else {
  858. newArr.push(textItem);
  859. }
  860. }
  861. }
  862. _app.log('绘制文本新数组:' + JSON.stringify(newArr));
  863. drawTexts(Context, newArr);
  864. }
  865. function setFont(textItem = {}) {
  866. if (textItem.font && typeof(textItem.font) === 'string') {
  867. _app.log(textItem.font)
  868. return textItem.font;
  869. } else {
  870. let fontStyle = 'normal';
  871. let fontVariant = 'normal';
  872. let fontWeight = 'normal';
  873. let fontSize = textItem.size || 10;
  874. let fontFamily = 'sans-serif';
  875. fontSize = Math.ceil(Number(fontSize));
  876. if (textItem.fontStyle && typeof(textItem.fontStyle) === 'string')
  877. fontStyle = textItem.fontStyle.trim();
  878. if (textItem.fontVariant && typeof(textItem.fontVariant) === 'string')
  879. fontVariant = textItem.fontVariant.trim();
  880. if (textItem.fontWeight && (typeof(textItem.fontWeight) === 'string' || typeof(textItem.fontWeight) === 'number'))
  881. fontWeight = textItem.fontWeight.trim();
  882. if (textItem.fontFamily && typeof(textItem.fontFamily) === 'string')
  883. fontFamily = textItem.fontFamily.trim();
  884. return fontStyle + ' ' +
  885. fontVariant + ' ' +
  886. fontWeight + ' ' +
  887. fontSize + 'px' + ' ' +
  888. fontFamily;
  889. }
  890. }
  891. function drawTexts(Context, texts) { // 绘制文本
  892. _app.log('准备绘制文本方法, texts:' + JSON.stringify(texts));
  893. if (texts && _app.isArray(texts)) {
  894. _app.log('准备绘制文本方法, 是数组');
  895. if (texts.length > 0) {
  896. for (let i = 0; i < texts.length; i++) {
  897. drawTextFn(Context, texts[i]);
  898. }
  899. }
  900. } else {
  901. _app.log('准备绘制文本方法, 不是数组');
  902. drawTextFn(Context, texts);
  903. }
  904. }
  905. function drawTextFn(Context, textItem) {
  906. _app.log('进入绘制文本方法, textItem:' + JSON.stringify(textItem));
  907. if (textItem && _app.isObject(textItem) && textItem.text) {
  908. Context.font = setFont(textItem);
  909. Context.setFillStyle(textItem.color);
  910. Context.setGlobalAlpha(textItem.alpha);
  911. Context.setTextAlign(textItem.textAlign);
  912. Context.setTextBaseline(textItem.textBaseline);
  913. Context.fillText(textItem.text, textItem.dx, textItem.dy);
  914. if (textItem.lineThrough && _app.isObject(textItem.lineThrough)) {
  915. _app.log('有删除线');
  916. let lineThrough = textItem.lineThrough;
  917. lineThrough.alpha = lineThrough.alpha !== undefined ? lineThrough.alpha : textItem.alpha;
  918. lineThrough.style = lineThrough.style || textItem.color;
  919. lineThrough.width = lineThrough.width !== undefined ? lineThrough.width : textItem.size / 10;
  920. lineThrough.cap = lineThrough.cap !== undefined ? lineThrough.cap : 'butt';
  921. _app.log('删除线对象:' + JSON.stringify(lineThrough));
  922. Context.setGlobalAlpha(lineThrough.alpha);
  923. Context.setStrokeStyle(lineThrough.style);
  924. Context.setLineWidth(lineThrough.width);
  925. Context.setLineCap(lineThrough.cap);
  926. let mx, my;
  927. switch (textItem.textAlign) {
  928. case 'left':
  929. mx = textItem.dx;
  930. break;
  931. case 'center':
  932. mx = textItem.dx - (textItem.textLength) / 2;
  933. break;
  934. default:
  935. mx = textItem.dx - (textItem.textLength);
  936. break;
  937. }
  938. switch (textItem.textBaseline) {
  939. case 'top':
  940. my = textItem.dy + (textItem.size * .5);
  941. break;
  942. case 'middle':
  943. my = textItem.dy;
  944. break;
  945. default:
  946. my = textItem.dy - (textItem.size * .5);
  947. break;
  948. }
  949. Context.beginPath();
  950. Context.moveTo(mx, my);
  951. Context.lineTo(mx + textItem.textLength, my);
  952. Context.stroke();
  953. Context.closePath();
  954. _app.log('删除线完毕');
  955. }
  956. Context.setGlobalAlpha(1);
  957. Context.font = '10px sans-serif';
  958. }
  959. }
  960. // export
  961. function drawImage(Context, images) { // 绘制图片
  962. _app.log('判断图片数据类型:' + JSON.stringify(images))
  963. if (images && _app.isArray(images)) {
  964. if (images.length > 0) {
  965. for (let i = 0; i < images.length; i++) {
  966. readyDrawImageFn(Context, images[i]);
  967. }
  968. }
  969. } else {
  970. readyDrawImageFn(Context, images);
  971. }
  972. }
  973. function readyDrawImageFn(Context, img) {
  974. _app.log('判断绘制图片形状, img:' + JSON.stringify(img));
  975. if (img.url) {
  976. if (img.circleSet) {
  977. drawCircleImage(Context, img);
  978. } else if (img.roundRectSet) {
  979. drawRoundRectImage(Context, img);
  980. } else {
  981. drawImageFn(Context, img);
  982. }
  983. }
  984. }
  985. function drawImageFn(Context, img) {
  986. _app.log('进入绘制默认图片方法, img:' + JSON.stringify(img));
  987. if (img.url) {
  988. const hasAlpha = !_app.isUndef(img.alpha);
  989. img.alpha = Number(!_app.isUndef(img.alpha) ? img.alpha : 1);
  990. Context.setGlobalAlpha(img.alpha);
  991. _app.log('绘制默认图片方法, 有url');
  992. if (img.dWidth && img.dHeight && img.sx && img.sy && img.sWidth && img.sHeight) {
  993. _app.log('绘制默认图片方法, 绘制第一种方案');
  994. Context.drawImage(img.url,
  995. Number(img.sx) || false, Number(img.sy) || false,
  996. Number(img.sWidth) || false, Number(img.sHeight) || false,
  997. Number(img.dx || 0), Number(img.dy || 0),
  998. Number(img.dWidth) || false, Number(img.dHeight) || false,);
  999. } else if (img.dWidth && img.dHeight) {
  1000. _app.log('绘制默认图片方法, 绘制第二种方案');
  1001. Context.drawImage(img.url, Number(img.dx || 0), Number(img.dy || 0),
  1002. Number(img.dWidth) || false, Number(img.dHeight) || false);
  1003. } else {
  1004. _app.log('绘制默认图片方法, 绘制第三种方案');
  1005. Context.drawImage(img.url, Number(img.dx || 0), Number(img.dy || 0));
  1006. }
  1007. if (hasAlpha) {
  1008. Context.setGlobalAlpha(1);
  1009. }
  1010. }
  1011. _app.log('绘制默认图片方法, 绘制完毕');
  1012. }
  1013. function drawCircleImage(Context, obj) {
  1014. _app.log('进入绘制圆形图片方法, obj:' + JSON.stringify(obj));
  1015. let {
  1016. dx,
  1017. dy,
  1018. dWidth,
  1019. dHeight,
  1020. circleSet,
  1021. imageInfo
  1022. } = obj;
  1023. let x, y, r;
  1024. if (typeof circleSet === 'object') {
  1025. x = circleSet.x;
  1026. y = circleSet.y;
  1027. r = circleSet.r;
  1028. }
  1029. if (!r) {
  1030. let d;
  1031. d = dWidth > dHeight ? dHeight : dWidth;
  1032. r = d / 2;
  1033. }
  1034. x = x ? dx + x : (dx || 0) + r;
  1035. y = y ? dy + y : (dy || 0) + r;
  1036. Context.save();
  1037. Context.beginPath();
  1038. Context.arc(x, y, r, 0, 2 * Math.PI, false);
  1039. Context.closePath();
  1040. Context.setGlobalAlpha(0);
  1041. Context.fillStyle = '#FFFFFF';
  1042. Context.fill();
  1043. Context.setGlobalAlpha(1);
  1044. Context.clip();
  1045. drawImageFn(Context, obj);
  1046. _app.log('默认图片绘制完毕');
  1047. Context.restore();
  1048. }
  1049. function drawRoundRectImage(Context, obj) { // 绘制矩形
  1050. _app.log('进入绘制矩形图片方法, obj:' + JSON.stringify(obj));
  1051. Context.save();
  1052. let {
  1053. dx,
  1054. dy,
  1055. dWidth,
  1056. dHeight,
  1057. roundRectSet,
  1058. imageInfo
  1059. } = obj;
  1060. let r;
  1061. if (typeof roundRectSet === 'object') {
  1062. r = roundRectSet.r;
  1063. }
  1064. r = r || dWidth * .1;
  1065. if (dWidth < 2 * r) {
  1066. r = dWidth / 2;
  1067. }
  1068. if (dHeight < 2 * r) {
  1069. r = dHeight / 2;
  1070. }
  1071. Context.beginPath();
  1072. Context.moveTo(dx + r, dy);
  1073. Context.arcTo(dx + dWidth, dy, dx + dWidth, dy + dHeight, r);
  1074. Context.arcTo(dx + dWidth, dy + dHeight, dx, dy + dHeight, r);
  1075. Context.arcTo(dx, dy + dHeight, dx, dy, r);
  1076. Context.arcTo(dx, dy, dx + dWidth, dy, r);
  1077. Context.closePath();
  1078. Context.setGlobalAlpha(0);
  1079. Context.fillStyle = '#FFFFFF';
  1080. Context.fill();
  1081. Context.setGlobalAlpha(1);
  1082. Context.clip();
  1083. drawImageFn(Context, obj);
  1084. Context.restore();
  1085. _app.log('进入绘制矩形图片方法, 绘制完毕');
  1086. }
  1087. // export
  1088. function drawQrCode(Context, qrCodeObj) { //生成二维码方法, 参考了 诗小柒 的二维码生成器代码
  1089. _app.log('进入绘制二维码方法')
  1090. _app.showLoading('正在生成二维码');
  1091. let qrcodeAlgObjCache = [];
  1092. let options = {
  1093. text: String(qrCodeObj.text || '') || '', // 生成内容
  1094. size: Number(qrCodeObj.size || 0) || 200, // 二维码大小
  1095. background: String(qrCodeObj.background || '') || '#ffffff', // 背景色
  1096. foreground: String(qrCodeObj.foreground || '') || '#000000', // 前景色
  1097. pdground: String(qrCodeObj.pdground || '') || '#000000', // 定位角点颜色
  1098. correctLevel: Number(qrCodeObj.correctLevel || 0) || 3, // 容错级别
  1099. image: String(qrCodeObj.image || '') || '', // 二维码图标
  1100. imageSize: Number(qrCodeObj.imageSize || 0) || 40, // 二维码图标大小
  1101. dx: Number(qrCodeObj.dx || 0) || 0, // x轴距离
  1102. dy: Number(qrCodeObj.dy || 0) || 0 // y轴距离
  1103. }
  1104. let qrCodeAlg = null;
  1105. let d = 0;
  1106. for (var i = 0, l = qrcodeAlgObjCache.length; i < l; i++) {
  1107. d = i;
  1108. if (qrcodeAlgObjCache[i].text == options.text && qrcodeAlgObjCache[i].text.correctLevel == options.correctLevel) {
  1109. qrCodeAlg = qrcodeAlgObjCache[i].obj;
  1110. break;
  1111. }
  1112. }
  1113. if (d == l) {
  1114. qrCodeAlg = new QRCodeAlg(options.text, options.correctLevel);
  1115. qrcodeAlgObjCache.push({
  1116. text: options.text,
  1117. correctLevel: options.correctLevel,
  1118. obj: qrCodeAlg
  1119. });
  1120. }
  1121. let getForeGround = function(config) {
  1122. let options = config.options;
  1123. if (options.pdground && (
  1124. (config.row > 1 && config.row < 5 && config.col > 1 && config.col < 5) ||
  1125. (config.row > (config.count - 6) && config.row < (config.count - 2) && config.col > 1 && config.col < 5) ||
  1126. (config.row > 1 && config.row < 5 && config.col > (config.count - 6) && config.col < (config.count - 2))
  1127. )) {
  1128. return options.pdground;
  1129. }
  1130. return options.foreground;
  1131. }
  1132. let count = qrCodeAlg.getModuleCount();
  1133. let ratioSize = options.size;
  1134. let ratioImgSize = options.imageSize;
  1135. //计算每个点的长宽
  1136. let tileW = (ratioSize / count).toPrecision(4);
  1137. let tileH = (ratioSize / count).toPrecision(4);
  1138. //绘制
  1139. for (let row = 0; row < count; row++) {
  1140. for (let col = 0; col < count; col++) {
  1141. let w = (Math.ceil((col + 1) * tileW) - Math.floor(col * tileW));
  1142. let h = (Math.ceil((row + 1) * tileW) - Math.floor(row * tileW));
  1143. let foreground = getForeGround({
  1144. row: row,
  1145. col: col,
  1146. count: count,
  1147. options: options
  1148. });
  1149. Context.setFillStyle(qrCodeAlg.modules[row][col] ? foreground : options.background);
  1150. Context.fillRect(options.dx + Math.round(col * tileW), options.dy + Math.round(row * tileH), w, h);
  1151. }
  1152. }
  1153. if (options.image) {
  1154. let x = options.dx + Number(((ratioSize - ratioImgSize) / 2).toFixed(2));
  1155. let y = options.dy + Number(((ratioSize - ratioImgSize) / 2).toFixed(2));
  1156. drawRoundedRect(Context, x, y, ratioImgSize, ratioImgSize, 2, 6, true, true)
  1157. Context.drawImage(options.image, x, y, ratioImgSize, ratioImgSize);
  1158. // 画圆角矩形
  1159. function drawRoundedRect(ctxi, x, y, width, height, r, lineWidth, fill, stroke) {
  1160. ctxi.setLineWidth(lineWidth);
  1161. ctxi.setFillStyle(options.background);
  1162. ctxi.setStrokeStyle(options.background);
  1163. ctxi.beginPath(); // draw top and top right corner
  1164. ctxi.moveTo(x + r, y);
  1165. ctxi.arcTo(x + width, y, x + width, y + r, r); // draw right side and bottom right corner
  1166. ctxi.arcTo(x + width, y + height, x + width - r, y + height, r); // draw bottom and bottom left corner
  1167. ctxi.arcTo(x, y + height, x, y + height - r, r); // draw left and top left corner
  1168. ctxi.arcTo(x, y, x + r, y, r);
  1169. ctxi.closePath();
  1170. if (fill) {
  1171. ctxi.fill();
  1172. }
  1173. if (stroke) {
  1174. ctxi.stroke();
  1175. }
  1176. }
  1177. }
  1178. _app.log('进入绘制二维码方法完毕')
  1179. _app.hideLoading();
  1180. }
  1181. function getShreUserPosterBackground(objs) { //检查背景图是否存在于本地, 若存在直接返回, 否则调用getShreUserPosterBackgroundFc方法
  1182. let {
  1183. backgroundImage,
  1184. type
  1185. } = objs;
  1186. return new Promise(async (resolve, reject) => {
  1187. try {
  1188. _app.showLoading('正在获取海报背景图');
  1189. const savedFilePath = await getShreUserPosterBackgroundFc(objs)
  1190. _app.hideLoading();
  1191. resolve(savedFilePath);
  1192. } catch (e) {
  1193. _app.hideLoading();
  1194. _app.showToast('获取分享用户背景图失败:' + JSON.stringify(e));
  1195. _app.log(JSON.stringify(e));
  1196. reject(e);
  1197. }
  1198. })
  1199. }
  1200. function getPosterStorage(type) {
  1201. return _app.getStorageSync(getStorageKey(type));
  1202. }
  1203. function removePosterStorage(type) {
  1204. const ShreUserPosterBackgroundKey = getStorageKey(type);
  1205. const pbg = _app.getStorageSync(ShreUserPosterBackgroundKey);
  1206. if (pbg && pbg.path) {
  1207. _app.removeStorageSync(ShreUserPosterBackgroundKey);
  1208. }
  1209. }
  1210. function setPosterStorage(type, data) {
  1211. _app.setStorage(getStorageKey(type), data);
  1212. }
  1213. function getStorageKey(type) {
  1214. return ShreUserPosterBackgroundKey + (type || 'default');
  1215. }
  1216. function getShreUserPosterBackgroundFc(objs, upimage) { //下载并保存背景图方法
  1217. let {
  1218. backgroundImage,
  1219. type
  1220. } = objs;
  1221. _app.log('获取分享背景图, 尝试清空本地数据');
  1222. return new Promise(async (resolve, reject) => {
  1223. try {
  1224. _app.showLoading('正在下载海报背景图');
  1225. _app.log('没有从后端获取的背景图片路径, 尝试从后端获取背景图片路径');
  1226. let image = backgroundImage?backgroundImage:(await _app.getPosterUrl(objs));
  1227. image = (await base64ToPathFn(image));
  1228. _app.log('尝试下载并保存背景图:' + image);
  1229. const savedFilePath = await _app.downLoadAndSaveFile_PromiseFc(image);
  1230. if (savedFilePath) {
  1231. _app.log('下载并保存背景图成功:' + savedFilePath);
  1232. const imageObj = await _app.getImageInfo_PromiseFc(savedFilePath);
  1233. _app.log('获取图片信息成功');
  1234. const returnObj = {
  1235. path: savedFilePath,
  1236. width: imageObj.width,
  1237. height: imageObj.height,
  1238. name: _app.fileNameInPath(image)
  1239. }
  1240. _app.log('拼接背景图信息对象成功:' + JSON.stringify(returnObj));
  1241. // #ifndef H5
  1242. setPosterStorage(type, { ...returnObj
  1243. });
  1244. // #endif
  1245. _app.hideLoading();
  1246. _app.log('返回背景图信息对象');
  1247. resolve({ ...returnObj
  1248. });
  1249. } else {
  1250. _app.hideLoading();
  1251. reject('not find savedFilePath');
  1252. }
  1253. } catch (e) {
  1254. //TODO handle the exception
  1255. reject(e);
  1256. }
  1257. });
  1258. }
  1259. module.exports = {
  1260. getSharePoster,
  1261. setText,
  1262. setImage,
  1263. drawText,
  1264. drawImage,
  1265. drawQrCode,
  1266. drawFillRect,
  1267. drawStrokeRect,
  1268. drawRoundStrokeRect,
  1269. drawRoundFillRect
  1270. }