stellar-ui-v2 1.38.9 → 1.38.10
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/components/ste-barcode/ste-barcode.vue +203 -213
- package/components/ste-qrcode/ste-qrcode.vue +218 -218
- package/package.json +1 -1
- package/utils/utils.js +3 -10
|
@@ -1,213 +1,203 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<view class="ste-barcode-root">
|
|
3
|
-
<!-- #ifdef H5 -->
|
|
4
|
-
<canvas
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
},
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
this.
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
// #
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
//
|
|
129
|
-
const
|
|
130
|
-
|
|
131
|
-
//
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
if (
|
|
185
|
-
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
</script>
|
|
205
|
-
|
|
206
|
-
<style>
|
|
207
|
-
.ste-barcode-root {
|
|
208
|
-
width: fit-content;
|
|
209
|
-
display: flex;
|
|
210
|
-
justify-content: center;
|
|
211
|
-
align-items: center;
|
|
212
|
-
}
|
|
213
|
-
</style>
|
|
1
|
+
<template>
|
|
2
|
+
<view class="ste-barcode-root">
|
|
3
|
+
<!-- #ifdef H5 || APP -->
|
|
4
|
+
<canvas :style="{ width: width + 'px', height: height + 'px' }" :canvas-id="canvasId" :id="canvasId" class="h5-canvas"></canvas>
|
|
5
|
+
<!-- #endif -->
|
|
6
|
+
|
|
7
|
+
<!-- #ifdef MP-WEIXIN || MP-ALIPAY -->
|
|
8
|
+
<canvas type="2d" :id="canvasId" :style="{ width: width + 'px', height: height + 'px' }" class="mp-canvas"></canvas>
|
|
9
|
+
<!-- #endif -->
|
|
10
|
+
</view>
|
|
11
|
+
</template>
|
|
12
|
+
|
|
13
|
+
<script>
|
|
14
|
+
/**
|
|
15
|
+
* ste-barcode 条形码
|
|
16
|
+
* @description 条形码组件
|
|
17
|
+
* @tutorial https://stellar-ui.intecloud.com.cn/pc/index/index?name=ste-barcode
|
|
18
|
+
* @property {String} content 条形码内容(仅支持数字和字母)
|
|
19
|
+
* @property {Number} width 条形码宽度,单位`px`
|
|
20
|
+
* @property {Number} height 条形码高度,单位`px`
|
|
21
|
+
* @property {String} background 背景色
|
|
22
|
+
* @property {String} foreground 前景色(条形码画笔颜色)
|
|
23
|
+
* @event {Function} loadImage 加载完成后返回条形码对应的图片数据
|
|
24
|
+
*/
|
|
25
|
+
import utils from '../../utils/utils';
|
|
26
|
+
import { PATTERNS, stringToCode128 } from './encode2';
|
|
27
|
+
|
|
28
|
+
export default {
|
|
29
|
+
group: '展示组件',
|
|
30
|
+
name: 'ste-barcode',
|
|
31
|
+
title: 'Barcode 条形码',
|
|
32
|
+
options: {
|
|
33
|
+
virtualHost: true,
|
|
34
|
+
},
|
|
35
|
+
props: {
|
|
36
|
+
content: {
|
|
37
|
+
type: String,
|
|
38
|
+
required: true,
|
|
39
|
+
},
|
|
40
|
+
width: {
|
|
41
|
+
type: Number,
|
|
42
|
+
default: 300,
|
|
43
|
+
},
|
|
44
|
+
height: {
|
|
45
|
+
type: Number,
|
|
46
|
+
default: 100,
|
|
47
|
+
},
|
|
48
|
+
background: {
|
|
49
|
+
type: String,
|
|
50
|
+
default: '#FFFFFF',
|
|
51
|
+
},
|
|
52
|
+
foreground: {
|
|
53
|
+
type: String,
|
|
54
|
+
default: '#000000',
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
|
|
58
|
+
data() {
|
|
59
|
+
return {
|
|
60
|
+
canvasId: 'ste-barcode-' + utils.guid(8),
|
|
61
|
+
};
|
|
62
|
+
},
|
|
63
|
+
|
|
64
|
+
mounted() {
|
|
65
|
+
this.initCanvas();
|
|
66
|
+
},
|
|
67
|
+
watch: {
|
|
68
|
+
content: {
|
|
69
|
+
handler(newVal) {
|
|
70
|
+
if (!newVal) return;
|
|
71
|
+
this.initCanvas();
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
methods: {
|
|
76
|
+
initCanvas() {
|
|
77
|
+
const canvas = utils.getCanvasContext(this.canvasId, this).then((res) => {
|
|
78
|
+
// #ifndef H5 || APP
|
|
79
|
+
const context = res.getContext('2d');
|
|
80
|
+
const dpr = utils.System.getWindowInfo().pixelRatio;
|
|
81
|
+
res.width = this.width * dpr;
|
|
82
|
+
res.height = this.height * dpr;
|
|
83
|
+
context.scale(dpr, dpr);
|
|
84
|
+
this.drawBarcodeMP(context, res);
|
|
85
|
+
|
|
86
|
+
// #endif
|
|
87
|
+
|
|
88
|
+
// #ifdef H5 || APP
|
|
89
|
+
this.drawBarcodeH5(res);
|
|
90
|
+
// #endif
|
|
91
|
+
});
|
|
92
|
+
},
|
|
93
|
+
// 将 PATTERNS 码序列转换为二进制序列
|
|
94
|
+
patternsToBinary(codes) {
|
|
95
|
+
let binary = '';
|
|
96
|
+
for (let i = 0; i < codes.length; i++) {
|
|
97
|
+
const pattern = PATTERNS[codes[i]];
|
|
98
|
+
for (let j = 0; j < 8; j += 2) {
|
|
99
|
+
// 添加黑色条
|
|
100
|
+
binary += '1'.repeat(pattern[j]);
|
|
101
|
+
// 添加白色空格
|
|
102
|
+
if (j + 1 < 8) {
|
|
103
|
+
binary += '0'.repeat(pattern[j + 1]);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return binary;
|
|
108
|
+
},
|
|
109
|
+
// H5环境下的绘制方法
|
|
110
|
+
drawBarcodeH5(context) {
|
|
111
|
+
if (!this.content) return;
|
|
112
|
+
// 生成编码数据
|
|
113
|
+
const codes = stringToCode128(this.content);
|
|
114
|
+
if (!codes || codes.length === 0) {
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// 转换为二进制序列
|
|
119
|
+
const barcodeData = this.patternsToBinary(codes);
|
|
120
|
+
|
|
121
|
+
// 清空画布
|
|
122
|
+
context.setFillStyle(this.background);
|
|
123
|
+
context.fillRect(0, 0, this.width, this.height);
|
|
124
|
+
|
|
125
|
+
// 设置条码颜色
|
|
126
|
+
context.setFillStyle(this.foreground);
|
|
127
|
+
|
|
128
|
+
// 直接使用画布宽度,不考虑边距
|
|
129
|
+
const unitWidth = this.width / barcodeData.length;
|
|
130
|
+
|
|
131
|
+
// 绘制条码
|
|
132
|
+
let x = 0;
|
|
133
|
+
for (let i = 0; i < barcodeData.length; i++) {
|
|
134
|
+
if (barcodeData[i] === '1') {
|
|
135
|
+
context.fillRect(x, 0, Math.ceil(unitWidth), this.height);
|
|
136
|
+
}
|
|
137
|
+
x += unitWidth;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
context.draw();
|
|
141
|
+
uni.canvasToTempFilePath({
|
|
142
|
+
canvasId: this.canvasId,
|
|
143
|
+
canvas: context,
|
|
144
|
+
complete: (res) => {
|
|
145
|
+
if (!res || !res.tempFilePath) {
|
|
146
|
+
console.error('图片生成失败');
|
|
147
|
+
} else {
|
|
148
|
+
this.$emit('loadImage', res.tempFilePath);
|
|
149
|
+
}
|
|
150
|
+
},
|
|
151
|
+
});
|
|
152
|
+
},
|
|
153
|
+
|
|
154
|
+
// 小程序环境下的绘制方法
|
|
155
|
+
drawBarcodeMP(context, canvas) {
|
|
156
|
+
if (!context || !this.content) return;
|
|
157
|
+
|
|
158
|
+
const codes = stringToCode128(this.content);
|
|
159
|
+
if (!codes || codes.length === 0) return;
|
|
160
|
+
|
|
161
|
+
// 清空画布
|
|
162
|
+
context.fillStyle = this.background;
|
|
163
|
+
context.fillRect(0, 0, this.width, this.height);
|
|
164
|
+
|
|
165
|
+
const barWeight = this.width / ((codes.length - 3) * 11 + 35);
|
|
166
|
+
let x = 0;
|
|
167
|
+
|
|
168
|
+
// 绘制条码
|
|
169
|
+
context.fillStyle = this.foreground;
|
|
170
|
+
for (let i = 0; i < codes.length; i++) {
|
|
171
|
+
const pattern = PATTERNS[codes[i]];
|
|
172
|
+
for (let bar = 0; bar < 8; bar += 2) {
|
|
173
|
+
const barW = pattern[bar] * barWeight;
|
|
174
|
+
if (barW > 0) {
|
|
175
|
+
context.fillRect(x, 0, barW, this.height);
|
|
176
|
+
}
|
|
177
|
+
x += barW + pattern[bar + 1] * barWeight;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
uni.canvasToTempFilePath({
|
|
182
|
+
canvas: canvas,
|
|
183
|
+
complete: (res) => {
|
|
184
|
+
if (!res || !res.tempFilePath) {
|
|
185
|
+
console.error('图片生成失败');
|
|
186
|
+
} else {
|
|
187
|
+
this.$emit('loadImage', res.tempFilePath);
|
|
188
|
+
}
|
|
189
|
+
},
|
|
190
|
+
});
|
|
191
|
+
},
|
|
192
|
+
},
|
|
193
|
+
};
|
|
194
|
+
</script>
|
|
195
|
+
|
|
196
|
+
<style>
|
|
197
|
+
.ste-barcode-root {
|
|
198
|
+
width: fit-content;
|
|
199
|
+
display: flex;
|
|
200
|
+
justify-content: center;
|
|
201
|
+
align-items: center;
|
|
202
|
+
}
|
|
203
|
+
</style>
|
|
@@ -1,218 +1,218 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<view class="ste-qrcode-root" :style="{ width: `${size}px`, height: `${size}px` }">
|
|
3
|
-
<view class="canvas-wrapper">
|
|
4
|
-
<!-- #ifdef H5 -->
|
|
5
|
-
<canvas :style="[compCanvasStyle]" :canvas-id="canvasId" :id="canvasId" class="h5-canvas"></canvas>
|
|
6
|
-
<!-- #endif -->
|
|
7
|
-
|
|
8
|
-
<!-- #ifdef MP-WEIXIN || MP-ALIPAY -->
|
|
9
|
-
<canvas type="2d" :id="canvasId" :style="[compCanvasStyle]" class="mp-canvas"></canvas>
|
|
10
|
-
<!-- #endif -->
|
|
11
|
-
</view>
|
|
12
|
-
</view>
|
|
13
|
-
</template>
|
|
14
|
-
|
|
15
|
-
<script>
|
|
16
|
-
/**
|
|
17
|
-
* ste-qrcode 二维码
|
|
18
|
-
* @description 二维码组件
|
|
19
|
-
* @tutorial https://stellar-ui.intecloud.com.cn/pc/index/index?name=ste-qrcode
|
|
20
|
-
* @property {String} content 二维码内容
|
|
21
|
-
* @property {Number} size 二维码尺寸,单位`px`
|
|
22
|
-
* @property {String} background 背景色
|
|
23
|
-
* @property {String} foreground 前景色(条形码画笔颜色)
|
|
24
|
-
* @property {String} foregroundImageSrc 二维码中间logo图
|
|
25
|
-
* @property {String} foregroundImageWidth logo图宽度, 默认二维码尺寸的四分之一
|
|
26
|
-
* @property {String} foregroundImageHeight logo图高度, 默认二维码尺寸的四分之一
|
|
27
|
-
* @event {Function} loadImage 加载完成后返回条形码对应的图片数据
|
|
28
|
-
*/
|
|
29
|
-
import UQRCode from './uqrcode';
|
|
30
|
-
import utils from '../../utils/utils';
|
|
31
|
-
|
|
32
|
-
export default {
|
|
33
|
-
group: '展示组件',
|
|
34
|
-
name: 'ste-qrcode',
|
|
35
|
-
title: 'QRcode 二维码',
|
|
36
|
-
options: {
|
|
37
|
-
virtualHost: true,
|
|
38
|
-
},
|
|
39
|
-
props: {
|
|
40
|
-
// 二维码内容
|
|
41
|
-
content: {
|
|
42
|
-
type: String,
|
|
43
|
-
required: true,
|
|
44
|
-
},
|
|
45
|
-
// 二维码尺寸
|
|
46
|
-
size: {
|
|
47
|
-
type: Number,
|
|
48
|
-
default: 100,
|
|
49
|
-
},
|
|
50
|
-
// 背景色
|
|
51
|
-
background: {
|
|
52
|
-
type: String,
|
|
53
|
-
default: '#FFFFFF',
|
|
54
|
-
},
|
|
55
|
-
// 前景色
|
|
56
|
-
foreground: {
|
|
57
|
-
type: String,
|
|
58
|
-
default: '#000000',
|
|
59
|
-
},
|
|
60
|
-
// 二维码logo
|
|
61
|
-
foregroundImageSrc: {
|
|
62
|
-
type: String,
|
|
63
|
-
default: '',
|
|
64
|
-
},
|
|
65
|
-
// logo尺寸 默认画布尺寸四分之一
|
|
66
|
-
foregroundImageWidth: {
|
|
67
|
-
type: Number,
|
|
68
|
-
default: null,
|
|
69
|
-
},
|
|
70
|
-
// logo尺寸 默认画布尺寸四分之一
|
|
71
|
-
foregroundImageHeight: {
|
|
72
|
-
type: Number,
|
|
73
|
-
default: null,
|
|
74
|
-
},
|
|
75
|
-
},
|
|
76
|
-
|
|
77
|
-
data() {
|
|
78
|
-
return {
|
|
79
|
-
canvasId: 'ste-qrcode-' + utils.guid(8),
|
|
80
|
-
canvasWidth: this.size,
|
|
81
|
-
canvasHeight: this.size,
|
|
82
|
-
};
|
|
83
|
-
},
|
|
84
|
-
mounted() {
|
|
85
|
-
this.initCanvas();
|
|
86
|
-
},
|
|
87
|
-
computed: {
|
|
88
|
-
compCanvasStyle() {
|
|
89
|
-
let style = {};
|
|
90
|
-
return {
|
|
91
|
-
width: this.canvasWidth + 'px',
|
|
92
|
-
height: this.canvasHeight + 'px',
|
|
93
|
-
transform: `scale(${this.size / this.canvasWidth}, ${this.size / this.canvasHeight})`,
|
|
94
|
-
};
|
|
95
|
-
},
|
|
96
|
-
},
|
|
97
|
-
watch: {
|
|
98
|
-
content: {
|
|
99
|
-
handler() {
|
|
100
|
-
this.initCanvas();
|
|
101
|
-
},
|
|
102
|
-
immediate: true,
|
|
103
|
-
},
|
|
104
|
-
},
|
|
105
|
-
methods: {
|
|
106
|
-
initCanvas() {
|
|
107
|
-
if (!this.content) return;
|
|
108
|
-
this.$nextTick(() => {
|
|
109
|
-
const canvas = utils.getCanvasContext(this.canvasId, this).then((res) => {
|
|
110
|
-
let context = res;
|
|
111
|
-
// #ifndef H5
|
|
112
|
-
context = res.getContext('2d');
|
|
113
|
-
// #endif
|
|
114
|
-
|
|
115
|
-
this.draw(context, res);
|
|
116
|
-
});
|
|
117
|
-
});
|
|
118
|
-
},
|
|
119
|
-
draw(ctx, canvas) {
|
|
120
|
-
const qr = new UQRCode();
|
|
121
|
-
qr.useDynamicSize = true;
|
|
122
|
-
|
|
123
|
-
qr.backgroundColor = this.background;
|
|
124
|
-
qr.foregroundColor = this.foreground;
|
|
125
|
-
qr.foregroundImageSrc = this.foregroundImageSrc ? `${this.foregroundImageSrc}?${new Date().getTime()}` : '';
|
|
126
|
-
this.foregroundImageWidth ? (qr.foregroundImageWidth = this.foregroundImageWidth) : '';
|
|
127
|
-
this.foregroundImageHeight ? (qr.foregroundImageHeight = this.foregroundImageHeight) : '';
|
|
128
|
-
// 设置二维码内容
|
|
129
|
-
qr.data = this.content;
|
|
130
|
-
// 设置二维码大小,必须与canvas设置的宽高一致
|
|
131
|
-
qr.size = this.size;
|
|
132
|
-
// 调用制作二维码方法
|
|
133
|
-
qr.make();
|
|
134
|
-
|
|
135
|
-
// #ifdef MP-WEIXIN || MP-ALIPAY
|
|
136
|
-
|
|
137
|
-
const dpr = utils.System.getWindowInfo().pixelRatio;
|
|
138
|
-
canvas.width = qr.dynamicSize * dpr;
|
|
139
|
-
canvas.height = qr.dynamicSize * dpr;
|
|
140
|
-
ctx.scale(dpr, dpr);
|
|
141
|
-
|
|
142
|
-
qr.loadImage = (src) => {
|
|
143
|
-
// 需要返回Promise对象,小程序下获取网络图片信息需先配置download域名白名单才能生效
|
|
144
|
-
return new Promise((resolve, reject) => {
|
|
145
|
-
var img = canvas.createImage();
|
|
146
|
-
img.src = src;
|
|
147
|
-
img.onload = () => {
|
|
148
|
-
// resolve返回img
|
|
149
|
-
resolve(img);
|
|
150
|
-
};
|
|
151
|
-
img.onerror = (err) => {
|
|
152
|
-
// reject返回错误信息
|
|
153
|
-
reject(err);
|
|
154
|
-
};
|
|
155
|
-
});
|
|
156
|
-
};
|
|
157
|
-
// #endif
|
|
158
|
-
|
|
159
|
-
// #ifdef H5
|
|
160
|
-
this.canvasWidth = qr.dynamicSize;
|
|
161
|
-
this.canvasHeight = qr.dynamicSize;
|
|
162
|
-
|
|
163
|
-
qr.loadImage = (src) => {
|
|
164
|
-
// 需要返回Promise对象
|
|
165
|
-
return new Promise((resolve, reject) => {
|
|
166
|
-
uni.getImageInfo({
|
|
167
|
-
src,
|
|
168
|
-
success: (res) => {
|
|
169
|
-
resolve(res.path);
|
|
170
|
-
},
|
|
171
|
-
fail: (err) => {
|
|
172
|
-
// reject返回错误信息
|
|
173
|
-
reject(err);
|
|
174
|
-
},
|
|
175
|
-
});
|
|
176
|
-
});
|
|
177
|
-
};
|
|
178
|
-
|
|
179
|
-
// #endif
|
|
180
|
-
|
|
181
|
-
// 设置uQRCode实例的canvas上下文
|
|
182
|
-
qr.canvasContext = ctx;
|
|
183
|
-
// 调用绘制方法将二维码图案绘制到canvas上
|
|
184
|
-
setTimeout(() => {
|
|
185
|
-
qr.drawCanvas().then(() => {
|
|
186
|
-
setTimeout(() => {
|
|
187
|
-
uni.canvasToTempFilePath({
|
|
188
|
-
canvas: canvas,
|
|
189
|
-
canvasId: this.canvasId,
|
|
190
|
-
|
|
191
|
-
complete: (res) => {
|
|
192
|
-
if (!res || !res.tempFilePath) {
|
|
193
|
-
console.error('图片生成失败');
|
|
194
|
-
} else {
|
|
195
|
-
this.$emit('loadImage', res.tempFilePath);
|
|
196
|
-
}
|
|
197
|
-
},
|
|
198
|
-
});
|
|
199
|
-
}, 1500);
|
|
200
|
-
});
|
|
201
|
-
}, 300);
|
|
202
|
-
},
|
|
203
|
-
},
|
|
204
|
-
};
|
|
205
|
-
</script>
|
|
206
|
-
|
|
207
|
-
<style lang="scss" scoped>
|
|
208
|
-
.ste-qrcode-root {
|
|
209
|
-
// width: fit-content;
|
|
210
|
-
// display: flex;
|
|
211
|
-
// justify-content: center;
|
|
212
|
-
// align-items: center;
|
|
213
|
-
position: relative;
|
|
214
|
-
.h5-canvas {
|
|
215
|
-
transform-origin: top left;
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
</style>
|
|
1
|
+
<template>
|
|
2
|
+
<view class="ste-qrcode-root" :style="{ width: `${size}px`, height: `${size}px` }">
|
|
3
|
+
<view class="canvas-wrapper">
|
|
4
|
+
<!-- #ifdef H5 || APP -->
|
|
5
|
+
<canvas :style="[compCanvasStyle]" :canvas-id="canvasId" :id="canvasId" class="h5-canvas"></canvas>
|
|
6
|
+
<!-- #endif -->
|
|
7
|
+
|
|
8
|
+
<!-- #ifdef MP-WEIXIN || MP-ALIPAY -->
|
|
9
|
+
<canvas type="2d" :id="canvasId" :style="[compCanvasStyle]" class="mp-canvas"></canvas>
|
|
10
|
+
<!-- #endif -->
|
|
11
|
+
</view>
|
|
12
|
+
</view>
|
|
13
|
+
</template>
|
|
14
|
+
|
|
15
|
+
<script>
|
|
16
|
+
/**
|
|
17
|
+
* ste-qrcode 二维码
|
|
18
|
+
* @description 二维码组件
|
|
19
|
+
* @tutorial https://stellar-ui.intecloud.com.cn/pc/index/index?name=ste-qrcode
|
|
20
|
+
* @property {String} content 二维码内容
|
|
21
|
+
* @property {Number} size 二维码尺寸,单位`px`
|
|
22
|
+
* @property {String} background 背景色
|
|
23
|
+
* @property {String} foreground 前景色(条形码画笔颜色)
|
|
24
|
+
* @property {String} foregroundImageSrc 二维码中间logo图
|
|
25
|
+
* @property {String} foregroundImageWidth logo图宽度, 默认二维码尺寸的四分之一
|
|
26
|
+
* @property {String} foregroundImageHeight logo图高度, 默认二维码尺寸的四分之一
|
|
27
|
+
* @event {Function} loadImage 加载完成后返回条形码对应的图片数据
|
|
28
|
+
*/
|
|
29
|
+
import UQRCode from './uqrcode';
|
|
30
|
+
import utils from '../../utils/utils';
|
|
31
|
+
|
|
32
|
+
export default {
|
|
33
|
+
group: '展示组件',
|
|
34
|
+
name: 'ste-qrcode',
|
|
35
|
+
title: 'QRcode 二维码',
|
|
36
|
+
options: {
|
|
37
|
+
virtualHost: true,
|
|
38
|
+
},
|
|
39
|
+
props: {
|
|
40
|
+
// 二维码内容
|
|
41
|
+
content: {
|
|
42
|
+
type: String,
|
|
43
|
+
required: true,
|
|
44
|
+
},
|
|
45
|
+
// 二维码尺寸
|
|
46
|
+
size: {
|
|
47
|
+
type: Number,
|
|
48
|
+
default: 100,
|
|
49
|
+
},
|
|
50
|
+
// 背景色
|
|
51
|
+
background: {
|
|
52
|
+
type: String,
|
|
53
|
+
default: '#FFFFFF',
|
|
54
|
+
},
|
|
55
|
+
// 前景色
|
|
56
|
+
foreground: {
|
|
57
|
+
type: String,
|
|
58
|
+
default: '#000000',
|
|
59
|
+
},
|
|
60
|
+
// 二维码logo
|
|
61
|
+
foregroundImageSrc: {
|
|
62
|
+
type: String,
|
|
63
|
+
default: '',
|
|
64
|
+
},
|
|
65
|
+
// logo尺寸 默认画布尺寸四分之一
|
|
66
|
+
foregroundImageWidth: {
|
|
67
|
+
type: Number,
|
|
68
|
+
default: null,
|
|
69
|
+
},
|
|
70
|
+
// logo尺寸 默认画布尺寸四分之一
|
|
71
|
+
foregroundImageHeight: {
|
|
72
|
+
type: Number,
|
|
73
|
+
default: null,
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
|
|
77
|
+
data() {
|
|
78
|
+
return {
|
|
79
|
+
canvasId: 'ste-qrcode-' + utils.guid(8),
|
|
80
|
+
canvasWidth: this.size,
|
|
81
|
+
canvasHeight: this.size,
|
|
82
|
+
};
|
|
83
|
+
},
|
|
84
|
+
mounted() {
|
|
85
|
+
this.initCanvas();
|
|
86
|
+
},
|
|
87
|
+
computed: {
|
|
88
|
+
compCanvasStyle() {
|
|
89
|
+
let style = {};
|
|
90
|
+
return {
|
|
91
|
+
width: this.canvasWidth + 'px',
|
|
92
|
+
height: this.canvasHeight + 'px',
|
|
93
|
+
transform: `scale(${this.size / this.canvasWidth}, ${this.size / this.canvasHeight})`,
|
|
94
|
+
};
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
watch: {
|
|
98
|
+
content: {
|
|
99
|
+
handler() {
|
|
100
|
+
this.initCanvas();
|
|
101
|
+
},
|
|
102
|
+
immediate: true,
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
methods: {
|
|
106
|
+
initCanvas() {
|
|
107
|
+
if (!this.content) return;
|
|
108
|
+
this.$nextTick(() => {
|
|
109
|
+
const canvas = utils.getCanvasContext(this.canvasId, this).then((res) => {
|
|
110
|
+
let context = res;
|
|
111
|
+
// #ifndef H5 || APP
|
|
112
|
+
context = res.getContext('2d');
|
|
113
|
+
// #endif
|
|
114
|
+
|
|
115
|
+
this.draw(context, res);
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
},
|
|
119
|
+
draw(ctx, canvas) {
|
|
120
|
+
const qr = new UQRCode();
|
|
121
|
+
qr.useDynamicSize = true;
|
|
122
|
+
|
|
123
|
+
qr.backgroundColor = this.background;
|
|
124
|
+
qr.foregroundColor = this.foreground;
|
|
125
|
+
qr.foregroundImageSrc = this.foregroundImageSrc ? `${this.foregroundImageSrc}?${new Date().getTime()}` : '';
|
|
126
|
+
this.foregroundImageWidth ? (qr.foregroundImageWidth = this.foregroundImageWidth) : '';
|
|
127
|
+
this.foregroundImageHeight ? (qr.foregroundImageHeight = this.foregroundImageHeight) : '';
|
|
128
|
+
// 设置二维码内容
|
|
129
|
+
qr.data = this.content;
|
|
130
|
+
// 设置二维码大小,必须与canvas设置的宽高一致
|
|
131
|
+
qr.size = this.size;
|
|
132
|
+
// 调用制作二维码方法
|
|
133
|
+
qr.make();
|
|
134
|
+
|
|
135
|
+
// #ifdef MP-WEIXIN || MP-ALIPAY
|
|
136
|
+
|
|
137
|
+
const dpr = utils.System.getWindowInfo().pixelRatio;
|
|
138
|
+
canvas.width = qr.dynamicSize * dpr;
|
|
139
|
+
canvas.height = qr.dynamicSize * dpr;
|
|
140
|
+
ctx.scale(dpr, dpr);
|
|
141
|
+
|
|
142
|
+
qr.loadImage = (src) => {
|
|
143
|
+
// 需要返回Promise对象,小程序下获取网络图片信息需先配置download域名白名单才能生效
|
|
144
|
+
return new Promise((resolve, reject) => {
|
|
145
|
+
var img = canvas.createImage();
|
|
146
|
+
img.src = src;
|
|
147
|
+
img.onload = () => {
|
|
148
|
+
// resolve返回img
|
|
149
|
+
resolve(img);
|
|
150
|
+
};
|
|
151
|
+
img.onerror = (err) => {
|
|
152
|
+
// reject返回错误信息
|
|
153
|
+
reject(err);
|
|
154
|
+
};
|
|
155
|
+
});
|
|
156
|
+
};
|
|
157
|
+
// #endif
|
|
158
|
+
|
|
159
|
+
// #ifdef H5 || APP
|
|
160
|
+
this.canvasWidth = qr.dynamicSize;
|
|
161
|
+
this.canvasHeight = qr.dynamicSize;
|
|
162
|
+
|
|
163
|
+
qr.loadImage = (src) => {
|
|
164
|
+
// 需要返回Promise对象
|
|
165
|
+
return new Promise((resolve, reject) => {
|
|
166
|
+
uni.getImageInfo({
|
|
167
|
+
src,
|
|
168
|
+
success: (res) => {
|
|
169
|
+
resolve(res.path);
|
|
170
|
+
},
|
|
171
|
+
fail: (err) => {
|
|
172
|
+
// reject返回错误信息
|
|
173
|
+
reject(err);
|
|
174
|
+
},
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
// #endif
|
|
180
|
+
|
|
181
|
+
// 设置uQRCode实例的canvas上下文
|
|
182
|
+
qr.canvasContext = ctx;
|
|
183
|
+
// 调用绘制方法将二维码图案绘制到canvas上
|
|
184
|
+
setTimeout(() => {
|
|
185
|
+
qr.drawCanvas().then(() => {
|
|
186
|
+
setTimeout(() => {
|
|
187
|
+
uni.canvasToTempFilePath({
|
|
188
|
+
canvas: canvas,
|
|
189
|
+
canvasId: this.canvasId,
|
|
190
|
+
|
|
191
|
+
complete: (res) => {
|
|
192
|
+
if (!res || !res.tempFilePath) {
|
|
193
|
+
console.error('图片生成失败');
|
|
194
|
+
} else {
|
|
195
|
+
this.$emit('loadImage', res.tempFilePath);
|
|
196
|
+
}
|
|
197
|
+
},
|
|
198
|
+
});
|
|
199
|
+
}, 1500);
|
|
200
|
+
});
|
|
201
|
+
}, 300);
|
|
202
|
+
},
|
|
203
|
+
},
|
|
204
|
+
};
|
|
205
|
+
</script>
|
|
206
|
+
|
|
207
|
+
<style lang="scss" scoped>
|
|
208
|
+
.ste-qrcode-root {
|
|
209
|
+
// width: fit-content;
|
|
210
|
+
// display: flex;
|
|
211
|
+
// justify-content: center;
|
|
212
|
+
// align-items: center;
|
|
213
|
+
position: relative;
|
|
214
|
+
.h5-canvas {
|
|
215
|
+
transform-origin: top left;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
</style>
|
package/package.json
CHANGED
package/utils/utils.js
CHANGED
|
@@ -441,14 +441,7 @@ let utils = {
|
|
|
441
441
|
* @param {String} childrenKey 下级数组键
|
|
442
442
|
* @param {Object | Function} otherAttributes 为每个对象添加的属性(可以是一个方法,参数是当前节点,返回的对象属性会被添加到当前节点中)
|
|
443
443
|
*/
|
|
444
|
-
formatTree(
|
|
445
|
-
tree,
|
|
446
|
-
valueKey = 'value',
|
|
447
|
-
childrenKey = 'children',
|
|
448
|
-
otherAttributes = {},
|
|
449
|
-
parentNode = '__root__',
|
|
450
|
-
depth = 0
|
|
451
|
-
) {
|
|
444
|
+
formatTree(tree, valueKey = 'value', childrenKey = 'children', otherAttributes = {}, parentNode = '__root__', depth = 0) {
|
|
452
445
|
const _formatTree = (tree, parentNode, depth) => {
|
|
453
446
|
const result = tree.map((item) => {
|
|
454
447
|
if (item[childrenKey] && item[childrenKey].length) {
|
|
@@ -622,12 +615,12 @@ let utils = {
|
|
|
622
615
|
getCanvasContext(canvasId, component) {
|
|
623
616
|
return new Promise((resolve, reject) => {
|
|
624
617
|
if (!canvasId || !component) reject();
|
|
625
|
-
// #ifdef H5
|
|
618
|
+
// #ifdef H5 || APP
|
|
626
619
|
resolve(uni.createCanvasContext(canvasId, component));
|
|
627
620
|
// #endif
|
|
628
621
|
|
|
629
622
|
// 小程序平台
|
|
630
|
-
// #ifndef H5
|
|
623
|
+
// #ifndef H5 || APP
|
|
631
624
|
const query = uni.createSelectorQuery().in(component);
|
|
632
625
|
query
|
|
633
626
|
.select(`#${canvasId}`)
|