@leafer-in/editor
Version:
106 lines (75 loc) • 3.5 kB
text/typescript
import { IUI, ILeaferCanvas, IRenderOptions, IRectInputData, IMatrixWithOptionHalfData } from '@leafer-ui/interface'
import { Paint, UI, MatrixHelper, getBoundsData, getMatrixData, BoundsHelper, LeafBoundsHelper } from '@leafer-ui/draw'
import { IStroker } from '@leafer-in/interface'
import { targetAttr } from '../decorator/data'
const { abs } = Math
const { copy, scale } = MatrixHelper
const { setListWithFn } = BoundsHelper
const { worldBounds } = LeafBoundsHelper
const matrix = getMatrixData() as IMatrixWithOptionHalfData
const bounds = getBoundsData()
export class Stroker extends UI implements IStroker {
public target: IUI | IUI[]
public list: IUI[] = []
constructor() {
super()
this.visible = 0
this.hittable = false
this.strokeAlign = 'center'
}
public setTarget(target: IUI | IUI[], style: IRectInputData): void {
this.set(style)
this.target = target
this.update()
}
public update(): void {
const { list } = this
if (list.length) {
setListWithFn(bounds, list, worldBounds)
this.set(bounds)
this.visible = true
} else this.visible = 0
}
public __draw(canvas: ILeaferCanvas, options: IRenderOptions): void {
const { list } = this
if (list.length) {
let leaf: IUI
const data = this.__, { stroke, strokeWidth, fill } = data, { bounds } = options
for (let i = 0; i < list.length; i++) {
leaf = list[i]
const { worldTransform, worldRenderBounds } = leaf
if (worldRenderBounds.width && worldRenderBounds.height && (!bounds || bounds.hit(worldRenderBounds, options.matrix))) {
const aScaleX = abs(worldTransform.scaleX), aScaleY = abs(worldTransform.scaleY)
copy(matrix, worldTransform)
matrix.half = strokeWidth % 2
if (aScaleX !== aScaleY) { // need no scale stroke, use rect path
scale(matrix, 1 / aScaleX, 1 / aScaleY)
canvas.setWorld(matrix, options.matrix)
canvas.beginPath()
data.strokeWidth = strokeWidth
const { x, y, width, height } = leaf.__layout.boxBounds
canvas.rect(x * aScaleX, y * aScaleY, width * aScaleX, height * aScaleY)
} else {
canvas.setWorld(matrix, options.matrix)
canvas.beginPath()
if (leaf.__.__useArrow) leaf.__drawPath(canvas)
else leaf.__.__pathForRender ? leaf.__drawRenderPath(canvas) : leaf.__drawPathByBox(canvas)
data.strokeWidth = strokeWidth / abs(worldTransform.scaleX)
}
if (stroke) typeof stroke === 'string' ? Paint.stroke(stroke, this, canvas) : Paint.strokes(stroke, this, canvas)
if (fill) typeof fill === 'string' ? Paint.fill(fill, this, canvas) : Paint.fills(fill, this, canvas)
}
}
data.strokeWidth = strokeWidth
}
}
public destroy(): void {
this.target = null
super.destroy()
}
}
function onTarget(stroker: Stroker): void {
const value = stroker.target
stroker.list = value ? (value instanceof Array ? value : [value]) : []
}