@leafer-ui/image 1.7.0 → 1.9.0

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leafer-ui/image",
3
- "version": "1.7.0",
3
+ "version": "1.9.0",
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.7.0",
26
- "@leafer-ui/draw": "1.7.0"
25
+ "@leafer/core": "1.9.0",
26
+ "@leafer-ui/draw": "1.9.0"
27
27
  },
28
28
  "devDependencies": {
29
- "@leafer/interface": "1.7.0",
30
- "@leafer-ui/interface": "1.7.0"
29
+ "@leafer/interface": "1.9.0",
30
+ "@leafer-ui/interface": "1.9.0"
31
31
  }
32
32
  }
package/src/check.ts CHANGED
@@ -7,10 +7,8 @@ import { Export } from '@leafer-ui/draw'
7
7
  import { createPattern } from './pattern'
8
8
 
9
9
 
10
- const { abs } = Math
11
-
12
10
  export function checkImage(ui: IUI, canvas: ILeaferCanvas, paint: ILeafPaint, allowDraw?: boolean): boolean {
13
- const { scaleX, scaleY } = ImageManager.patternLocked ? ui.__world : ui.__nowWorld
11
+ const { scaleX, scaleY } = ui.getRenderScaleData(true, paint.scaleFixed)
14
12
  const { pixelRatio } = canvas, { data } = paint
15
13
 
16
14
  if (!data || (paint.patternId === scaleX + '-' + scaleY + '-' + pixelRatio && !Export.running)) {
@@ -21,10 +19,10 @@ export function checkImage(ui: IUI, canvas: ILeaferCanvas, paint: ILeafPaint, al
21
19
  if (data.repeat) {
22
20
  allowDraw = false
23
21
  } else {
24
- if (!(paint.changeful || ResizeEvent.isResizing(ui) || Export.running)) {
22
+ if (!(paint.changeful || (Platform.name === 'miniapp' && ResizeEvent.isResizing(ui)) || Export.running)) { // 小程序resize过程中直接绘制原图(绕过垃圾回收bug)
25
23
  let { width, height } = data
26
- width *= abs(scaleX) * pixelRatio
27
- height *= abs(scaleY) * pixelRatio
24
+ width *= scaleX * pixelRatio
25
+ height *= scaleY * pixelRatio
28
26
  if (data.scaleX) {
29
27
  width *= data.scaleX
30
28
  height *= data.scaleY
@@ -35,6 +33,10 @@ export function checkImage(ui: IUI, canvas: ILeaferCanvas, paint: ILeafPaint, al
35
33
  }
36
34
 
37
35
  if (allowDraw) {
36
+ if (ui.__.__isFastShadow) { // fix: 快速阴影时,直接 drawImage 会无阴影,需fill一下
37
+ canvas.fillStyle = paint.style || '#000'
38
+ canvas.fill()
39
+ }
38
40
  drawImage(ui, canvas, paint, data) // 直接绘制图像,不生成图案
39
41
  return true
40
42
  } else {
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,10 @@ 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, editing } = paint
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
18
+ if (scaleFixed) leafPaint.scaleFixed = scaleFixed
19
19
  leafPaint.data = getPatternData(paint, box, image)
20
20
  }
21
21
 
@@ -24,7 +24,7 @@ export function getPatternData(paint: IImagePaint, box: IBoundsData, image: ILea
24
24
  if (paint.mode === 'strench' as string) paint.mode = 'stretch' // 兼容代码,后续可移除
25
25
 
26
26
  let { width, height } = image
27
- const { opacity, mode, align, offset, scale, size, rotation, skew, repeat, filters } = paint
27
+ const { opacity, mode, align, offset, scale, size, rotation, skew, clipSize, repeat, gap, filters } = paint
28
28
  const sameBox = box.width === width && box.height === height
29
29
 
30
30
  const data: ILeafPaintPatternData = { mode }
@@ -46,9 +46,9 @@ export function getPatternData(paint: IImagePaint, box: IBoundsData, image: ILea
46
46
  scaleY = tempScaleData.scaleY
47
47
  }
48
48
 
49
- if (align) {
49
+ if (align || gap || repeat) {
50
50
  if (scaleX) BoundsHelper.scale(tempImage, scaleX, scaleY, true)
51
- AlignHelper.toPoint(align, tempImage, box, tempImage, true, true)
51
+ if (align) AlignHelper.toPoint(align, tempImage, box, tempImage, true, true)
52
52
  }
53
53
  }
54
54
 
@@ -60,11 +60,13 @@ export function getPatternData(paint: IImagePaint, box: IBoundsData, image: ILea
60
60
  break
61
61
  case 'normal':
62
62
  case 'clip':
63
- if (tempImage.x || tempImage.y || scaleX || rotation || skew) clipMode(data, box, tempImage.x, tempImage.y, scaleX, scaleY, rotation, skew)
63
+ if (tempImage.x || tempImage.y || scaleX || clipSize || rotation || skew) clipMode(data, box, tempImage.x, tempImage.y, scaleX, scaleY, rotation, skew, paint.clipSize)
64
64
  break
65
65
  case 'repeat':
66
- 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)
67
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)
68
70
  break
69
71
  case 'fit':
70
72
  case 'cover':
@@ -88,6 +90,21 @@ export function getPatternData(paint: IImagePaint, box: IBoundsData, image: ILea
88
90
  data.height = height
89
91
  if (opacity) data.opacity = opacity
90
92
  if (filters) data.filters = filters
91
- if (repeat) data.repeat = typeof repeat === 'string' ? (repeat === 'x' ? 'repeat-x' : 'repeat-y') : 'repeat'
93
+ if (repeat) data.repeat = isString(repeat) ? (repeat === 'x' ? 'repeat-x' : 'repeat-y') : 'repeat'
92
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
93
110
  }
package/src/mode.ts CHANGED
@@ -1,11 +1,11 @@
1
- import { IBoundsData, IPointData, IMatrixData, IAlign } from '@leafer/interface'
2
- import { MatrixHelper } from '@leafer/core'
1
+ import { IBoundsData, IPointData, IMatrixData, IAlign, ISizeData } from '@leafer/interface'
2
+ import { getMatrixData, MatrixHelper } from '@leafer/core'
3
3
 
4
4
  import { ILeafPaintPatternData } from '@leafer-ui/interface'
5
5
 
6
6
 
7
- let origin = {} as IPointData
8
- const { get, rotateOfOuter, translate, scaleOfOuter, scale: scaleHelper, rotate, skew: skewHelper } = MatrixHelper
7
+ let origin = {} as IPointData, tempMatrix = getMatrixData()
8
+ const { get, rotateOfOuter, translate, scaleOfOuter, multiplyParent, scale: scaleHelper, rotate, skew: skewHelper } = MatrixHelper
9
9
 
10
10
  export function fillOrFitMode(data: ILeafPaintPatternData, box: IBoundsData, x: number, y: number, scaleX: number, scaleY: number, rotation: number): void {
11
11
  const transform: IMatrixData = get()
@@ -15,41 +15,51 @@ export function fillOrFitMode(data: ILeafPaintPatternData, box: IBoundsData, x:
15
15
  data.transform = transform
16
16
  }
17
17
 
18
-
19
- export function clipMode(data: ILeafPaintPatternData, box: IBoundsData, x: number, y: number, scaleX: number, scaleY: number, rotation: number, skew: IPointData): void {
20
- // rotate -> skew -> scale -> translate
18
+ export function clipMode(data: ILeafPaintPatternData, box: IBoundsData, x: number, y: number, scaleX: number, scaleY: number, rotation: number, skew: IPointData, clipSize?: ISizeData): void {
21
19
  const transform: IMatrixData = get()
22
- if (rotation) rotate(transform, rotation)
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)
21
+ if (clipSize) {
22
+ tempMatrix.a = box.width / clipSize.width, tempMatrix.d = box.height / clipSize.height
23
+ multiplyParent(transform, tempMatrix)
24
+ }
26
25
  data.transform = transform
27
26
  }
28
27
 
29
-
30
- 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 {
31
29
  const transform = get()
32
- if (rotation) {
33
- if (align === 'center') {
34
- rotateOfOuter(transform, { x: width / 2, y: height / 2 }, rotation)
35
- } else {
36
- rotate(transform, rotation)
37
- switch (rotation) {
38
- case 90:
39
- translate(transform, height, 0)
40
- break
41
- case 180:
42
- translate(transform, width, height)
43
- break
44
- case 270:
45
- translate(transform, 0, width)
46
- break
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
+ }
47
49
  }
48
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)
49
55
  }
50
- origin.x = box.x + x
51
- origin.y = box.y + y
52
- translate(transform, origin.x, origin.y)
53
- if (scaleX) scaleOfOuter(transform, origin, scaleX, scaleY)
54
56
  data.transform = transform
55
- }
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
@@ -1,24 +1,25 @@
1
- import { Platform, MatrixHelper, ImageManager } from '@leafer/core'
1
+ import { Platform, MatrixHelper } from '@leafer/core'
2
2
 
3
3
  import { IUI, ILeafPaint, IMatrixData } from '@leafer-ui/interface'
4
4
 
5
5
 
6
6
  const { get, scale, copy } = MatrixHelper
7
- const { ceil, abs } = Math
7
+ const { floor, max, abs } = Math
8
8
 
9
9
  export function createPattern(ui: IUI, paint: ILeafPaint, pixelRatio: number): boolean {
10
-
11
- let { scaleX, scaleY } = ImageManager.patternLocked ? ui.__world : ui.__nowWorld
12
-
10
+ let { scaleX, scaleY } = ui.getRenderScaleData(true, paint.scaleFixed)
13
11
  const id = scaleX + '-' + scaleY + '-' + pixelRatio
14
12
 
15
13
  if (paint.patternId !== id && !ui.destroyed) {
16
14
 
17
- scaleX = abs(scaleX) // maybe -1
18
- scaleY = abs(scaleY)
19
-
20
15
  const { image, data } = paint
21
- 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)
22
23
 
23
24
  if (sx) {
24
25
  sx = abs(sx) // maybe -1
@@ -30,8 +31,6 @@ export function createPattern(ui: IUI, paint: ILeafPaint, pixelRatio: number): b
30
31
  scaleY *= sy
31
32
  }
32
33
 
33
- scaleX *= pixelRatio
34
- scaleY *= pixelRatio
35
34
  width *= scaleX
36
35
  height *= scaleY
37
36
 
@@ -70,7 +69,12 @@ export function createPattern(ui: IUI, paint: ILeafPaint, pixelRatio: number): b
70
69
  scale(imageMatrix, 1 / scaleX, 1 / scaleY)
71
70
  }
72
71
 
73
- const canvas = image.getCanvas(ceil(width) || 1, ceil(height) || 1, data.opacity, data.filters)
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)
74
78
  const pattern = image.getPattern(canvas, repeat || (Platform.origin.noRepeat || 'no-repeat'), imageMatrix, paint)
75
79
 
76
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 instanceof Array) {
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 instanceof Array)) input = [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
  }