uview-plus 3.8.86 → 3.8.106
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/changelog.md +150 -3
- package/components/u-action-sheet/u-action-sheet.vue +21 -2
- package/components/u-barcode/u-barcode.vue +0 -2
- package/components/u-button/u-button.vue +2 -5
- package/components/u-canvas/u-canvas.vue +368 -74
- package/components/u-cell/u-cell.vue +8 -0
- package/components/u-datetime-picker/u-datetime-picker.vue +53 -4
- package/components/u-dragsort/u-dragsort.vue +55 -31
- package/components/u-icon/u-icon.vue +12 -3
- package/components/u-icon/util.js +81 -10
- package/components/u-index-item/u-index-item.vue +1 -1
- package/components/u-index-list/u-index-list.vue +1 -1
- package/components/u-novel-reader/content-normalizer.js +80 -0
- package/components/u-novel-reader/layout-engine.js +225 -0
- package/components/u-novel-reader/measure-adapter.js +69 -0
- package/components/u-novel-reader/novelReader.js +35 -0
- package/components/u-novel-reader/persistence.js +144 -0
- package/components/u-novel-reader/props.js +100 -0
- package/components/u-novel-reader/reader-catalog.vue +234 -0
- package/components/u-novel-reader/reader-content.vue +226 -0
- package/components/u-novel-reader/reader-core.js +151 -0
- package/components/u-novel-reader/reader-settings.vue +325 -0
- package/components/u-novel-reader/reader-toolbar.vue +313 -0
- package/components/u-novel-reader/theme-vars.scss +49 -0
- package/components/u-novel-reader/u-novel-reader.vue +836 -0
- package/components/u-poster/u-poster.vue +236 -219
- package/components/u-qrcode/qrcode.js +56 -49
- package/components/u-qrcode/u-qrcode.vue +159 -88
- package/components/u-scroll-list/scrollWxs.wxs +1 -1
- package/components/u-slider/u-slider.vue +1 -1
- package/components/u-swipe-action-item/index.wxs +43 -25
- package/components/u-swipe-action-item/nvue.js +9 -0
- package/components/u-swipe-action-item/other.js +32 -21
- package/components/u-swipe-action-item/props.js +5 -0
- package/components/u-swipe-action-item/swipeActionItem.js +1 -0
- package/components/u-swipe-action-item/u-swipe-action-item.vue +28 -4
- package/components/u-switch/u-switch.vue +1 -1
- package/components/u-tabbar/u-tabbar.vue +2 -1
- package/components/u-tabbar-item/u-tabbar-item.vue +64 -21
- package/components/u-tabs/u-tabs.vue +11 -8
- package/components/u-tabs-pro/u-tabs-pro.vue +212 -0
- package/components/u-text/text.js +1 -1
- package/components/u-text/u-text.vue +18 -6
- package/components/u-upload/u-upload.vue +1 -1
- package/components/u-waterfall/u-waterfall.vue +118 -65
- package/libs/config/config.js +1 -1
- package/libs/config/props.js +1 -0
- package/libs/function/index.js +66 -0
- package/libs/mixin/mixin.js +4 -50
- package/libs/root/index.js +78 -5
- package/libs/root/page.js +7 -7
- package/libs/root/root.js +73 -3
- package/libs/util/app-nvue-webview-canvas.js +486 -0
- package/libs/util/gcanvas/bridge/bridge-weex.js +0 -2
- package/libs/util/gcanvas/context-2d/FillStyleLinearGradient.js +0 -0
- package/libs/util/gcanvas/context-2d/FillStylePattern.js +0 -0
- package/libs/util/gcanvas/context-2d/FillStyleRadialGradient.js +0 -0
- package/libs/util/gcanvas/context-2d/RenderingContext.js +0 -0
- package/libs/util/gcanvas/context-webgl/ActiveInfo.js +0 -0
- package/libs/util/gcanvas/context-webgl/Buffer.js +0 -0
- package/libs/util/gcanvas/context-webgl/Framebuffer.js +0 -0
- package/libs/util/gcanvas/context-webgl/GLenum.js +0 -0
- package/libs/util/gcanvas/context-webgl/GLmethod.js +0 -0
- package/libs/util/gcanvas/context-webgl/GLtype.js +0 -0
- package/libs/util/gcanvas/context-webgl/Program.js +0 -0
- package/libs/util/gcanvas/context-webgl/Renderbuffer.js +0 -0
- package/libs/util/gcanvas/context-webgl/RenderingContext.js +0 -0
- package/libs/util/gcanvas/context-webgl/Shader.js +0 -0
- package/libs/util/gcanvas/context-webgl/ShaderPrecisionFormat.js +0 -0
- package/libs/util/gcanvas/context-webgl/Texture.js +0 -0
- package/libs/util/gcanvas/context-webgl/UniformLocation.js +0 -0
- package/libs/util/gcanvas/context-webgl/classUtils.js +0 -0
- package/libs/util/gcanvas/env/canvas.js +0 -0
- package/libs/util/gcanvas/env/image.js +0 -0
- package/libs/util/gcanvas/env/tool.js +0 -0
- package/libs/util/gcanvas/index.js +3 -3
- package/package.json +1 -1
- package/types/comps/swipeActionItem.d.ts +13 -0
- package/types/comps/tabs.d.ts +2 -1
- package/types/comps/text.d.ts +1 -1
- package/types/func.d.ts +23 -0
- package/types/index.d.ts +1 -0
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
<!-- #endif -->
|
|
23
23
|
|
|
24
24
|
<!-- #ifdef APP-PLUS -->
|
|
25
|
+
<!-- #ifndef APP-NVUE -->
|
|
25
26
|
<canvas
|
|
26
27
|
class="u-canvas__canvas"
|
|
27
28
|
:id="canvasId"
|
|
@@ -33,15 +34,15 @@
|
|
|
33
34
|
@touchend="onTouchEnd"
|
|
34
35
|
/>
|
|
35
36
|
<!-- #endif -->
|
|
37
|
+
<!-- #endif -->
|
|
36
38
|
|
|
37
39
|
<!-- #ifdef APP-NVUE -->
|
|
38
|
-
<
|
|
40
|
+
<web-view
|
|
39
41
|
class="u-canvas__canvas"
|
|
40
|
-
ref="
|
|
42
|
+
ref="web"
|
|
43
|
+
src="/static/app-plus/up-canvas/local.html"
|
|
41
44
|
:style="{ width: actualWidth + unit, height: actualHeight + unit }"
|
|
42
|
-
@
|
|
43
|
-
@touchmove="onTouchMove"
|
|
44
|
-
@touchend="onTouchEnd"
|
|
45
|
+
@onPostMessage="onWebViewMessage"
|
|
45
46
|
/>
|
|
46
47
|
<!-- #endif -->
|
|
47
48
|
</view>
|
|
@@ -50,10 +51,9 @@
|
|
|
50
51
|
<script>
|
|
51
52
|
// #ifdef APP-NVUE
|
|
52
53
|
import {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
} from '../../libs/util/gcanvas/index.js';
|
|
54
|
+
createWebViewCanvasBridge,
|
|
55
|
+
createWebViewCanvasContext
|
|
56
|
+
} from '../../libs/util/app-nvue-webview-canvas.js';
|
|
57
57
|
// #endif
|
|
58
58
|
|
|
59
59
|
export default {
|
|
@@ -125,13 +125,27 @@ export default {
|
|
|
125
125
|
this._selectorResult = null;
|
|
126
126
|
this._canvasElement = null;
|
|
127
127
|
this._imageCache = Object.create(null);
|
|
128
|
+
this._imageDataCache = Object.create(null);
|
|
128
129
|
this._isNvue = false;
|
|
130
|
+
this._initPromise = null;
|
|
131
|
+
this._webViewBridge = null;
|
|
132
|
+
this._webViewContext = null;
|
|
133
|
+
this._webViewInitSignature = null;
|
|
134
|
+
this._webViewSessionId = null;
|
|
129
135
|
},
|
|
130
136
|
mounted() {
|
|
131
137
|
this.$nextTick(() => {
|
|
132
138
|
this.initCanvas();
|
|
133
139
|
});
|
|
134
140
|
},
|
|
141
|
+
beforeUnmount() {
|
|
142
|
+
if (this._webViewBridge) {
|
|
143
|
+
this._webViewBridge.destroy();
|
|
144
|
+
}
|
|
145
|
+
this._webViewBridge = null;
|
|
146
|
+
this._webViewContext = null;
|
|
147
|
+
this.ctx = null;
|
|
148
|
+
},
|
|
135
149
|
methods: {
|
|
136
150
|
parseSize(value) {
|
|
137
151
|
if (typeof value === 'number') {
|
|
@@ -157,22 +171,29 @@ export default {
|
|
|
157
171
|
onTouchEnd(event) {
|
|
158
172
|
this.$emit('touchend', event);
|
|
159
173
|
},
|
|
174
|
+
onWebViewMessage(event) {
|
|
175
|
+
if (this._webViewBridge) {
|
|
176
|
+
this._webViewBridge.handleMessage(event);
|
|
177
|
+
}
|
|
178
|
+
},
|
|
179
|
+
onWebViewTouch(message) {
|
|
180
|
+
const eventType = message.eventType;
|
|
181
|
+
if (!['touchstart', 'touchmove', 'touchend'].includes(eventType)) return;
|
|
182
|
+
this.$emit(eventType, {
|
|
183
|
+
type: eventType,
|
|
184
|
+
detail: {
|
|
185
|
+
x: message.x,
|
|
186
|
+
y: message.y
|
|
187
|
+
},
|
|
188
|
+
touches: message.touches || [],
|
|
189
|
+
changedTouches: message.changedTouches || [],
|
|
190
|
+
canvasWidth: message.canvasWidth,
|
|
191
|
+
canvasHeight: message.canvasHeight
|
|
192
|
+
});
|
|
193
|
+
},
|
|
160
194
|
async getCanvasNode(id = this.canvasId, isCanvas = true) {
|
|
161
195
|
return new Promise((resolve) => {
|
|
162
196
|
try {
|
|
163
|
-
// #ifdef APP-NVUE
|
|
164
|
-
setTimeout(() => {
|
|
165
|
-
const gcanvas = this.$refs.gcanvas;
|
|
166
|
-
if (!gcanvas) {
|
|
167
|
-
resolve(false);
|
|
168
|
-
return;
|
|
169
|
-
}
|
|
170
|
-
this._isNvue = true;
|
|
171
|
-
resolve(enable(gcanvas, { bridge: WeexBridge }));
|
|
172
|
-
}, 100);
|
|
173
|
-
// #endif
|
|
174
|
-
|
|
175
|
-
// #ifndef APP-NVUE
|
|
176
197
|
uni.createSelectorQuery()
|
|
177
198
|
.in(this)
|
|
178
199
|
.select(`#${id}`)
|
|
@@ -182,11 +203,18 @@ export default {
|
|
|
182
203
|
size: true
|
|
183
204
|
},
|
|
184
205
|
(res) => {
|
|
206
|
+
// #ifdef APP-PLUS
|
|
207
|
+
resolve(res || {
|
|
208
|
+
width: this.actualWidth,
|
|
209
|
+
height: this.actualHeight
|
|
210
|
+
});
|
|
211
|
+
return;
|
|
212
|
+
// #endif
|
|
213
|
+
|
|
185
214
|
resolve(res || false);
|
|
186
215
|
}
|
|
187
216
|
)
|
|
188
217
|
.exec();
|
|
189
|
-
// #endif
|
|
190
218
|
} catch (error) {
|
|
191
219
|
console.error('获取画布节点失败:', error);
|
|
192
220
|
resolve(false);
|
|
@@ -200,14 +228,12 @@ export default {
|
|
|
200
228
|
return this.ctx;
|
|
201
229
|
},
|
|
202
230
|
getCanvasContext() {
|
|
203
|
-
// #ifdef APP-
|
|
204
|
-
return
|
|
231
|
+
// #ifdef APP-NVUE
|
|
232
|
+
return this._webViewContext;
|
|
205
233
|
// #endif
|
|
206
234
|
|
|
207
|
-
// #ifdef APP-
|
|
208
|
-
return this.
|
|
209
|
-
? this._canvasElement.getContext('2d')
|
|
210
|
-
: null;
|
|
235
|
+
// #ifdef APP-PLUS
|
|
236
|
+
return uni.createCanvasContext(this.canvasId, this);
|
|
211
237
|
// #endif
|
|
212
238
|
|
|
213
239
|
// #ifdef MP || H5
|
|
@@ -229,10 +255,32 @@ export default {
|
|
|
229
255
|
}
|
|
230
256
|
},
|
|
231
257
|
async initCanvas(force = false) {
|
|
258
|
+
if (this._initPromise) {
|
|
259
|
+
return this._initPromise;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
const initPromise = this._initializeCanvas(force);
|
|
263
|
+
this._initPromise = initPromise;
|
|
264
|
+
|
|
265
|
+
try {
|
|
266
|
+
return await initPromise;
|
|
267
|
+
} finally {
|
|
268
|
+
if (this._initPromise === initPromise) {
|
|
269
|
+
this._initPromise = null;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
},
|
|
273
|
+
async _initializeCanvas(force = false) {
|
|
232
274
|
try {
|
|
233
275
|
if (this.useRootHeightAndWidth) {
|
|
234
276
|
await this.setNewSize();
|
|
235
277
|
}
|
|
278
|
+
// #ifdef APP-NVUE
|
|
279
|
+
if (typeof createWebViewCanvasBridge === 'function') {
|
|
280
|
+
return await this._initializeWebViewCanvas(force);
|
|
281
|
+
}
|
|
282
|
+
// #endif
|
|
283
|
+
|
|
236
284
|
if (this.ctx && !force) {
|
|
237
285
|
this.$emit('ready', {
|
|
238
286
|
width: this.actualWidth,
|
|
@@ -247,10 +295,17 @@ export default {
|
|
|
247
295
|
}
|
|
248
296
|
|
|
249
297
|
this._selectorResult = this._canvasNode;
|
|
250
|
-
this._canvasElement = this.
|
|
251
|
-
|
|
298
|
+
this._canvasElement = this._isNvue
|
|
299
|
+
? this._canvasNode
|
|
300
|
+
: (this._canvasNode.node || null);
|
|
301
|
+
const systemInfo = uni.getSystemInfoSync() || {};
|
|
302
|
+
const pixelRatio = Number(systemInfo.pixelRatio) || 1;
|
|
303
|
+
// 微信开发者工具的模拟器预览通常按高密度屏幕缩放,至少使用 2 倍 backing store。
|
|
304
|
+
this.dpr = systemInfo.platform === 'devtools'
|
|
305
|
+
? Math.max(pixelRatio, 2)
|
|
306
|
+
: pixelRatio;
|
|
252
307
|
|
|
253
|
-
// #ifdef MP
|
|
308
|
+
// #ifdef MP
|
|
254
309
|
if (this._canvasElement) {
|
|
255
310
|
this._canvasElement.width = Math.ceil(this.actualWidth * this.dpr);
|
|
256
311
|
this._canvasElement.height = Math.ceil(this.actualHeight * this.dpr);
|
|
@@ -262,7 +317,7 @@ export default {
|
|
|
262
317
|
return false;
|
|
263
318
|
}
|
|
264
319
|
|
|
265
|
-
// #ifdef MP
|
|
320
|
+
// #ifdef MP
|
|
266
321
|
if (typeof this.ctx.setTransform === 'function') {
|
|
267
322
|
this.ctx.setTransform(this.dpr, 0, 0, this.dpr, 0, 0);
|
|
268
323
|
} else if (typeof this.ctx.scale === 'function') {
|
|
@@ -282,6 +337,64 @@ export default {
|
|
|
282
337
|
return false;
|
|
283
338
|
}
|
|
284
339
|
},
|
|
340
|
+
async _initializeWebViewCanvas(force = false) {
|
|
341
|
+
this._isNvue = true;
|
|
342
|
+
const systemInfo = uni.getSystemInfoSync() || {};
|
|
343
|
+
this.dpr = Math.max(1, Number(systemInfo.pixelRatio) || 1);
|
|
344
|
+
|
|
345
|
+
if (!this._webViewBridge) {
|
|
346
|
+
this._webViewBridge = createWebViewCanvasBridge({
|
|
347
|
+
getWebView: () => this.$refs.web,
|
|
348
|
+
onTouch: message => this.onWebViewTouch(message),
|
|
349
|
+
onReady: (message) => {
|
|
350
|
+
if (
|
|
351
|
+
this._webViewSessionId &&
|
|
352
|
+
message.sessionId &&
|
|
353
|
+
this._webViewSessionId !== message.sessionId
|
|
354
|
+
) {
|
|
355
|
+
this._webViewInitSignature = null;
|
|
356
|
+
}
|
|
357
|
+
this._webViewSessionId = message.sessionId || null;
|
|
358
|
+
},
|
|
359
|
+
onError: error => console.error('Canvas WebView错误:', error)
|
|
360
|
+
});
|
|
361
|
+
this._webViewContext = createWebViewCanvasContext({
|
|
362
|
+
bridge: this._webViewBridge,
|
|
363
|
+
resolveImage: source => this.resolveNvueImageSource(source),
|
|
364
|
+
measureText: (text, state) => {
|
|
365
|
+
const matched = String(state.font || '').match(/(\d+(?:\.\d+)?)px/);
|
|
366
|
+
const fontSize = matched ? Number(matched[1]) : this.fontSize;
|
|
367
|
+
return { width: String(text).length * fontSize * 0.6 };
|
|
368
|
+
}
|
|
369
|
+
});
|
|
370
|
+
this.ctx = this._webViewContext;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
await this._webViewBridge.ready();
|
|
374
|
+
const signature = [
|
|
375
|
+
this.actualWidth,
|
|
376
|
+
this.actualHeight,
|
|
377
|
+
this.dpr,
|
|
378
|
+
this.disableScroll ? 1 : 0
|
|
379
|
+
].join(':');
|
|
380
|
+
if (force || this._webViewInitSignature !== signature) {
|
|
381
|
+
await this._webViewBridge.request('init', {
|
|
382
|
+
width: this.actualWidth,
|
|
383
|
+
height: this.actualHeight,
|
|
384
|
+
dpr: this.dpr,
|
|
385
|
+
disableScroll: this.disableScroll
|
|
386
|
+
});
|
|
387
|
+
this._webViewInitSignature = signature;
|
|
388
|
+
this.applyFont();
|
|
389
|
+
await this.clearCanvas();
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
this.$emit('ready', {
|
|
393
|
+
width: this.actualWidth,
|
|
394
|
+
height: this.actualHeight
|
|
395
|
+
});
|
|
396
|
+
return true;
|
|
397
|
+
},
|
|
285
398
|
refresh() {
|
|
286
399
|
return this.initCanvas(true);
|
|
287
400
|
},
|
|
@@ -300,7 +413,7 @@ export default {
|
|
|
300
413
|
this.setFillStyle(this.bgColor);
|
|
301
414
|
this.fill();
|
|
302
415
|
}
|
|
303
|
-
this.draw();
|
|
416
|
+
return this.draw();
|
|
304
417
|
},
|
|
305
418
|
callContext(method, ...args) {
|
|
306
419
|
if (this.ctx && typeof this.ctx[method] === 'function') {
|
|
@@ -341,12 +454,28 @@ export default {
|
|
|
341
454
|
arc(x, y, radius, startAngle, endAngle, anticlockwise = false) {
|
|
342
455
|
return this.callContext('arc', x, y, radius, startAngle, endAngle, anticlockwise);
|
|
343
456
|
},
|
|
457
|
+
arcTo(x1, y1, x2, y2, radius) {
|
|
458
|
+
return this.callContext('arcTo', x1, y1, x2, y2, radius);
|
|
459
|
+
},
|
|
344
460
|
bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y) {
|
|
345
461
|
return this.callContext('bezierCurveTo', cp1x, cp1y, cp2x, cp2y, x, y);
|
|
346
462
|
},
|
|
347
463
|
quadraticCurveTo(cpx, cpy, x, y) {
|
|
348
464
|
return this.callContext('quadraticCurveTo', cpx, cpy, x, y);
|
|
349
465
|
},
|
|
466
|
+
ellipse(x, y, radiusX, radiusY, rotation, startAngle, endAngle, anticlockwise = false) {
|
|
467
|
+
return this.callContext(
|
|
468
|
+
'ellipse',
|
|
469
|
+
x,
|
|
470
|
+
y,
|
|
471
|
+
radiusX,
|
|
472
|
+
radiusY,
|
|
473
|
+
rotation,
|
|
474
|
+
startAngle,
|
|
475
|
+
endAngle,
|
|
476
|
+
anticlockwise
|
|
477
|
+
);
|
|
478
|
+
},
|
|
350
479
|
clip() {
|
|
351
480
|
return this.callContext('clip');
|
|
352
481
|
},
|
|
@@ -365,6 +494,15 @@ export default {
|
|
|
365
494
|
scale(x, y) {
|
|
366
495
|
return this.callContext('scale', x, y);
|
|
367
496
|
},
|
|
497
|
+
setTransform(a, b, c, d, e, f) {
|
|
498
|
+
return this.callContext('setTransform', a, b, c, d, e, f);
|
|
499
|
+
},
|
|
500
|
+
transform(a, b, c, d, e, f) {
|
|
501
|
+
return this.callContext('transform', a, b, c, d, e, f);
|
|
502
|
+
},
|
|
503
|
+
resetTransform() {
|
|
504
|
+
return this.callContext('resetTransform');
|
|
505
|
+
},
|
|
368
506
|
setFillStyle(color) {
|
|
369
507
|
if (!this.ctx) return;
|
|
370
508
|
if (typeof this.ctx.setFillStyle === 'function') {
|
|
@@ -405,6 +543,21 @@ export default {
|
|
|
405
543
|
this.ctx.lineJoin = lineJoin;
|
|
406
544
|
}
|
|
407
545
|
},
|
|
546
|
+
setMiterLimit(miterLimit) {
|
|
547
|
+
if (!this.ctx) return;
|
|
548
|
+
if (typeof this.ctx.setMiterLimit === 'function') {
|
|
549
|
+
this.ctx.setMiterLimit(miterLimit);
|
|
550
|
+
} else {
|
|
551
|
+
this.ctx.miterLimit = miterLimit;
|
|
552
|
+
}
|
|
553
|
+
},
|
|
554
|
+
setLineDash(segments = []) {
|
|
555
|
+
return this.callContext('setLineDash', segments);
|
|
556
|
+
},
|
|
557
|
+
getLineDash() {
|
|
558
|
+
const result = this.callContext('getLineDash');
|
|
559
|
+
return Array.isArray(result) ? result : [];
|
|
560
|
+
},
|
|
408
561
|
setTextAlign(align = 'left') {
|
|
409
562
|
if (!this.ctx) return;
|
|
410
563
|
if (typeof this.ctx.setTextAlign === 'function') {
|
|
@@ -448,6 +601,14 @@ export default {
|
|
|
448
601
|
this.ctx.globalAlpha = alpha;
|
|
449
602
|
}
|
|
450
603
|
},
|
|
604
|
+
setGlobalCompositeOperation(operation) {
|
|
605
|
+
if (!this.ctx) return;
|
|
606
|
+
if (typeof this.ctx.setGlobalCompositeOperation === 'function') {
|
|
607
|
+
this.ctx.setGlobalCompositeOperation(operation);
|
|
608
|
+
} else {
|
|
609
|
+
this.ctx.globalCompositeOperation = operation;
|
|
610
|
+
}
|
|
611
|
+
},
|
|
451
612
|
setShadow(offsetX = 0, offsetY = 0, blur = 0, color = 'rgba(0,0,0,0)') {
|
|
452
613
|
if (!this.ctx) return;
|
|
453
614
|
if (typeof this.ctx.setShadow === 'function') {
|
|
@@ -479,6 +640,12 @@ export default {
|
|
|
479
640
|
fillText(text, x, y) {
|
|
480
641
|
return this.callContext('fillText', String(text), x, y);
|
|
481
642
|
},
|
|
643
|
+
strokeText(text, x, y, maxWidth) {
|
|
644
|
+
if (maxWidth === undefined) {
|
|
645
|
+
return this.callContext('strokeText', String(text), x, y);
|
|
646
|
+
}
|
|
647
|
+
return this.callContext('strokeText', String(text), x, y, maxWidth);
|
|
648
|
+
},
|
|
482
649
|
measureText(text) {
|
|
483
650
|
if (this.ctx && typeof this.ctx.measureText === 'function') {
|
|
484
651
|
return this.ctx.measureText(String(text));
|
|
@@ -487,6 +654,12 @@ export default {
|
|
|
487
654
|
width: String(text).length * this.fontSize * 0.6
|
|
488
655
|
};
|
|
489
656
|
},
|
|
657
|
+
measureTextAsync(text) {
|
|
658
|
+
if (this.ctx && typeof this.ctx.measureTextAsync === 'function') {
|
|
659
|
+
return this.ctx.measureTextAsync(String(text));
|
|
660
|
+
}
|
|
661
|
+
return Promise.resolve(this.measureText(text));
|
|
662
|
+
},
|
|
490
663
|
createLinearGradient(x0, y0, x1, y1) {
|
|
491
664
|
if (this.ctx && typeof this.ctx.createLinearGradient === 'function') {
|
|
492
665
|
return this.ctx.createLinearGradient(x0, y0, x1, y1);
|
|
@@ -499,17 +672,75 @@ export default {
|
|
|
499
672
|
}
|
|
500
673
|
return null;
|
|
501
674
|
},
|
|
675
|
+
createPattern(image, repetition = 'repeat') {
|
|
676
|
+
if (this.ctx && typeof this.ctx.createPattern === 'function') {
|
|
677
|
+
return this.ctx.createPattern(image, repetition);
|
|
678
|
+
}
|
|
679
|
+
return null;
|
|
680
|
+
},
|
|
681
|
+
async resolveNvueImageSource(src) {
|
|
682
|
+
if (typeof src !== 'string' || src.indexOf('data:image/') === 0) {
|
|
683
|
+
return src;
|
|
684
|
+
}
|
|
685
|
+
if (this._imageDataCache[src]) {
|
|
686
|
+
return this._imageDataCache[src];
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
const task = (async () => {
|
|
690
|
+
const localPath = await new Promise((resolve, reject) => {
|
|
691
|
+
uni.getImageInfo({
|
|
692
|
+
src,
|
|
693
|
+
success: res => resolve(res.path || res.tempFilePath),
|
|
694
|
+
fail: reject
|
|
695
|
+
});
|
|
696
|
+
});
|
|
697
|
+
if (!localPath) {
|
|
698
|
+
throw new Error(`Canvas图片未返回本地路径: ${src}`);
|
|
699
|
+
}
|
|
700
|
+
return this.readNvueFileAsDataURL(localPath);
|
|
701
|
+
})();
|
|
702
|
+
this._imageDataCache[src] = task;
|
|
703
|
+
try {
|
|
704
|
+
const dataUrl = await task;
|
|
705
|
+
this._imageDataCache[src] = dataUrl;
|
|
706
|
+
return dataUrl;
|
|
707
|
+
} catch (error) {
|
|
708
|
+
delete this._imageDataCache[src];
|
|
709
|
+
throw error;
|
|
710
|
+
}
|
|
711
|
+
},
|
|
712
|
+
readNvueFileAsDataURL(path) {
|
|
713
|
+
return new Promise((resolve, reject) => {
|
|
714
|
+
// #ifdef APP-NVUE
|
|
715
|
+
if (typeof plus === 'undefined' || !plus.io) {
|
|
716
|
+
reject(new Error('HTML5+ FileReader不可用'));
|
|
717
|
+
return;
|
|
718
|
+
}
|
|
719
|
+
plus.io.resolveLocalFileSystemURL(path, (entry) => {
|
|
720
|
+
entry.file((file) => {
|
|
721
|
+
const reader = new plus.io.FileReader();
|
|
722
|
+
reader.onloadend = event => resolve(event.target.result);
|
|
723
|
+
reader.onerror = reject;
|
|
724
|
+
reader.readAsDataURL(file);
|
|
725
|
+
}, reject);
|
|
726
|
+
}, reject);
|
|
727
|
+
return;
|
|
728
|
+
// #endif
|
|
729
|
+
|
|
730
|
+
resolve(path);
|
|
731
|
+
});
|
|
732
|
+
},
|
|
502
733
|
loadImage(src) {
|
|
734
|
+
// #ifdef APP-NVUE
|
|
735
|
+
return this.resolveNvueImageSource(src);
|
|
736
|
+
// #endif
|
|
737
|
+
|
|
503
738
|
if (this._imageCache[src]) {
|
|
504
739
|
return Promise.resolve(this._imageCache[src]);
|
|
505
740
|
}
|
|
506
741
|
return new Promise((resolve, reject) => {
|
|
507
742
|
let image = null;
|
|
508
743
|
|
|
509
|
-
// #ifdef APP-NVUE
|
|
510
|
-
image = new GImage();
|
|
511
|
-
// #endif
|
|
512
|
-
|
|
513
744
|
// #ifdef MP
|
|
514
745
|
const canvas = this.getCanvasElement();
|
|
515
746
|
if (canvas && typeof canvas.createImage === 'function') {
|
|
@@ -539,7 +770,11 @@ export default {
|
|
|
539
770
|
if (!this.ctx || typeof this.ctx.drawImage !== 'function') {
|
|
540
771
|
return false;
|
|
541
772
|
}
|
|
542
|
-
if (typeof source !== 'string'
|
|
773
|
+
if (typeof source !== 'string') {
|
|
774
|
+
this.ctx.drawImage(source, ...args);
|
|
775
|
+
return true;
|
|
776
|
+
}
|
|
777
|
+
if (typeof this.ctx.setFillStyle === 'function' && !this._isNvue) {
|
|
543
778
|
this.ctx.drawImage(source, ...args);
|
|
544
779
|
return true;
|
|
545
780
|
}
|
|
@@ -560,14 +795,32 @@ export default {
|
|
|
560
795
|
return new Promise((resolve, reject) => {
|
|
561
796
|
const width = options.width || this.actualWidth;
|
|
562
797
|
const height = options.height || this.actualHeight;
|
|
798
|
+
const hasDestWidth = options.destWidth !== undefined && options.destWidth !== null;
|
|
799
|
+
const hasDestHeight = options.destHeight !== undefined && options.destHeight !== null;
|
|
800
|
+
let destWidth = hasDestWidth ? options.destWidth : width;
|
|
801
|
+
let destHeight = hasDestHeight ? options.destHeight : height;
|
|
802
|
+
|
|
803
|
+
// MP、H5 和 APP-PLUS 保持逻辑绘制坐标,只提升默认导出像素。
|
|
804
|
+
// #ifdef MP || H5 || APP-PLUS
|
|
805
|
+
if (!hasDestWidth) {
|
|
806
|
+
destWidth = Math.round(width * this.dpr);
|
|
807
|
+
}
|
|
808
|
+
if (!hasDestHeight) {
|
|
809
|
+
destHeight = Math.round(height * this.dpr);
|
|
810
|
+
}
|
|
811
|
+
// #endif
|
|
812
|
+
|
|
813
|
+
const defaultFileType = 'png';
|
|
563
814
|
const request = {
|
|
564
815
|
x: options.x || 0,
|
|
565
816
|
y: options.y || 0,
|
|
566
817
|
width,
|
|
567
818
|
height,
|
|
568
|
-
destWidth
|
|
569
|
-
destHeight
|
|
570
|
-
fileType: options.fileType ||
|
|
819
|
+
destWidth,
|
|
820
|
+
destHeight,
|
|
821
|
+
fileType: options.fileType === undefined || options.fileType === null
|
|
822
|
+
? defaultFileType
|
|
823
|
+
: options.fileType,
|
|
571
824
|
quality: options.quality === undefined ? 1 : options.quality
|
|
572
825
|
};
|
|
573
826
|
const success = (res) => {
|
|
@@ -630,18 +883,14 @@ export default {
|
|
|
630
883
|
|
|
631
884
|
// #ifdef APP-NVUE
|
|
632
885
|
if (this.ctx && typeof this.ctx.toTempFilePath === 'function') {
|
|
633
|
-
this.ctx.toTempFilePath(
|
|
634
|
-
request.x,
|
|
635
|
-
request.y,
|
|
636
|
-
request.width,
|
|
637
|
-
request.height,
|
|
638
|
-
request.destWidth,
|
|
639
|
-
request.destHeight,
|
|
640
|
-
request.fileType,
|
|
641
|
-
request.quality,
|
|
886
|
+
Promise.resolve(this.ctx.toTempFilePath(request)).then(
|
|
642
887
|
(res) => {
|
|
643
888
|
success(res);
|
|
644
889
|
complete(res);
|
|
890
|
+
},
|
|
891
|
+
(error) => {
|
|
892
|
+
fail(error);
|
|
893
|
+
complete(error);
|
|
645
894
|
}
|
|
646
895
|
);
|
|
647
896
|
return;
|
|
@@ -667,51 +916,96 @@ export default {
|
|
|
667
916
|
fileType,
|
|
668
917
|
quality,
|
|
669
918
|
width: this.actualWidth,
|
|
670
|
-
height: this.actualHeight
|
|
671
|
-
destWidth: this.actualWidth,
|
|
672
|
-
destHeight: this.actualHeight
|
|
919
|
+
height: this.actualHeight
|
|
673
920
|
});
|
|
674
921
|
return res.tempFilePath || res.apFilePath;
|
|
675
922
|
},
|
|
676
923
|
getImageData(options = {}) {
|
|
677
924
|
return new Promise((resolve, reject) => {
|
|
925
|
+
const success = (res) => {
|
|
926
|
+
if (typeof options.success === 'function') options.success(res);
|
|
927
|
+
resolve(res);
|
|
928
|
+
};
|
|
929
|
+
const fail = (err) => {
|
|
930
|
+
if (typeof options.fail === 'function') options.fail(err);
|
|
931
|
+
reject(err);
|
|
932
|
+
};
|
|
933
|
+
const complete = (res) => {
|
|
934
|
+
if (typeof options.complete === 'function') options.complete(res);
|
|
935
|
+
};
|
|
936
|
+
// #ifdef APP-NVUE
|
|
937
|
+
if (this.ctx && typeof this.ctx.getImageData === 'function') {
|
|
938
|
+
Promise.resolve(this.ctx.getImageData({
|
|
939
|
+
x: options.x || 0,
|
|
940
|
+
y: options.y || 0,
|
|
941
|
+
width: options.width || this.actualWidth,
|
|
942
|
+
height: options.height || this.actualHeight
|
|
943
|
+
})).then((res) => {
|
|
944
|
+
success(res);
|
|
945
|
+
complete(res);
|
|
946
|
+
}, (error) => {
|
|
947
|
+
fail(error);
|
|
948
|
+
complete(error);
|
|
949
|
+
});
|
|
950
|
+
return;
|
|
951
|
+
}
|
|
952
|
+
// #endif
|
|
953
|
+
|
|
678
954
|
const request = {
|
|
679
955
|
canvasId: this.canvasId,
|
|
680
956
|
x: options.x || 0,
|
|
681
957
|
y: options.y || 0,
|
|
682
958
|
width: options.width || this.actualWidth,
|
|
683
959
|
height: options.height || this.actualHeight,
|
|
684
|
-
success
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
},
|
|
688
|
-
fail: (err) => {
|
|
689
|
-
if (typeof options.fail === 'function') options.fail(err);
|
|
690
|
-
reject(err);
|
|
691
|
-
},
|
|
692
|
-
complete: options.complete
|
|
960
|
+
success,
|
|
961
|
+
fail,
|
|
962
|
+
complete
|
|
693
963
|
};
|
|
694
964
|
uni.canvasGetImageData(request, this);
|
|
695
965
|
});
|
|
696
966
|
},
|
|
697
967
|
putImageData(options = {}) {
|
|
698
968
|
return new Promise((resolve, reject) => {
|
|
969
|
+
const success = (res) => {
|
|
970
|
+
if (typeof options.success === 'function') options.success(res);
|
|
971
|
+
resolve(res);
|
|
972
|
+
};
|
|
973
|
+
const fail = (err) => {
|
|
974
|
+
if (typeof options.fail === 'function') options.fail(err);
|
|
975
|
+
reject(err);
|
|
976
|
+
};
|
|
977
|
+
const complete = (res) => {
|
|
978
|
+
if (typeof options.complete === 'function') options.complete(res);
|
|
979
|
+
};
|
|
980
|
+
// #ifdef APP-NVUE
|
|
981
|
+
if (this.ctx && typeof this.ctx.putImageData === 'function') {
|
|
982
|
+
Promise.resolve(this.ctx.putImageData({
|
|
983
|
+
x: options.x || 0,
|
|
984
|
+
y: options.y || 0,
|
|
985
|
+
width: options.width || (options.data && options.data.width) || this.actualWidth,
|
|
986
|
+
height: options.height || (options.data && options.data.height) || this.actualHeight,
|
|
987
|
+
data: options.data
|
|
988
|
+
})).then((res) => {
|
|
989
|
+
success(res);
|
|
990
|
+
complete(res);
|
|
991
|
+
}, (error) => {
|
|
992
|
+
fail(error);
|
|
993
|
+
complete(error);
|
|
994
|
+
});
|
|
995
|
+
return;
|
|
996
|
+
}
|
|
997
|
+
// #endif
|
|
998
|
+
|
|
699
999
|
const request = {
|
|
700
1000
|
canvasId: this.canvasId,
|
|
701
1001
|
x: options.x || 0,
|
|
702
1002
|
y: options.y || 0,
|
|
703
|
-
width: options.width || this.actualWidth,
|
|
704
|
-
height: options.height || this.actualHeight,
|
|
1003
|
+
width: options.width || (options.data && options.data.width) || this.actualWidth,
|
|
1004
|
+
height: options.height || (options.data && options.data.height) || this.actualHeight,
|
|
705
1005
|
data: options.data,
|
|
706
|
-
success
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
},
|
|
710
|
-
fail: (err) => {
|
|
711
|
-
if (typeof options.fail === 'function') options.fail(err);
|
|
712
|
-
reject(err);
|
|
713
|
-
},
|
|
714
|
-
complete: options.complete
|
|
1006
|
+
success,
|
|
1007
|
+
fail,
|
|
1008
|
+
complete
|
|
715
1009
|
};
|
|
716
1010
|
uni.canvasPutImageData(request, this);
|
|
717
1011
|
});
|
|
@@ -90,6 +90,11 @@
|
|
|
90
90
|
}
|
|
91
91
|
},
|
|
92
92
|
mixins: [mpMixin, mixin, props],
|
|
93
|
+
inject: {
|
|
94
|
+
uActionSheet: {
|
|
95
|
+
default: null
|
|
96
|
+
}
|
|
97
|
+
},
|
|
93
98
|
computed: {
|
|
94
99
|
titleTextStyle() {
|
|
95
100
|
return addStyle(this.titleStyle)
|
|
@@ -123,6 +128,9 @@
|
|
|
123
128
|
this.$emit('click', {
|
|
124
129
|
name: this.name
|
|
125
130
|
})
|
|
131
|
+
if (this.stop && typeof this.uActionSheet?.slotClickHandler === 'function') {
|
|
132
|
+
this.uActionSheet.slotClickHandler()
|
|
133
|
+
}
|
|
126
134
|
// 如果配置了url(此props参数通过mixin引入)参数,跳转页面
|
|
127
135
|
this.openPage()
|
|
128
136
|
// 是否阻止事件传播
|