Research-Stack/3-Mathematical-Models/bezier-kit/packages/style/test/split.spec.ts

82 lines
2.8 KiB
TypeScript

import { describe, expect, it } from 'vitest'
import type { StyledBezierPath } from '../src/types'
import { createStyledPathSplitter } from '../src/split'
import { expectPointClose } from './helpers'
const makeGradientPath = (): StyledBezierPath => ({
path: {
start: { x: 0, y: 0 },
segments: [
{ cp1: { x: 0, y: 100 }, cp2: { x: 100, y: 100 }, end: { x: 100, y: 0 } },
{ cp1: { x: 100, y: -100 }, cp2: { x: 200, y: -100 }, end: { x: 200, y: 0 } },
],
},
stroke: {
width: 5,
gradient: {
x1: 0,
y1: 0,
x2: 1,
y2: 1,
stops: [
{ offset: 0, color: '#ff0000' },
{ offset: 1, color: '#0000ff' },
],
},
},
})
const makeSimplePath = (): StyledBezierPath => ({
path: {
start: { x: 0, y: 0 },
segments: [{ cp1: { x: 30, y: 50 }, cp2: { x: 70, y: 50 }, end: { x: 100, y: 0 } }],
},
stroke: { width: 3, color: '#ffffff' },
})
describe('createStyledPathSplitter', () => {
it('左の終点と右の始点が一致する', () => {
const split = createStyledPathSplitter(makeSimplePath())
const [left, right] = split(0.5)
const leftEnd = left.path.segments[left.path.segments.length - 1]!.end
expectPointClose(leftEnd, right.path.start, 4)
})
it('stroke が保持される(グラデーションなし)', () => {
const split = createStyledPathSplitter(makeSimplePath())
const [left, right] = split(0.5)
expect(left.stroke?.width).toBe(3)
expect(left.stroke?.color).toBe('#ffffff')
expect(right.stroke?.width).toBe(3)
expect(right.stroke?.color).toBe('#ffffff')
})
it('グラデーション付きパスの分割でグラデーションが保持される', () => {
const split = createStyledPathSplitter(makeGradientPath())
const [left, right] = split(0.5)
expect(left.stroke?.gradient).toBeDefined()
expect(right.stroke?.gradient).toBeDefined()
expect(left.stroke?.gradient?.stops).toHaveLength(2)
expect(right.stroke?.gradient?.stops).toHaveLength(2)
})
it('分割後のグラデーション座標が remap される', () => {
const original = makeGradientPath()
const split = createStyledPathSplitter(original)
const [left] = split(0.5)
const origGrad = original.stroke!.gradient!
const leftGrad = left.stroke!.gradient!
expect(Number.isFinite(leftGrad.x1)).toBe(true)
expect(Number.isFinite(leftGrad.y1)).toBe(true)
expect(Number.isFinite(leftGrad.x2)).toBe(true)
expect(Number.isFinite(leftGrad.y2)).toBe(true)
expect(leftGrad.stops[0]?.color).toBe(origGrad.stops[0]?.color)
expect(leftGrad.stops[1]?.color).toBe(origGrad.stops[1]?.color)
})
it('ratio 範囲外は clamp される(createPathSplitter に委譲)', () => {
const split = createStyledPathSplitter(makeSimplePath())
const [left0] = split(-5)
expectPointClose(left0.path.start, { x: 0, y: 0 })
})
})