uni-canvas-image 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +12 -0
- package/src/common/index.js +137 -0
- package/src/index.js +3 -0
- package/src/util/coverImage.js +74 -0
- package/src/util/houseImage.js +144 -0
- package/src/util/noteImage.js +98 -0
package/package.json
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "uni-canvas-image",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "租房项目使用uniapp canvas合并图片",
|
|
5
|
+
"main": "src/index.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
9
|
+
},
|
|
10
|
+
"author": "",
|
|
11
|
+
"license": "ISC"
|
|
12
|
+
}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
export const directionEnum = { NORTH: '北', EAST: '东', SOUTH: '南', WEST: '西', NORTH_EAST: '东北', SOUTH_EAST: '东南', SOUTH_WEST: '西南', NORTH_WEST: '西北' }
|
|
2
|
+
|
|
3
|
+
export async function getImageInfo(src, targetRatio) {
|
|
4
|
+
return new Promise(async (resolve, reject) => {
|
|
5
|
+
if (src && src.endsWith('.mp4')) src = src.replace('.mp4', '.png')
|
|
6
|
+
if (src) {
|
|
7
|
+
const imageInfo = await uni.getImageInfo({ src })
|
|
8
|
+
const newImageInfo = {
|
|
9
|
+
...imageInfo,
|
|
10
|
+
...getMaxSizeByRatio(imageInfo.width, imageInfo.height, targetRatio),
|
|
11
|
+
type: 'image',
|
|
12
|
+
}
|
|
13
|
+
resolve(newImageInfo)
|
|
14
|
+
} else {
|
|
15
|
+
resolve({
|
|
16
|
+
type: 'rect2',
|
|
17
|
+
color: '#f2f2f2',
|
|
18
|
+
})
|
|
19
|
+
}
|
|
20
|
+
})
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function getMaxSizeByRatio(width, height, targetRatio = 5 / 4) {
|
|
24
|
+
// const targetRatio = 5 / 4 // 1.25
|
|
25
|
+
const originalRatio = width / height
|
|
26
|
+
let sWidth, sHeight
|
|
27
|
+
let sx = 0
|
|
28
|
+
let sy = 0
|
|
29
|
+
|
|
30
|
+
if (originalRatio > targetRatio) {
|
|
31
|
+
// 原始图片更宽,以高度为基准
|
|
32
|
+
sHeight = height
|
|
33
|
+
sWidth = Math.round(sHeight * targetRatio)
|
|
34
|
+
sx = (width - sWidth) / 2
|
|
35
|
+
} else {
|
|
36
|
+
// 原始图片更高或比例相同,以宽度为基准
|
|
37
|
+
sWidth = width
|
|
38
|
+
sHeight = Math.round(sWidth / targetRatio)
|
|
39
|
+
sy = (height - sHeight) / 2
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return { sx, sy, sWidth, sHeight }
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export async function base64ToBlob(base64Data) {
|
|
46
|
+
const response = await fetch(base64Data)
|
|
47
|
+
return await response.blob()
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export async function drawImageToCanvas(arr, canvasId = 'canvas-1', api) {
|
|
51
|
+
return new Promise((resolve, reject) => {
|
|
52
|
+
const ctx = uni.createCanvasContext(canvasId)
|
|
53
|
+
arr.forEach((item) => {
|
|
54
|
+
if (item.type === 'image') {
|
|
55
|
+
const { path, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight } = item
|
|
56
|
+
ctx.drawImage(path, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)
|
|
57
|
+
} else if (item.type === 'text') {
|
|
58
|
+
const { text, x = 10, y = 20, fontSize = 16, color = '#000' } = item
|
|
59
|
+
ctx.setFontSize(fontSize)
|
|
60
|
+
ctx.setFillStyle(color)
|
|
61
|
+
ctx.setTextBaseline('top')
|
|
62
|
+
ctx.fillText(text, x, y)
|
|
63
|
+
} else if (item.type === 'rect') {
|
|
64
|
+
const { x, y, width, height, borderRadius, color } = item
|
|
65
|
+
ctx.fillStyle = color // 填充
|
|
66
|
+
roundedRectPath(ctx, x, y, width, height, borderRadius) // x, y, width, height, radius
|
|
67
|
+
ctx.fill()
|
|
68
|
+
} else if (item.type === 'rect2') {
|
|
69
|
+
console.log(item, 'item')
|
|
70
|
+
const { dx: x, dy: y, dWidth: width, dHeight: height, color } = item
|
|
71
|
+
ctx.setFillStyle(color) // 填充
|
|
72
|
+
ctx.fillRect(x, y, width, height) // x, y
|
|
73
|
+
}
|
|
74
|
+
})
|
|
75
|
+
ctx.draw(false, () => {
|
|
76
|
+
uni.canvasToTempFilePath({
|
|
77
|
+
canvasId,
|
|
78
|
+
fileType: 'jpg',
|
|
79
|
+
quality: 0.1,
|
|
80
|
+
destWidth: 1500,
|
|
81
|
+
destHeight: 1200,
|
|
82
|
+
success: async (tempRes) => {
|
|
83
|
+
ctx.clearRect(0, 0, 375, 300)
|
|
84
|
+
let filePath
|
|
85
|
+
// #ifdef MP-WEIXIN
|
|
86
|
+
filePath = tempRes.tempFilePath
|
|
87
|
+
// #endif
|
|
88
|
+
// #ifdef H5
|
|
89
|
+
const blob = await base64ToBlob(tempRes.tempFilePath)
|
|
90
|
+
filePath = URL.createObjectURL(blob)
|
|
91
|
+
// #endif
|
|
92
|
+
if (!api) return resolve(filePath)
|
|
93
|
+
else {
|
|
94
|
+
const { result } = await api('/third-party/open/upload/uploadFile', filePath, {}, 'file')
|
|
95
|
+
resolve(result)
|
|
96
|
+
// #ifdef MP-WEIXIN
|
|
97
|
+
uni.getFileSystemManager().unlink({ filePath })
|
|
98
|
+
// #endif
|
|
99
|
+
// #ifdef H5
|
|
100
|
+
URL.revokeObjectURL(filePath)
|
|
101
|
+
// #endif
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
fail: (err) => {
|
|
105
|
+
console.error('生成临时文件失败:', err)
|
|
106
|
+
},
|
|
107
|
+
})
|
|
108
|
+
})
|
|
109
|
+
})
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function roundedRectPath(ctx, x, y, width, height, radius) {
|
|
113
|
+
// 防止半径超过宽高一半
|
|
114
|
+
radius = Math.min(radius, width / 2, height / 2)
|
|
115
|
+
ctx.beginPath()
|
|
116
|
+
ctx.moveTo(x + radius, y) // 左上开始,略过圆角
|
|
117
|
+
ctx.lineTo(x + width - radius, y) // 上边线
|
|
118
|
+
ctx.quadraticCurveTo(x + width, y, x + width, y + radius) // 右上圆角
|
|
119
|
+
ctx.lineTo(x + width, y + height - radius) // 右边线
|
|
120
|
+
ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height) // 右下圆角
|
|
121
|
+
ctx.lineTo(x + radius, y + height) // 下边线
|
|
122
|
+
ctx.quadraticCurveTo(x, y + height, x, y + height - radius) // 左下圆角
|
|
123
|
+
ctx.lineTo(x, y + radius) // 左边线
|
|
124
|
+
ctx.quadraticCurveTo(x, y, x + radius, y) // 左上圆角
|
|
125
|
+
ctx.closePath()
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export function handleParagraph(text, lineLength = 25, line = 2) {
|
|
129
|
+
if (!text) return []
|
|
130
|
+
const textArray = []
|
|
131
|
+
for (let i = 0; i < line; i++) {
|
|
132
|
+
let str = text.slice(i * lineLength, (i + 1) * lineLength)
|
|
133
|
+
if (i === line - 1 && text.length > (i + 1) * lineLength) str = str.slice(0, -1) + '...'
|
|
134
|
+
if (str.trim()) textArray.push(str)
|
|
135
|
+
}
|
|
136
|
+
return textArray
|
|
137
|
+
}
|
package/src/index.js
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { getMaxSizeByRatio, drawImageToCanvas } from '../common/index'
|
|
2
|
+
|
|
3
|
+
const canvasSize = {
|
|
4
|
+
w: 375,
|
|
5
|
+
h: 300,
|
|
6
|
+
}
|
|
7
|
+
const imgSize = {
|
|
8
|
+
w: 0,
|
|
9
|
+
h: 0,
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const coverImage = (params = {}) => {
|
|
13
|
+
const { data, canvasId, api } = params
|
|
14
|
+
return new Promise(async (resolve, reject) => {
|
|
15
|
+
const imgs = data?.filter((i) => i.type === 'image').map((i) => i.content)
|
|
16
|
+
if (imgs.length === 0) return resolve('')
|
|
17
|
+
else if (imgs.length < 4) return resolve(imgs[0]) //小于4 为1张不用拼图
|
|
18
|
+
const newImageInfos = await handleImgInfo(imgs)
|
|
19
|
+
const drawImgs = await calculateOperation(newImageInfos)
|
|
20
|
+
const newDrawImgs = drawImgs.map((i) => {
|
|
21
|
+
return {
|
|
22
|
+
...i,
|
|
23
|
+
dx: i.x,
|
|
24
|
+
dy: i.y,
|
|
25
|
+
dWidth: imgSize.w,
|
|
26
|
+
dHeight: imgSize.h,
|
|
27
|
+
type: 'image',
|
|
28
|
+
}
|
|
29
|
+
})
|
|
30
|
+
const url = await drawImageToCanvas(newDrawImgs, canvasId, api)
|
|
31
|
+
resolve(url)
|
|
32
|
+
})
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async function handleImgInfo(imgs) {
|
|
36
|
+
return new Promise(async (resolve, reject) => {
|
|
37
|
+
const imageInfos = await Promise.all(imgs.map((src) => uni.getImageInfo({ src })))
|
|
38
|
+
const newImageInfos = imageInfos.map((i) => {
|
|
39
|
+
return {
|
|
40
|
+
...i,
|
|
41
|
+
...getMaxSizeByRatio(i.width, i.height),
|
|
42
|
+
}
|
|
43
|
+
})
|
|
44
|
+
resolve(newImageInfos)
|
|
45
|
+
})
|
|
46
|
+
}
|
|
47
|
+
function calculateOperation(newImageInfos) {
|
|
48
|
+
let drawImgs = []
|
|
49
|
+
let count
|
|
50
|
+
const length = newImageInfos.length
|
|
51
|
+
if (length === 4 || length < 9) {
|
|
52
|
+
imgSize.w = canvasSize.w / 2
|
|
53
|
+
imgSize.h = canvasSize.h / 2
|
|
54
|
+
count = 4
|
|
55
|
+
} else if (length >= 9) {
|
|
56
|
+
imgSize.w = canvasSize.w / 3
|
|
57
|
+
imgSize.h = canvasSize.h / 3
|
|
58
|
+
count = 9
|
|
59
|
+
}
|
|
60
|
+
drawImgs = newImageInfos.slice(0, count)
|
|
61
|
+
drawImgs = drawImgs.map((i, index) => {
|
|
62
|
+
if (count === 4) {
|
|
63
|
+
i.x = index % 2 === 0 ? 0 : canvasSize.w / 2
|
|
64
|
+
i.y = index < 2 ? 0 : canvasSize.h / 2
|
|
65
|
+
} else if (count === 9) {
|
|
66
|
+
i.x = index % 3 === 0 ? 0 : index % 3 === 1 ? canvasSize.w / 3 : (canvasSize.w / 3) * 2
|
|
67
|
+
i.y = index < 3 ? 0 : index < 6 ? canvasSize.h / 3 : (canvasSize.h / 3) * 2
|
|
68
|
+
}
|
|
69
|
+
return i
|
|
70
|
+
})
|
|
71
|
+
return drawImgs
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export default coverImage
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { directionEnum, getImageInfo, drawImageToCanvas, handleParagraph } from '../common/index'
|
|
2
|
+
const categoryEnum = [
|
|
3
|
+
{ text: '单价', x: 10, y: 246, fontSize: 14, color: '#9B9B9B' },
|
|
4
|
+
{ text: '(元/m²/天)', x: 34, y: 248, fontSize: 10, color: '#9B9B9B' },
|
|
5
|
+
{ text: '面积', x: 160, y: 246, fontSize: 14, color: '#9B9B9B' },
|
|
6
|
+
{ text: '(m²)', x: 184, y: 248, fontSize: 10, color: '#9B9B9B' },
|
|
7
|
+
{ text: '朝向', x: 310, y: 246, fontSize: 14, color: '#9B9B9B' },
|
|
8
|
+
{ text: '¥', x: 10, y: 276, fontSize: 10, color: '#FF703B' },
|
|
9
|
+
{ name: '单价', key: 'rentDayCeilPrice', x: 20, y: 270, fontSize: 18, color: '#FF703B' },
|
|
10
|
+
{ name: '面积', key: 'houseArea', x: 160, y: 270, fontSize: 18, color: '#FF703B' },
|
|
11
|
+
{ name: '朝向', key: 'direction', x: 310, y: 270, fontSize: 18, color: '#FF703B' },
|
|
12
|
+
]
|
|
13
|
+
/**
|
|
14
|
+
*
|
|
15
|
+
* @param {Object Array} data 房源数据数组
|
|
16
|
+
* @returns {String} 处理后的图片URL
|
|
17
|
+
*/
|
|
18
|
+
async function houseImage(params = {}) {
|
|
19
|
+
const { data, canvasId, api } = params
|
|
20
|
+
if (!data) return reject('数据不能为空')
|
|
21
|
+
const items = Array.isArray(data) ? data : [data]
|
|
22
|
+
return items.length > 1
|
|
23
|
+
? await handleItems(items, canvasId, api) // 多个房源
|
|
24
|
+
: await handleItem(items[0], canvasId, api) // 单个房源
|
|
25
|
+
}
|
|
26
|
+
//单个房源
|
|
27
|
+
async function handleItem(obj, canvasId, api) {
|
|
28
|
+
return new Promise(async (resolve, reject) => {
|
|
29
|
+
const imgInfo = await getImageInfo(obj.imageUrl, 750 / 340)
|
|
30
|
+
const newImgInfo = {
|
|
31
|
+
...imgInfo,
|
|
32
|
+
dx: 0,
|
|
33
|
+
dy: 0,
|
|
34
|
+
dWidth: 375,
|
|
35
|
+
dHeight: 170,
|
|
36
|
+
}
|
|
37
|
+
const paragraphInfos = handleParagraph(obj.title)
|
|
38
|
+
const titleInfos = paragraphInfos.map((text, index) => {
|
|
39
|
+
return {
|
|
40
|
+
type: 'text',
|
|
41
|
+
text,
|
|
42
|
+
x: 10,
|
|
43
|
+
y: 180 + index * 20,
|
|
44
|
+
fontSize: 14,
|
|
45
|
+
color: '#000',
|
|
46
|
+
}
|
|
47
|
+
})
|
|
48
|
+
const tagsInfos = hanleTagsInfo(obj.tags, 14, titleInfos.length > 1 ? 224 : 216)
|
|
49
|
+
const categoryInfos = handleCategoryInfo(obj, categoryEnum)
|
|
50
|
+
const newObj = [newImgInfo, ...titleInfos, ...tagsInfos, ...categoryInfos]
|
|
51
|
+
const url = await drawImageToCanvas(newObj, canvasId, api)
|
|
52
|
+
resolve(url)
|
|
53
|
+
})
|
|
54
|
+
}
|
|
55
|
+
function handleItems(arr, canvasId, api) {
|
|
56
|
+
return new Promise(async (resolve, reject) => {
|
|
57
|
+
const newObj = []
|
|
58
|
+
const newArr = arr.slice(0, 2)
|
|
59
|
+
console.log('🚀 ~ handleItems ~ newArr:', newArr)
|
|
60
|
+
for (let i = 0; i < newArr.length; i++) {
|
|
61
|
+
const obj = newArr[i]
|
|
62
|
+
// 图片
|
|
63
|
+
const imgInfo = await getImageInfo(obj.imageUrl, 1 / 1)
|
|
64
|
+
const newImgInfo = {
|
|
65
|
+
...imgInfo,
|
|
66
|
+
dx: 0,
|
|
67
|
+
dy: i * 152,
|
|
68
|
+
dWidth: 148,
|
|
69
|
+
dHeight: 148,
|
|
70
|
+
}
|
|
71
|
+
// 标题
|
|
72
|
+
const paragraphInfos = handleParagraph(obj.title, 14)
|
|
73
|
+
const titleInfos = paragraphInfos.map((text, index) => {
|
|
74
|
+
return {
|
|
75
|
+
type: 'text',
|
|
76
|
+
text,
|
|
77
|
+
x: 160,
|
|
78
|
+
y: 10 + i * 152 + index * 20,
|
|
79
|
+
fontSize: 14,
|
|
80
|
+
color: '#000',
|
|
81
|
+
}
|
|
82
|
+
})
|
|
83
|
+
// 标签
|
|
84
|
+
const tagsInfos = hanleTagsInfo(obj.tags, 160, 60 + i * 152)
|
|
85
|
+
// 分类信息
|
|
86
|
+
const category = [
|
|
87
|
+
{ text: '单价', x: 160, y: 90 + i * 152, fontSize: 14, color: '#9B9B9B' },
|
|
88
|
+
{ text: '(元/m²/天)', x: 184, y: 92 + i * 152, fontSize: 10, color: '#9B9B9B' },
|
|
89
|
+
{ text: '面积', x: 290, y: 90 + i * 152, fontSize: 14, color: '#9B9B9B' },
|
|
90
|
+
{ text: '(m²)', x: 314, y: 92 + i * 152, fontSize: 10, color: '#9B9B9B' },
|
|
91
|
+
{ text: '¥', x: 160, y: 124 + i * 152, fontSize: 10, color: '#FF703B' },
|
|
92
|
+
{ name: '单价', key: 'rentDayCeilPrice', x: 170, y: 118 + i * 152, fontSize: 18, color: '#FF703B' },
|
|
93
|
+
{ name: '面积', key: 'houseArea', x: 290, y: 118 + i * 152, fontSize: 18, color: '#FF703B' },
|
|
94
|
+
]
|
|
95
|
+
const categoryInfos = handleCategoryInfo(obj, category)
|
|
96
|
+
newObj.push(newImgInfo, ...titleInfos, ...tagsInfos, ...categoryInfos)
|
|
97
|
+
}
|
|
98
|
+
const url = await drawImageToCanvas(newObj, canvasId, api)
|
|
99
|
+
resolve(url)
|
|
100
|
+
})
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function hanleTagsInfo(tags, x = 14, y = 224) {
|
|
104
|
+
if (!tags || tags.length === 0) return []
|
|
105
|
+
const tagsInfos = tags.map((tag, index) => {
|
|
106
|
+
return {
|
|
107
|
+
type: 'text',
|
|
108
|
+
text: tag,
|
|
109
|
+
// 前面标签的长度和间距计算x坐标
|
|
110
|
+
x: x + tags.slice(0, index).reduce((acc, cur) => acc + cur.length, 0) * 12 + index * 18, // 根据
|
|
111
|
+
y,
|
|
112
|
+
fontSize: 12,
|
|
113
|
+
color: '#377DF3',
|
|
114
|
+
}
|
|
115
|
+
})
|
|
116
|
+
//tga背景颜色
|
|
117
|
+
const rects = tagsInfos.map((tag, index) => {
|
|
118
|
+
return {
|
|
119
|
+
type: 'rect',
|
|
120
|
+
x: tag.x - 4,
|
|
121
|
+
y: tag.y - 6,
|
|
122
|
+
width: tag.text.length * 12 + 8,
|
|
123
|
+
height: 20,
|
|
124
|
+
borderRadius: 4,
|
|
125
|
+
color: '#ebf1ff',
|
|
126
|
+
}
|
|
127
|
+
})
|
|
128
|
+
return [...rects, ...tagsInfos]
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function handleCategoryInfo(obj, categoryEnum) {
|
|
132
|
+
const newArr = categoryEnum.map((item) => {
|
|
133
|
+
item.type = 'text'
|
|
134
|
+
if (item.name) {
|
|
135
|
+
if (item.key === 'direction') {
|
|
136
|
+
item.text = directionEnum[obj?.direction[0]] + (obj?.direction.length > 1 ? '...' : '')
|
|
137
|
+
} else item.text = obj[item.key] || ''
|
|
138
|
+
}
|
|
139
|
+
return item
|
|
140
|
+
})
|
|
141
|
+
return newArr
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export default houseImage
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { getImageInfo, drawImageToCanvas, handleParagraph } from '../common/index'
|
|
2
|
+
/**
|
|
3
|
+
*
|
|
4
|
+
* @param {Object Array} data 笔记数据数组
|
|
5
|
+
* @returns {String} 处理后的图片URL
|
|
6
|
+
*/
|
|
7
|
+
async function noteImage(params = {}) {
|
|
8
|
+
const { data, canvasId, api } = params
|
|
9
|
+
if (!data) return reject('数据不能为空')
|
|
10
|
+
const items = Array.isArray(data) ? data : [data]
|
|
11
|
+
return items.length > 1
|
|
12
|
+
? await handleItems(items, canvasId, api) // 多个房源
|
|
13
|
+
: await handleItem(items[0], canvasId, api) // 单个房源
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function handleItem(obj, canvasId) {
|
|
17
|
+
return new Promise(async (resolve, reject) => {
|
|
18
|
+
const imgInfo = await getImageInfo(obj.imageUrl, 750 / 340)
|
|
19
|
+
const newImgInfo = {
|
|
20
|
+
...imgInfo,
|
|
21
|
+
dx: 0,
|
|
22
|
+
dy: 0,
|
|
23
|
+
dWidth: 375,
|
|
24
|
+
dHeight: 170,
|
|
25
|
+
}
|
|
26
|
+
const paragraphInfos = handleParagraph(obj.title)
|
|
27
|
+
const titleInfos = paragraphInfos.map((text, index) => {
|
|
28
|
+
return {
|
|
29
|
+
type: 'text',
|
|
30
|
+
text,
|
|
31
|
+
x: 10,
|
|
32
|
+
y: 180 + index * 20,
|
|
33
|
+
fontSize: 14,
|
|
34
|
+
color: '#000',
|
|
35
|
+
}
|
|
36
|
+
})
|
|
37
|
+
const contentInfos = handleParagraph(obj.content, 31, 3)
|
|
38
|
+
const newContentInfos = contentInfos.map((text, index) => {
|
|
39
|
+
return {
|
|
40
|
+
type: 'text',
|
|
41
|
+
text,
|
|
42
|
+
x: 10,
|
|
43
|
+
y: 230 + index * 18,
|
|
44
|
+
fontSize: 12,
|
|
45
|
+
color: '#9B9B9B',
|
|
46
|
+
}
|
|
47
|
+
})
|
|
48
|
+
const newObj = [newImgInfo, ...titleInfos, ...newContentInfos]
|
|
49
|
+
const url = await drawImageToCanvas(newObj, canvasId, api)
|
|
50
|
+
resolve(url)
|
|
51
|
+
})
|
|
52
|
+
}
|
|
53
|
+
function handleItems(arr, canvasId) {
|
|
54
|
+
return new Promise(async (resolve, reject) => {
|
|
55
|
+
const newObj = []
|
|
56
|
+
const newArr = arr.slice(0, 2)
|
|
57
|
+
for (let i = 0; i < newArr.length; i++) {
|
|
58
|
+
const obj = newArr[i]
|
|
59
|
+
// 图片
|
|
60
|
+
const imgInfo = await getImageInfo(obj.imageUrl, 1 / 1)
|
|
61
|
+
const newImgInfo = {
|
|
62
|
+
...imgInfo,
|
|
63
|
+
dx: 10,
|
|
64
|
+
dy: i * 140 + 10,
|
|
65
|
+
dWidth: 120,
|
|
66
|
+
dHeight: 120,
|
|
67
|
+
}
|
|
68
|
+
const paragraphInfos = handleParagraph(obj.title, 16)
|
|
69
|
+
const titleInfos = paragraphInfos.map((text, index) => {
|
|
70
|
+
return {
|
|
71
|
+
type: 'text',
|
|
72
|
+
text,
|
|
73
|
+
x: 144,
|
|
74
|
+
y: 10 + i * 140 + index * 20,
|
|
75
|
+
fontSize: 14,
|
|
76
|
+
color: '#000',
|
|
77
|
+
}
|
|
78
|
+
})
|
|
79
|
+
const contentInfos = handleParagraph(obj.content, 24, 4)
|
|
80
|
+
const newContentInfos = contentInfos.map((text, index) => {
|
|
81
|
+
return {
|
|
82
|
+
type: 'text',
|
|
83
|
+
text,
|
|
84
|
+
x: 144,
|
|
85
|
+
y: 60 + i * 140 + index * 18,
|
|
86
|
+
fontSize: 10,
|
|
87
|
+
color: '#9B9B9B',
|
|
88
|
+
}
|
|
89
|
+
})
|
|
90
|
+
newObj.push(newImgInfo, ...titleInfos, ...newContentInfos)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const url = await drawImageToCanvas(newObj, canvasId, api)
|
|
94
|
+
resolve(url)
|
|
95
|
+
})
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export default noteImage
|