Source: core/Graphics.js

  1. import {Container} from './Container';
  2. import {FrameBuffer} from '../filters/FrameBuffer';
  3. import {Utils} from '../utils/Utils';
  4. const FUNCTION = 'fn';
  5. const INSTANCE = 'in';
  6. /* eslint max-len: 0 */
  7. /**
  8. * 形状对象,继承至Container
  9. *
  10. *
  11. * ```js
  12. * const options = {
  13. * cache: true,
  14. * bounds: new JC.Bounds(-50, -50, 50, 50)
  15. * };
  16. * function drawRect(ctx) {
  17. * ctx.fillStyle = 'red';
  18. * ctx.fillRect(-10, -10, 10, 10);
  19. * }
  20. *
  21. * function Cricle(options) {
  22. * this.radius = options.radius || 0;
  23. * this.color = options.color || '#3a3cfd';
  24. * }
  25. * Cricle.prototype.render = function(ctx) {
  26. * ctx.beginPath();
  27. * ctx.fillStyle = this.color;
  28. * ctx.arc(0, 0, this.radius, 0, Math.PI * 2, true);
  29. * ctx.closePath();
  30. * ctx.fill();
  31. * }
  32. *
  33. * const rect = new JC.Graphics(drawRect);
  34. * const cricle = new JC.Graphics(new Cricle());
  35. *
  36. * ```
  37. *
  38. * @class
  39. * @memberof JC
  40. * @extends JC.Container
  41. * @param {function|object} mesh 绘制对象,可以是函数,也可以是带有render方法的对象,绘制时会将当前绘图环境传递给它
  42. * @param {object} options 绘制对象
  43. * @param {boolean} [options.cache] 是否缓存改绘制对象,加入绘制对象非常复杂并后续无需更新时设置为 true 可以优化性能
  44. * @param {JC.Bounds} [options.bounds] 绘制对象的包围盒,在需要缓存时需要手动设置
  45. */
  46. function Graphics(mesh, options) {
  47. Container.call(this);
  48. options = options || {};
  49. this.mesh = mesh;
  50. this.meshType = Utils.isFunction(mesh) ? FUNCTION :
  51. Utils.isObject(mesh) && Utils.isFunction(mesh.render) ? INSTANCE : '';
  52. if (this.meshType === '') console.error('不支持的绘制对象');
  53. this.cache = options.cache || false;
  54. this.cached = false;
  55. this.setBounds(options.bounds);
  56. this.frameBuffer = null;
  57. }
  58. Graphics.prototype = Object.create(Container.prototype);
  59. /**
  60. * 更新对象本身的矩阵姿态以及透明度
  61. *
  62. * @private
  63. * @param {context} ctx
  64. */
  65. Graphics.prototype.renderMe = function(ctx) {
  66. if (!this.meshType) return;
  67. if (this.cached || this.cache) {
  68. if (this.cache) {
  69. if (this.frameBuffer === null) this.frameBuffer = new FrameBuffer();
  70. this.frameBuffer.clear();
  71. this.__co = this._bounds.getRectangle();
  72. this.__co.px = this.__co.py = 0;
  73. this.frameBuffer.setSize(this.__co);
  74. this.frameBuffer.setTransform(1, 0, 0, 1, -this.__co.x, -this.__co.y);
  75. this._drawBack(this.frameBuffer.ctx);
  76. this.cached = true;
  77. this.cache = false;
  78. }
  79. this.frameBuffer &&
  80. ctx.drawImage(
  81. this.frameBuffer.canvas,
  82. this.__co.x - this.__co.px,
  83. this.__co.y - this.__co.py,
  84. this.frameBuffer.width,
  85. this.frameBuffer.height
  86. );
  87. } else {
  88. this._drawBack(ctx);
  89. }
  90. };
  91. /**
  92. * 调用绘制函数
  93. *
  94. * @private
  95. * @param {context} ctx
  96. */
  97. Graphics.prototype._drawBack = function(ctx) {
  98. if (this.meshType === FUNCTION) {
  99. this.mesh(ctx);
  100. } else if (this.meshType === INSTANCE) {
  101. this.mesh.render(ctx);
  102. }
  103. };
  104. export {Graphics};