diff --git a/packages/g-canvas/__tests__/bugs/issue-202-spec.js b/packages/g-canvas/__tests__/bugs/issue-202-spec.js index b8955b0b5..159aed900 100644 --- a/packages/g-canvas/__tests__/bugs/issue-202-spec.js +++ b/packages/g-canvas/__tests__/bugs/issue-202-spec.js @@ -12,7 +12,7 @@ describe('#202', () => { height: 500, }); - it.only('the transformation from canvas coordinates to relative coordinates should be effective', (done) => { + it('the transformation from canvas coordinates to relative coordinates should be effective', (done) => { const group = canvas.addGroup(); const circle = group.addShape('circle', { attrs: { diff --git a/packages/g-canvas/tests/bugs/issue-222-spec.js b/packages/g-canvas/tests/bugs/issue-222-spec.js new file mode 100644 index 000000000..a05213400 --- /dev/null +++ b/packages/g-canvas/tests/bugs/issue-222-spec.js @@ -0,0 +1,54 @@ +const expect = require('chai').expect; +import Canvas from '../../src/canvas'; + +const dom = document.createElement('div'); +document.body.appendChild(dom); +dom.id = 'c1'; + +describe('#187', () => { + const canvas = new Canvas({ + container: dom, + width: 600, + height: 600, + localRefresh: true, // 由于局部刷新依赖于图形的包围盒计算,因此测试时 localRefresh 需要为 true + }); + + it('bbox calculation should be correct for path with arc', () => { + const shape1 = canvas.addShape('path', { + attrs: { + fill: '#1890ff', + path: [ + ['M', 227.31794680557064, 200.00000266808433], + ['L', 87.61525298763183, 98.50004569833794], + ['A', 172.6820363488079, 172.6820363488079, 0, 0, 0, 63.08757910043951, 253.36168385505405], + ['L', 227.31794680557064, 200.00000266808433], + ['Z'], + ], + }, + }); + const shape2 = canvas.addShape('path', { + attrs: { + fill: '#5D7092', + fillOpacity: 0.85, + lineWidth: 0, + path: [ + ['M', 227.31796092753956, 200.00000629398966], + ['L', 63.08757910043951, 253.36168385505405], + ['A', 172.68203634880794, 172.68203634880794, 0, 0, 0, 345.526943245539, 325.8797870175248], + ['L', 227.31796092753956, 200.00000629398966], + ['z'], + ], + }, + }); + const bbox1 = shape1.getBBox(); + const bbox2 = shape2.getBBox(); + expect(bbox1.minX).eqls(54.63591866828193); + expect(bbox1.minY).eqls(98.50004569833794); + expect(bbox1.maxX).eqls(227.31794680557064); + expect(bbox1.maxY).eqls(253.36168385505414); + expect(bbox2.minX).eqls(63.087579100439484); + expect(bbox2.minY).eqls(200.00000629398966); + expect(bbox2.maxX).eqls(345.526943245539); + expect(bbox2.maxY).eqls(372.68203634880797); + }); +}); diff --git a/packages/g-math/src/arc.ts b/packages/g-math/src/arc.ts index 3deef916a..5b3b84c6b 100644 --- a/packages/g-math/src/arc.ts +++ b/packages/g-math/src/arc.ts @@ -72,8 +72,14 @@ export default { const xs = [startAngle, endAngle]; for (let i = -Math.PI * 2; i <= Math.PI * 2; i += Math.PI) { const xAngle = xDim + i; - if (startAngle < xAngle && xAngle < endAngle) { - xs.push(xAngle); + if (startAngle < endAngle) { + if (startAngle < xAngle && xAngle < endAngle) { + xs.push(xAngle); + } + } else { + if (endAngle < xAngle && xAngle < startAngle) { + xs.push(xAngle); + } } } @@ -93,8 +99,14 @@ export default { const ys = [startAngle, endAngle]; for (let i = -Math.PI * 2; i <= Math.PI * 2; i += Math.PI) { const yAngle = yDim + i; - if (startAngle < yAngle && yAngle < endAngle) { - ys.push(yAngle); + if (startAngle < endAngle) { + if (startAngle < yAngle && yAngle < endAngle) { + ys.push(yAngle); + } + } else { + if (endAngle < yAngle && yAngle < startAngle) { + ys.push(yAngle); + } } } diff --git a/packages/g-math/tests/unit/ellipse-arc-spec.js b/packages/g-math/tests/unit/ellipse-arc-spec.js index 59dbd7baf..63512f754 100644 --- a/packages/g-math/tests/unit/ellipse-arc-spec.js +++ b/packages/g-math/tests/unit/ellipse-arc-spec.js @@ -135,6 +135,48 @@ describe('ellipse arc test', () => { expect(box.width).eqls(p11.x - p21.x); }); + it('box, ellipse 0 when startAngle > endAngle', () => { + // 1 / 2 圆弧,旋转 0 + const xRotation = 0; + const box = arc.box(100, 100, 20, 10, xRotation, Math.PI, 0); + const p1 = arc.pointAt(100, 100, 20, 10, 0, Math.PI, 0, 0); + const p2 = arc.pointAt(100, 100, 20, 10, 0, Math.PI, 0, 1); + const p11 = rotation({ x: 100, y: 100 }, p1, xRotation); + const p21 = rotation({ x: 100, y: 100 }, p2, xRotation); + + ctx.beginPath(); + ctx.ellipse(100, 100, 20, 10, xRotation, 0, Math.PI); + ctx.stroke(); + + ctx.beginPath(); + ctx.strokeRect(box.x, box.y, box.width, box.height); + expect(box.x).eqls(p11.x); + expect(box.y).eqls(p11.y); + expect(box.width).eqls(p21.x - p11.x); + expect(box.height).eqls(10); + }); + + it('box, ellipse 90 when startAngle > endAngle', () => { + // 1 / 2 圆弧,旋转 90 + const xRotation = Math.PI / 2; + const box = arc.box(100, 100, 20, 10, xRotation, Math.PI, 0); + const p1 = arc.pointAt(100, 100, 20, 10, 0, Math.PI, 0, 0); + const p2 = arc.pointAt(100, 100, 20, 10, 0, Math.PI, 0, 1); + const p11 = rotation({ x: 100, y: 100 }, p1, xRotation); + const p21 = rotation({ x: 100, y: 100 }, p2, xRotation); + + ctx.beginPath(); + ctx.ellipse(100, 100, 20, 10, xRotation, 0, Math.PI); + ctx.stroke(); + + ctx.beginPath(); + ctx.strokeRect(box.x, box.y, box.width, box.height); + expect(box.x).eqls(p21.x - 10); + expect(box.y).eqls(p11.y); + expect(box.width).eqls(10); + expect(box.height).eqls(40); + }); + it('tangent angle', () => { expect(arc.tangentAngle(0, 0, 10, 10, 0, 0, Math.PI, 0)).eqls(Math.PI / 2); expect(arc.tangentAngle(0, 0, 10, 10, 0, 0, Math.PI, 1)).eqls(Math.PI / 2 + Math.PI);