uview-ultra 4.5.74 → 4.5.75

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 CHANGED
@@ -1,3 +1,28 @@
1
+ ## 4.5.75
2
+ feat: 新增 up-lottie 动画组件(对齐 uview-plus 3.8.135)
3
+
4
+ 加载 AE 导出的 Lottie JSON 并播放。API 与 uview-plus 3.x 的 u-lottie 完全一致,.vue / .uvue 两套实现同步提供。
5
+
6
+ 新增:
7
+ - up-lottie 组件,props:filePath(http(s) 地址;H5 / App-Vue 额外支持本地静态路径)、animationData(直接传 JSON 对象,优先级高于 filePath)、contentModel(ScaleToFill / AspectFill / Center,默认 AspectFill)、loop(默认 false)、autoplay(默认 true)
8
+ - 实例方法:reload / playAnimation / pauseAnimation / resumeAnimation / cancelAnimation
9
+ - 事件 statechange:ready / play / pause / resume / stop / complete / error(error 附 message);微信小程序从 event.detail 读取,统一按 event.detail || event 兼容
10
+ - 新增示例页 pages/componentsD/lottie,含填充模式切换、播放控制与状态日志
11
+
12
+ 平台实现分两条轨:
13
+ - .vue(uni-app Vue3):H5 / App-Vue 走 lottie-web 5.13.0 的 SVG 渲染器,H5 端引擎按需 import() 拆成独立异步 chunk、不进共享入口包,加载失败会重置缓存以便重试;微信小程序 / 鸿蒙走 lottie-miniprogram 1.0.12 + up-canvas 的 canvas 渲染器,鸿蒙无 DOM canvas 节点,由 harmony-canvas-adapter 把旧版 CanvasContext 适配成标准 2D 上下文;nvue 与其他小程序统一通过 statechange 的 error 类型暴露,不发散报错
14
+ - .uvue(uni-app x):无 DOM,不走 SVG 渲染器,直接用 up-canvas 暴露的原生 CanvasRenderingContext2D 承载 lottie-miniprogram 的 canvas 渲染器。lottie-miniprogram 在模块加载期就会调用 wx.getSystemInfoSync(),而 uni-app x 没有 wx 全局,因此单独提供一份注入了 wx 桩的副本 libs/lottie-miniprogram.uvue.js(原文件保持不动,供 .vue 侧使用)
15
+ - .uvue 侧初始化前会探测 2D API 覆盖度(save / restore / bezierCurveTo / setTransform / fillText 等 16 项),缺失时通过 error 事件报出具体缺哪个方法,不会静默白屏
16
+
17
+ 已知限制:
18
+ - 同一页面仅支持一个并行的 canvas 轨实例(lottie-miniprogram 持有全局 canvas 引用,组件内已加互斥守卫)
19
+ - 微信小程序 / 鸿蒙 / uni-app x 无法读取本地 JSON 文件,请改用 animationData 或 http(s) 地址
20
+ - 图片类资源在 canvas 轨下受平台限制(小程序不支持动态创建 canvas),建议保持图片原始宽高与 JSON 描述一致
21
+ - 远程 JSON 可包含可执行表达式(lottie 的 expressions 特性),请仅加载可信来源
22
+ - .uvue 侧本次仅完成编译级验证(全项目 109 页面编译通过),未做真机运行时验证;.vue 侧与 3.x 实现一致
23
+
24
+ 体量:引擎资源约 451 KB(lottie_svg.min.js 242 KB、lottie-miniprogram.min.js 209 KB、lottie-miniprogram.uvue.js 210 KB 含 wx 桩)。H5 端 lottie-web 为异步 chunk 不影响首屏;仅使用 up-lottie 的项目才会引入对应引擎,不影响其他组件。
25
+
1
26
  ## 4.5.74
2
27
  fix: 对齐 uview-plus 3.8.129 ~ 3.8.137 的上游修复
3
28
 
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2019 wechat-miniprogram
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Bodymovin
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,47 @@
1
+ # -*- coding: utf-8 -*-
2
+ """生成 uvue 专用的 lottie-miniprogram 副本。
3
+
4
+ lottie-miniprogram 在**模块加载期**就会执行 `var b = wx.getSystemInfoSync()`,
5
+ 而 uni-app x 没有 wx 全局,直接 import 会在启动时抛 ReferenceError。
6
+ 这里在文件最前面补一个模块作用域的 wx 桩,后续压缩代码里的 `wx` 引用
7
+ 会解析到这个局部变量(比挂 globalThis 更可靠,不依赖运行时全局对象)。
8
+
9
+ 只补 getSystemInfoSync / request 两项:
10
+ - getSystemInfoSync:lottie 只用来取 pixelRatio(dpr 我们显式传 1)
11
+ - request:仅在按 path 加载远程 JSON 时使用,本组件只用 animationData
12
+
13
+ 原始文件保持不动,供 .vue 侧(微信小程序/鸿蒙,有真实 wx)使用。
14
+ """
15
+ import io
16
+
17
+ SRC = 'lottie-miniprogram.min.js'
18
+ DST = 'lottie-miniprogram.uvue.js'
19
+
20
+ SHIM = """/* ------------------------------------------------------------------
21
+ * uni-app x 适配层(本文件由 lottie-miniprogram.min.js 自动生成)
22
+ * lottie-miniprogram 在模块加载期即调用 wx.getSystemInfoSync(),
23
+ * 而 uni-app x 没有 wx 全局,故在此补一个模块作用域的 wx 桩。
24
+ * 下方代码与 lottie-miniprogram.min.js 完全一致,未做任何修改。
25
+ * ------------------------------------------------------------------ */
26
+ var wx = {
27
+ getSystemInfoSync: function () {
28
+ try {
29
+ var info = (typeof uni !== 'undefined' && uni.getSystemInfoSync) ? (uni.getSystemInfoSync() || {}) : {}
30
+ return { pixelRatio: info.pixelRatio || 1, platform: info.platform || '' }
31
+ } catch (e) {
32
+ return { pixelRatio: 1, platform: '' }
33
+ }
34
+ },
35
+ request: function () {}
36
+ };
37
+
38
+ """
39
+
40
+ with io.open(SRC, 'rb') as f:
41
+ body = f.read()
42
+
43
+ with io.open(DST, 'wb') as f:
44
+ f.write(SHIM.encode('utf-8'))
45
+ f.write(body)
46
+
47
+ print('generated %s, size=%d' % (DST, len(SHIM.encode('utf-8')) + len(body)))
@@ -0,0 +1,394 @@
1
+ function parseFontSize(font) {
2
+ const matched = String(font || '').match(/(\d+(?:\.\d+)?)px/)
3
+ return matched ? Number(matched[1]) : 10
4
+ }
5
+
6
+ export function createHarmonyCanvasAdapter(options = {}) {
7
+ const legacy = options.context
8
+ if (!legacy) {
9
+ throw new Error('harmony canvas context is required')
10
+ }
11
+
12
+ const width = Number(options.width) > 0 ? Number(options.width) : 1
13
+ const height = Number(options.height) > 0 ? Number(options.height) : 1
14
+
15
+ const state = {
16
+ fillStyle: '#000000',
17
+ strokeStyle: '#000000',
18
+ lineWidth: 1,
19
+ lineCap: 'butt',
20
+ lineJoin: 'miter',
21
+ miterLimit: 10,
22
+ lineDashOffset: 0,
23
+ lineDash: [],
24
+ globalAlpha: 1,
25
+ globalCompositeOperation: 'source-over',
26
+ font: '10px sans-serif'
27
+ }
28
+ const stack = []
29
+ const rafIds = new Set()
30
+ let dirty = false
31
+ let flushing = false
32
+ let destroyed = false
33
+ let flushTimer = null
34
+
35
+ const flush = () => {
36
+ if (destroyed || !dirty || flushing) return
37
+ dirty = false
38
+ flushing = true
39
+ let released = false
40
+ const release = () => {
41
+ if (released) return
42
+ released = true
43
+ flushing = false
44
+ if (dirty) scheduleFlush()
45
+ }
46
+ try {
47
+ if (typeof legacy.draw === 'function') {
48
+ legacy.draw(false, release)
49
+ setTimeout(release, 80)
50
+ } else {
51
+ release()
52
+ }
53
+ } catch (error) {
54
+ release()
55
+ }
56
+ }
57
+
58
+ const scheduleFlush = () => {
59
+ if (destroyed || flushTimer !== null) return
60
+ const timer = setTimeout(() => {
61
+ rafIds.delete(timer)
62
+ if (flushTimer === timer) flushTimer = null
63
+ flush()
64
+ }, 0)
65
+ flushTimer = timer
66
+ rafIds.add(timer)
67
+ }
68
+
69
+ const markDirty = () => {
70
+ dirty = true
71
+ scheduleFlush()
72
+ }
73
+
74
+ const sync = () => {
75
+ if (typeof legacy.setFillStyle === 'function') {
76
+ legacy.setFillStyle(state.fillStyle)
77
+ }
78
+ if (typeof legacy.setStrokeStyle === 'function') {
79
+ legacy.setStrokeStyle(state.strokeStyle)
80
+ }
81
+ if (typeof legacy.setLineWidth === 'function') {
82
+ legacy.setLineWidth(state.lineWidth)
83
+ }
84
+ if (typeof legacy.setLineCap === 'function') {
85
+ legacy.setLineCap(state.lineCap)
86
+ }
87
+ if (typeof legacy.setLineJoin === 'function') {
88
+ legacy.setLineJoin(state.lineJoin)
89
+ }
90
+ if (typeof legacy.setMiterLimit === 'function') {
91
+ legacy.setMiterLimit(state.miterLimit)
92
+ }
93
+ if (typeof legacy.setGlobalAlpha === 'function') {
94
+ legacy.setGlobalAlpha(state.globalAlpha)
95
+ }
96
+ if (typeof legacy.setGlobalCompositeOperation === 'function') {
97
+ legacy.setGlobalCompositeOperation(state.globalCompositeOperation)
98
+ }
99
+ if (typeof legacy.setLineDash === 'function') {
100
+ legacy.setLineDash(state.lineDash, state.lineDashOffset)
101
+ }
102
+ if (typeof legacy.setFontSize === 'function') {
103
+ legacy.setFontSize(parseFontSize(state.font))
104
+ }
105
+ }
106
+
107
+ const canvas = {
108
+ width,
109
+ height,
110
+ getContext() {
111
+ return context
112
+ },
113
+ requestAnimationFrame(callback) {
114
+ const timer = setTimeout(() => {
115
+ rafIds.delete(timer)
116
+ if (destroyed) return
117
+ try {
118
+ callback(Date.now())
119
+ } finally {
120
+ flush()
121
+ }
122
+ }, 33)
123
+ rafIds.add(timer)
124
+ return timer
125
+ },
126
+ cancelAnimationFrame(timer) {
127
+ if (rafIds.has(timer)) {
128
+ clearTimeout(timer)
129
+ rafIds.delete(timer)
130
+ }
131
+ },
132
+ createImage() {
133
+ const image = {
134
+ width: 0,
135
+ height: 0,
136
+ _src: '',
137
+ _localPath: '',
138
+ onload: null,
139
+ onerror: null,
140
+ addEventListener(type, callback) {
141
+ if (type === 'load') image.onload = callback
142
+ if (type === 'error') image.onerror = callback
143
+ }
144
+ }
145
+ Object.defineProperty(image, 'src', {
146
+ get() {
147
+ return image._src
148
+ },
149
+ set(value) {
150
+ image._src = value
151
+ uni.getImageInfo({
152
+ src: value,
153
+ success(result) {
154
+ image.width = result.width || 0
155
+ image.height = result.height || 0
156
+ image._localPath = result.path || value
157
+ if (typeof image.onload === 'function') image.onload()
158
+ },
159
+ fail() {
160
+ if (typeof image.onerror === 'function') image.onerror()
161
+ }
162
+ })
163
+ }
164
+ })
165
+ return image
166
+ }
167
+ }
168
+
169
+ const context = {
170
+ canvas,
171
+ get fillStyle() {
172
+ return state.fillStyle
173
+ },
174
+ set fillStyle(value) {
175
+ state.fillStyle = value
176
+ },
177
+ get strokeStyle() {
178
+ return state.strokeStyle
179
+ },
180
+ set strokeStyle(value) {
181
+ state.strokeStyle = value
182
+ },
183
+ get lineWidth() {
184
+ return state.lineWidth
185
+ },
186
+ set lineWidth(value) {
187
+ state.lineWidth = value
188
+ },
189
+ get lineCap() {
190
+ return state.lineCap
191
+ },
192
+ set lineCap(value) {
193
+ state.lineCap = value
194
+ },
195
+ get lineJoin() {
196
+ return state.lineJoin
197
+ },
198
+ set lineJoin(value) {
199
+ state.lineJoin = value
200
+ },
201
+ get miterLimit() {
202
+ return state.miterLimit
203
+ },
204
+ set miterLimit(value) {
205
+ state.miterLimit = value
206
+ },
207
+ get lineDashOffset() {
208
+ return state.lineDashOffset
209
+ },
210
+ set lineDashOffset(value) {
211
+ state.lineDashOffset = value
212
+ },
213
+ get globalAlpha() {
214
+ return state.globalAlpha
215
+ },
216
+ set globalAlpha(value) {
217
+ state.globalAlpha = value
218
+ },
219
+ get globalCompositeOperation() {
220
+ return state.globalCompositeOperation
221
+ },
222
+ set globalCompositeOperation(value) {
223
+ state.globalCompositeOperation = value
224
+ },
225
+ get font() {
226
+ return state.font
227
+ },
228
+ set font(value) {
229
+ state.font = value
230
+ },
231
+ save() {
232
+ stack.push(Object.assign({}, state))
233
+ if (typeof legacy.save === 'function') legacy.save()
234
+ },
235
+ restore() {
236
+ if (stack.length) Object.assign(state, stack.pop())
237
+ if (typeof legacy.restore === 'function') legacy.restore()
238
+ sync()
239
+ },
240
+ translate(x, y) {
241
+ legacy.translate(x, y)
242
+ },
243
+ scale(x, y) {
244
+ legacy.scale(x, y)
245
+ },
246
+ rotate(angle) {
247
+ legacy.rotate(angle)
248
+ },
249
+ transform(a, b, c, d, e, f) {
250
+ if (typeof legacy.transform === 'function') {
251
+ legacy.transform(a, b, c, d, e, f)
252
+ }
253
+ },
254
+ setTransform(a, b, c, d, e, f) {
255
+ if (typeof legacy.setTransform === 'function') {
256
+ legacy.setTransform(a, b, c, d, e, f)
257
+ } else if (typeof legacy.transform === 'function') {
258
+ legacy.transform(a, b, c, d, e, f)
259
+ }
260
+ },
261
+ beginPath() {
262
+ legacy.beginPath()
263
+ },
264
+ closePath() {
265
+ legacy.closePath()
266
+ },
267
+ moveTo(x, y) {
268
+ legacy.moveTo(x, y)
269
+ },
270
+ lineTo(x, y) {
271
+ legacy.lineTo(x, y)
272
+ },
273
+ bezierCurveTo(a, b, c, d, e, f) {
274
+ legacy.bezierCurveTo(a, b, c, d, e, f)
275
+ },
276
+ quadraticCurveTo(a, b, c, d) {
277
+ if (typeof legacy.quadraticCurveTo === 'function') {
278
+ legacy.quadraticCurveTo(a, b, c, d)
279
+ }
280
+ },
281
+ rect(x, y, w, h) {
282
+ legacy.rect(x, y, w, h)
283
+ },
284
+ arc(x, y, radius, start, end, anticlockwise) {
285
+ if (typeof legacy.arc === 'function') {
286
+ legacy.arc(x, y, radius, start, end, anticlockwise)
287
+ }
288
+ },
289
+ fill() {
290
+ sync()
291
+ legacy.fill()
292
+ markDirty()
293
+ },
294
+ stroke() {
295
+ sync()
296
+ legacy.stroke()
297
+ markDirty()
298
+ },
299
+ clip() {
300
+ if (typeof legacy.clip === 'function') {
301
+ legacy.clip()
302
+ }
303
+ },
304
+ clearRect(x, y, w, h) {
305
+ if (typeof legacy.clearRect === 'function') {
306
+ legacy.clearRect(x, y, w, h)
307
+ }
308
+ markDirty()
309
+ },
310
+ fillRect(x, y, w, h) {
311
+ sync()
312
+ if (typeof legacy.fillRect === 'function') {
313
+ legacy.fillRect(x, y, w, h)
314
+ }
315
+ markDirty()
316
+ },
317
+ strokeRect(x, y, w, h) {
318
+ sync()
319
+ if (typeof legacy.strokeRect === 'function') {
320
+ legacy.strokeRect(x, y, w, h)
321
+ }
322
+ markDirty()
323
+ },
324
+ drawImage() {
325
+ const image = arguments[0]
326
+ const source = image && (image._localPath || image._src || image.src)
327
+ if (!source) return
328
+ sync()
329
+ const args = Array.prototype.slice.call(arguments, 1)
330
+ try {
331
+ if (args.length >= 8) {
332
+ legacy.drawImage(source, args[4], args[5], args[6], args[7])
333
+ } else if (args.length >= 4) {
334
+ legacy.drawImage(source, args[0], args[1], args[2], args[3])
335
+ } else {
336
+ legacy.drawImage(
337
+ source,
338
+ args[0] || 0,
339
+ args[1] || 0,
340
+ image.width || 0,
341
+ image.height || 0
342
+ )
343
+ }
344
+ markDirty()
345
+ } catch (error) {
346
+ // 单张图片绘制失败时跳过,避免中断整个动画
347
+ }
348
+ },
349
+ createLinearGradient(x0, y0, x1, y1) {
350
+ return legacy.createLinearGradient(x0, y0, x1, y1)
351
+ },
352
+ createRadialGradient(x0, y0, r0, x1, y1, r1) {
353
+ return legacy.createRadialGradient(x0, y0, r0, x1, y1, r1)
354
+ },
355
+ setLineDash(segments, offset) {
356
+ state.lineDash = Array.isArray(segments) ? segments.slice() : []
357
+ if (typeof offset === 'number') {
358
+ state.lineDashOffset = offset
359
+ }
360
+ },
361
+ fillText(text, x, y) {
362
+ sync()
363
+ if (typeof legacy.fillText === 'function') {
364
+ legacy.fillText(text, x, y)
365
+ }
366
+ markDirty()
367
+ },
368
+ strokeText(text, x, y) {
369
+ sync()
370
+ if (typeof legacy.strokeText === 'function') {
371
+ legacy.strokeText(text, x, y)
372
+ }
373
+ markDirty()
374
+ },
375
+ measureText(text) {
376
+ const fontSize = parseFontSize(state.font)
377
+ return { width: String(text == null ? '' : text).length * fontSize * 0.6 }
378
+ }
379
+ }
380
+
381
+ return {
382
+ canvas,
383
+ context,
384
+ flush,
385
+ destroy() {
386
+ destroyed = true
387
+ rafIds.forEach((timer) => clearTimeout(timer))
388
+ rafIds.clear()
389
+ flushTimer = null
390
+ dirty = false
391
+ stack.length = 0
392
+ }
393
+ }
394
+ }