@leafer-in/stroke-sides 2.3.0 → 2.3.2
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/dist/stroke-sides.cjs +135 -0
- package/dist/stroke-sides.esm.js +133 -0
- package/dist/stroke-sides.esm.min.js +2 -0
- package/dist/stroke-sides.esm.min.js.map +1 -0
- package/dist/stroke-sides.js +119 -0
- package/dist/stroke-sides.min.cjs +2 -0
- package/dist/stroke-sides.min.cjs.map +1 -0
- package/dist/stroke-sides.min.js +2 -0
- package/dist/stroke-sides.min.js.map +1 -0
- package/package.json +6 -6
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var draw = require("@leafer-ui/draw");
|
|
4
|
+
|
|
5
|
+
var core = require("@leafer/core");
|
|
6
|
+
|
|
7
|
+
var core$1 = require("@leafer-ui/core");
|
|
8
|
+
|
|
9
|
+
function fillStroke(stroke, ui, canvas, renderOptions) {
|
|
10
|
+
canvas.beginPath();
|
|
11
|
+
const {data: data, windingRule: windingRule} = ui.__.__pathForStroke;
|
|
12
|
+
core.PathDrawer.drawPathByData(canvas, data);
|
|
13
|
+
if (core.isObject(stroke)) {
|
|
14
|
+
drawStrokesStyle(stroke, ui, canvas, renderOptions);
|
|
15
|
+
} else {
|
|
16
|
+
canvas.fillStyle = stroke;
|
|
17
|
+
windingRule ? canvas.fill(windingRule) : canvas.fill();
|
|
18
|
+
}
|
|
19
|
+
if (ui.__.__fillAfterStroke) ui.__drawRenderPath(canvas);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function drawStrokesStyle(strokes, ui, canvas, renderOptions) {
|
|
23
|
+
let item;
|
|
24
|
+
for (let i = 0, len = strokes.length; i < len; i++) {
|
|
25
|
+
item = strokes[i];
|
|
26
|
+
if (item.image && draw.PaintImage.checkImage(item, false, ui, canvas, renderOptions)) continue;
|
|
27
|
+
if (item.style) {
|
|
28
|
+
const {windingRule: windingRule} = ui.__.__pathForStroke;
|
|
29
|
+
if (item.originPaint.blendMode) {
|
|
30
|
+
canvas.saveBlendMode(item.originPaint.blendMode);
|
|
31
|
+
canvas.fillStyle = item.style;
|
|
32
|
+
windingRule ? canvas.fill(windingRule) : canvas.fill();
|
|
33
|
+
canvas.restoreBlendMode();
|
|
34
|
+
} else {
|
|
35
|
+
canvas.fillStyle = item.style;
|
|
36
|
+
windingRule ? canvas.fill(windingRule) : canvas.fill();
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function createRectStrokePath(width, height, cornerRadius, strokeWidth, strokeAlign) {
|
|
43
|
+
if (cornerRadius) {
|
|
44
|
+
const [r0, r1, r2, r3] = cornerRadius;
|
|
45
|
+
const [t, r_w, b, l] = strokeWidth;
|
|
46
|
+
const hasRadius = r0 + r1 + r2 + r3 > 0;
|
|
47
|
+
if (hasRadius) {
|
|
48
|
+
const data = [];
|
|
49
|
+
const expand = strokeAlign === "inside" ? 0 : strokeAlign === "center" ? .5 : 1;
|
|
50
|
+
const shrink = 1 - expand;
|
|
51
|
+
const ox = -l * expand, oy = -t * expand;
|
|
52
|
+
const ow = width + (l + r_w) * expand;
|
|
53
|
+
const oh = height + (t + b) * expand;
|
|
54
|
+
const outerR = [ r0 + Math.max(t, l) * expand, r1 + Math.max(t, r_w) * expand, r2 + Math.max(b, r_w) * expand, r3 + Math.max(b, l) * expand ];
|
|
55
|
+
const ix = l * shrink, iy = t * shrink;
|
|
56
|
+
const iw = width - (l + r_w) * shrink;
|
|
57
|
+
const ih = height - (t + b) * shrink;
|
|
58
|
+
core.PathCommandDataHelper.roundRect(data, ox, oy, ow, oh, outerR);
|
|
59
|
+
if (iw > 0 && ih > 0) {
|
|
60
|
+
const innerR = [ Math.max(0, r0 - Math.max(t, l) * shrink), Math.max(0, r1 - Math.max(t, r_w) * shrink), Math.max(0, r2 - Math.max(b, r_w) * shrink), Math.max(0, r3 - Math.max(b, l) * shrink) ];
|
|
61
|
+
core.PathCommandDataHelper.roundRect(data, ix, iy, iw, ih, innerR);
|
|
62
|
+
}
|
|
63
|
+
return {
|
|
64
|
+
data: data,
|
|
65
|
+
windingRule: "evenodd"
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return createRectStrokePathNoRadius(width, height, strokeWidth, strokeAlign);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function createRectStrokePathNoRadius(width, height, strokeWidth, strokeAlign) {
|
|
73
|
+
const data = [];
|
|
74
|
+
const [t, r_w, b, l] = strokeWidth;
|
|
75
|
+
const ext = strokeAlign === "inside" ? 0 : strokeAlign === "center" ? .5 : 1;
|
|
76
|
+
const ins = 1 - ext;
|
|
77
|
+
const xL = -l * ext;
|
|
78
|
+
const xR = width + r_w * ext;
|
|
79
|
+
const yT = -t * ext;
|
|
80
|
+
const yB = height + b * ext;
|
|
81
|
+
const innerYStart = t * ins;
|
|
82
|
+
const innerYEnd = height - b * ins;
|
|
83
|
+
const innerHeight = Math.max(0, innerYEnd - innerYStart);
|
|
84
|
+
if (t > 0) core.PathCommandDataHelper.rect(data, xL, yT, xR - xL, t);
|
|
85
|
+
if (b > 0) core.PathCommandDataHelper.rect(data, xL, yB - b, xR - xL, b);
|
|
86
|
+
if (l > 0 && innerHeight > 0) {
|
|
87
|
+
core.PathCommandDataHelper.rect(data, xL, innerYStart, l, innerHeight);
|
|
88
|
+
}
|
|
89
|
+
if (r_w > 0 && innerHeight > 0) {
|
|
90
|
+
core.PathCommandDataHelper.rect(data, xR - r_w, innerYStart, r_w, innerHeight);
|
|
91
|
+
}
|
|
92
|
+
return {
|
|
93
|
+
data: data
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function strokeWidthType(defaultValue) {
|
|
98
|
+
return core$1.decorateLeafAttr(defaultValue, key => core$1.attr({
|
|
99
|
+
set(value) {
|
|
100
|
+
if (this.__setAttr(key, value)) {
|
|
101
|
+
core$1.doStrokeType(this);
|
|
102
|
+
const data = this.__;
|
|
103
|
+
data.__useStroke = true;
|
|
104
|
+
let hasStrokeSides;
|
|
105
|
+
core$1.DataHelper.stintSet(data, "__hasStrokeSides", hasStrokeSides = core$1.isArray(value) && Math.max(...value));
|
|
106
|
+
if (hasStrokeSides) {
|
|
107
|
+
core$1.doBoundsType(this);
|
|
108
|
+
} else if (data.__pathForStroke) data.__pathForStroke = undefined;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}));
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
draw.Plugin.add("stroke-sides");
|
|
115
|
+
|
|
116
|
+
draw.Rect.addAttr("strokeWidth", 1, strokeWidthType);
|
|
117
|
+
|
|
118
|
+
draw.Box.addAttr("strokeWidth", 1, strokeWidthType);
|
|
119
|
+
|
|
120
|
+
draw.Paint.fillStroke = fillStroke;
|
|
121
|
+
|
|
122
|
+
const {stintSet: stintSet} = draw.DataHelper;
|
|
123
|
+
|
|
124
|
+
draw.Rect.prototype.__updatePath = draw.Box.prototype.__updatePath = function() {
|
|
125
|
+
const data = this.__;
|
|
126
|
+
if (data.__hasStrokeSides) {
|
|
127
|
+
const {width: width, height: height, cornerRadius: cornerRadius, strokeWidth: strokeWidth, strokeAlign: strokeAlign} = data;
|
|
128
|
+
data.__pathForStroke = data.__pathInputed ? undefined : createRectStrokePath(width, height, cornerRadius && draw.MathHelper.fourNumber(cornerRadius), draw.MathHelper.fourNumber(strokeWidth), strokeAlign);
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
draw.BoxData.prototype.__checkComplex = draw.RectData.prototype.__checkComplex = function() {
|
|
133
|
+
const t = this;
|
|
134
|
+
stintSet(t, "__complex", t.__isFills || t.__isStrokes || t.cornerRadius || t.__hasStrokeSides || t.__useEffect);
|
|
135
|
+
};
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { PaintImage, Plugin, Rect, Box, Paint, DataHelper as DataHelper$1, MathHelper, BoxData, RectData } from "@leafer-ui/draw";
|
|
2
|
+
|
|
3
|
+
import { PathDrawer, isObject, PathCommandDataHelper } from "@leafer/core";
|
|
4
|
+
|
|
5
|
+
import { decorateLeafAttr, attr, doStrokeType, DataHelper, isArray, doBoundsType } from "@leafer-ui/core";
|
|
6
|
+
|
|
7
|
+
function fillStroke(stroke, ui, canvas, renderOptions) {
|
|
8
|
+
canvas.beginPath();
|
|
9
|
+
const {data: data, windingRule: windingRule} = ui.__.__pathForStroke;
|
|
10
|
+
PathDrawer.drawPathByData(canvas, data);
|
|
11
|
+
if (isObject(stroke)) {
|
|
12
|
+
drawStrokesStyle(stroke, ui, canvas, renderOptions);
|
|
13
|
+
} else {
|
|
14
|
+
canvas.fillStyle = stroke;
|
|
15
|
+
windingRule ? canvas.fill(windingRule) : canvas.fill();
|
|
16
|
+
}
|
|
17
|
+
if (ui.__.__fillAfterStroke) ui.__drawRenderPath(canvas);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function drawStrokesStyle(strokes, ui, canvas, renderOptions) {
|
|
21
|
+
let item;
|
|
22
|
+
for (let i = 0, len = strokes.length; i < len; i++) {
|
|
23
|
+
item = strokes[i];
|
|
24
|
+
if (item.image && PaintImage.checkImage(item, false, ui, canvas, renderOptions)) continue;
|
|
25
|
+
if (item.style) {
|
|
26
|
+
const {windingRule: windingRule} = ui.__.__pathForStroke;
|
|
27
|
+
if (item.originPaint.blendMode) {
|
|
28
|
+
canvas.saveBlendMode(item.originPaint.blendMode);
|
|
29
|
+
canvas.fillStyle = item.style;
|
|
30
|
+
windingRule ? canvas.fill(windingRule) : canvas.fill();
|
|
31
|
+
canvas.restoreBlendMode();
|
|
32
|
+
} else {
|
|
33
|
+
canvas.fillStyle = item.style;
|
|
34
|
+
windingRule ? canvas.fill(windingRule) : canvas.fill();
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function createRectStrokePath(width, height, cornerRadius, strokeWidth, strokeAlign) {
|
|
41
|
+
if (cornerRadius) {
|
|
42
|
+
const [r0, r1, r2, r3] = cornerRadius;
|
|
43
|
+
const [t, r_w, b, l] = strokeWidth;
|
|
44
|
+
const hasRadius = r0 + r1 + r2 + r3 > 0;
|
|
45
|
+
if (hasRadius) {
|
|
46
|
+
const data = [];
|
|
47
|
+
const expand = strokeAlign === "inside" ? 0 : strokeAlign === "center" ? .5 : 1;
|
|
48
|
+
const shrink = 1 - expand;
|
|
49
|
+
const ox = -l * expand, oy = -t * expand;
|
|
50
|
+
const ow = width + (l + r_w) * expand;
|
|
51
|
+
const oh = height + (t + b) * expand;
|
|
52
|
+
const outerR = [ r0 + Math.max(t, l) * expand, r1 + Math.max(t, r_w) * expand, r2 + Math.max(b, r_w) * expand, r3 + Math.max(b, l) * expand ];
|
|
53
|
+
const ix = l * shrink, iy = t * shrink;
|
|
54
|
+
const iw = width - (l + r_w) * shrink;
|
|
55
|
+
const ih = height - (t + b) * shrink;
|
|
56
|
+
PathCommandDataHelper.roundRect(data, ox, oy, ow, oh, outerR);
|
|
57
|
+
if (iw > 0 && ih > 0) {
|
|
58
|
+
const innerR = [ Math.max(0, r0 - Math.max(t, l) * shrink), Math.max(0, r1 - Math.max(t, r_w) * shrink), Math.max(0, r2 - Math.max(b, r_w) * shrink), Math.max(0, r3 - Math.max(b, l) * shrink) ];
|
|
59
|
+
PathCommandDataHelper.roundRect(data, ix, iy, iw, ih, innerR);
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
data: data,
|
|
63
|
+
windingRule: "evenodd"
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return createRectStrokePathNoRadius(width, height, strokeWidth, strokeAlign);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function createRectStrokePathNoRadius(width, height, strokeWidth, strokeAlign) {
|
|
71
|
+
const data = [];
|
|
72
|
+
const [t, r_w, b, l] = strokeWidth;
|
|
73
|
+
const ext = strokeAlign === "inside" ? 0 : strokeAlign === "center" ? .5 : 1;
|
|
74
|
+
const ins = 1 - ext;
|
|
75
|
+
const xL = -l * ext;
|
|
76
|
+
const xR = width + r_w * ext;
|
|
77
|
+
const yT = -t * ext;
|
|
78
|
+
const yB = height + b * ext;
|
|
79
|
+
const innerYStart = t * ins;
|
|
80
|
+
const innerYEnd = height - b * ins;
|
|
81
|
+
const innerHeight = Math.max(0, innerYEnd - innerYStart);
|
|
82
|
+
if (t > 0) PathCommandDataHelper.rect(data, xL, yT, xR - xL, t);
|
|
83
|
+
if (b > 0) PathCommandDataHelper.rect(data, xL, yB - b, xR - xL, b);
|
|
84
|
+
if (l > 0 && innerHeight > 0) {
|
|
85
|
+
PathCommandDataHelper.rect(data, xL, innerYStart, l, innerHeight);
|
|
86
|
+
}
|
|
87
|
+
if (r_w > 0 && innerHeight > 0) {
|
|
88
|
+
PathCommandDataHelper.rect(data, xR - r_w, innerYStart, r_w, innerHeight);
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
data: data
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function strokeWidthType(defaultValue) {
|
|
96
|
+
return decorateLeafAttr(defaultValue, key => attr({
|
|
97
|
+
set(value) {
|
|
98
|
+
if (this.__setAttr(key, value)) {
|
|
99
|
+
doStrokeType(this);
|
|
100
|
+
const data = this.__;
|
|
101
|
+
data.__useStroke = true;
|
|
102
|
+
let hasStrokeSides;
|
|
103
|
+
DataHelper.stintSet(data, "__hasStrokeSides", hasStrokeSides = isArray(value) && Math.max(...value));
|
|
104
|
+
if (hasStrokeSides) {
|
|
105
|
+
doBoundsType(this);
|
|
106
|
+
} else if (data.__pathForStroke) data.__pathForStroke = undefined;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}));
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
Plugin.add("stroke-sides");
|
|
113
|
+
|
|
114
|
+
Rect.addAttr("strokeWidth", 1, strokeWidthType);
|
|
115
|
+
|
|
116
|
+
Box.addAttr("strokeWidth", 1, strokeWidthType);
|
|
117
|
+
|
|
118
|
+
Paint.fillStroke = fillStroke;
|
|
119
|
+
|
|
120
|
+
const {stintSet: stintSet} = DataHelper$1;
|
|
121
|
+
|
|
122
|
+
Rect.prototype.__updatePath = Box.prototype.__updatePath = function() {
|
|
123
|
+
const data = this.__;
|
|
124
|
+
if (data.__hasStrokeSides) {
|
|
125
|
+
const {width: width, height: height, cornerRadius: cornerRadius, strokeWidth: strokeWidth, strokeAlign: strokeAlign} = data;
|
|
126
|
+
data.__pathForStroke = data.__pathInputed ? undefined : createRectStrokePath(width, height, cornerRadius && MathHelper.fourNumber(cornerRadius), MathHelper.fourNumber(strokeWidth), strokeAlign);
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
BoxData.prototype.__checkComplex = RectData.prototype.__checkComplex = function() {
|
|
131
|
+
const t = this;
|
|
132
|
+
stintSet(t, "__complex", t.__isFills || t.__isStrokes || t.cornerRadius || t.__hasStrokeSides || t.__useEffect);
|
|
133
|
+
};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{PaintImage as t,Plugin as e,Rect as o,Box as r,Paint as i,DataHelper as a,MathHelper as n,BoxData as _,RectData as s}from"@leafer-ui/draw";import{PathDrawer as l,isObject as d,PathCommandDataHelper as h}from"@leafer/core";import{decorateLeafAttr as c,attr as f,doStrokeType as u,DataHelper as m,isArray as p,doBoundsType as k}from"@leafer-ui/core";function S(t,e,o,r,i){if(o){const[a,n,_,s]=o,[l,d,c,f]=r;if(a+n+_+s>0){const o=[],r="inside"===i?0:"center"===i?.5:1,u=1-r,m=-f*r,p=-l*r,k=t+(f+d)*r,S=e+(l+c)*r,M=[a+Math.max(l,f)*r,n+Math.max(l,d)*r,_+Math.max(c,d)*r,s+Math.max(c,f)*r],x=f*u,g=l*u,y=t-(f+d)*u,R=e-(l+c)*u;if(h.roundRect(o,m,p,k,S,M),y>0&&R>0){const t=[Math.max(0,a-Math.max(l,f)*u),Math.max(0,n-Math.max(l,d)*u),Math.max(0,_-Math.max(c,d)*u),Math.max(0,s-Math.max(c,f)*u)];h.roundRect(o,x,g,y,R,t)}return{data:o,windingRule:"evenodd"}}}return function(t,e,o,r){const i=[],[a,n,_,s]=o,l="inside"===r?0:"center"===r?.5:1,d=1-l,c=-s*l,f=t+n*l,u=-a*l,m=e+_*l,p=a*d,k=e-_*d,S=Math.max(0,k-p);a>0&&h.rect(i,c,u,f-c,a);_>0&&h.rect(i,c,m-_,f-c,_);s>0&&S>0&&h.rect(i,c,p,s,S);n>0&&S>0&&h.rect(i,f-n,p,n,S);return{data:i}}(t,e,r,i)}function M(t){return c(t,t=>f({set(e){if(this.__setAttr(t,e)){u(this);const t=this.__;let o;t.__useStroke=!0,m.stintSet(t,"__hasStrokeSides",o=p(e)&&Math.max(...e)),o?k(this):t.__pathForStroke&&(t.__pathForStroke=void 0)}}}))}e.add("stroke-sides"),o.addAttr("strokeWidth",1,M),r.addAttr("strokeWidth",1,M),i.fillStroke=function(e,o,r,i){r.beginPath();const{data:a,windingRule:n}=o.__.__pathForStroke;l.drawPathByData(r,a),d(e)?function(e,o,r,i){let a;for(let n=0,_=e.length;n<_;n++)if(a=e[n],(!a.image||!t.checkImage(a,!1,o,r,i))&&a.style){const{windingRule:t}=o.__.__pathForStroke;a.originPaint.blendMode?(r.saveBlendMode(a.originPaint.blendMode),r.fillStyle=a.style,t?r.fill(t):r.fill(),r.restoreBlendMode()):(r.fillStyle=a.style,t?r.fill(t):r.fill())}}(e,o,r,i):(r.fillStyle=e,n?r.fill(n):r.fill()),o.__.__fillAfterStroke&&o.__drawRenderPath(r)};const{stintSet:x}=a;o.prototype.__updatePath=r.prototype.__updatePath=function(){const t=this.__;if(t.__hasStrokeSides){const{width:e,height:o,cornerRadius:r,strokeWidth:i,strokeAlign:a}=t;t.__pathForStroke=t.__pathInputed?void 0:S(e,o,r&&n.fourNumber(r),n.fourNumber(i),a)}},_.prototype.__checkComplex=s.prototype.__checkComplex=function(){const t=this;x(t,"__complex",t.__isFills||t.__isStrokes||t.cornerRadius||t.__hasStrokeSides||t.__useEffect)};
|
|
2
|
+
//# sourceMappingURL=stroke-sides.esm.min.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stroke-sides.esm.min.js","sources":["../../../../../../src/in/packages/stroke-sides/src/path.ts","../../../../../../src/in/packages/stroke-sides/src/decorator.ts","../../../../../../src/in/packages/stroke-sides/src/index.ts","../../../../../../src/in/packages/stroke-sides/src/fillSroke.ts"],"sourcesContent":["import { IPathCommandData, IPathCommandDataWithWindingRule } from '@leafer/interface'\nimport { PathCommandDataHelper } from \"@leafer/core\"\nimport { IStrokeAlign } from '@leafer-ui/interface'\n\n/**\n * 矩形描边路径生成器\n * 支持非均匀描边(上右下左宽度不同)与圆角逻辑\n */\nexport function createRectStrokePath(width: number, height: number, cornerRadius: number[] | undefined, strokeWidth: number[], strokeAlign: IStrokeAlign): IPathCommandDataWithWindingRule {\n\n if (cornerRadius) {\n const [r0, r1, r2, r3] = cornerRadius\n const [t, r_w, b, l] = strokeWidth\n\n const hasRadius = (r0 + r1 + r2 + r3) > 0\n\n // 场景 A: 包含圆角,必须使用 evenodd 挖空法\n if (hasRadius) {\n const data: IPathCommandData = []\n const expand = strokeAlign === 'inside' ? 0 : (strokeAlign === 'center' ? 0.5 : 1)\n const shrink = 1 - expand\n\n // 外边界参数\n const ox = -l * expand, oy = -t * expand\n const ow = width + (l + r_w) * expand\n const oh = height + (t + b) * expand\n const outerR = [\n r0 + Math.max(t, l) * expand,\n r1 + Math.max(t, r_w) * expand,\n r2 + Math.max(b, r_w) * expand,\n r3 + Math.max(b, l) * expand\n ]\n\n // 内边界参数\n const ix = l * shrink, iy = t * shrink\n const iw = width - (l + r_w) * shrink\n const ih = height - (t + b) * shrink\n\n // 绘制外框\n PathCommandDataHelper.roundRect(data, ox, oy, ow, oh, outerR)\n\n // 只有内框有空间时才绘制内框(进行掏空)\n if (iw > 0 && ih > 0) {\n const innerR = [\n Math.max(0, r0 - Math.max(t, l) * shrink),\n Math.max(0, r1 - Math.max(t, r_w) * shrink),\n Math.max(0, r2 - Math.max(b, r_w) * shrink),\n Math.max(0, r3 - Math.max(b, l) * shrink)\n ]\n PathCommandDataHelper.roundRect(data, ix, iy, iw, ih, innerR)\n }\n\n return { data, windingRule: 'evenodd' }\n }\n }\n\n\n\n // 场景 B: 纯直角,采用四边拼接法 (性能最优,无 WindingRule 依赖)\n return createRectStrokePathNoRadius(width, height, strokeWidth, strokeAlign)\n}\n\n/**\n * 纯直角矩形描边生成器 (拼接法)\n */\nfunction createRectStrokePathNoRadius(\n width: number,\n height: number,\n strokeWidth: number[],\n strokeAlign: IStrokeAlign\n): IPathCommandDataWithWindingRule {\n const data: IPathCommandData = []\n const [t, r_w, b, l] = strokeWidth\n\n const ext = strokeAlign === 'inside' ? 0 : (strokeAlign === 'center' ? 0.5 : 1)\n const ins = 1 - ext\n\n // 计算外部极值边界坐标\n const xL = -l * ext\n const xR = width + r_w * ext\n const yT = -t * ext\n const yB = height + b * ext\n\n // 计算内部裁剪边界坐标 (用于侧边填充高度)\n const innerYStart = t * ins\n const innerYEnd = height - b * ins\n const innerHeight = Math.max(0, innerYEnd - innerYStart)\n\n // 1. Top Bar: 覆盖全宽\n if (t > 0) PathCommandDataHelper.rect(data, xL, yT, xR - xL, t)\n\n // 2. Bottom Bar: 覆盖全宽\n if (b > 0) PathCommandDataHelper.rect(data, xL, yB - b, xR - xL, b)\n\n // 3. Left Bar: 填充中间高度,避免与 Top/Bottom 重合\n if (l > 0 && innerHeight > 0) {\n PathCommandDataHelper.rect(data, xL, innerYStart, l, innerHeight)\n }\n\n // 4. Right Bar: 填充中间高度\n if (r_w > 0 && innerHeight > 0) {\n PathCommandDataHelper.rect(data, xR - r_w, innerYStart, r_w, innerHeight)\n }\n\n return { data }\n}","import { IUIData, IValue } from '@leafer-ui/interface'\nimport { decorateLeafAttr, attr, doStrokeType, doBoundsType, isArray, DataHelper } from '@leafer-ui/core'\n\nexport function strokeWidthType(defaultValue?: IValue) {\n return decorateLeafAttr(defaultValue, (key: string) => attr({\n set(value: IValue) {\n if (this.__setAttr(key, value)) {\n doStrokeType(this)\n const data = this.__\n data.__useStroke = true\n let hasStrokeSides\n DataHelper.stintSet(data as IUIData, '__hasStrokeSides', hasStrokeSides = isArray(value) && Math.max(...value))\n if (hasStrokeSides) {\n doBoundsType(this)\n } else if ((data as IUIData).__pathForStroke) (data as IUIData).__pathForStroke = undefined\n }\n }\n }))\n}","import { Paint, Plugin, Rect, Box, RectData, DataHelper, MathHelper, BoxData } from '@leafer-ui/draw'\nimport { fillStroke } from './fillSroke'\nimport { createRectStrokePath } from './path'\nimport { strokeWidthType } from './decorator'\nimport { IRectData } from '@leafer-ui/interface'\n\nPlugin.add('stroke-sides')\n\nRect.addAttr('strokeWidth', 1, strokeWidthType)\nBox.addAttr('strokeWidth', 1, strokeWidthType)\n\nPaint.fillStroke = fillStroke\n\nconst { stintSet } = DataHelper\n\nRect.prototype.__updatePath = Box.prototype.__updatePath = function (): void {\n const data = this.__\n if (data.__hasStrokeSides) {\n const { width, height, cornerRadius, strokeWidth, strokeAlign } = data\n data.__pathForStroke = data.__pathInputed ? undefined : createRectStrokePath(width, height, cornerRadius && MathHelper.fourNumber(cornerRadius), MathHelper.fourNumber(strokeWidth), strokeAlign)\n }\n}\n\nBoxData.prototype.__checkComplex = RectData.prototype.__checkComplex = function (): void {\n const t = this as IRectData\n stintSet(t, '__complex', (t.__isFills || t.__isStrokes || t.cornerRadius || t.__hasStrokeSides || t.__useEffect) as boolean)\n}","import { ILeaferCanvas, IRenderOptions } from '@leafer/interface'\nimport { isObject, PathDrawer } from \"@leafer/core\"\n\nimport { IUI, ILeafPaint, ILeafStrokePaint } from '@leafer-ui/interface'\nimport { PaintImage } from \"@leafer-ui/draw\"\n\n\nexport function fillStroke(stroke: string | ILeafPaint[], ui: IUI, canvas: ILeaferCanvas, renderOptions: IRenderOptions): void {\n\n canvas.beginPath()\n const { data, windingRule } = ui.__.__pathForStroke\n PathDrawer.drawPathByData(canvas, data)\n\n if (isObject(stroke)) {\n drawStrokesStyle(stroke, ui, canvas, renderOptions)\n } else {\n\n canvas.fillStyle = stroke\n windingRule ? canvas.fill(windingRule) : canvas.fill()\n\n }\n\n if (ui.__.__fillAfterStroke) ui.__drawRenderPath(canvas)\n}\n\n\nfunction drawStrokesStyle(strokes: ILeafStrokePaint[], ui: IUI, canvas: ILeaferCanvas, renderOptions: IRenderOptions): void {\n let item: ILeafStrokePaint\n\n for (let i = 0, len = strokes.length; i < len; i++) {\n item = strokes[i]\n\n if (item.image && PaintImage.checkImage(item, false, ui, canvas, renderOptions)) continue\n\n if (item.style) {\n\n const { windingRule } = ui.__.__pathForStroke\n\n if (item.originPaint.blendMode) {\n canvas.saveBlendMode(item.originPaint.blendMode)\n canvas.fillStyle = item.style\n windingRule ? canvas.fill(windingRule) : canvas.fill()\n canvas.restoreBlendMode()\n } else {\n canvas.fillStyle = item.style\n windingRule ? canvas.fill(windingRule) : canvas.fill()\n }\n }\n }\n}"],"names":["createRectStrokePath","width","height","cornerRadius","strokeWidth","strokeAlign","r0","r1","r2","r3","t","r_w","b","l","data","expand","shrink","ox","oy","ow","oh","outerR","Math","max","ix","iy","iw","ih","PathCommandDataHelper","roundRect","innerR","windingRule","ext","ins","xL","xR","yT","yB","innerYStart","innerYEnd","innerHeight","rect","createRectStrokePathNoRadius","strokeWidthType","defaultValue","decorateLeafAttr","key","attr","set","value","this","__setAttr","doStrokeType","__","hasStrokeSides","__useStroke","DataHelper","stintSet","isArray","doBoundsType","__pathForStroke","undefined","Plugin","add","Rect","addAttr","Box","Paint","fillStroke","stroke","ui","canvas","renderOptions","beginPath","PathDrawer","drawPathByData","isObject","strokes","item","i","len","length","image","PaintImage","checkImage","style","originPaint","blendMode","saveBlendMode","fillStyle","fill","restoreBlendMode","drawStrokesStyle","__fillAfterStroke","__drawRenderPath","prototype","__updatePath","__hasStrokeSides","__pathInputed","MathHelper","fourNumber","BoxData","__checkComplex","RectData","__isFills","__isStrokes","__useEffect"],"mappings":"mWAQM,SAAUA,EAAqBC,EAAeC,EAAgBC,EAAoCC,EAAuBC,GAE3H,GAAIF,EAAc,CACd,MAAOG,EAAIC,EAAIC,EAAIC,GAAMN,GAClBO,EAAGC,EAAKC,EAAGC,GAAKT,EAKvB,GAHmBE,EAAKC,EAAKC,EAAKC,EAAM,EAGzB,CACX,MAAMK,EAAyB,GACzBC,EAAyB,WAAhBV,EAA2B,EAAqB,WAAhBA,EAA2B,GAAM,EAC1EW,EAAS,EAAID,EAGbE,GAAMJ,EAAIE,EAAQG,GAAMR,EAAIK,EAC5BI,EAAKlB,GAASY,EAAIF,GAAOI,EACzBK,EAAKlB,GAAUQ,EAAIE,GAAKG,EACxBM,EAAS,CACXf,EAAKgB,KAAKC,IAAIb,EAAGG,GAAKE,EACtBR,EAAKe,KAAKC,IAAIb,EAAGC,GAAOI,EACxBP,EAAKc,KAAKC,IAAIX,EAAGD,GAAOI,EACxBN,EAAKa,KAAKC,IAAIX,EAAGC,GAAKE,GAIpBS,EAAKX,EAAIG,EAAQS,EAAKf,EAAIM,EAC1BU,EAAKzB,GAASY,EAAIF,GAAOK,EACzBW,EAAKzB,GAAUQ,EAAIE,GAAKI,EAM9B,GAHAY,EAAsBC,UAAUf,EAAMG,EAAIC,EAAIC,EAAIC,EAAIC,GAGlDK,EAAK,GAAKC,EAAK,EAAG,CAClB,MAAMG,EAAS,CACXR,KAAKC,IAAI,EAAGjB,EAAKgB,KAAKC,IAAIb,EAAGG,GAAKG,GAClCM,KAAKC,IAAI,EAAGhB,EAAKe,KAAKC,IAAIb,EAAGC,GAAOK,GACpCM,KAAKC,IAAI,EAAGf,EAAKc,KAAKC,IAAIX,EAAGD,GAAOK,GACpCM,KAAKC,IAAI,EAAGd,EAAKa,KAAKC,IAAIX,EAAGC,GAAKG,IAEtCY,EAAsBC,UAAUf,EAAMU,EAAIC,EAAIC,EAAIC,EAAIG,EAC1D,CAEA,MAAO,CAAEhB,OAAMiB,YAAa,UAChC,CACJ,CAKA,OAMJ,SACI9B,EACAC,EACAE,EACAC,GAEA,MAAMS,EAAyB,IACxBJ,EAAGC,EAAKC,EAAGC,GAAKT,EAEjB4B,EAAsB,WAAhB3B,EAA2B,EAAqB,WAAhBA,EAA2B,GAAM,EACvE4B,EAAM,EAAID,EAGVE,GAAMrB,EAAImB,EACVG,EAAKlC,EAAQU,EAAMqB,EACnBI,GAAM1B,EAAIsB,EACVK,EAAKnC,EAASU,EAAIoB,EAGlBM,EAAc5B,EAAIuB,EAClBM,EAAYrC,EAASU,EAAIqB,EACzBO,EAAclB,KAAKC,IAAI,EAAGgB,EAAYD,GAGxC5B,EAAI,GAAGkB,EAAsBa,KAAK3B,EAAMoB,EAAIE,EAAID,EAAKD,EAAIxB,GAGzDE,EAAI,GAAGgB,EAAsBa,KAAK3B,EAAMoB,EAAIG,EAAKzB,EAAGuB,EAAKD,EAAItB,GAG7DC,EAAI,GAAK2B,EAAc,GACvBZ,EAAsBa,KAAK3B,EAAMoB,EAAII,EAAazB,EAAG2B,GAIrD7B,EAAM,GAAK6B,EAAc,GACzBZ,EAAsBa,KAAK3B,EAAMqB,EAAKxB,EAAK2B,EAAa3B,EAAK6B,GAGjE,MAAO,CAAE1B,OACb,CA9CW4B,CAA6BzC,EAAOC,EAAQE,EAAaC,EACpE,CCzDM,SAAUsC,EAAgBC,GAC5B,OAAOC,EAAiBD,EAAeE,GAAgBC,EAAK,CACxD,GAAAC,CAAIC,GACA,GAAIC,KAAKC,UAAUL,EAAKG,GAAQ,CAC5BG,EAAaF,MACb,MAAMpC,EAAOoC,KAAKG,GAElB,IAAIC,EADJxC,EAAKyC,aAAc,EAEnBC,EAAWC,SAAS3C,EAAiB,mBAAoBwC,EAAiBI,EAAQT,IAAU3B,KAAKC,OAAO0B,IACpGK,EACAK,EAAaT,MACLpC,EAAiB8C,kBAAkB9C,EAAiB8C,qBAAkBC,EACtF,CACJ,IAER,CCZAC,EAAOC,IAAI,gBAEXC,EAAKC,QAAQ,cAAe,EAAGtB,GAC/BuB,EAAID,QAAQ,cAAe,EAAGtB,GAE9BwB,EAAMC,WCJA,SAAqBC,EAA+BC,EAASC,EAAuBC,GAEtFD,EAAOE,YACP,MAAM3D,KAAEA,EAAIiB,YAAEA,GAAgBuC,EAAGjB,GAAGO,gBACpCc,EAAWC,eAAeJ,EAAQzD,GAE9B8D,EAASP,GAajB,SAA0BQ,EAA6BP,EAASC,EAAuBC,GACnF,IAAIM,EAEJ,IAAK,IAAIC,EAAI,EAAGC,EAAMH,EAAQI,OAAQF,EAAIC,EAAKD,IAG3C,GAFAD,EAAOD,EAAQE,KAEXD,EAAKI,QAASC,EAAWC,WAAWN,GAAM,EAAOR,EAAIC,EAAQC,KAE7DM,EAAKO,MAAO,CAEZ,MAAMtD,YAAEA,GAAgBuC,EAAGjB,GAAGO,gBAE1BkB,EAAKQ,YAAYC,WACjBhB,EAAOiB,cAAcV,EAAKQ,YAAYC,WACtChB,EAAOkB,UAAYX,EAAKO,MACxBtD,EAAcwC,EAAOmB,KAAK3D,GAAewC,EAAOmB,OAChDnB,EAAOoB,qBAEPpB,EAAOkB,UAAYX,EAAKO,MACxBtD,EAAcwC,EAAOmB,KAAK3D,GAAewC,EAAOmB,OAExD,CAER,CAnCQE,CAAiBvB,EAAQC,EAAIC,EAAQC,IAGrCD,EAAOkB,UAAYpB,EACnBtC,EAAcwC,EAAOmB,KAAK3D,GAAewC,EAAOmB,QAIhDpB,EAAGjB,GAAGwC,mBAAmBvB,EAAGwB,iBAAiBvB,EACrD,EDVA,MAAMd,SAAEA,GAAaD,EAErBQ,EAAK+B,UAAUC,aAAe9B,EAAI6B,UAAUC,aAAe,WACvD,MAAMlF,EAAOoC,KAAKG,GAClB,GAAIvC,EAAKmF,iBAAkB,CACvB,MAAMhG,MAAEA,EAAKC,OAAEA,EAAMC,aAAEA,EAAYC,YAAEA,EAAWC,YAAEA,GAAgBS,EAClEA,EAAK8C,gBAAkB9C,EAAKoF,mBAAgBrC,EAAY7D,EAAqBC,EAAOC,EAAQC,GAAgBgG,EAAWC,WAAWjG,GAAegG,EAAWC,WAAWhG,GAAcC,EACzL,CACJ,EAEAgG,EAAQN,UAAUO,eAAiBC,EAASR,UAAUO,eAAiB,WACnE,MAAM5F,EAAIwC,KACVO,EAAS/C,EAAG,YAAcA,EAAE8F,WAAa9F,EAAE+F,aAAe/F,EAAEP,cAAgBO,EAAEuF,kBAAoBvF,EAAEgG,YACxG"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
(function(draw, core, core$1) {
|
|
2
|
+
"use strict";
|
|
3
|
+
function fillStroke(stroke, ui, canvas, renderOptions) {
|
|
4
|
+
canvas.beginPath();
|
|
5
|
+
const {data: data, windingRule: windingRule} = ui.__.__pathForStroke;
|
|
6
|
+
core.PathDrawer.drawPathByData(canvas, data);
|
|
7
|
+
if (core.isObject(stroke)) {
|
|
8
|
+
drawStrokesStyle(stroke, ui, canvas, renderOptions);
|
|
9
|
+
} else {
|
|
10
|
+
canvas.fillStyle = stroke;
|
|
11
|
+
windingRule ? canvas.fill(windingRule) : canvas.fill();
|
|
12
|
+
}
|
|
13
|
+
if (ui.__.__fillAfterStroke) ui.__drawRenderPath(canvas);
|
|
14
|
+
}
|
|
15
|
+
function drawStrokesStyle(strokes, ui, canvas, renderOptions) {
|
|
16
|
+
let item;
|
|
17
|
+
for (let i = 0, len = strokes.length; i < len; i++) {
|
|
18
|
+
item = strokes[i];
|
|
19
|
+
if (item.image && draw.PaintImage.checkImage(item, false, ui, canvas, renderOptions)) continue;
|
|
20
|
+
if (item.style) {
|
|
21
|
+
const {windingRule: windingRule} = ui.__.__pathForStroke;
|
|
22
|
+
if (item.originPaint.blendMode) {
|
|
23
|
+
canvas.saveBlendMode(item.originPaint.blendMode);
|
|
24
|
+
canvas.fillStyle = item.style;
|
|
25
|
+
windingRule ? canvas.fill(windingRule) : canvas.fill();
|
|
26
|
+
canvas.restoreBlendMode();
|
|
27
|
+
} else {
|
|
28
|
+
canvas.fillStyle = item.style;
|
|
29
|
+
windingRule ? canvas.fill(windingRule) : canvas.fill();
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
function createRectStrokePath(width, height, cornerRadius, strokeWidth, strokeAlign) {
|
|
35
|
+
if (cornerRadius) {
|
|
36
|
+
const [r0, r1, r2, r3] = cornerRadius;
|
|
37
|
+
const [t, r_w, b, l] = strokeWidth;
|
|
38
|
+
const hasRadius = r0 + r1 + r2 + r3 > 0;
|
|
39
|
+
if (hasRadius) {
|
|
40
|
+
const data = [];
|
|
41
|
+
const expand = strokeAlign === "inside" ? 0 : strokeAlign === "center" ? .5 : 1;
|
|
42
|
+
const shrink = 1 - expand;
|
|
43
|
+
const ox = -l * expand, oy = -t * expand;
|
|
44
|
+
const ow = width + (l + r_w) * expand;
|
|
45
|
+
const oh = height + (t + b) * expand;
|
|
46
|
+
const outerR = [ r0 + Math.max(t, l) * expand, r1 + Math.max(t, r_w) * expand, r2 + Math.max(b, r_w) * expand, r3 + Math.max(b, l) * expand ];
|
|
47
|
+
const ix = l * shrink, iy = t * shrink;
|
|
48
|
+
const iw = width - (l + r_w) * shrink;
|
|
49
|
+
const ih = height - (t + b) * shrink;
|
|
50
|
+
core.PathCommandDataHelper.roundRect(data, ox, oy, ow, oh, outerR);
|
|
51
|
+
if (iw > 0 && ih > 0) {
|
|
52
|
+
const innerR = [ Math.max(0, r0 - Math.max(t, l) * shrink), Math.max(0, r1 - Math.max(t, r_w) * shrink), Math.max(0, r2 - Math.max(b, r_w) * shrink), Math.max(0, r3 - Math.max(b, l) * shrink) ];
|
|
53
|
+
core.PathCommandDataHelper.roundRect(data, ix, iy, iw, ih, innerR);
|
|
54
|
+
}
|
|
55
|
+
return {
|
|
56
|
+
data: data,
|
|
57
|
+
windingRule: "evenodd"
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return createRectStrokePathNoRadius(width, height, strokeWidth, strokeAlign);
|
|
62
|
+
}
|
|
63
|
+
function createRectStrokePathNoRadius(width, height, strokeWidth, strokeAlign) {
|
|
64
|
+
const data = [];
|
|
65
|
+
const [t, r_w, b, l] = strokeWidth;
|
|
66
|
+
const ext = strokeAlign === "inside" ? 0 : strokeAlign === "center" ? .5 : 1;
|
|
67
|
+
const ins = 1 - ext;
|
|
68
|
+
const xL = -l * ext;
|
|
69
|
+
const xR = width + r_w * ext;
|
|
70
|
+
const yT = -t * ext;
|
|
71
|
+
const yB = height + b * ext;
|
|
72
|
+
const innerYStart = t * ins;
|
|
73
|
+
const innerYEnd = height - b * ins;
|
|
74
|
+
const innerHeight = Math.max(0, innerYEnd - innerYStart);
|
|
75
|
+
if (t > 0) core.PathCommandDataHelper.rect(data, xL, yT, xR - xL, t);
|
|
76
|
+
if (b > 0) core.PathCommandDataHelper.rect(data, xL, yB - b, xR - xL, b);
|
|
77
|
+
if (l > 0 && innerHeight > 0) {
|
|
78
|
+
core.PathCommandDataHelper.rect(data, xL, innerYStart, l, innerHeight);
|
|
79
|
+
}
|
|
80
|
+
if (r_w > 0 && innerHeight > 0) {
|
|
81
|
+
core.PathCommandDataHelper.rect(data, xR - r_w, innerYStart, r_w, innerHeight);
|
|
82
|
+
}
|
|
83
|
+
return {
|
|
84
|
+
data: data
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
function strokeWidthType(defaultValue) {
|
|
88
|
+
return core$1.decorateLeafAttr(defaultValue, key => core$1.attr({
|
|
89
|
+
set(value) {
|
|
90
|
+
if (this.__setAttr(key, value)) {
|
|
91
|
+
core$1.doStrokeType(this);
|
|
92
|
+
const data = this.__;
|
|
93
|
+
data.__useStroke = true;
|
|
94
|
+
let hasStrokeSides;
|
|
95
|
+
core$1.DataHelper.stintSet(data, "__hasStrokeSides", hasStrokeSides = core$1.isArray(value) && Math.max(...value));
|
|
96
|
+
if (hasStrokeSides) {
|
|
97
|
+
core$1.doBoundsType(this);
|
|
98
|
+
} else if (data.__pathForStroke) data.__pathForStroke = undefined;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}));
|
|
102
|
+
}
|
|
103
|
+
draw.Plugin.add("stroke-sides");
|
|
104
|
+
draw.Rect.addAttr("strokeWidth", 1, strokeWidthType);
|
|
105
|
+
draw.Box.addAttr("strokeWidth", 1, strokeWidthType);
|
|
106
|
+
draw.Paint.fillStroke = fillStroke;
|
|
107
|
+
const {stintSet: stintSet} = draw.DataHelper;
|
|
108
|
+
draw.Rect.prototype.__updatePath = draw.Box.prototype.__updatePath = function() {
|
|
109
|
+
const data = this.__;
|
|
110
|
+
if (data.__hasStrokeSides) {
|
|
111
|
+
const {width: width, height: height, cornerRadius: cornerRadius, strokeWidth: strokeWidth, strokeAlign: strokeAlign} = data;
|
|
112
|
+
data.__pathForStroke = data.__pathInputed ? undefined : createRectStrokePath(width, height, cornerRadius && draw.MathHelper.fourNumber(cornerRadius), draw.MathHelper.fourNumber(strokeWidth), strokeAlign);
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
draw.BoxData.prototype.__checkComplex = draw.RectData.prototype.__checkComplex = function() {
|
|
116
|
+
const t = this;
|
|
117
|
+
stintSet(t, "__complex", t.__isFills || t.__isStrokes || t.cornerRadius || t.__hasStrokeSides || t.__useEffect);
|
|
118
|
+
};
|
|
119
|
+
})(LeaferUI, LeaferUI, LeaferUI);
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";var t=require("@leafer-ui/draw"),e=require("@leafer/core"),a=require("@leafer-ui/core");function r(t,a,r,o,i){if(r){const[n,l,d,s]=r,[h,_,c,u]=o;if(n+l+d+s>0){const r=[],o="inside"===i?0:"center"===i?.5:1,f=1-o,m=-u*o,p=-h*o,k=t+(u+_)*o,S=a+(h+c)*o,x=[n+Math.max(h,u)*o,l+Math.max(h,_)*o,d+Math.max(c,_)*o,s+Math.max(c,u)*o],M=u*f,P=h*f,y=t-(u+_)*f,g=a-(h+c)*f;if(e.PathCommandDataHelper.roundRect(r,m,p,k,S,x),y>0&&g>0){const t=[Math.max(0,n-Math.max(h,u)*f),Math.max(0,l-Math.max(h,_)*f),Math.max(0,d-Math.max(c,_)*f),Math.max(0,s-Math.max(c,u)*f)];e.PathCommandDataHelper.roundRect(r,M,P,y,g,t)}return{data:r,windingRule:"evenodd"}}}return function(t,a,r,o){const i=[],[n,l,d,s]=r,h="inside"===o?0:"center"===o?.5:1,_=1-h,c=-s*h,u=t+l*h,f=-n*h,m=a+d*h,p=n*_,k=a-d*_,S=Math.max(0,k-p);n>0&&e.PathCommandDataHelper.rect(i,c,f,u-c,n);d>0&&e.PathCommandDataHelper.rect(i,c,m-d,u-c,d);s>0&&S>0&&e.PathCommandDataHelper.rect(i,c,p,s,S);l>0&&S>0&&e.PathCommandDataHelper.rect(i,u-l,p,l,S);return{data:i}}(t,a,o,i)}function o(t){return a.decorateLeafAttr(t,t=>a.attr({set(e){if(this.__setAttr(t,e)){a.doStrokeType(this);const t=this.__;let r;t.__useStroke=!0,a.DataHelper.stintSet(t,"__hasStrokeSides",r=a.isArray(e)&&Math.max(...e)),r?a.doBoundsType(this):t.__pathForStroke&&(t.__pathForStroke=void 0)}}}))}t.Plugin.add("stroke-sides"),t.Rect.addAttr("strokeWidth",1,o),t.Box.addAttr("strokeWidth",1,o),t.Paint.fillStroke=function(a,r,o,i){o.beginPath();const{data:n,windingRule:l}=r.__.__pathForStroke;e.PathDrawer.drawPathByData(o,n),e.isObject(a)?function(e,a,r,o){let i;for(let n=0,l=e.length;n<l;n++)if(i=e[n],(!i.image||!t.PaintImage.checkImage(i,!1,a,r,o))&&i.style){const{windingRule:t}=a.__.__pathForStroke;i.originPaint.blendMode?(r.saveBlendMode(i.originPaint.blendMode),r.fillStyle=i.style,t?r.fill(t):r.fill(),r.restoreBlendMode()):(r.fillStyle=i.style,t?r.fill(t):r.fill())}}(a,r,o,i):(o.fillStyle=a,l?o.fill(l):o.fill()),r.__.__fillAfterStroke&&r.__drawRenderPath(o)};const{stintSet:i}=t.DataHelper;t.Rect.prototype.__updatePath=t.Box.prototype.__updatePath=function(){const e=this.__;if(e.__hasStrokeSides){const{width:a,height:o,cornerRadius:i,strokeWidth:n,strokeAlign:l}=e;e.__pathForStroke=e.__pathInputed?void 0:r(a,o,i&&t.MathHelper.fourNumber(i),t.MathHelper.fourNumber(n),l)}},t.BoxData.prototype.__checkComplex=t.RectData.prototype.__checkComplex=function(){const t=this;i(t,"__complex",t.__isFills||t.__isStrokes||t.cornerRadius||t.__hasStrokeSides||t.__useEffect)};
|
|
2
|
+
//# sourceMappingURL=stroke-sides.min.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stroke-sides.min.cjs","sources":["../../../../../../src/in/packages/stroke-sides/src/path.ts","../../../../../../src/in/packages/stroke-sides/src/decorator.ts","../../../../../../src/in/packages/stroke-sides/src/index.ts","../../../../../../src/in/packages/stroke-sides/src/fillSroke.ts"],"sourcesContent":["import { IPathCommandData, IPathCommandDataWithWindingRule } from '@leafer/interface'\nimport { PathCommandDataHelper } from \"@leafer/core\"\nimport { IStrokeAlign } from '@leafer-ui/interface'\n\n/**\n * 矩形描边路径生成器\n * 支持非均匀描边(上右下左宽度不同)与圆角逻辑\n */\nexport function createRectStrokePath(width: number, height: number, cornerRadius: number[] | undefined, strokeWidth: number[], strokeAlign: IStrokeAlign): IPathCommandDataWithWindingRule {\n\n if (cornerRadius) {\n const [r0, r1, r2, r3] = cornerRadius\n const [t, r_w, b, l] = strokeWidth\n\n const hasRadius = (r0 + r1 + r2 + r3) > 0\n\n // 场景 A: 包含圆角,必须使用 evenodd 挖空法\n if (hasRadius) {\n const data: IPathCommandData = []\n const expand = strokeAlign === 'inside' ? 0 : (strokeAlign === 'center' ? 0.5 : 1)\n const shrink = 1 - expand\n\n // 外边界参数\n const ox = -l * expand, oy = -t * expand\n const ow = width + (l + r_w) * expand\n const oh = height + (t + b) * expand\n const outerR = [\n r0 + Math.max(t, l) * expand,\n r1 + Math.max(t, r_w) * expand,\n r2 + Math.max(b, r_w) * expand,\n r3 + Math.max(b, l) * expand\n ]\n\n // 内边界参数\n const ix = l * shrink, iy = t * shrink\n const iw = width - (l + r_w) * shrink\n const ih = height - (t + b) * shrink\n\n // 绘制外框\n PathCommandDataHelper.roundRect(data, ox, oy, ow, oh, outerR)\n\n // 只有内框有空间时才绘制内框(进行掏空)\n if (iw > 0 && ih > 0) {\n const innerR = [\n Math.max(0, r0 - Math.max(t, l) * shrink),\n Math.max(0, r1 - Math.max(t, r_w) * shrink),\n Math.max(0, r2 - Math.max(b, r_w) * shrink),\n Math.max(0, r3 - Math.max(b, l) * shrink)\n ]\n PathCommandDataHelper.roundRect(data, ix, iy, iw, ih, innerR)\n }\n\n return { data, windingRule: 'evenodd' }\n }\n }\n\n\n\n // 场景 B: 纯直角,采用四边拼接法 (性能最优,无 WindingRule 依赖)\n return createRectStrokePathNoRadius(width, height, strokeWidth, strokeAlign)\n}\n\n/**\n * 纯直角矩形描边生成器 (拼接法)\n */\nfunction createRectStrokePathNoRadius(\n width: number,\n height: number,\n strokeWidth: number[],\n strokeAlign: IStrokeAlign\n): IPathCommandDataWithWindingRule {\n const data: IPathCommandData = []\n const [t, r_w, b, l] = strokeWidth\n\n const ext = strokeAlign === 'inside' ? 0 : (strokeAlign === 'center' ? 0.5 : 1)\n const ins = 1 - ext\n\n // 计算外部极值边界坐标\n const xL = -l * ext\n const xR = width + r_w * ext\n const yT = -t * ext\n const yB = height + b * ext\n\n // 计算内部裁剪边界坐标 (用于侧边填充高度)\n const innerYStart = t * ins\n const innerYEnd = height - b * ins\n const innerHeight = Math.max(0, innerYEnd - innerYStart)\n\n // 1. Top Bar: 覆盖全宽\n if (t > 0) PathCommandDataHelper.rect(data, xL, yT, xR - xL, t)\n\n // 2. Bottom Bar: 覆盖全宽\n if (b > 0) PathCommandDataHelper.rect(data, xL, yB - b, xR - xL, b)\n\n // 3. Left Bar: 填充中间高度,避免与 Top/Bottom 重合\n if (l > 0 && innerHeight > 0) {\n PathCommandDataHelper.rect(data, xL, innerYStart, l, innerHeight)\n }\n\n // 4. Right Bar: 填充中间高度\n if (r_w > 0 && innerHeight > 0) {\n PathCommandDataHelper.rect(data, xR - r_w, innerYStart, r_w, innerHeight)\n }\n\n return { data }\n}","import { IUIData, IValue } from '@leafer-ui/interface'\nimport { decorateLeafAttr, attr, doStrokeType, doBoundsType, isArray, DataHelper } from '@leafer-ui/core'\n\nexport function strokeWidthType(defaultValue?: IValue) {\n return decorateLeafAttr(defaultValue, (key: string) => attr({\n set(value: IValue) {\n if (this.__setAttr(key, value)) {\n doStrokeType(this)\n const data = this.__\n data.__useStroke = true\n let hasStrokeSides\n DataHelper.stintSet(data as IUIData, '__hasStrokeSides', hasStrokeSides = isArray(value) && Math.max(...value))\n if (hasStrokeSides) {\n doBoundsType(this)\n } else if ((data as IUIData).__pathForStroke) (data as IUIData).__pathForStroke = undefined\n }\n }\n }))\n}","import { Paint, Plugin, Rect, Box, RectData, DataHelper, MathHelper, BoxData } from '@leafer-ui/draw'\nimport { fillStroke } from './fillSroke'\nimport { createRectStrokePath } from './path'\nimport { strokeWidthType } from './decorator'\nimport { IRectData } from '@leafer-ui/interface'\n\nPlugin.add('stroke-sides')\n\nRect.addAttr('strokeWidth', 1, strokeWidthType)\nBox.addAttr('strokeWidth', 1, strokeWidthType)\n\nPaint.fillStroke = fillStroke\n\nconst { stintSet } = DataHelper\n\nRect.prototype.__updatePath = Box.prototype.__updatePath = function (): void {\n const data = this.__\n if (data.__hasStrokeSides) {\n const { width, height, cornerRadius, strokeWidth, strokeAlign } = data\n data.__pathForStroke = data.__pathInputed ? undefined : createRectStrokePath(width, height, cornerRadius && MathHelper.fourNumber(cornerRadius), MathHelper.fourNumber(strokeWidth), strokeAlign)\n }\n}\n\nBoxData.prototype.__checkComplex = RectData.prototype.__checkComplex = function (): void {\n const t = this as IRectData\n stintSet(t, '__complex', (t.__isFills || t.__isStrokes || t.cornerRadius || t.__hasStrokeSides || t.__useEffect) as boolean)\n}","import { ILeaferCanvas, IRenderOptions } from '@leafer/interface'\nimport { isObject, PathDrawer } from \"@leafer/core\"\n\nimport { IUI, ILeafPaint, ILeafStrokePaint } from '@leafer-ui/interface'\nimport { PaintImage } from \"@leafer-ui/draw\"\n\n\nexport function fillStroke(stroke: string | ILeafPaint[], ui: IUI, canvas: ILeaferCanvas, renderOptions: IRenderOptions): void {\n\n canvas.beginPath()\n const { data, windingRule } = ui.__.__pathForStroke\n PathDrawer.drawPathByData(canvas, data)\n\n if (isObject(stroke)) {\n drawStrokesStyle(stroke, ui, canvas, renderOptions)\n } else {\n\n canvas.fillStyle = stroke\n windingRule ? canvas.fill(windingRule) : canvas.fill()\n\n }\n\n if (ui.__.__fillAfterStroke) ui.__drawRenderPath(canvas)\n}\n\n\nfunction drawStrokesStyle(strokes: ILeafStrokePaint[], ui: IUI, canvas: ILeaferCanvas, renderOptions: IRenderOptions): void {\n let item: ILeafStrokePaint\n\n for (let i = 0, len = strokes.length; i < len; i++) {\n item = strokes[i]\n\n if (item.image && PaintImage.checkImage(item, false, ui, canvas, renderOptions)) continue\n\n if (item.style) {\n\n const { windingRule } = ui.__.__pathForStroke\n\n if (item.originPaint.blendMode) {\n canvas.saveBlendMode(item.originPaint.blendMode)\n canvas.fillStyle = item.style\n windingRule ? canvas.fill(windingRule) : canvas.fill()\n canvas.restoreBlendMode()\n } else {\n canvas.fillStyle = item.style\n windingRule ? canvas.fill(windingRule) : canvas.fill()\n }\n }\n }\n}"],"names":["createRectStrokePath","width","height","cornerRadius","strokeWidth","strokeAlign","r0","r1","r2","r3","t","r_w","b","l","data","expand","shrink","ox","oy","ow","oh","outerR","Math","max","ix","iy","iw","ih","PathCommandDataHelper","roundRect","innerR","windingRule","ext","ins","xL","xR","yT","yB","innerYStart","innerYEnd","innerHeight","rect","createRectStrokePathNoRadius","strokeWidthType","defaultValue","decorateLeafAttr","key","attr","set","value","this","__setAttr","doStrokeType","__","hasStrokeSides","__useStroke","DataHelper","stintSet","isArray","doBoundsType","__pathForStroke","undefined","Plugin","add","Rect","addAttr","Box","Paint","fillStroke","stroke","ui","canvas","renderOptions","beginPath","PathDrawer","drawPathByData","isObject","strokes","item","i","len","length","image","PaintImage","checkImage","style","originPaint","blendMode","saveBlendMode","fillStyle","fill","restoreBlendMode","drawStrokesStyle","__fillAfterStroke","__drawRenderPath","prototype","__updatePath","__hasStrokeSides","__pathInputed","MathHelper","fourNumber","BoxData","__checkComplex","RectData","__isFills","__isStrokes","__useEffect"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
!function(t,e,a){"use strict";function r(t,a,r,o,i){if(r){const[n,l,d,s]=r,[h,_,c,f]=o;if(n+l+d+s>0){const r=[],o="inside"===i?0:"center"===i?.5:1,m=1-o,p=-f*o,u=-h*o,k=t+(f+_)*o,S=a+(h+c)*o,x=[n+Math.max(h,f)*o,l+Math.max(h,_)*o,d+Math.max(c,_)*o,s+Math.max(c,f)*o],M=f*m,P=h*m,y=t-(f+_)*m,g=a-(h+c)*m;if(e.PathCommandDataHelper.roundRect(r,p,u,k,S,x),y>0&&g>0){const t=[Math.max(0,n-Math.max(h,f)*m),Math.max(0,l-Math.max(h,_)*m),Math.max(0,d-Math.max(c,_)*m),Math.max(0,s-Math.max(c,f)*m)];e.PathCommandDataHelper.roundRect(r,M,P,y,g,t)}return{data:r,windingRule:"evenodd"}}}return function(t,a,r,o){const i=[],[n,l,d,s]=r,h="inside"===o?0:"center"===o?.5:1,_=1-h,c=-s*h,f=t+l*h,m=-n*h,p=a+d*h,u=n*_,k=a-d*_,S=Math.max(0,k-u);n>0&&e.PathCommandDataHelper.rect(i,c,m,f-c,n);d>0&&e.PathCommandDataHelper.rect(i,c,p-d,f-c,d);s>0&&S>0&&e.PathCommandDataHelper.rect(i,c,u,s,S);l>0&&S>0&&e.PathCommandDataHelper.rect(i,f-l,u,l,S);return{data:i}}(t,a,o,i)}function o(t){return a.decorateLeafAttr(t,t=>a.attr({set(e){if(this.__setAttr(t,e)){a.doStrokeType(this);const t=this.__;let r;t.__useStroke=!0,a.DataHelper.stintSet(t,"__hasStrokeSides",r=a.isArray(e)&&Math.max(...e)),r?a.doBoundsType(this):t.__pathForStroke&&(t.__pathForStroke=void 0)}}}))}t.Plugin.add("stroke-sides"),t.Rect.addAttr("strokeWidth",1,o),t.Box.addAttr("strokeWidth",1,o),t.Paint.fillStroke=function(a,r,o,i){o.beginPath();const{data:n,windingRule:l}=r.__.__pathForStroke;e.PathDrawer.drawPathByData(o,n),e.isObject(a)?function(e,a,r,o){let i;for(let n=0,l=e.length;n<l;n++)if(i=e[n],(!i.image||!t.PaintImage.checkImage(i,!1,a,r,o))&&i.style){const{windingRule:t}=a.__.__pathForStroke;i.originPaint.blendMode?(r.saveBlendMode(i.originPaint.blendMode),r.fillStyle=i.style,t?r.fill(t):r.fill(),r.restoreBlendMode()):(r.fillStyle=i.style,t?r.fill(t):r.fill())}}(a,r,o,i):(o.fillStyle=a,l?o.fill(l):o.fill()),r.__.__fillAfterStroke&&r.__drawRenderPath(o)};const{stintSet:i}=t.DataHelper;t.Rect.prototype.__updatePath=t.Box.prototype.__updatePath=function(){const e=this.__;if(e.__hasStrokeSides){const{width:a,height:o,cornerRadius:i,strokeWidth:n,strokeAlign:l}=e;e.__pathForStroke=e.__pathInputed?void 0:r(a,o,i&&t.MathHelper.fourNumber(i),t.MathHelper.fourNumber(n),l)}},t.BoxData.prototype.__checkComplex=t.RectData.prototype.__checkComplex=function(){const t=this;i(t,"__complex",t.__isFills||t.__isStrokes||t.cornerRadius||t.__hasStrokeSides||t.__useEffect)}}(LeaferUI,LeaferUI,LeaferUI);
|
|
2
|
+
//# sourceMappingURL=stroke-sides.min.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stroke-sides.min.js","sources":["../../../../../../src/in/packages/stroke-sides/src/path.ts","../../../../../../src/in/packages/stroke-sides/src/decorator.ts","../../../../../../src/in/packages/stroke-sides/src/index.ts","../../../../../../src/in/packages/stroke-sides/src/fillSroke.ts"],"sourcesContent":["import { IPathCommandData, IPathCommandDataWithWindingRule } from '@leafer/interface'\nimport { PathCommandDataHelper } from \"@leafer/core\"\nimport { IStrokeAlign } from '@leafer-ui/interface'\n\n/**\n * 矩形描边路径生成器\n * 支持非均匀描边(上右下左宽度不同)与圆角逻辑\n */\nexport function createRectStrokePath(width: number, height: number, cornerRadius: number[] | undefined, strokeWidth: number[], strokeAlign: IStrokeAlign): IPathCommandDataWithWindingRule {\n\n if (cornerRadius) {\n const [r0, r1, r2, r3] = cornerRadius\n const [t, r_w, b, l] = strokeWidth\n\n const hasRadius = (r0 + r1 + r2 + r3) > 0\n\n // 场景 A: 包含圆角,必须使用 evenodd 挖空法\n if (hasRadius) {\n const data: IPathCommandData = []\n const expand = strokeAlign === 'inside' ? 0 : (strokeAlign === 'center' ? 0.5 : 1)\n const shrink = 1 - expand\n\n // 外边界参数\n const ox = -l * expand, oy = -t * expand\n const ow = width + (l + r_w) * expand\n const oh = height + (t + b) * expand\n const outerR = [\n r0 + Math.max(t, l) * expand,\n r1 + Math.max(t, r_w) * expand,\n r2 + Math.max(b, r_w) * expand,\n r3 + Math.max(b, l) * expand\n ]\n\n // 内边界参数\n const ix = l * shrink, iy = t * shrink\n const iw = width - (l + r_w) * shrink\n const ih = height - (t + b) * shrink\n\n // 绘制外框\n PathCommandDataHelper.roundRect(data, ox, oy, ow, oh, outerR)\n\n // 只有内框有空间时才绘制内框(进行掏空)\n if (iw > 0 && ih > 0) {\n const innerR = [\n Math.max(0, r0 - Math.max(t, l) * shrink),\n Math.max(0, r1 - Math.max(t, r_w) * shrink),\n Math.max(0, r2 - Math.max(b, r_w) * shrink),\n Math.max(0, r3 - Math.max(b, l) * shrink)\n ]\n PathCommandDataHelper.roundRect(data, ix, iy, iw, ih, innerR)\n }\n\n return { data, windingRule: 'evenodd' }\n }\n }\n\n\n\n // 场景 B: 纯直角,采用四边拼接法 (性能最优,无 WindingRule 依赖)\n return createRectStrokePathNoRadius(width, height, strokeWidth, strokeAlign)\n}\n\n/**\n * 纯直角矩形描边生成器 (拼接法)\n */\nfunction createRectStrokePathNoRadius(\n width: number,\n height: number,\n strokeWidth: number[],\n strokeAlign: IStrokeAlign\n): IPathCommandDataWithWindingRule {\n const data: IPathCommandData = []\n const [t, r_w, b, l] = strokeWidth\n\n const ext = strokeAlign === 'inside' ? 0 : (strokeAlign === 'center' ? 0.5 : 1)\n const ins = 1 - ext\n\n // 计算外部极值边界坐标\n const xL = -l * ext\n const xR = width + r_w * ext\n const yT = -t * ext\n const yB = height + b * ext\n\n // 计算内部裁剪边界坐标 (用于侧边填充高度)\n const innerYStart = t * ins\n const innerYEnd = height - b * ins\n const innerHeight = Math.max(0, innerYEnd - innerYStart)\n\n // 1. Top Bar: 覆盖全宽\n if (t > 0) PathCommandDataHelper.rect(data, xL, yT, xR - xL, t)\n\n // 2. Bottom Bar: 覆盖全宽\n if (b > 0) PathCommandDataHelper.rect(data, xL, yB - b, xR - xL, b)\n\n // 3. Left Bar: 填充中间高度,避免与 Top/Bottom 重合\n if (l > 0 && innerHeight > 0) {\n PathCommandDataHelper.rect(data, xL, innerYStart, l, innerHeight)\n }\n\n // 4. Right Bar: 填充中间高度\n if (r_w > 0 && innerHeight > 0) {\n PathCommandDataHelper.rect(data, xR - r_w, innerYStart, r_w, innerHeight)\n }\n\n return { data }\n}","import { IUIData, IValue } from '@leafer-ui/interface'\nimport { decorateLeafAttr, attr, doStrokeType, doBoundsType, isArray, DataHelper } from '@leafer-ui/core'\n\nexport function strokeWidthType(defaultValue?: IValue) {\n return decorateLeafAttr(defaultValue, (key: string) => attr({\n set(value: IValue) {\n if (this.__setAttr(key, value)) {\n doStrokeType(this)\n const data = this.__\n data.__useStroke = true\n let hasStrokeSides\n DataHelper.stintSet(data as IUIData, '__hasStrokeSides', hasStrokeSides = isArray(value) && Math.max(...value))\n if (hasStrokeSides) {\n doBoundsType(this)\n } else if ((data as IUIData).__pathForStroke) (data as IUIData).__pathForStroke = undefined\n }\n }\n }))\n}","import { Paint, Plugin, Rect, Box, RectData, DataHelper, MathHelper, BoxData } from '@leafer-ui/draw'\nimport { fillStroke } from './fillSroke'\nimport { createRectStrokePath } from './path'\nimport { strokeWidthType } from './decorator'\nimport { IRectData } from '@leafer-ui/interface'\n\nPlugin.add('stroke-sides')\n\nRect.addAttr('strokeWidth', 1, strokeWidthType)\nBox.addAttr('strokeWidth', 1, strokeWidthType)\n\nPaint.fillStroke = fillStroke\n\nconst { stintSet } = DataHelper\n\nRect.prototype.__updatePath = Box.prototype.__updatePath = function (): void {\n const data = this.__\n if (data.__hasStrokeSides) {\n const { width, height, cornerRadius, strokeWidth, strokeAlign } = data\n data.__pathForStroke = data.__pathInputed ? undefined : createRectStrokePath(width, height, cornerRadius && MathHelper.fourNumber(cornerRadius), MathHelper.fourNumber(strokeWidth), strokeAlign)\n }\n}\n\nBoxData.prototype.__checkComplex = RectData.prototype.__checkComplex = function (): void {\n const t = this as IRectData\n stintSet(t, '__complex', (t.__isFills || t.__isStrokes || t.cornerRadius || t.__hasStrokeSides || t.__useEffect) as boolean)\n}","import { ILeaferCanvas, IRenderOptions } from '@leafer/interface'\nimport { isObject, PathDrawer } from \"@leafer/core\"\n\nimport { IUI, ILeafPaint, ILeafStrokePaint } from '@leafer-ui/interface'\nimport { PaintImage } from \"@leafer-ui/draw\"\n\n\nexport function fillStroke(stroke: string | ILeafPaint[], ui: IUI, canvas: ILeaferCanvas, renderOptions: IRenderOptions): void {\n\n canvas.beginPath()\n const { data, windingRule } = ui.__.__pathForStroke\n PathDrawer.drawPathByData(canvas, data)\n\n if (isObject(stroke)) {\n drawStrokesStyle(stroke, ui, canvas, renderOptions)\n } else {\n\n canvas.fillStyle = stroke\n windingRule ? canvas.fill(windingRule) : canvas.fill()\n\n }\n\n if (ui.__.__fillAfterStroke) ui.__drawRenderPath(canvas)\n}\n\n\nfunction drawStrokesStyle(strokes: ILeafStrokePaint[], ui: IUI, canvas: ILeaferCanvas, renderOptions: IRenderOptions): void {\n let item: ILeafStrokePaint\n\n for (let i = 0, len = strokes.length; i < len; i++) {\n item = strokes[i]\n\n if (item.image && PaintImage.checkImage(item, false, ui, canvas, renderOptions)) continue\n\n if (item.style) {\n\n const { windingRule } = ui.__.__pathForStroke\n\n if (item.originPaint.blendMode) {\n canvas.saveBlendMode(item.originPaint.blendMode)\n canvas.fillStyle = item.style\n windingRule ? canvas.fill(windingRule) : canvas.fill()\n canvas.restoreBlendMode()\n } else {\n canvas.fillStyle = item.style\n windingRule ? canvas.fill(windingRule) : canvas.fill()\n }\n }\n }\n}"],"names":["createRectStrokePath","width","height","cornerRadius","strokeWidth","strokeAlign","r0","r1","r2","r3","t","r_w","b","l","data","expand","shrink","ox","oy","ow","oh","outerR","Math","max","ix","iy","iw","ih","PathCommandDataHelper","roundRect","innerR","windingRule","ext","ins","xL","xR","yT","yB","innerYStart","innerYEnd","innerHeight","rect","createRectStrokePathNoRadius","strokeWidthType","defaultValue","decorateLeafAttr","key","attr","set","value","this","__setAttr","doStrokeType","__","hasStrokeSides","__useStroke","DataHelper","stintSet","isArray","doBoundsType","__pathForStroke","undefined","Plugin","add","Rect","addAttr","Box","Paint","fillStroke","stroke","ui","canvas","renderOptions","beginPath","PathDrawer","drawPathByData","isObject","strokes","item","i","len","length","image","PaintImage","checkImage","style","originPaint","blendMode","saveBlendMode","fillStyle","fill","restoreBlendMode","drawStrokesStyle","__fillAfterStroke","__drawRenderPath","prototype","__updatePath","__hasStrokeSides","__pathInputed","MathHelper","fourNumber","BoxData","__checkComplex","RectData","__isFills","__isStrokes","__useEffect"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@leafer-in/stroke-sides",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.2",
|
|
4
4
|
"description": "@leafer-in/stroke-sides",
|
|
5
5
|
"author": "Chao (Leafer) Wan",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"type": "module",
|
|
8
|
-
"main": "dist/stroke-sides.esm.js",
|
|
8
|
+
"main": "dist/stroke-sides.esm.min.js",
|
|
9
9
|
"exports": {
|
|
10
|
-
"import": "./dist/stroke-sides.esm.js",
|
|
11
|
-
"require": "./dist/stroke-sides.cjs",
|
|
10
|
+
"import": "./dist/stroke-sides.esm.min.js",
|
|
11
|
+
"require": "./dist/stroke-sides.min.cjs",
|
|
12
12
|
"types": "./types/index.d.ts"
|
|
13
13
|
},
|
|
14
14
|
"types": "types/index.d.ts",
|
|
15
|
-
"unpkg": "dist/stroke-sides.js",
|
|
16
|
-
"jsdelivr": "dist/stroke-sides.js",
|
|
15
|
+
"unpkg": "dist/stroke-sides.min.js",
|
|
16
|
+
"jsdelivr": "dist/stroke-sides.min.js",
|
|
17
17
|
"files": [
|
|
18
18
|
"src",
|
|
19
19
|
"types",
|