@leafer-ui/image 1.8.0 → 1.9.1
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 +5 -5
- package/src/check.ts +1 -1
- package/src/data.ts +25 -9
- package/src/mode.ts +34 -28
- package/src/pattern.ts +14 -5
- package/src/recycle.ts +3 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@leafer-ui/image",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.9.1",
|
|
4
4
|
"description": "@leafer-ui/image",
|
|
5
5
|
"author": "Chao (Leafer) Wan",
|
|
6
6
|
"license": "MIT",
|
|
@@ -22,11 +22,11 @@
|
|
|
22
22
|
"leaferjs"
|
|
23
23
|
],
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@leafer/core": "1.
|
|
26
|
-
"@leafer-ui/draw": "1.
|
|
25
|
+
"@leafer/core": "1.9.1",
|
|
26
|
+
"@leafer-ui/draw": "1.9.1"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
|
-
"@leafer/interface": "1.
|
|
30
|
-
"@leafer-ui/interface": "1.
|
|
29
|
+
"@leafer/interface": "1.9.1",
|
|
30
|
+
"@leafer-ui/interface": "1.9.1"
|
|
31
31
|
}
|
|
32
32
|
}
|
package/src/check.ts
CHANGED
|
@@ -19,7 +19,7 @@ export function checkImage(ui: IUI, canvas: ILeaferCanvas, paint: ILeafPaint, al
|
|
|
19
19
|
if (data.repeat) {
|
|
20
20
|
allowDraw = false
|
|
21
21
|
} else {
|
|
22
|
-
if (!(paint.changeful || ResizeEvent.isResizing(ui) || Export.running)) {
|
|
22
|
+
if (!(paint.changeful || (Platform.name === 'miniapp' && ResizeEvent.isResizing(ui)) || Export.running)) { // 小程序resize过程中直接绘制原图(绕过垃圾回收bug)
|
|
23
23
|
let { width, height } = data
|
|
24
24
|
width *= scaleX * pixelRatio
|
|
25
25
|
height *= scaleY * pixelRatio
|
package/src/data.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { IBoundsData, ILeaferImage, IScaleData } from '@leafer/interface'
|
|
2
|
-
import { MatrixHelper, MathHelper, Bounds, AlignHelper, BoundsHelper, PointHelper } from '@leafer/core'
|
|
1
|
+
import { IBoundsData, IGap, ILeaferImage, IPointData, IPointGap, IScaleData } from '@leafer/interface'
|
|
2
|
+
import { MatrixHelper, MathHelper, Bounds, AlignHelper, BoundsHelper, PointHelper, isObject, isString } from '@leafer/core'
|
|
3
3
|
|
|
4
4
|
import { IImagePaint, ILeafPaint, ILeafPaintPatternData } from '@leafer-ui/interface'
|
|
5
5
|
|
|
@@ -12,10 +12,9 @@ const tempScaleData = {} as IScaleData
|
|
|
12
12
|
const tempImage = {} as IBoundsData
|
|
13
13
|
|
|
14
14
|
export function createData(leafPaint: ILeafPaint, image: ILeaferImage, paint: IImagePaint, box: IBoundsData): void {
|
|
15
|
-
const { changeful, sync,
|
|
15
|
+
const { changeful, sync, scaleFixed } = paint
|
|
16
16
|
if (changeful) leafPaint.changeful = changeful
|
|
17
17
|
if (sync) leafPaint.sync = sync
|
|
18
|
-
if (editing) leafPaint.editing = editing
|
|
19
18
|
if (scaleFixed) leafPaint.scaleFixed = scaleFixed
|
|
20
19
|
leafPaint.data = getPatternData(paint, box, image)
|
|
21
20
|
}
|
|
@@ -25,7 +24,7 @@ export function getPatternData(paint: IImagePaint, box: IBoundsData, image: ILea
|
|
|
25
24
|
if (paint.mode === 'strench' as string) paint.mode = 'stretch' // 兼容代码,后续可移除
|
|
26
25
|
|
|
27
26
|
let { width, height } = image
|
|
28
|
-
const { opacity, mode, align, offset, scale, size, rotation, skew, clipSize, repeat, filters } = paint
|
|
27
|
+
const { opacity, mode, align, offset, scale, size, rotation, skew, clipSize, repeat, gap, filters } = paint
|
|
29
28
|
const sameBox = box.width === width && box.height === height
|
|
30
29
|
|
|
31
30
|
const data: ILeafPaintPatternData = { mode }
|
|
@@ -47,9 +46,9 @@ export function getPatternData(paint: IImagePaint, box: IBoundsData, image: ILea
|
|
|
47
46
|
scaleY = tempScaleData.scaleY
|
|
48
47
|
}
|
|
49
48
|
|
|
50
|
-
if (align) {
|
|
49
|
+
if (align || gap || repeat) {
|
|
51
50
|
if (scaleX) BoundsHelper.scale(tempImage, scaleX, scaleY, true)
|
|
52
|
-
AlignHelper.toPoint(align, tempImage, box, tempImage, true, true)
|
|
51
|
+
if (align) AlignHelper.toPoint(align, tempImage, box, tempImage, true, true)
|
|
53
52
|
}
|
|
54
53
|
}
|
|
55
54
|
|
|
@@ -64,8 +63,10 @@ export function getPatternData(paint: IImagePaint, box: IBoundsData, image: ILea
|
|
|
64
63
|
if (tempImage.x || tempImage.y || scaleX || clipSize || rotation || skew) clipMode(data, box, tempImage.x, tempImage.y, scaleX, scaleY, rotation, skew, paint.clipSize)
|
|
65
64
|
break
|
|
66
65
|
case 'repeat':
|
|
67
|
-
if (!sameBox || scaleX || rotation) repeatMode(data, box, width, height, tempImage.x, tempImage.y, scaleX, scaleY, rotation, align)
|
|
66
|
+
if (!sameBox || scaleX || rotation || skew) repeatMode(data, box, width, height, tempImage.x, tempImage.y, scaleX, scaleY, rotation, skew, align, paint.freeTransform)
|
|
68
67
|
if (!repeat) data.repeat = 'repeat'
|
|
68
|
+
const count = isObject(repeat)
|
|
69
|
+
if (gap || count) data.gap = getGapData(gap, count && repeat, tempImage.width, tempImage.height, box)
|
|
69
70
|
break
|
|
70
71
|
case 'fit':
|
|
71
72
|
case 'cover':
|
|
@@ -89,6 +90,21 @@ export function getPatternData(paint: IImagePaint, box: IBoundsData, image: ILea
|
|
|
89
90
|
data.height = height
|
|
90
91
|
if (opacity) data.opacity = opacity
|
|
91
92
|
if (filters) data.filters = filters
|
|
92
|
-
if (repeat) data.repeat =
|
|
93
|
+
if (repeat) data.repeat = isString(repeat) ? (repeat === 'x' ? 'repeat-x' : 'repeat-y') : 'repeat'
|
|
93
94
|
return data
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
function getGapData(gap: IGap | IPointGap, repeat: IPointData, width: number, height: number, box: IBoundsData): IPointData {
|
|
99
|
+
let xGap: IGap, yGap: IGap
|
|
100
|
+
if (isObject(gap)) xGap = gap.x, yGap = gap.y
|
|
101
|
+
else xGap = yGap = gap
|
|
102
|
+
return { x: getGapValue(xGap, width, box.width, repeat && repeat.x), y: getGapValue(yGap, height, box.height, repeat && repeat.y) }
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function getGapValue(gap: IGap, size: number, totalSize: number, rows: number): number {
|
|
106
|
+
const auto = isString(gap) || rows
|
|
107
|
+
const remain = rows ? totalSize - rows * size : totalSize % size
|
|
108
|
+
const value = auto ? remain / ((rows || Math.floor(totalSize / size)) - 1) : gap
|
|
109
|
+
return gap === 'auto' ? (value < 0 ? 0 : value) : value
|
|
94
110
|
}
|
package/src/mode.ts
CHANGED
|
@@ -15,14 +15,9 @@ export function fillOrFitMode(data: ILeafPaintPatternData, box: IBoundsData, x:
|
|
|
15
15
|
data.transform = transform
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
|
|
19
18
|
export function clipMode(data: ILeafPaintPatternData, box: IBoundsData, x: number, y: number, scaleX: number, scaleY: number, rotation: number, skew: IPointData, clipSize?: ISizeData): void {
|
|
20
|
-
// rotate -> skew -> scale -> translate
|
|
21
19
|
const transform: IMatrixData = get()
|
|
22
|
-
|
|
23
|
-
if (skew) skewHelper(transform, skew.x, skew.y)
|
|
24
|
-
if (scaleX) scaleHelper(transform, scaleX, scaleY)
|
|
25
|
-
translate(transform, box.x + x, box.y + y)
|
|
20
|
+
layout(transform, box, x, y, scaleX, scaleY, rotation, skew)
|
|
26
21
|
if (clipSize) {
|
|
27
22
|
tempMatrix.a = box.width / clipSize.width, tempMatrix.d = box.height / clipSize.height
|
|
28
23
|
multiplyParent(transform, tempMatrix)
|
|
@@ -30,30 +25,41 @@ export function clipMode(data: ILeafPaintPatternData, box: IBoundsData, x: numbe
|
|
|
30
25
|
data.transform = transform
|
|
31
26
|
}
|
|
32
27
|
|
|
33
|
-
|
|
34
|
-
export function repeatMode(data: ILeafPaintPatternData, box: IBoundsData, width: number, height: number, x: number, y: number, scaleX: number, scaleY: number, rotation: number, align: IAlign): void {
|
|
28
|
+
export function repeatMode(data: ILeafPaintPatternData, box: IBoundsData, width: number, height: number, x: number, y: number, scaleX: number, scaleY: number, rotation: number, skew: IPointData, align: IAlign, freeTransform?: boolean): void {
|
|
35
29
|
const transform = get()
|
|
36
|
-
if (
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
30
|
+
if (freeTransform) { // 自由变换
|
|
31
|
+
layout(transform, box, x, y, scaleX, scaleY, rotation, skew)
|
|
32
|
+
} else {
|
|
33
|
+
if (rotation) {
|
|
34
|
+
if (align === 'center') {
|
|
35
|
+
rotateOfOuter(transform, { x: width / 2, y: height / 2 }, rotation)
|
|
36
|
+
} else {
|
|
37
|
+
rotate(transform, rotation)
|
|
38
|
+
switch (rotation) {
|
|
39
|
+
case 90:
|
|
40
|
+
translate(transform, height, 0)
|
|
41
|
+
break
|
|
42
|
+
case 180:
|
|
43
|
+
translate(transform, width, height)
|
|
44
|
+
break
|
|
45
|
+
case 270:
|
|
46
|
+
translate(transform, 0, width)
|
|
47
|
+
break
|
|
48
|
+
}
|
|
51
49
|
}
|
|
52
50
|
}
|
|
51
|
+
origin.x = box.x + x
|
|
52
|
+
origin.y = box.y + y
|
|
53
|
+
translate(transform, origin.x, origin.y)
|
|
54
|
+
if (scaleX) scaleOfOuter(transform, origin, scaleX, scaleY)
|
|
53
55
|
}
|
|
54
|
-
origin.x = box.x + x
|
|
55
|
-
origin.y = box.y + y
|
|
56
|
-
translate(transform, origin.x, origin.y)
|
|
57
|
-
if (scaleX) scaleOfOuter(transform, origin, scaleX, scaleY)
|
|
58
56
|
data.transform = transform
|
|
59
|
-
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function layout(transform: IMatrixData, box: IBoundsData, x: number, y: number, scaleX: number, scaleY: number, rotation: number, skew: IPointData) {
|
|
60
|
+
// rotate -> skew -> scale -> translate
|
|
61
|
+
if (rotation) rotate(transform, rotation)
|
|
62
|
+
if (skew) skewHelper(transform, skew.x, skew.y)
|
|
63
|
+
if (scaleX) scaleHelper(transform, scaleX, scaleY)
|
|
64
|
+
translate(transform, box.x + x, box.y + y)
|
|
65
|
+
}
|
package/src/pattern.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { IUI, ILeafPaint, IMatrixData } from '@leafer-ui/interface'
|
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
const { get, scale, copy } = MatrixHelper
|
|
7
|
-
const {
|
|
7
|
+
const { floor, max, abs } = Math
|
|
8
8
|
|
|
9
9
|
export function createPattern(ui: IUI, paint: ILeafPaint, pixelRatio: number): boolean {
|
|
10
10
|
let { scaleX, scaleY } = ui.getRenderScaleData(true, paint.scaleFixed)
|
|
@@ -13,7 +13,13 @@ export function createPattern(ui: IUI, paint: ILeafPaint, pixelRatio: number): b
|
|
|
13
13
|
if (paint.patternId !== id && !ui.destroyed) {
|
|
14
14
|
|
|
15
15
|
const { image, data } = paint
|
|
16
|
-
let imageScale: number, imageMatrix: IMatrixData, { width, height, scaleX: sx, scaleY: sy, transform, repeat } = data
|
|
16
|
+
let imageScale: number, imageMatrix: IMatrixData, { width, height, scaleX: sx, scaleY: sy, transform, repeat, gap } = data
|
|
17
|
+
|
|
18
|
+
scaleX *= pixelRatio
|
|
19
|
+
scaleY *= pixelRatio
|
|
20
|
+
|
|
21
|
+
const xGap = gap && (gap.x * scaleX)
|
|
22
|
+
const yGap = gap && (gap.y * scaleY)
|
|
17
23
|
|
|
18
24
|
if (sx) {
|
|
19
25
|
sx = abs(sx) // maybe -1
|
|
@@ -25,8 +31,6 @@ export function createPattern(ui: IUI, paint: ILeafPaint, pixelRatio: number): b
|
|
|
25
31
|
scaleY *= sy
|
|
26
32
|
}
|
|
27
33
|
|
|
28
|
-
scaleX *= pixelRatio
|
|
29
|
-
scaleY *= pixelRatio
|
|
30
34
|
width *= scaleX
|
|
31
35
|
height *= scaleY
|
|
32
36
|
|
|
@@ -65,7 +69,12 @@ export function createPattern(ui: IUI, paint: ILeafPaint, pixelRatio: number): b
|
|
|
65
69
|
scale(imageMatrix, 1 / scaleX, 1 / scaleY)
|
|
66
70
|
}
|
|
67
71
|
|
|
68
|
-
|
|
72
|
+
if (imageMatrix) {
|
|
73
|
+
const canvasWidth = width + (xGap || 0), canvasHeight = height + (yGap || 0)
|
|
74
|
+
scale(imageMatrix, canvasWidth / max(floor(canvasWidth), 1), canvasHeight / max(floor(canvasHeight), 1)) // 缩放至floor画布宽高的状态
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const canvas = image.getCanvas(width, height, data.opacity, data.filters, xGap, yGap)
|
|
69
78
|
const pattern = image.getPattern(canvas, repeat || (Platform.origin.noRepeat || 'no-repeat'), imageMatrix, paint)
|
|
70
79
|
|
|
71
80
|
paint.style = pattern
|
package/src/recycle.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { IBooleanMap, ILeaferImage, IObject } from '@leafer/interface'
|
|
2
|
-
import { ImageManager } from '@leafer/core'
|
|
2
|
+
import { ImageManager, isArray } from '@leafer/core'
|
|
3
3
|
|
|
4
4
|
import { IImagePaint, ILeafPaint, IPaintAttr, IUIData } from '@leafer-ui/interface'
|
|
5
5
|
|
|
@@ -7,7 +7,7 @@ import { IImagePaint, ILeafPaint, IPaintAttr, IUIData } from '@leafer-ui/interfa
|
|
|
7
7
|
export function recycleImage(attrName: IPaintAttr, data: IUIData): IBooleanMap {
|
|
8
8
|
const paints: ILeafPaint[] = (data as IObject)['_' + attrName]
|
|
9
9
|
|
|
10
|
-
if (paints
|
|
10
|
+
if (isArray(paints)) {
|
|
11
11
|
|
|
12
12
|
let paint: ILeafPaint, image: ILeaferImage, recycleMap: IBooleanMap, input: IImagePaint[], url: string
|
|
13
13
|
|
|
@@ -26,7 +26,7 @@ export function recycleImage(attrName: IPaintAttr, data: IUIData): IBooleanMap {
|
|
|
26
26
|
if (image.loading) {
|
|
27
27
|
if (!input) {
|
|
28
28
|
input = (data.__input && data.__input[attrName]) || []
|
|
29
|
-
if (!(input
|
|
29
|
+
if (!isArray(input)) input = [input]
|
|
30
30
|
}
|
|
31
31
|
image.unload(paints[i].loadId, !input.some((item: IImagePaint) => item.url === url))
|
|
32
32
|
}
|