| /** |
| * 贝塞尔曲线 |
| * @module zrender/shape/BezierCurve |
| */ |
| import Path from '../Path'; |
| import * as vec2 from '../../core/vector'; |
| import { quadraticSubdivide, cubicSubdivide, quadraticAt, cubicAt, quadraticDerivativeAt, cubicDerivativeAt } from '../../core/curve'; |
| var out = []; |
| |
| function someVectorAt(shape, t, isTangent) { |
| var cpx2 = shape.cpx2; |
| var cpy2 = shape.cpy2; |
| |
| if (cpx2 === null || cpy2 === null) { |
| return [(isTangent ? cubicDerivativeAt : cubicAt)(shape.x1, shape.cpx1, shape.cpx2, shape.x2, t), (isTangent ? cubicDerivativeAt : cubicAt)(shape.y1, shape.cpy1, shape.cpy2, shape.y2, t)]; |
| } else { |
| return [(isTangent ? quadraticDerivativeAt : quadraticAt)(shape.x1, shape.cpx1, shape.x2, t), (isTangent ? quadraticDerivativeAt : quadraticAt)(shape.y1, shape.cpy1, shape.y2, t)]; |
| } |
| } |
| |
| export default Path.extend({ |
| type: 'bezier-curve', |
| shape: { |
| x1: 0, |
| y1: 0, |
| x2: 0, |
| y2: 0, |
| cpx1: 0, |
| cpy1: 0, |
| // cpx2: 0, |
| // cpy2: 0 |
| // Curve show percent, for animating |
| percent: 1 |
| }, |
| style: { |
| stroke: '#000', |
| fill: null |
| }, |
| buildPath: function (ctx, shape) { |
| var x1 = shape.x1; |
| var y1 = shape.y1; |
| var x2 = shape.x2; |
| var y2 = shape.y2; |
| var cpx1 = shape.cpx1; |
| var cpy1 = shape.cpy1; |
| var cpx2 = shape.cpx2; |
| var cpy2 = shape.cpy2; |
| var percent = shape.percent; |
| |
| if (percent === 0) { |
| return; |
| } |
| |
| ctx.moveTo(x1, y1); |
| |
| if (cpx2 == null || cpy2 == null) { |
| if (percent < 1) { |
| quadraticSubdivide(x1, cpx1, x2, percent, out); |
| cpx1 = out[1]; |
| x2 = out[2]; |
| quadraticSubdivide(y1, cpy1, y2, percent, out); |
| cpy1 = out[1]; |
| y2 = out[2]; |
| } |
| |
| ctx.quadraticCurveTo(cpx1, cpy1, x2, y2); |
| } else { |
| if (percent < 1) { |
| cubicSubdivide(x1, cpx1, cpx2, x2, percent, out); |
| cpx1 = out[1]; |
| cpx2 = out[2]; |
| x2 = out[3]; |
| cubicSubdivide(y1, cpy1, cpy2, y2, percent, out); |
| cpy1 = out[1]; |
| cpy2 = out[2]; |
| y2 = out[3]; |
| } |
| |
| ctx.bezierCurveTo(cpx1, cpy1, cpx2, cpy2, x2, y2); |
| } |
| }, |
| |
| /** |
| * Get point at percent |
| * @param {number} t |
| * @return {Array.<number>} |
| */ |
| pointAt: function (t) { |
| return someVectorAt(this.shape, t, false); |
| }, |
| |
| /** |
| * Get tangent at percent |
| * @param {number} t |
| * @return {Array.<number>} |
| */ |
| tangentAt: function (t) { |
| var p = someVectorAt(this.shape, t, true); |
| return vec2.normalize(p, p); |
| } |
| }); |