|
@@ -1,15 +1,10 @@
|
1
|
|
-import Taro, { Component } from '@tarojs/taro';
|
|
1
|
+import Taro, { Component } from "@tarojs/taro";
|
2
|
2
|
// import PropTypes from 'prop-types';
|
3
|
|
-import { Canvas } from '@tarojs/components';
|
4
|
|
-import { randomString, getHeight, downloadImageAndInfo } from './utils/tools';
|
5
|
|
-import {
|
6
|
|
- drawImage,
|
7
|
|
- drawText,
|
8
|
|
- drawBlock,
|
9
|
|
- drawLine,
|
10
|
|
-} from './utils/draw';
|
11
|
|
-import './index.css';
|
12
|
|
-import rtLog from '@/utils/rtLog';
|
|
3
|
+import { Canvas } from "@tarojs/components";
|
|
4
|
+import { randomString, getHeight, downloadImageAndInfo } from "./utils/tools";
|
|
5
|
+import { drawImage, drawText, drawBlock, drawLine } from "./utils/draw";
|
|
6
|
+import "./index.css";
|
|
7
|
+import rtLog from "@/utils/rtLog";
|
13
|
8
|
|
14
|
9
|
let count = 1;
|
15
|
10
|
export default class CanvasDrawer extends Component {
|
|
@@ -26,8 +21,8 @@ export default class CanvasDrawer extends Component {
|
26
|
21
|
pxWidth: 0,
|
27
|
22
|
pxHeight: 0,
|
28
|
23
|
debug: false,
|
29
|
|
- factor: 0,
|
30
|
|
- }
|
|
24
|
+ factor: 0
|
|
25
|
+ };
|
31
|
26
|
this.canvasId = randomString(10);
|
32
|
27
|
this.ctx = null;
|
33
|
28
|
this.cache = {};
|
|
@@ -46,12 +41,12 @@ export default class CanvasDrawer extends Component {
|
46
|
41
|
const screenWidth = sysInfo.screenWidth;
|
47
|
42
|
this.setState({
|
48
|
43
|
factor: screenWidth / 750
|
49
|
|
- })
|
|
44
|
+ });
|
50
|
45
|
this.onCreate();
|
51
|
|
- }, 0)
|
|
46
|
+ }, 0);
|
52
|
47
|
}
|
53
|
48
|
|
54
|
|
- componentWillUnmount() { }
|
|
49
|
+ componentWillUnmount() {}
|
55
|
50
|
|
56
|
51
|
/**
|
57
|
52
|
* @description rpx => px 基础方法
|
|
@@ -65,7 +60,7 @@ export default class CanvasDrawer extends Component {
|
65
|
60
|
return parseInt(rpx * factor);
|
66
|
61
|
}
|
67
|
62
|
return rpx * factor;
|
68
|
|
- }
|
|
63
|
+ };
|
69
|
64
|
/**
|
70
|
65
|
* @description px => rpx
|
71
|
66
|
* @param { number } px - 需要转换的数值
|
|
@@ -78,7 +73,7 @@ export default class CanvasDrawer extends Component {
|
78
|
73
|
return parseInt(px / factor);
|
79
|
74
|
}
|
80
|
75
|
return px / factor;
|
81
|
|
- }
|
|
76
|
+ };
|
82
|
77
|
|
83
|
78
|
/**
|
84
|
79
|
* @description 下载图片并获取图片信息
|
|
@@ -88,19 +83,22 @@ export default class CanvasDrawer extends Component {
|
88
|
83
|
_downloadImageAndInfo = (image, index) => {
|
89
|
84
|
return new Promise((resolve, reject) => {
|
90
|
85
|
downloadImageAndInfo(image, index, this.toRpx)
|
91
|
|
- .then(
|
92
|
|
- (result) => {
|
|
86
|
+ .then(result => {
|
93
|
87
|
this.drawArr.push(result);
|
94
|
88
|
resolve();
|
95
|
|
- }
|
96
|
|
- )
|
97
|
|
- .catch(err => {
|
98
|
|
- console.log(err);
|
99
|
|
- rtLog.error('下载图片失败, 图片地址 ('+ image +'), 错误消息: ' + ( err.message || err.errMsg || err))
|
100
|
|
- reject(err)
|
101
|
|
- });
|
102
|
|
- })
|
103
|
|
- }
|
|
89
|
+ })
|
|
90
|
+ .catch(err => {
|
|
91
|
+ console.log(err);
|
|
92
|
+ rtLog.error(
|
|
93
|
+ "下载图片失败, 图片地址 (" +
|
|
94
|
+ (image && image.url ? image.url : "无") +
|
|
95
|
+ "), 错误消息: " +
|
|
96
|
+ (err.message || err.errMsg || err)
|
|
97
|
+ );
|
|
98
|
+ reject(err);
|
|
99
|
+ });
|
|
100
|
+ });
|
|
101
|
+ };
|
104
|
102
|
/**
|
105
|
103
|
* @param {} images=[]
|
106
|
104
|
*/
|
|
@@ -108,10 +106,12 @@ export default class CanvasDrawer extends Component {
|
108
|
106
|
const drawList = [];
|
109
|
107
|
let imagesTemp = images;
|
110
|
108
|
|
111
|
|
- imagesTemp.forEach((image, index) => drawList.push(this._downloadImageAndInfo(image, index)));
|
|
109
|
+ imagesTemp.forEach((image, index) =>
|
|
110
|
+ drawList.push(this._downloadImageAndInfo(image, index))
|
|
111
|
+ );
|
112
|
112
|
|
113
|
113
|
return Promise.all(drawList);
|
114
|
|
- }
|
|
114
|
+ };
|
115
|
115
|
|
116
|
116
|
/**
|
117
|
117
|
* @param
|
|
@@ -124,17 +124,17 @@ export default class CanvasDrawer extends Component {
|
124
|
124
|
.then(() => {
|
125
|
125
|
resolve();
|
126
|
126
|
})
|
127
|
|
- .catch((e) => {
|
|
127
|
+ .catch(e => {
|
128
|
128
|
console.log(e);
|
129
|
|
- reject(e)
|
|
129
|
+ reject(e);
|
130
|
130
|
});
|
131
|
131
|
} else {
|
132
|
|
- setTimeout(()=>{
|
|
132
|
+ setTimeout(() => {
|
133
|
133
|
resolve(1);
|
134
|
|
- }, 500)
|
|
134
|
+ }, 500);
|
135
|
135
|
}
|
136
|
|
- })
|
137
|
|
- }
|
|
136
|
+ });
|
|
137
|
+ };
|
138
|
138
|
|
139
|
139
|
/**
|
140
|
140
|
* @param {} w
|
|
@@ -142,53 +142,61 @@ export default class CanvasDrawer extends Component {
|
142
|
142
|
* @param {} debug
|
143
|
143
|
*/
|
144
|
144
|
initCanvas = (w, h, debug) => {
|
145
|
|
- return new Promise((resolve) => {
|
146
|
|
- console.debug('-----------start to init canvas state------------')
|
147
|
|
- this.setState({
|
148
|
|
- pxWidth: this.toPx(w),
|
149
|
|
- pxHeight: this.toPx(h),
|
150
|
|
- debug,
|
151
|
|
- }, () => {
|
152
|
|
- console.debug('-----------finish init canvas state------------')
|
153
|
|
- resolve()
|
154
|
|
- });
|
|
145
|
+ return new Promise(resolve => {
|
|
146
|
+ console.debug("-----------start to init canvas state------------");
|
|
147
|
+ this.setState(
|
|
148
|
+ {
|
|
149
|
+ pxWidth: this.toPx(w),
|
|
150
|
+ pxHeight: this.toPx(h),
|
|
151
|
+ debug
|
|
152
|
+ },
|
|
153
|
+ () => {
|
|
154
|
+ console.debug("-----------finish init canvas state------------");
|
|
155
|
+ resolve();
|
|
156
|
+ }
|
|
157
|
+ );
|
155
|
158
|
});
|
156
|
|
- }
|
|
159
|
+ };
|
157
|
160
|
/**
|
158
|
161
|
* @param { boolean }
|
159
|
162
|
*/
|
160
|
163
|
onCreate = () => {
|
161
|
164
|
const { onCreateFail, config } = this.props;
|
162
|
|
- Taro.showLoading({ mask: true, title: '生成中...' });
|
163
|
|
- console.debug('-----start to download images---')
|
164
|
|
- return this.downloadResourceTransit()
|
|
165
|
+ Taro.showLoading({ mask: true, title: "生成中..." });
|
|
166
|
+ console.debug("-----start to download images---");
|
|
167
|
+ return this.downloadResourceTransit()
|
165
|
168
|
.then(() => {
|
166
|
|
- console.debug('-----finish download images---')
|
|
169
|
+ console.debug("-----finish download images---");
|
167
|
170
|
this.create(config);
|
168
|
171
|
})
|
169
|
|
- .catch((err) => {
|
|
172
|
+ .catch(err => {
|
170
|
173
|
Taro.hideLoading();
|
171
|
|
- Taro.showToast({ icon: 'none', title: err.message || err.errMsg || '下载图片失败' });
|
|
174
|
+ Taro.showToast({
|
|
175
|
+ icon: "none",
|
|
176
|
+ title: err.message || err.errMsg || "下载图片失败"
|
|
177
|
+ });
|
172
|
178
|
console.error(err);
|
173
|
179
|
if (!onCreateFail) {
|
174
|
|
- console.warn('您必须实现 taro-plugin-canvas 组件的 onCreateFail 方法,详见文档 https://github.com/chuyun/taro-plugin-canvas#fail');
|
|
180
|
+ console.warn(
|
|
181
|
+ "您必须实现 taro-plugin-canvas 组件的 onCreateFail 方法,详见文档 https://github.com/chuyun/taro-plugin-canvas#fail"
|
|
182
|
+ );
|
175
|
183
|
}
|
176
|
184
|
onCreateFail && onCreateFail(err);
|
177
|
|
- })
|
178
|
|
- }
|
|
185
|
+ });
|
|
186
|
+ };
|
179
|
187
|
|
180
|
188
|
/**
|
181
|
189
|
* @param { object } config
|
182
|
190
|
*/
|
183
|
|
- create = (config) => {
|
184
|
|
- console.debug('-----create canvas---', this.canvasId, this.$scope)
|
|
191
|
+ create = config => {
|
|
192
|
+ console.debug("-----create canvas---", this.canvasId, this.$scope);
|
185
|
193
|
this.ctx = Taro.createCanvasContext(this.canvasId, this.$scope);
|
186
|
|
- console.debug('-----finish create canvas---')
|
|
194
|
+ console.debug("-----finish create canvas---");
|
187
|
195
|
const height = getHeight(config);
|
188
|
|
- console.debug('-----ready to init canvas---')
|
|
196
|
+ console.debug("-----ready to init canvas---");
|
189
|
197
|
this.initCanvas(config.width, height, config.debug)
|
190
|
198
|
.then(() => {
|
191
|
|
- console.debug('-----finish init canvas---')
|
|
199
|
+ console.debug("-----finish init canvas---");
|
192
|
200
|
// 设置画布底色
|
193
|
201
|
if (config.backgroundColor) {
|
194
|
202
|
this.ctx.save();
|
|
@@ -200,107 +208,119 @@ export default class CanvasDrawer extends Component {
|
200
|
208
|
texts = [],
|
201
|
209
|
// images = [],
|
202
|
210
|
blocks = [],
|
203
|
|
- lines = [],
|
|
211
|
+ lines = []
|
204
|
212
|
} = config;
|
205
|
213
|
const queue = this.drawArr
|
206
|
|
- .concat(texts.map((item) => {
|
207
|
|
- item.type = 'text';
|
208
|
|
- item.zIndex = item.zIndex || 0;
|
209
|
|
- return item;
|
210
|
|
- }))
|
211
|
|
- .concat(blocks.map((item) => {
|
212
|
|
- item.type = 'block';
|
213
|
|
- item.zIndex = item.zIndex || 0;
|
214
|
|
- return item;
|
215
|
|
- }))
|
216
|
|
- .concat(lines.map((item) => {
|
217
|
|
- item.type = 'line';
|
218
|
|
- item.zIndex = item.zIndex || 0;
|
219
|
|
- return item;
|
220
|
|
- }));
|
|
214
|
+ .concat(
|
|
215
|
+ texts.map(item => {
|
|
216
|
+ item.type = "text";
|
|
217
|
+ item.zIndex = item.zIndex || 0;
|
|
218
|
+ return item;
|
|
219
|
+ })
|
|
220
|
+ )
|
|
221
|
+ .concat(
|
|
222
|
+ blocks.map(item => {
|
|
223
|
+ item.type = "block";
|
|
224
|
+ item.zIndex = item.zIndex || 0;
|
|
225
|
+ return item;
|
|
226
|
+ })
|
|
227
|
+ )
|
|
228
|
+ .concat(
|
|
229
|
+ lines.map(item => {
|
|
230
|
+ item.type = "line";
|
|
231
|
+ item.zIndex = item.zIndex || 0;
|
|
232
|
+ return item;
|
|
233
|
+ })
|
|
234
|
+ );
|
221
|
235
|
// 按照顺序排序
|
222
|
236
|
queue.sort((a, b) => a.zIndex - b.zIndex);
|
223
|
237
|
|
224
|
|
- queue.forEach((item) => {
|
|
238
|
+ queue.forEach(item => {
|
225
|
239
|
let drawOptions = {
|
226
|
240
|
ctx: this.ctx,
|
227
|
241
|
toPx: this.toPx,
|
228
|
|
- toRpx: this.toRpx,
|
229
|
|
- }
|
230
|
|
- if (item.type === 'image') {
|
231
|
|
- drawImage(item,drawOptions)
|
232
|
|
- } else if (item.type === 'text') {
|
233
|
|
- drawText(item,drawOptions)
|
234
|
|
- } else if (item.type === 'block') {
|
235
|
|
- drawBlock(item,drawOptions)
|
236
|
|
- } else if (item.type === 'line') {
|
237
|
|
- drawLine(item,drawOptions)
|
|
242
|
+ toRpx: this.toRpx
|
|
243
|
+ };
|
|
244
|
+ if (item.type === "image") {
|
|
245
|
+ drawImage(item, drawOptions);
|
|
246
|
+ } else if (item.type === "text") {
|
|
247
|
+ drawText(item, drawOptions);
|
|
248
|
+ } else if (item.type === "block") {
|
|
249
|
+ drawBlock(item, drawOptions);
|
|
250
|
+ } else if (item.type === "line") {
|
|
251
|
+ drawLine(item, drawOptions);
|
238
|
252
|
}
|
239
|
253
|
});
|
240
|
254
|
|
241
|
255
|
const res = Taro.getSystemInfoSync();
|
242
|
256
|
const platform = res.platform;
|
243
|
257
|
let time = 0;
|
244
|
|
- if (platform === 'android') {
|
|
258
|
+ if (platform === "android") {
|
245
|
259
|
// 在安卓平台,经测试发现如果海报过于复杂在转换时需要做延时,要不然样式会错乱
|
246
|
260
|
time = 300;
|
247
|
261
|
}
|
248
|
|
- console.debug('-----start to draw---')
|
|
262
|
+ console.debug("-----start to draw---");
|
249
|
263
|
this.ctx.draw(false, () => {
|
250
|
|
- console.debug('-----finish draw---')
|
|
264
|
+ console.debug("-----finish draw---");
|
251
|
265
|
setTimeout(() => {
|
252
|
|
- console.debug('-----ready to read file---')
|
|
266
|
+ console.debug("-----ready to read file---");
|
253
|
267
|
this.getTempFile();
|
254
|
268
|
}, time);
|
255
|
269
|
});
|
256
|
270
|
})
|
257
|
|
- .catch((err) => {
|
258
|
|
- Taro.showToast({ icon: 'none', title: err.errMsg || '生成失败' });
|
|
271
|
+ .catch(err => {
|
|
272
|
+ Taro.showToast({ icon: "none", title: err.errMsg || "生成失败" });
|
259
|
273
|
console.error(err);
|
260
|
274
|
});
|
261
|
|
- }
|
|
275
|
+ };
|
262
|
276
|
|
263
|
|
- getTempFile = (otherOptions) => {
|
|
277
|
+ getTempFile = otherOptions => {
|
264
|
278
|
const { onCreateSuccess, onCreateFail } = this.props;
|
265
|
|
- Taro.canvasToTempFilePath({
|
266
|
|
- canvasId: this.canvasId,
|
267
|
|
- success: (result) => {
|
268
|
|
- console.debug('-----read file success---')
|
269
|
|
- if (!onCreateSuccess) {
|
270
|
|
- console.warn('您必须实现 taro-plugin-canvas 组件的 onCreateSuccess 方法,详见文档 https://github.com/chuyun/taro-plugin-canvas#success');
|
271
|
|
- }
|
272
|
|
- onCreateSuccess && onCreateSuccess(result);
|
273
|
|
- },
|
274
|
|
- fail: (error) => {
|
275
|
|
- const { errMsg } = error;
|
276
|
|
- console.log(errMsg)
|
277
|
|
- if (errMsg === 'canvasToTempFilePath:fail:create bitmap failed') {
|
278
|
|
- count += 1;
|
279
|
|
- if (count <= 3) {
|
280
|
|
- this.getTempFile(otherOptions);
|
281
|
|
- } else {
|
282
|
|
- if (!onCreateFail) {
|
283
|
|
- console.warn('您必须实现 taro-plugin-canvas 组件的 onCreateFail 方法,详见文档 https://github.com/chuyun/taro-plugin-canvas#fail');
|
|
279
|
+ Taro.canvasToTempFilePath(
|
|
280
|
+ {
|
|
281
|
+ canvasId: this.canvasId,
|
|
282
|
+ success: result => {
|
|
283
|
+ console.debug("-----read file success---");
|
|
284
|
+ if (!onCreateSuccess) {
|
|
285
|
+ console.warn(
|
|
286
|
+ "您必须实现 taro-plugin-canvas 组件的 onCreateSuccess 方法,详见文档 https://github.com/chuyun/taro-plugin-canvas#success"
|
|
287
|
+ );
|
|
288
|
+ }
|
|
289
|
+ onCreateSuccess && onCreateSuccess(result);
|
|
290
|
+ },
|
|
291
|
+ fail: error => {
|
|
292
|
+ const { errMsg } = error;
|
|
293
|
+ console.log(errMsg);
|
|
294
|
+ if (errMsg === "canvasToTempFilePath:fail:create bitmap failed") {
|
|
295
|
+ count += 1;
|
|
296
|
+ if (count <= 3) {
|
|
297
|
+ this.getTempFile(otherOptions);
|
|
298
|
+ } else {
|
|
299
|
+ if (!onCreateFail) {
|
|
300
|
+ console.warn(
|
|
301
|
+ "您必须实现 taro-plugin-canvas 组件的 onCreateFail 方法,详见文档 https://github.com/chuyun/taro-plugin-canvas#fail"
|
|
302
|
+ );
|
|
303
|
+ }
|
|
304
|
+ onCreateFail && onCreateFail(error);
|
284
|
305
|
}
|
285
|
|
- onCreateFail && onCreateFail(error);
|
286
|
306
|
}
|
287
|
307
|
}
|
288
|
308
|
},
|
289
|
|
- }, this.$scope);
|
290
|
|
- }
|
|
309
|
+ this.$scope
|
|
310
|
+ );
|
|
311
|
+ };
|
291
|
312
|
|
292
|
313
|
render() {
|
293
|
314
|
const { pxWidth, pxHeight, debug } = this.state;
|
294
|
|
- if(pxWidth && pxHeight){
|
|
315
|
+ if (pxWidth && pxHeight) {
|
295
|
316
|
return (
|
296
|
317
|
<Canvas
|
297
|
318
|
canvas-id={this.canvasId}
|
298
|
319
|
style={`width:${pxWidth}px; height:${pxHeight}px;`}
|
299
|
|
- className={`${debug ? 'debug' : 'pro'} canvas`}
|
|
320
|
+ className={`${debug ? "debug" : "pro"} canvas`}
|
300
|
321
|
/>
|
301
|
322
|
);
|
302
|
323
|
}
|
303
|
324
|
return null;
|
304
|
325
|
}
|
305
|
326
|
}
|
306
|
|
-
|