[improvement] Select unfilled shapes by clicking on their stroke (#438)
* removes touch events from middle of shapes * Improve ellipse * selectable stroke when not selected, fill when selected * Update BrushSession.spec.ts * Fix test
This commit is contained in:
parent
c67c0871ff
commit
52ae47371d
8 changed files with 230 additions and 185 deletions
1
apps/www/next-env.d.ts
vendored
1
apps/www/next-env.d.ts
vendored
|
@ -1,5 +1,4 @@
|
|||
/// <reference types="next" />
|
||||
/// <reference types="next/types/global" />
|
||||
/// <reference types="next/image-types/global" />
|
||||
|
||||
// NOTE: This file should not be edited
|
||||
|
|
|
@ -39,17 +39,7 @@ export abstract class TLShapeUtil<T extends TLShape, E extends Element = any, M
|
|||
|
||||
hitTestBounds = (shape: T, bounds: TLBounds) => {
|
||||
const shapeBounds = this.getBounds(shape)
|
||||
|
||||
if (!shape.rotation) {
|
||||
return (
|
||||
Utils.boundsContain(bounds, shapeBounds) ||
|
||||
Utils.boundsContain(shapeBounds, bounds) ||
|
||||
Utils.boundsCollide(shapeBounds, bounds)
|
||||
)
|
||||
}
|
||||
|
||||
const corners = Utils.getRotatedCorners(shapeBounds, shape.rotation)
|
||||
|
||||
return (
|
||||
corners.every((point) => Utils.pointInBounds(point, bounds)) ||
|
||||
intersectPolylineBounds(corners, bounds).length > 0
|
||||
|
|
|
@ -218,6 +218,26 @@ const tlcss = css`
|
|||
contain: layout style size;
|
||||
}
|
||||
|
||||
.tl-stroke-hitarea {
|
||||
cursor: pointer;
|
||||
fill: none;
|
||||
stroke: transparent;
|
||||
stroke-width: calc(24px * var(--tl-scale));
|
||||
pointer-events: stroke;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
}
|
||||
|
||||
.tl-fill-hitarea {
|
||||
cursor: pointer;
|
||||
fill: transparent;
|
||||
stroke: transparent;
|
||||
stroke-width: calc(24px * var(--tl-scale));
|
||||
pointer-events: all;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
}
|
||||
|
||||
.tl-counter-scaled {
|
||||
transform: scale(var(--tl-scale));
|
||||
}
|
||||
|
@ -354,6 +374,7 @@ const tlcss = css`
|
|||
|
||||
.tl-handle {
|
||||
pointer-events: all;
|
||||
cursor: grab;
|
||||
}
|
||||
|
||||
.tl-handle:hover .tl-handle-bg {
|
||||
|
@ -365,6 +386,7 @@ const tlcss = css`
|
|||
}
|
||||
|
||||
.tl-handle:active .tl-handle-bg {
|
||||
cursor: grabbing;
|
||||
fill: var(--tl-selectFill);
|
||||
}
|
||||
|
||||
|
@ -389,6 +411,7 @@ const tlcss = css`
|
|||
stroke-width: calc(3px * var(--tl-scale));
|
||||
fill: var(--tl-selectFill);
|
||||
stroke: var(--tl-selected);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.tl-centered-g {
|
||||
|
|
|
@ -6,9 +6,9 @@ describe('Brush session', () => {
|
|||
const app = new TldrawTestApp()
|
||||
.loadDocument(mockDocument)
|
||||
.selectNone()
|
||||
.movePointer([-10, -10])
|
||||
.movePointer([-48, -48])
|
||||
.startSession(SessionType.Brush)
|
||||
.movePointer([10, 10])
|
||||
.movePointer([48, 48])
|
||||
.completeSession()
|
||||
expect(app.status).toBe(TDStatus.Idle)
|
||||
expect(app.selectedIds.length).toBe(1)
|
||||
|
|
|
@ -144,16 +144,7 @@ export class ArrowUtil extends TDShapeUtil<T, E> {
|
|||
shaftPath =
|
||||
arrowDist > 2 ? (
|
||||
<>
|
||||
<path
|
||||
d={path}
|
||||
fill="none"
|
||||
strokeWidth={Math.max(8, strokeWidth * 2)}
|
||||
strokeDasharray="none"
|
||||
strokeDashoffset="none"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
pointerEvents="stroke"
|
||||
/>
|
||||
<path className="tl-stroke-hitarea" d={path} />
|
||||
<path
|
||||
d={path}
|
||||
fill={styles.stroke}
|
||||
|
@ -207,17 +198,7 @@ export class ArrowUtil extends TDShapeUtil<T, E> {
|
|||
// Curved arrow path
|
||||
shaftPath = (
|
||||
<>
|
||||
<path
|
||||
d={path}
|
||||
fill="none"
|
||||
stroke="none"
|
||||
strokeWidth={Math.max(8, strokeWidth)}
|
||||
strokeDasharray="none"
|
||||
strokeDashoffset="none"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
pointerEvents="stroke"
|
||||
/>
|
||||
<path className="tl-stroke-hitarea" d={path} />
|
||||
<path
|
||||
d={path}
|
||||
fill={isDraw ? styles.stroke : 'none'}
|
||||
|
@ -227,7 +208,7 @@ export class ArrowUtil extends TDShapeUtil<T, E> {
|
|||
strokeDashoffset={strokeDashoffset}
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
pointerEvents="stroke"
|
||||
pointerEvents="none"
|
||||
/>
|
||||
</>
|
||||
)
|
||||
|
@ -238,30 +219,38 @@ export class ArrowUtil extends TDShapeUtil<T, E> {
|
|||
<g pointerEvents="none" opacity={isGhost ? GHOSTED_OPACITY : 1}>
|
||||
{shaftPath}
|
||||
{startArrowHead && (
|
||||
<path
|
||||
d={`M ${startArrowHead.left} L ${start.point} ${startArrowHead.right}`}
|
||||
fill="none"
|
||||
stroke={styles.stroke}
|
||||
strokeWidth={sw}
|
||||
strokeDashoffset="none"
|
||||
strokeDasharray="none"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
pointerEvents="stroke"
|
||||
/>
|
||||
<>
|
||||
<path
|
||||
className="tl-stroke-hitarea"
|
||||
d={`M ${startArrowHead.left} L ${start.point} ${startArrowHead.right}`}
|
||||
/>
|
||||
<path
|
||||
d={`M ${startArrowHead.left} L ${start.point} ${startArrowHead.right}`}
|
||||
fill="none"
|
||||
stroke={styles.stroke}
|
||||
strokeWidth={sw}
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
pointerEvents="none"
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
{endArrowHead && (
|
||||
<path
|
||||
d={`M ${endArrowHead.left} L ${end.point} ${endArrowHead.right}`}
|
||||
fill="none"
|
||||
stroke={styles.stroke}
|
||||
strokeWidth={sw}
|
||||
strokeDashoffset="none"
|
||||
strokeDasharray="none"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
pointerEvents="stroke"
|
||||
/>
|
||||
<>
|
||||
<path
|
||||
className="tl-stroke-hitarea"
|
||||
d={`M ${endArrowHead.left} L ${end.point} ${endArrowHead.right}`}
|
||||
/>
|
||||
<path
|
||||
d={`M ${endArrowHead.left} L ${end.point} ${endArrowHead.right}`}
|
||||
fill="none"
|
||||
stroke={styles.stroke}
|
||||
strokeWidth={sw}
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
pointerEvents="none"
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</g>
|
||||
</SVGContainer>
|
||||
|
|
|
@ -51,121 +51,131 @@ export class DrawUtil extends TDShapeUtil<T, E> {
|
|||
)
|
||||
}
|
||||
|
||||
Component = TDShapeUtil.Component<T, E, TDMeta>(({ shape, meta, isGhost, events }, ref) => {
|
||||
const { points, style, isComplete } = shape
|
||||
Component = TDShapeUtil.Component<T, E, TDMeta>(
|
||||
({ shape, meta, isSelected, isGhost, events }, ref) => {
|
||||
const { points, style, isComplete } = shape
|
||||
|
||||
const polygonPathTDSnapshot = React.useMemo(() => {
|
||||
return getFillPath(shape)
|
||||
}, [points, style.size])
|
||||
const polygonPathTDSnapshot = React.useMemo(() => {
|
||||
return getFillPath(shape)
|
||||
}, [points, style.size])
|
||||
|
||||
const pathTDSnapshot = React.useMemo(() => {
|
||||
return style.dash === DashStyle.Draw
|
||||
? getDrawStrokePathTDSnapshot(shape)
|
||||
: getSolidStrokePathTDSnapshot(shape)
|
||||
}, [points, style.size, style.dash, isComplete])
|
||||
const pathTDSnapshot = React.useMemo(() => {
|
||||
return style.dash === DashStyle.Draw
|
||||
? getDrawStrokePathTDSnapshot(shape)
|
||||
: getSolidStrokePathTDSnapshot(shape)
|
||||
}, [points, style.size, style.dash, isComplete])
|
||||
|
||||
const styles = getShapeStyle(style, meta.isDarkMode)
|
||||
const { stroke, fill, strokeWidth } = styles
|
||||
const styles = getShapeStyle(style, meta.isDarkMode)
|
||||
const { stroke, fill, strokeWidth } = styles
|
||||
|
||||
// For very short lines, draw a point instead of a line
|
||||
const bounds = this.getBounds(shape)
|
||||
// For very short lines, draw a point instead of a line
|
||||
const bounds = this.getBounds(shape)
|
||||
|
||||
const verySmall = bounds.width <= strokeWidth / 2 && bounds.height <= strokeWidth / 2
|
||||
const verySmall = bounds.width <= strokeWidth / 2 && bounds.height <= strokeWidth / 2
|
||||
|
||||
if (verySmall) {
|
||||
const sw = 1 + strokeWidth
|
||||
if (verySmall) {
|
||||
const sw = 1 + strokeWidth
|
||||
|
||||
return (
|
||||
<SVGContainer ref={ref} id={shape.id + '_svg'} {...events}>
|
||||
<circle
|
||||
r={sw}
|
||||
fill={stroke}
|
||||
stroke={stroke}
|
||||
pointerEvents="all"
|
||||
opacity={isGhost ? GHOSTED_OPACITY : 1}
|
||||
/>
|
||||
</SVGContainer>
|
||||
)
|
||||
}
|
||||
return (
|
||||
<SVGContainer ref={ref} id={shape.id + '_svg'} {...events}>
|
||||
<circle
|
||||
r={sw}
|
||||
fill={stroke}
|
||||
stroke={stroke}
|
||||
pointerEvents="all"
|
||||
opacity={isGhost ? GHOSTED_OPACITY : 1}
|
||||
/>
|
||||
</SVGContainer>
|
||||
)
|
||||
}
|
||||
|
||||
const shouldFill =
|
||||
style.isFilled &&
|
||||
points.length > 3 &&
|
||||
Vec.dist(points[0], points[points.length - 1]) < strokeWidth * 2
|
||||
const shouldFill =
|
||||
style.isFilled &&
|
||||
points.length > 3 &&
|
||||
Vec.dist(points[0], points[points.length - 1]) < strokeWidth * 2
|
||||
|
||||
if (shape.style.dash === DashStyle.Draw) {
|
||||
return (
|
||||
<SVGContainer ref={ref} id={shape.id + '_svg'} {...events}>
|
||||
<g opacity={isGhost ? GHOSTED_OPACITY : 1}>
|
||||
<path
|
||||
className={shouldFill && isSelected ? 'tl-fill-hitarea' : 'tl-stroke-hitarea'}
|
||||
d={pathTDSnapshot}
|
||||
/>
|
||||
{shouldFill && (
|
||||
<path
|
||||
d={polygonPathTDSnapshot}
|
||||
stroke="none"
|
||||
fill={fill}
|
||||
strokeLinejoin="round"
|
||||
strokeLinecap="round"
|
||||
pointerEvents="none"
|
||||
/>
|
||||
)}
|
||||
<path
|
||||
d={pathTDSnapshot}
|
||||
fill={stroke}
|
||||
stroke={stroke}
|
||||
strokeWidth={strokeWidth / 2}
|
||||
strokeLinejoin="round"
|
||||
strokeLinecap="round"
|
||||
pointerEvents="none"
|
||||
/>
|
||||
</g>
|
||||
</SVGContainer>
|
||||
)
|
||||
}
|
||||
|
||||
// For solid, dash and dotted lines, draw a regular stroke path
|
||||
|
||||
const strokeDasharray = {
|
||||
[DashStyle.Draw]: 'none',
|
||||
[DashStyle.Solid]: `none`,
|
||||
[DashStyle.Dotted]: `0.1 ${strokeWidth * 4}`,
|
||||
[DashStyle.Dashed]: `${strokeWidth * 4} ${strokeWidth * 4}`,
|
||||
}[style.dash]
|
||||
|
||||
const strokeDashoffset = {
|
||||
[DashStyle.Draw]: 'none',
|
||||
[DashStyle.Solid]: `none`,
|
||||
[DashStyle.Dotted]: `0`,
|
||||
[DashStyle.Dashed]: `0`,
|
||||
}[style.dash]
|
||||
|
||||
const sw = 1 + strokeWidth * 1.5
|
||||
|
||||
if (shape.style.dash === DashStyle.Draw) {
|
||||
return (
|
||||
<SVGContainer ref={ref} id={shape.id + '_svg'} {...events}>
|
||||
<g opacity={isGhost ? GHOSTED_OPACITY : 1}>
|
||||
{shouldFill && (
|
||||
<path
|
||||
d={polygonPathTDSnapshot}
|
||||
stroke="none"
|
||||
fill={fill}
|
||||
strokeLinejoin="round"
|
||||
strokeLinecap="round"
|
||||
pointerEvents="fill"
|
||||
/>
|
||||
)}
|
||||
<path
|
||||
className={shouldFill && isSelected ? 'tl-fill-hitarea' : 'tl-stroke-hitarea'}
|
||||
d={pathTDSnapshot}
|
||||
/>
|
||||
<path
|
||||
d={pathTDSnapshot}
|
||||
fill={stroke}
|
||||
stroke={stroke}
|
||||
strokeWidth={strokeWidth / 2}
|
||||
fill={shouldFill ? fill : 'none'}
|
||||
stroke="none"
|
||||
strokeWidth={Math.min(4, strokeWidth * 2)}
|
||||
strokeLinejoin="round"
|
||||
strokeLinecap="round"
|
||||
pointerEvents="all"
|
||||
pointerEvents="none"
|
||||
/>
|
||||
<path
|
||||
d={pathTDSnapshot}
|
||||
fill="none"
|
||||
stroke={stroke}
|
||||
strokeWidth={sw}
|
||||
strokeDasharray={strokeDasharray}
|
||||
strokeDashoffset={strokeDashoffset}
|
||||
strokeLinejoin="round"
|
||||
strokeLinecap="round"
|
||||
pointerEvents="none"
|
||||
/>
|
||||
</g>
|
||||
</SVGContainer>
|
||||
)
|
||||
}
|
||||
|
||||
// For solid, dash and dotted lines, draw a regular stroke path
|
||||
|
||||
const strokeDasharray = {
|
||||
[DashStyle.Draw]: 'none',
|
||||
[DashStyle.Solid]: `none`,
|
||||
[DashStyle.Dotted]: `0.1 ${strokeWidth * 4}`,
|
||||
[DashStyle.Dashed]: `${strokeWidth * 4} ${strokeWidth * 4}`,
|
||||
}[style.dash]
|
||||
|
||||
const strokeDashoffset = {
|
||||
[DashStyle.Draw]: 'none',
|
||||
[DashStyle.Solid]: `none`,
|
||||
[DashStyle.Dotted]: `0`,
|
||||
[DashStyle.Dashed]: `0`,
|
||||
}[style.dash]
|
||||
|
||||
const sw = 1 + strokeWidth * 1.5
|
||||
|
||||
return (
|
||||
<SVGContainer ref={ref} id={shape.id + '_svg'} {...events}>
|
||||
<g opacity={isGhost ? GHOSTED_OPACITY : 1}>
|
||||
<path
|
||||
d={pathTDSnapshot}
|
||||
fill={shouldFill ? fill : 'none'}
|
||||
stroke="none"
|
||||
strokeWidth={Math.min(4, strokeWidth * 2)}
|
||||
strokeLinejoin="round"
|
||||
strokeLinecap="round"
|
||||
pointerEvents={shouldFill ? 'all' : 'stroke'}
|
||||
/>
|
||||
<path
|
||||
d={pathTDSnapshot}
|
||||
fill="none"
|
||||
stroke={stroke}
|
||||
strokeWidth={sw}
|
||||
strokeDasharray={strokeDasharray}
|
||||
strokeDashoffset={strokeDashoffset}
|
||||
strokeLinejoin="round"
|
||||
strokeLinecap="round"
|
||||
pointerEvents="stroke"
|
||||
/>
|
||||
</g>
|
||||
</SVGContainer>
|
||||
)
|
||||
})
|
||||
)
|
||||
|
||||
Indicator = TDShapeUtil.Indicator<T>(({ shape }) => {
|
||||
const { points } = shape
|
||||
|
|
|
@ -39,7 +39,7 @@ export class EllipseUtil extends TDShapeUtil<T, E> {
|
|||
}
|
||||
|
||||
Component = TDShapeUtil.Component<T, E, TDMeta>(
|
||||
({ shape, isGhost, isBinding, meta, events }, ref) => {
|
||||
({ shape, isGhost, isSelected, isBinding, meta, events }, ref) => {
|
||||
const {
|
||||
radius: [radiusX, radiusY],
|
||||
style,
|
||||
|
@ -68,18 +68,25 @@ export class EllipseUtil extends TDShapeUtil<T, E> {
|
|||
ry={ry + 2}
|
||||
/>
|
||||
)}
|
||||
<ellipse
|
||||
className={isSelected ? 'tl-fill-hitarea' : 'tl-stroke-hitarea'}
|
||||
cx={radiusX}
|
||||
cy={radiusY}
|
||||
rx={radiusX}
|
||||
ry={radiusY}
|
||||
/>
|
||||
<path
|
||||
d={getEllipseIndicatorPathTDSnapshot(shape, this.getCenter(shape))}
|
||||
stroke="none"
|
||||
fill={style.isFilled ? styles.fill : 'none'}
|
||||
pointerEvents="all"
|
||||
pointerEvents="none"
|
||||
/>
|
||||
<path
|
||||
d={path}
|
||||
fill={styles.stroke}
|
||||
stroke={styles.stroke}
|
||||
strokeWidth={styles.strokeWidth}
|
||||
pointerEvents="all"
|
||||
pointerEvents="none"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
opacity={isGhost ? GHOSTED_OPACITY : 1}
|
||||
|
@ -111,16 +118,23 @@ export class EllipseUtil extends TDShapeUtil<T, E> {
|
|||
/>
|
||||
)}
|
||||
<ellipse
|
||||
className={isSelected ? 'tl-fill-hitarea' : 'tl-stroke-hitarea'}
|
||||
cx={radiusX}
|
||||
cy={radiusY}
|
||||
rx={rx}
|
||||
ry={ry}
|
||||
rx={radiusX}
|
||||
ry={radiusY}
|
||||
/>
|
||||
<ellipse
|
||||
cx={radiusX}
|
||||
cy={radiusY}
|
||||
rx={radiusX}
|
||||
ry={radiusY}
|
||||
fill={styles.fill}
|
||||
stroke={styles.stroke}
|
||||
strokeWidth={sw}
|
||||
strokeDasharray={strokeDasharray}
|
||||
strokeDashoffset={strokeDashoffset}
|
||||
pointerEvents="all"
|
||||
pointerEvents="none"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
|
@ -130,7 +144,16 @@ export class EllipseUtil extends TDShapeUtil<T, E> {
|
|||
)
|
||||
|
||||
Indicator = TDShapeUtil.Indicator<T, M>(({ shape }) => {
|
||||
return <path d={getEllipseIndicatorPathTDSnapshot(shape, this.getCenter(shape))} />
|
||||
const {
|
||||
radius: [radiusX, radiusY],
|
||||
style: { dash },
|
||||
} = shape
|
||||
|
||||
return dash === DashStyle.Draw ? (
|
||||
<path d={getEllipseIndicatorPathTDSnapshot(shape, this.getCenter(shape))} />
|
||||
) : (
|
||||
<ellipse cx={radiusX} cy={radiusY} rx={radiusX} ry={radiusY} />
|
||||
)
|
||||
})
|
||||
|
||||
hitTestPoint = (shape: T, point: number[]): boolean => {
|
||||
|
|
|
@ -41,7 +41,7 @@ export class RectangleUtil extends TDShapeUtil<T, E> {
|
|||
}
|
||||
|
||||
Component = TDShapeUtil.Component<T, E, TDMeta>(
|
||||
({ shape, isBinding, isGhost, meta, events }, ref) => {
|
||||
({ shape, isBinding, isSelected, isGhost, meta, events }, ref) => {
|
||||
const { id, size, style } = shape
|
||||
|
||||
const styles = getShapeStyle(style, meta.isDarkMode)
|
||||
|
@ -50,6 +50,7 @@ export class RectangleUtil extends TDShapeUtil<T, E> {
|
|||
|
||||
if (style.dash === DashStyle.Draw) {
|
||||
const pathTDSnapshot = getRectanglePath(shape)
|
||||
const indicatorPath = getRectangleIndicatorPathTDSnapshot(shape)
|
||||
|
||||
return (
|
||||
<SVGContainer ref={ref} id={shape.id + '_svg'} {...events}>
|
||||
|
@ -63,18 +64,20 @@ export class RectangleUtil extends TDShapeUtil<T, E> {
|
|||
/>
|
||||
)}
|
||||
<path
|
||||
d={getRectangleIndicatorPathTDSnapshot(shape)}
|
||||
className={isSelected ? 'tl-fill-hitarea' : 'tl-stroke-hitarea'}
|
||||
d={indicatorPath}
|
||||
/>
|
||||
<path
|
||||
d={indicatorPath}
|
||||
fill={style.isFilled ? styles.fill : 'none'}
|
||||
radius={strokeWidth}
|
||||
stroke="none"
|
||||
pointerEvents="all"
|
||||
pointerEvents="none"
|
||||
/>
|
||||
<path
|
||||
d={pathTDSnapshot}
|
||||
fill={styles.stroke}
|
||||
stroke={styles.stroke}
|
||||
strokeWidth={styles.strokeWidth}
|
||||
pointerEvents="all"
|
||||
pointerEvents="none"
|
||||
opacity={isGhost ? GHOSTED_OPACITY : 1}
|
||||
/>
|
||||
</SVGContainer>
|
||||
|
@ -107,9 +110,6 @@ export class RectangleUtil extends TDShapeUtil<T, E> {
|
|||
y1={start[1]}
|
||||
x2={end[0]}
|
||||
y2={end[1]}
|
||||
stroke={styles.stroke}
|
||||
strokeWidth={sw}
|
||||
strokeLinecap="round"
|
||||
strokeDasharray={strokeDasharray}
|
||||
strokeDashoffset={strokeDashoffset}
|
||||
/>
|
||||
|
@ -118,26 +118,37 @@ export class RectangleUtil extends TDShapeUtil<T, E> {
|
|||
|
||||
return (
|
||||
<SVGContainer ref={ref} id={shape.id + '_svg'} {...events}>
|
||||
{isBinding && (
|
||||
<g opacity={isGhost ? GHOSTED_OPACITY : 1}>
|
||||
{isBinding && (
|
||||
<rect
|
||||
className="tl-binding-indicator"
|
||||
x={sw / 2 - 32}
|
||||
y={sw / 2 - 32}
|
||||
width={w + 64}
|
||||
height={h + 64}
|
||||
/>
|
||||
)}
|
||||
<rect
|
||||
className="tl-binding-indicator"
|
||||
x={sw / 2 - 32}
|
||||
y={sw / 2 - 32}
|
||||
width={w + 64}
|
||||
height={h + 64}
|
||||
className={isSelected ? 'tl-fill-hitarea' : 'tl-stroke-hitarea'}
|
||||
x={sw / 2}
|
||||
y={sw / 2}
|
||||
width={w}
|
||||
height={h}
|
||||
/>
|
||||
)}
|
||||
<rect
|
||||
x={sw / 2}
|
||||
y={sw / 2}
|
||||
width={w}
|
||||
height={h}
|
||||
fill={styles.fill}
|
||||
strokeWidth={sw}
|
||||
stroke="none"
|
||||
pointerEvents="all"
|
||||
/>
|
||||
<g pointerEvents="stroke">{paths}</g>
|
||||
{style.isFilled && (
|
||||
<rect
|
||||
x={sw / 2}
|
||||
y={sw / 2}
|
||||
width={w}
|
||||
height={h}
|
||||
fill={styles.fill}
|
||||
pointerEvents="none"
|
||||
/>
|
||||
)}
|
||||
<g pointerEvents="none" stroke={styles.stroke} strokeWidth={sw} strokeLinecap="round">
|
||||
{paths}
|
||||
</g>
|
||||
</g>
|
||||
</SVGContainer>
|
||||
)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue