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

962 lines
39 KiB

7 months ago
  1. # Painter 画板 测试版
  2. > uniapp 海报画板,更优雅的海报生成方案
  3. > [查看更多 站点 1](https://limeui.qcoon.cn/#/painter)
  4. > [查看更多 站点 2](http://liangei.gitee.io/limeui/#/painter)
  5. > Q 群:1169785031
  6. ## 平台兼容
  7. | H5 | 微信小程序 | 支付宝小程序 | 百度小程序 | 头条小程序 | QQ 小程序 | App |
  8. | --- | ---------- | ------------ | ---------- | ---------- | --------- | --- |
  9. | √ | √ | √ | 未测 | √ | √ | √ |
  10. ## 安装
  11. 在市场导入**[海报画板](https://ext.dcloud.net.cn/plugin?id=2389)uni_modules**版本的即可,无需`import`
  12. ## 代码演示
  13. ### 插件demo
  14. - lime-painter 为 demo
  15. - 位于 uni_modules/lime-painter/components/lime-painter
  16. - 导入插件后直接使用可查看demo
  17. ```vue
  18. <lime-painter />
  19. ```
  20. ### 基本用法
  21. - 插件提供 JSON 及 Template 的方式绘制海报
  22. - 参考 css 块状流布局模拟 css schema。
  23. - 另外flex布局还不是成完善,请谨慎使用,普通的流布局我觉得已经够用了。
  24. #### 方式一 Template
  25. - 提供`l-painter-view`、`l-painter-text`、`l-painter-image`、`l-painter-qrcode`四种类型组件
  26. - 通过 `css` 属性绘制样式,与 style 使用方式保持一致。
  27. ```html
  28. <l-painter>
  29. //如果使用Template出现顺序错乱,可使用`template` 等所有变量完成再显示
  30. <template v-if="show">
  31. <l-painter-view
  32. css="background: #07c160; height: 120rpx; width: 120rpx; display: inline-block"
  33. ></l-painter-view>
  34. <l-painter-view
  35. css="background: #1989fa; height: 120rpx; width: 120rpx; border-top-right-radius: 60rpx; border-bottom-left-radius: 60rpx; display: inline-block; margin: 0 30rpx;"
  36. ></l-painter-view>
  37. <l-painter-view
  38. css="background: #ff9d00; height: 120rpx; width: 120rpx; border-radius: 50%; display: inline-block"
  39. ></l-painter-view>
  40. <template>
  41. </l-painter>
  42. ```
  43. #### 方式二 JSON
  44. - 在 json 里四种类型组件的`type`为`view`、`text`、`image`、`qrcode`
  45. - 通过 `board` 设置海报所需的 JSON 数据进行绘制或`ref`获取组件实例调用组件内的`render(json)`
  46. - 所有类型的 schema 都具有`css`字段,css 的 key 值使用**驼峰**如:`lineHeight`
  47. ```html
  48. <l-painter :board="poster"/>
  49. ```
  50. ```js
  51. data() {
  52. return {
  53. poster: {
  54. css: {
  55. // 根节点若无尺寸,自动获取父级节点
  56. width: '750rpx'
  57. },
  58. views: [
  59. {
  60. css: {
  61. background: "#07c160",
  62. height: "120rpx",
  63. width: "120rpx",
  64. display: "inline-block"
  65. },
  66. type: "view"
  67. },
  68. {
  69. css: {
  70. background: "#1989fa",
  71. height: "120rpx",
  72. width: "120rpx",
  73. borderTopRightRadius: "60rpx",
  74. borderBottomLeftRadius: "60rpx",
  75. display: "inline-block",
  76. margin: "0 30rpx"
  77. },
  78. views: [],
  79. type: "view"
  80. },
  81. {
  82. css: {
  83. background: "#ff9d00",
  84. height: "120rpx",
  85. width: "120rpx",
  86. borderRadius: "50%",
  87. display: "inline-block"
  88. },
  89. views: [],
  90. type: "view"
  91. },
  92. ]
  93. }
  94. }
  95. }
  96. ```
  97. ### View 容器
  98. - 类似于 `div` 可以嵌套承载更多的 view、text、image,qrcode 共同构建一颗完整的节点树
  99. - 在 JSON 里具有 `views` 的数组字段,用于嵌套承载节点。
  100. #### 方式一 Template
  101. ```html
  102. <l-painter>
  103. <l-painter-view css="background: #f0f0f0; padding-top: 100rpx;">
  104. <l-painter-view
  105. css="background: #d9d9d9; width: 33.33%; height: 100rpx; display: inline-block"
  106. ></l-painter-view>
  107. <l-painter-view
  108. css="background: #bfbfbf; width: 66.66%; height: 100rpx; display: inline-block"
  109. ></l-painter-view>
  110. </l-painter-view>
  111. </l-painter>
  112. ```
  113. #### 方式二 JSON
  114. ```js
  115. {
  116. css: {},
  117. views: [
  118. {
  119. type: 'view',
  120. css: {
  121. background: '#f0f0f0',
  122. paddingTop: '100rpx'
  123. },
  124. views: [
  125. {
  126. type: 'view',
  127. css: {
  128. background: '#d9d9d9',
  129. width: '33.33%',
  130. height: '100rpx',
  131. display: 'inline-block'
  132. }
  133. },
  134. {
  135. type: 'view',
  136. css: {
  137. background: '#bfbfbf',
  138. width: '66.66%',
  139. height: '100rpx',
  140. display: 'inline-block'
  141. }
  142. }
  143. ],
  144. }
  145. ]
  146. }
  147. ```
  148. ### Text 文本
  149. - 通过 `text` 属性填写文本内容。
  150. - 支持`\n`换行符
  151. - 支持省略号,使用 css 的`line-clamp`设置行数,当文字内容超过会显示省略号。
  152. - 支持`text-decoration`
  153. #### 方式一 Template
  154. ```html
  155. <l-painter>
  156. <l-painter-view css="background: #e0e2db; padding: 30rpx; color: #222a29">
  157. <l-painter-text
  158. text="登鹳雀楼\n白日依山尽,黄河入海流\n欲穷千里目,更上一层楼"
  159. />
  160. <l-painter-text
  161. text="登鹳雀楼\n白日依山尽,黄河入海流\n欲穷千里目,更上一层楼"
  162. css="text-align:center; padding-top: 20rpx; text-decoration: line-through "
  163. />
  164. <l-painter-text
  165. text="登鹳雀楼\n白日依山尽,黄河入海流\n欲穷千里目,更上一层楼"
  166. css="text-align:right; padding-top: 20rpx"
  167. />
  168. <l-painter-text
  169. text="水调歌头\n明月几时有?把酒问青天。不知天上宫阙,今夕是何年。我欲乘风归去,又恐琼楼玉宇,高处不胜寒。起舞弄清影,何似在人间。"
  170. css="line-clamp: 3; padding-top: 20rpx; background: linear-gradient(,#ff971b 0%, #ff5000 100%); background-clip: text"
  171. />
  172. </l-painter-view>
  173. </l-painter>
  174. ```
  175. #### 方式二 JSON
  176. ```js
  177. // 基础用法
  178. {
  179. type: 'text',
  180. text: '登鹳雀楼\n白日依山尽,黄河入海流\n欲穷千里目,更上一层楼',
  181. },
  182. {
  183. type: 'text',
  184. text: '登鹳雀楼\n白日依山尽,黄河入海流\n欲穷千里目,更上一层楼',
  185. css: {
  186. // 设置居中对齐
  187. textAlign: 'center',
  188. // 设置中划线
  189. textDecoration: 'line-through'
  190. }
  191. },
  192. {
  193. type: 'text',
  194. text: '登鹳雀楼\n白日依山尽,黄河入海流\n欲穷千里目,更上一层楼',
  195. css: {
  196. // 设置右对齐
  197. textAlign: 'right',
  198. }
  199. },
  200. {
  201. type: 'text',
  202. text: '登鹳雀楼\n白日依山尽,黄河入海流\n欲穷千里目,更上一层楼',
  203. css: {
  204. // 设置行数,超出显示省略号
  205. lineClamp: 3,
  206. // 渐变文字
  207. background: 'linear-gradient(,#ff971b 0%, #1989fa 100%)',
  208. backgroundClip: 'text'
  209. }
  210. }
  211. ```
  212. ### Image 图片
  213. - 通过 `src` 属性填写图片路径。
  214. - 图片路径支持:网络图片,本地 static 里的图片路径,缓存路径,**字节的static目录是写相对路径**
  215. - 通过 `css``object-fit`属性可以设置图片的填充方式,可选值见下方 CSS 表格。
  216. - 通过 `css``object-position`配合 `object-fit` 可以设置图片的对齐方式,类似于`background-position`,详情见下方 CSS 表格。
  217. - 使用网络图片时:小程序需要去公众平台配置 [downloadFile](https://mp.weixin.qq.com/) 域名
  218. - 使用网络图片时:**H5 和 Nvue 需要决跨域问题**
  219. #### 方式一 Template
  220. ```html
  221. <l-painter>
  222. <!-- 基础用法 -->
  223. <l-painter-image
  224. src="https://m.360buyimg.com/babel/jfs/t1/196317/32/13733/288158/60f4ea39E6fb378ed/d69205b1a8ed3c97.jpg"
  225. css="width: 200rpx; height: 200rpx"
  226. />
  227. <!-- 填充方式 -->
  228. <!-- css object-fit 设置 填充方式 见下方表格-->
  229. <l-painter-image
  230. src="https://m.360buyimg.com/babel/jfs/t1/196317/32/13733/288158/60f4ea39E6fb378ed/d69205b1a8ed3c97.jpg"
  231. css="width: 200rpx; height: 200rpx; object-fit: contain; background: #eee"
  232. />
  233. <!-- css object-position 设置 图片的对齐方式-->
  234. <l-painter-image
  235. src="https://m.360buyimg.com/babel/jfs/t1/196317/32/13733/288158/60f4ea39E6fb378ed/d69205b1a8ed3c97.jpg"
  236. css="width: 200rpx; height: 200rpx; object-fit: contain; object-position: 50% 50%; background: #eee"
  237. />
  238. </l-painter>
  239. ```
  240. #### 方式二 JSON
  241. ```js
  242. // 基础用法
  243. {
  244. type: 'image',
  245. src: 'https://m.360buyimg.com/babel/jfs/t1/196317/32/13733/288158/60f4ea39E6fb378ed/d69205b1a8ed3c97.jpg',
  246. css: {
  247. width: '200rpx',
  248. height: '200rpx'
  249. }
  250. },
  251. // 填充方式
  252. // css objectFit 设置 填充方式 见下方表格
  253. {
  254. type: 'image',
  255. src: 'https://m.360buyimg.com/babel/jfs/t1/196317/32/13733/288158/60f4ea39E6fb378ed/d69205b1a8ed3c97.jpg',
  256. css: {
  257. width: '200rpx',
  258. height: '200rpx',
  259. objectFit: 'contain'
  260. }
  261. },
  262. // css objectPosition 设置 图片的对齐方式
  263. {
  264. type: 'image',
  265. src: 'https://m.360buyimg.com/babel/jfs/t1/196317/32/13733/288158/60f4ea39E6fb378ed/d69205b1a8ed3c97.jpg',
  266. css: {
  267. width: '200rpx',
  268. height: '200rpx',
  269. objectFit: 'contain',
  270. objectPosition: '50% 50%'
  271. }
  272. }
  273. ```
  274. ### Qrcode 二维码
  275. - 通过`text`属性填写需要生成二维码的文本。
  276. - 通过 `css` 里的 `color` 可设置生成码点的颜色。
  277. - 通过 `css` 里的 `background`可设置背景色。
  278. - 通过 `css `里的 `width`、`height`设置尺寸。
  279. #### 方式一 Template
  280. ```html
  281. <l-painter>
  282. <l-painter-qrcode
  283. text="limeui.qcoon.cn"
  284. css="width: 200rpx; height: 200rpx"
  285. />
  286. </l-painter>
  287. ```
  288. #### 方式二 JSON
  289. ```js
  290. {
  291. type: 'qrcode',
  292. text: 'limeui.qcoon.cn',
  293. css: {
  294. width: '200rpx',
  295. height: '200rpx',
  296. }
  297. }
  298. ```
  299. ### 富文本
  300. - 这是一个有限支持的测试能力,只能通过JSON方式,不要抱太大希望!
  301. - 首先需要把富文本转成JSON,这需要引入`parser`这个包,如果你不使用是不会进入主包
  302. ```html
  303. <l-painter ref="painter"/>
  304. ```
  305. ```js
  306. import parseHtml from '@/uni_modules/lime-painter/parser'
  307. const json = parseHtml(`<p><span>测试测试</span><img src="/static/logo.png"/></p>`)
  308. this.$refs.painter.render(json)
  309. ```
  310. ### 生成图片
  311. - 方式1、通过设置`isCanvasToTempFilePath`自动生成图片并在 `@success` 事件里接收海报临时路径
  312. - 方式2、通过调用内部方法生成图片:
  313. ```html
  314. <l-painter ref="painter">...code</l-painter>
  315. ```
  316. ```js
  317. this.$refs.painter.canvasToTempFilePathSync({
  318. fileType: "jpg",
  319. // 如果返回的是base64是无法使用 saveImageToPhotosAlbum,需要设置 pathType为url
  320. pathType: 'url',
  321. quality: 1,
  322. success: (res) => {
  323. console.log(res.tempFilePath);
  324. // 非H5 保存到相册
  325. // H5 提示用户长按图另存
  326. uni.saveImageToPhotosAlbum({
  327. filePath: res.tempFilePath,
  328. success: function () {
  329. console.log('save success');
  330. }
  331. });
  332. },
  333. });
  334. ```
  335. ### 主动调用方式
  336. - 通过获取组件实例内部的`render`函数 传递`JSON`即可
  337. ```html
  338. <l-painter ref="painter" />
  339. ```
  340. ```js
  341. // 渲染
  342. this.$refs.painter.render(jsonSchema);
  343. // 生成图片
  344. this.$refs.painter.canvasToTempFilePathSync({
  345. fileType: "jpg",
  346. // 如果返回的是base64是无法使用 saveImageToPhotosAlbum,需要设置 pathType为url
  347. pathType: 'url',
  348. quality: 1,
  349. success: (res) => {
  350. console.log(res.tempFilePath);
  351. // 非H5 保存到相册
  352. uni.saveImageToPhotosAlbum({
  353. filePath: res.tempFilePath,
  354. success: function () {
  355. console.log('save success');
  356. }
  357. });
  358. },
  359. });
  360. ```
  361. ### H5跨域
  362. - 一般是需要后端或管理OSS资源的大佬处理
  363. - 一般OSS的处理方式:
  364. 1、设置来源
  365. ```cmd
  366. *
  367. ```
  368. 2、允许Methods
  369. ```html
  370. GET
  371. ```
  372. 3、允许Headers
  373. ```html
  374. access-control-allow-origin:*
  375. ```
  376. 4、最后如果还是不行,可试下给插件设置`useCORS`
  377. ```html
  378. <l-painter useCORS>
  379. ```
  380. ### 海报示例
  381. - 提供一份示例,只把插件当成生成图片的工具,非必要不要在弹窗里使用。
  382. - 通过设置`isCanvasToTempFilePath`主动生成图片,再由 `@success` 事件接收海报临时路径
  383. - 设置`hidden`隐藏画板。
  384. 请注意,示例用到了图片,海报的渲染是包括下载图片的时间,也许在某天图片会失效或访问超级慢,请更换为你的图片再查看,另外如果你是小程序请在使用示例时把**不校验合法域名**勾上!!!!!不然不显示还以为是插件的锅,求求了大佬们!
  385. #### 方式一 Template
  386. ```html
  387. <image :src="path" mode="widthFix"></image>
  388. <l-painter
  389. isCanvasToTempFilePath
  390. @success="path = $event"
  391. hidden
  392. css="width: 750rpx; padding-bottom: 40rpx; background: linear-gradient(,#ff971b 0%, #ff5000 100%)"
  393. >
  394. <l-painter-image
  395. src="https://m.360buyimg.com/babel/jfs/t1/196317/32/13733/288158/60f4ea39E6fb378ed/d69205b1a8ed3c97.jpg"
  396. css="margin-left: 40rpx; margin-top: 40rpx; width: 84rpx; height: 84rpx; border-radius: 50%;"
  397. />
  398. <l-painter-view
  399. css="margin-top: 40rpx; padding-left: 20rpx; display: inline-block"
  400. >
  401. <l-painter-text
  402. text="隔壁老王"
  403. css="display: block; padding-bottom: 10rpx; color: #fff; font-size: 32rpx; fontWeight: bold"
  404. />
  405. <l-painter-text
  406. text="为您挑选了一个好物"
  407. css="color: rgba(255,255,255,.7); font-size: 24rpx"
  408. />
  409. </l-painter-view>
  410. <l-painter-view
  411. css="margin-left: 40rpx; margin-top: 30rpx; padding: 32rpx; box-sizing: border-box; background: #fff; border-radius: 16rpx; width: 670rpx; box-shadow: 0 20rpx 58rpx rgba(0,0,0,.15)"
  412. >
  413. <l-painter-image
  414. src="https://m.360buyimg.com/babel/jfs/t1/196317/32/13733/288158/60f4ea39E6fb378ed/d69205b1a8ed3c97.jpg"
  415. css="object-fit: cover; object-position: 50% 50%; width: 606rpx; height: 606rpx; border-radius: 12rpx;"
  416. />
  417. <l-painter-view
  418. css="margin-top: 32rpx; color: #FF0000; font-weight: bold; font-size: 28rpx; line-height: 1em;"
  419. >
  420. <l-painter-text text="¥" css="vertical-align: bottom" />
  421. <l-painter-text
  422. text="39"
  423. css="vertical-align: bottom; font-size: 58rpx"
  424. />
  425. <l-painter-text text=".39" css="vertical-align: bottom" />
  426. <l-painter-text
  427. text="¥59.99"
  428. css="vertical-align: bottom; padding-left: 10rpx; font-weight: normal; text-decoration: line-through; color: #999999"
  429. />
  430. </l-painter-view>
  431. <l-painter-view css="margin-top: 32rpx; font-size: 26rpx; color: #8c5400">
  432. <l-painter-text text="自营" css="color: #212121; background: #ffb400;" />
  433. <l-painter-text
  434. text="30天最低价"
  435. css="margin-left: 16rpx; background: #fff4d9; text-decoration: line-through;"
  436. />
  437. <l-painter-text
  438. text="满减优惠"
  439. css="margin-left: 16rpx; background: #fff4d9"
  440. />
  441. <l-painter-text
  442. text="超高好评"
  443. css="margin-left: 16rpx; background: #fff4d9"
  444. />
  445. </l-painter-view>
  446. <l-painter-view css="margin-top: 30rpx">
  447. <l-painter-text
  448. css="line-clamp: 2; color: #333333; line-height: 1.8em; font-size: 36rpx; width: 478rpx; padding-right:32rpx; box-sizing: border-box"
  449. text="360儿童电话手表9X 智能语音问答定位支付手表 4G全网通20米游泳级防水视频通话拍照手表男女孩星空蓝"
  450. ></l-painter-text>
  451. <l-painter-qrcode
  452. css="width: 128rpx; height: 128rpx;"
  453. text="limeui.qcoon.cn"
  454. ></l-painter-qrcode>
  455. </l-painter-view>
  456. </l-painter-view>
  457. </l-painter>
  458. ```
  459. ```js
  460. data() {
  461. return {
  462. path: ''
  463. }
  464. }
  465. ```
  466. #### 方式二 JSON
  467. ```html
  468. <image :src="path" mode="widthFix"></image>
  469. <l-painter
  470. :board="poster"
  471. isCanvasToTempFilePath
  472. @success="path = $event"
  473. hidden
  474. />
  475. ```
  476. ```js
  477. data() {
  478. return {
  479. path: '',
  480. poster: {
  481. css: {
  482. width: "750rpx",
  483. paddingBottom: "40rpx",
  484. background: "linear-gradient(,#000 0%, #ff5000 100%)"
  485. },
  486. views: [
  487. {
  488. src: "https://m.360buyimg.com/babel/jfs/t1/196317/32/13733/288158/60f4ea39E6fb378ed/d69205b1a8ed3c97.jpg",
  489. type: "image",
  490. css: {
  491. background: "#fff",
  492. objectFit: "cover",
  493. marginLeft: "40rpx",
  494. marginTop: "40rpx",
  495. width: "84rpx",
  496. border: "2rpx solid #fff",
  497. boxSizing: "border-box",
  498. height: "84rpx",
  499. borderRadius: "50%"
  500. }
  501. },
  502. {
  503. type: "view",
  504. css: {
  505. marginTop: "40rpx",
  506. paddingLeft: "20rpx",
  507. display: "inline-block"
  508. },
  509. views: [
  510. {
  511. text: "隔壁老王",
  512. type: "text",
  513. css: {
  514. display: "block",
  515. paddingBottom: "10rpx",
  516. color: "#fff",
  517. fontSize: "32rpx",
  518. fontWeight: "bold"
  519. }
  520. },
  521. {
  522. text: "为您挑选了一个好物",
  523. type: "text",
  524. css: {
  525. color: "rgba(255,255,255,.7)",
  526. fontSize: "24rpx"
  527. },
  528. }
  529. ],
  530. },
  531. {
  532. css: {
  533. marginLeft: "40rpx",
  534. marginTop: "30rpx",
  535. padding: "32rpx",
  536. boxSizing: "border-box",
  537. background: "#fff",
  538. borderRadius: "16rpx",
  539. width: "670rpx",
  540. boxShadow: "0 20rpx 58rpx rgba(0,0,0,.15)"
  541. },
  542. views: [
  543. {
  544. src: "https://m.360buyimg.com/babel/jfs/t1/196317/32/13733/288158/60f4ea39E6fb378ed/d69205b1a8ed3c97.jpg",
  545. type: "image",
  546. css: {
  547. objectFit: "cover",
  548. objectPosition: "50% 50%",
  549. width: "606rpx",
  550. height: "606rpx"
  551. },
  552. }, {
  553. css: {
  554. marginTop: "32rpx",
  555. color: "#FF0000",
  556. fontWeight: "bold",
  557. fontSize: "28rpx",
  558. lineHeight: "1em"
  559. },
  560. views: [{
  561. text: "¥",
  562. type: "text",
  563. css: {
  564. verticalAlign: "bottom"
  565. },
  566. }, {
  567. text: "39",
  568. type: "text",
  569. css: {
  570. verticalAlign: "bottom",
  571. fontSize: "58rpx"
  572. },
  573. }, {
  574. text: ".39",
  575. type: "text",
  576. css: {
  577. verticalAlign: "bottom"
  578. },
  579. }, {
  580. text: "¥59.99",
  581. type: "text",
  582. css: {
  583. verticalAlign: "bottom",
  584. paddingLeft: "10rpx",
  585. fontWeight: "normal",
  586. textDecoration: "line-through",
  587. color: "#999999"
  588. }
  589. }],
  590. type: "view"
  591. }, {
  592. css: {
  593. marginTop: "32rpx",
  594. fontSize: "26rpx",
  595. color: "#8c5400"
  596. },
  597. views: [{
  598. text: "自营",
  599. type: "text",
  600. css: {
  601. color: "#212121",
  602. background: "#ffb400"
  603. },
  604. }, {
  605. text: "30天最低价",
  606. type: "text",
  607. css: {
  608. marginLeft: "16rpx",
  609. background: "#fff4d9",
  610. textDecoration: "line-through"
  611. },
  612. }, {
  613. text: "满减优惠",
  614. type: "text",
  615. css: {
  616. marginLeft: "16rpx",
  617. background: "#fff4d9"
  618. },
  619. }, {
  620. text: "超高好评",
  621. type: "text",
  622. css: {
  623. marginLeft: "16rpx",
  624. background: "#fff4d9"
  625. },
  626. }],
  627. type: "view"
  628. }, {
  629. css: {
  630. marginTop: "30rpx"
  631. },
  632. views: [
  633. {
  634. text: "360儿童电话手表9X 智能语音问答定位支付手表 4G全网通20米游泳级防水视频通话拍照手表男女孩星空蓝",
  635. type: "text",
  636. css: {
  637. paddingRight: "32rpx",
  638. boxSizing: "border-box",
  639. lineClamp: 2,
  640. color: "#333333",
  641. lineHeight: "1.8em",
  642. fontSize: "36rpx",
  643. width: "478rpx"
  644. },
  645. }, {
  646. text: "limeui.qcoon.cn",
  647. type: "qrcode",
  648. css: {
  649. width: "128rpx",
  650. height: "128rpx",
  651. },
  652. }],
  653. type: "view"
  654. }],
  655. type: "view"
  656. }
  657. ]
  658. }
  659. }
  660. }
  661. ```
  662. ### 自定义字体
  663. - 需要平台的支持,已知微信小程序支持,其它的没试过,如果可行请告之
  664. ```
  665. // 需要在app.vue中下载字体
  666. uni.loadFontFace({
  667. global:true,
  668. scopes: ['native'],
  669. family: '自定义字体名称',
  670. source: 'url("https://sungd.github.io/Pacifico.ttf")',
  671. success() {
  672. console.log('success')
  673. }
  674. })
  675. // 然后就可以在插件的css中写font-family: '自定义字体名称'
  676. ```
  677. ### Nvue
  678. - 必须为HBX 3.4.11及以上
  679. ### 原生小程序
  680. - 插件里的`painter.js`支持在原生小程序中使用
  681. - new Painter 之后在`source`里传入 JSON
  682. - 再调用`render`绘制海报
  683. - 如需生成图片,请查看微信小程序 cavnas 的[canvasToTempFilePath](https://developers.weixin.qq.com/miniprogram/dev/api/canvas/wx.canvasToTempFilePath.html)
  684. ```html
  685. <canvas type="2d" id="painter" style="width: 100%"></canvas>
  686. ```
  687. ```js
  688. import { Painter } from "./painter";
  689. page({
  690. data: {
  691. poster: {
  692. css: {
  693. width: "750rpx",
  694. },
  695. views: [
  696. {
  697. type: "view",
  698. css: {
  699. background: "#d2d4c8",
  700. paddingTop: "100rpx",
  701. },
  702. views: [
  703. {
  704. type: "view",
  705. css: {
  706. background: "#5f7470",
  707. width: "33.33%",
  708. height: "100rpx",
  709. display: "inline-block",
  710. },
  711. },
  712. {
  713. type: "view",
  714. css: {
  715. background: "#889696",
  716. width: "33.33%",
  717. height: "100rpx",
  718. display: "inline-block",
  719. },
  720. },
  721. {
  722. type: "view",
  723. css: {
  724. background: "#b8bdb5",
  725. width: "33.33%",
  726. height: "100rpx",
  727. display: "inline-block",
  728. },
  729. },
  730. ],
  731. },
  732. ],
  733. },
  734. },
  735. async onLoad() {
  736. const res = await this.getCentext();
  737. const painter = new Painter(res);
  738. // 返回计算布局后的整个内容尺寸
  739. const { width, height } = await painter.source(this.data.poster);
  740. // 得到计算后的尺寸后 可给canvas尺寸赋值,达到动态响应效果
  741. // 渲染
  742. await painter.render();
  743. },
  744. // 获取canvas 2d
  745. // 非2d 需要传一个 createImage 方法用于获取图片信息 即把 getImageInfo 的 success 通过 promise resolve 返回
  746. getCentext() {
  747. return new Promise((resolve) => {
  748. wx.createSelectorQuery()
  749. .select(`#painter`)
  750. .node()
  751. .exec((res) => {
  752. let { node: canvas } = res[0];
  753. resolve({
  754. canvas,
  755. context: canvas.getContext("2d"),
  756. width: canvas.width,
  757. height: canvas.height,
  758. // createImage: getImageInfo()
  759. pixelRatio: 2,
  760. });
  761. });
  762. });
  763. },
  764. });
  765. ```
  766. ### 旧版(1.6.x)更新
  767. - 由于 1.8.x 版放弃了以定位的方式,所以 1.6.x 版更新之后要每个样式都加上`position: absolute`
  768. - 旧版的 `image` mode 模式被放弃,使用`object-fit`
  769. - 旧版的 `isRenderImage` 改成 `is-canvas-to-temp-file-path`
  770. - 旧版的 `maxLines` 改成 `line-clamp`
  771. ## API
  772. ### Props
  773. | 参数 | 说明 | 类型 | 默认值 |
  774. | -------------------------- | ------------------------------------------------------------ | ---------------- | ------------ |
  775. | board | JSON 方式的海报元素对象集 | <em>object</em> | - |
  776. | css | 海报内容最外层的样式,可以理解为`body` | <em>object</em> | 参数请向下看 |
  777. | custom-style | canvas 元素的样式 | <em>string</em> | |
  778. | hidden | 隐藏画板 | <em>boolean</em> | `false` |
  779. | is-canvas-to-temp-file-path | 是否生成图片,在`@success`事件接收图片地址 | <em>boolean</em> | `false` |
  780. | after-delay | 生成图片错乱,可延时生成图片 | <em>number</em> | `100` |
  781. | type | canvas 类型,对微信头条支付宝小程序可有效,可选值:`2d`,`''` | <em>string</em> | `2d` |
  782. | file-type | 生成图片的后缀类型, 可选值:`png`、`jpg` | <em>string</em> | `png` |
  783. | path-type | 生成图片路径类型,可选值`url`、`base64` | <em>string</em> | `-` |
  784. | pixel-ratio | 生成图片的像素密度,默认为对应手机的像素密度,`nvue`无效 | <em>number</em> | `-` |
  785. | hidpi | H5和APP是否使用高清处理 | <em>boolean</em> | `true` |
  786. | width | **废弃** 画板的宽度,一般只用于通过内部方法时加上 | <em>number</em> | `` |
  787. | height | **废弃** 画板的高度 ,同上 | <em>number</em> | `` |
  788. ### css
  789. | 属性名 | 支持的值或类型 | 默认值 |
  790. | ----------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------- |
  791. | (min\max)width | 支持`%`、`rpx`、`px` | - |
  792. | height | 同上 | - |
  793. | color | `string` | - |
  794. | position | 定位,可选值:`absolute`、`fixed` | - |
  795. | ↳ left、top、right、bottom | 配合`position`才生效,支持`%`、`rpx`、`px` | - |
  796. | margin | 可简写或各方向分别写,如:`margin-top`,支持`auto`、`rpx`、`px` | - |
  797. | padding | 可简写或各方向分别写,支持`rpx`、`px` | - |
  798. | border | 可简写或各个值分开写:`border-width`、`border-style` 、`border-color`,简写请按顺序写 | - |
  799. | line-clamp | `number`,超过行数显示省略号 | - |
  800. | vertical-align | 文字垂直对齐,可选值:`bottom`、`top`、`middle` | `middle` |
  801. | line-height | 文字行高,支持`rpx`、`px`、`em` | `1.4em` |
  802. | font-weight | 文字粗细,可选值:`normal`、`bold` | `normal` |
  803. | font-size | 文字大小,`string`,支持`rpx`、`px` | `14px` |
  804. | text-decoration | 文本修饰,可选值:`underline` 、`line-through`、`overline` | - |
  805. | text-stroke | 文字描边,可简写或各个值分开写,如:`text-stroke-color`, `text-stroke-width` | - |
  806. | text-align | 文本水平对齐,可选值:`right` 、`center` | `left` |
  807. | display | 框类型,可选值:`block`、`inline-block`、`flex`、`none`,当为`none`时是不渲染该段, `flex`功能简陋。 | - |
  808. | flex | 配合 display: flex; 属性定义了在分配多余空间,目前只用为数值如: flex: 1 | - |
  809. | align-self | 配合 display: flex; 单个项目垂直轴对齐方式: `flex-start` `flex-end` `center` | `flex-start` |
  810. | justify-content | 配合 display: flex; 水平轴对齐方式: `flex-start` `flex-end` `center` | `flex-start` |
  811. | align-items | 配合 display: flex; 垂直轴对齐方式: `flex-start` `flex-end` `center` | `flex-start` |
  812. | border-radius | 圆角边框,支持`%`、`rpx`、`px` | - |
  813. | box-sizing | 可选值:`border-box` | - |
  814. | box-shadow | 投影 | - |
  815. | background(color) | 支持渐变,但必须写百分比!如:`linear-gradient(,#ff971b 0%, #ff5000 100%)`、`radial-gradient(#0ff 15%, #f0f 60%)`,目前 radial-gradient 渐变的圆心为元素中点,半径为最长边,不支持设置 | - |
  816. | background-clip | 文字渐变,配合`background`背景渐变,设置`background-clip: text` 达到文字渐变效果 | - |
  817. | background-image | view 元素背景:`url(src)`,若只是设置背景图,请不要设置`background-repeat` | - |
  818. | background-repeat | 设置是否及如何重复背景纹理,可选值:`repeat`、`repeat-x`、`repeat-y`、`no-repeat` | `repeat` |
  819. | [object-fit](https://developer.mozilla.org/zh-CN/docs/Web/CSS/object-fit/) | 图片元素适应容器方式,类似于`mode`,可选值:`cover`、 `contain``fill``none` | - |
  820. | [object-position](https://developer.mozilla.org/zh-CN/docs/Web/CSS/object-position) | 图片的对齐方式,配合`object-fit`使用 | - |
  821. ### 图片填充模式 object-fit
  822. | 名称 | 含义 |
  823. | ------- | ------------------------------------------------------ |
  824. | contain | 保持宽高缩放图片,使图片的长边能完全显示出来 |
  825. | cover | 保持宽高缩放图片,使图片的短边能完全显示出来,裁剪长边 |
  826. | fill | 拉伸图片,使图片填满元素 |
  827. | none | 保持图片原有尺寸 |
  828. ### 事件 Events
  829. | 事件名 | 说明 | 返回值 |
  830. | -------- | ---------------------------------------------------------------- | ------ |
  831. | success | 生成图片成功,若使用`is-canvas-to-temp-filePath` 可以接收图片地址 | path |
  832. | fail | 生成图片失败 | error |
  833. | done | 绘制成功 | |
  834. | progress | 绘制进度 | number |
  835. ### 暴露函数 Expose
  836. | 事件名 | 说明 | 返回值 |
  837. | -------- | ---------------------------------------------------------------- | ------ |
  838. | render(object) | 渲染器,传入JSON 绘制海报 | promise |
  839. | [canvasToTempFilePath](https://uniapp.dcloud.io/api/canvas/canvasToTempFilePath.html#canvastotempfilepath)(object) | 把当前画布指定区域的内容导出生成指定大小的图片,并返回文件临时路径。 | |
  840. | canvasToTempFilePathSync(object) | 同步接口,同上 | |
  841. ## 常见问题
  842. - 1、H5 端使用网络图片需要解决跨域问题。
  843. - 2、小程序使用网络图片需要去公众平台增加下载白名单!二级域名也需要配!
  844. - 3、H5 端生成图片是 base64,有时显示只有一半可以使用原生标签`<IMG/>`
  845. - 4、发生保存图片倾斜变形或提示 native buffer exceed size limit 时,使用 pixel-ratio="2"参数,降分辨率。
  846. - 5、h5 保存图片不需要调接口,提示用户长按图片保存。
  847. - 6、画板不能隐藏,包括`v-if`,`v-show`、`display:none`、`opacity:0`,另外也不要把画板放在弹窗里。如果需要隐藏画板请设置 `custom-style="position: fixed; left: 200%"`
  848. - 7、微信小程序真机调试请使用 **真机调试2.0**,不支持1.0。
  849. - 8、微信小程序打开调试时可以生但并闭无法生成时,这种情况一般是没有在公众号配置download域名
  850. - 9、HBX 3.4.5之前的版本不支持vue3
  851. - 10、在微信开发工具上 canvas 层级最高无法zindex,并不影响真机
  852. - 11、请不要导入非uni_modules插件
  853. - 12、关于QQ小程序 报 Propertyor method"toJSON"is not defined 请把基础库调到 1.50.3
  854. - 13、支付宝小程序 IDE 不支持 生成图片 请以真机调试结果为准
  855. - 14、返回值为字符串 `data:,` 大概是尺寸超过限制,设置 pixel-ratio="2"
  856. - 华为手机 APP 上无法生成图片,请使用 HBX2.9.11++(已过时,忽略这条)
  857. - IOS APP 请勿使用 HBX2.9.3.20201014 的版本!这个版本无法生成图片。(已过时,忽略这条)
  858. - 苹果微信 7.0.20 存在闪退和图片无法 onload 为微信 bug(已过时,忽略这条)
  859. - 微信小程序 IOS 旧接口 如父级设置圆角,子级也设会导致子级的失效,为旧接口BUG。
  860. - 微信小程序 安卓 旧接口 如使用图片必须加背景色,为旧接口BUG。
  861. - 微信小程序 安卓端 [图片可能在首次可以加载成功,再次加载会不触发任何事件](https://developers.weixin.qq.com/community/develop/doc/000ee2b8dacf4009337f51f4556800?highLine=canvas%25202d%2520createImage),临时解决方法是给图片加个时间戳
  862. ## 打赏
  863. 如果你觉得本插件,解决了你的问题,赠人玫瑰,手留余香。
  864. ![](https://testingcf.jsdelivr.net/gh/liangei/image@1.9/alipay.png)
  865. ![](https://testingcf.jsdelivr.net/gh/liangei/image@1.9/wpay.png)