| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324 | var matrix = require("../core/matrix");var vector = require("../core/vector");/** * 提供变换扩展 * @module zrender/mixin/Transformable * @author pissang (https://www.github.com/pissang) */var mIdentity = matrix.identity;var EPSILON = 5e-5;function isNotAroundZero(val) {  return val > EPSILON || val < -EPSILON;}/** * @alias module:zrender/mixin/Transformable * @constructor */var Transformable = function (opts) {  opts = opts || {}; // If there are no given position, rotation, scale  if (!opts.position) {    /**     * 平移     * @type {Array.<number>}     * @default [0, 0]     */    this.position = [0, 0];  }  if (opts.rotation == null) {    /**     * 旋转     * @type {Array.<number>}     * @default 0     */    this.rotation = 0;  }  if (!opts.scale) {    /**     * 缩放     * @type {Array.<number>}     * @default [1, 1]     */    this.scale = [1, 1];  }  /**   * 旋转和缩放的原点   * @type {Array.<number>}   * @default null   */  this.origin = this.origin || null;};var transformableProto = Transformable.prototype;transformableProto.transform = null;/** * 判断是否需要有坐标变换 * 如果有坐标变换, 则从position, rotation, scale以及父节点的transform计算出自身的transform矩阵 */transformableProto.needLocalTransform = function () {  return isNotAroundZero(this.rotation) || isNotAroundZero(this.position[0]) || isNotAroundZero(this.position[1]) || isNotAroundZero(this.scale[0] - 1) || isNotAroundZero(this.scale[1] - 1);};var scaleTmp = [];transformableProto.updateTransform = function () {  var parent = this.parent;  var parentHasTransform = parent && parent.transform;  var needLocalTransform = this.needLocalTransform();  var m = this.transform;  if (!(needLocalTransform || parentHasTransform)) {    m && mIdentity(m);    return;  }  m = m || matrix.create();  if (needLocalTransform) {    this.getLocalTransform(m);  } else {    mIdentity(m);  } // 应用父节点变换  if (parentHasTransform) {    if (needLocalTransform) {      matrix.mul(m, parent.transform, m);    } else {      matrix.copy(m, parent.transform);    }  } // 保存这个变换矩阵  this.transform = m;  var globalScaleRatio = this.globalScaleRatio;  if (globalScaleRatio != null && globalScaleRatio !== 1) {    this.getGlobalScale(scaleTmp);    var relX = scaleTmp[0] < 0 ? -1 : 1;    var relY = scaleTmp[1] < 0 ? -1 : 1;    var sx = ((scaleTmp[0] - relX) * globalScaleRatio + relX) / scaleTmp[0] || 0;    var sy = ((scaleTmp[1] - relY) * globalScaleRatio + relY) / scaleTmp[1] || 0;    m[0] *= sx;    m[1] *= sx;    m[2] *= sy;    m[3] *= sy;  }  this.invTransform = this.invTransform || matrix.create();  matrix.invert(this.invTransform, m);};transformableProto.getLocalTransform = function (m) {  return Transformable.getLocalTransform(this, m);};/** * 将自己的transform应用到context上 * @param {CanvasRenderingContext2D} ctx */transformableProto.setTransform = function (ctx) {  var m = this.transform;  var dpr = ctx.dpr || 1;  if (m) {    ctx.setTransform(dpr * m[0], dpr * m[1], dpr * m[2], dpr * m[3], dpr * m[4], dpr * m[5]);  } else {    ctx.setTransform(dpr, 0, 0, dpr, 0, 0);  }};transformableProto.restoreTransform = function (ctx) {  var dpr = ctx.dpr || 1;  ctx.setTransform(dpr, 0, 0, dpr, 0, 0);};var tmpTransform = [];var originTransform = matrix.create();transformableProto.setLocalTransform = function (m) {  if (!m) {    // TODO return or set identity?    return;  }  var sx = m[0] * m[0] + m[1] * m[1];  var sy = m[2] * m[2] + m[3] * m[3];  var position = this.position;  var scale = this.scale;  if (isNotAroundZero(sx - 1)) {    sx = Math.sqrt(sx);  }  if (isNotAroundZero(sy - 1)) {    sy = Math.sqrt(sy);  }  if (m[0] < 0) {    sx = -sx;  }  if (m[3] < 0) {    sy = -sy;  }  position[0] = m[4];  position[1] = m[5];  scale[0] = sx;  scale[1] = sy;  this.rotation = Math.atan2(-m[1] / sy, m[0] / sx);};/** * 分解`transform`矩阵到`position`, `rotation`, `scale` */transformableProto.decomposeTransform = function () {  if (!this.transform) {    return;  }  var parent = this.parent;  var m = this.transform;  if (parent && parent.transform) {    // Get local transform and decompose them to position, scale, rotation    matrix.mul(tmpTransform, parent.invTransform, m);    m = tmpTransform;  }  var origin = this.origin;  if (origin && (origin[0] || origin[1])) {    originTransform[4] = origin[0];    originTransform[5] = origin[1];    matrix.mul(tmpTransform, m, originTransform);    tmpTransform[4] -= origin[0];    tmpTransform[5] -= origin[1];    m = tmpTransform;  }  this.setLocalTransform(m);};/** * Get global scale * @return {Array.<number>} */transformableProto.getGlobalScale = function (out) {  var m = this.transform;  out = out || [];  if (!m) {    out[0] = 1;    out[1] = 1;    return out;  }  out[0] = Math.sqrt(m[0] * m[0] + m[1] * m[1]);  out[1] = Math.sqrt(m[2] * m[2] + m[3] * m[3]);  if (m[0] < 0) {    out[0] = -out[0];  }  if (m[3] < 0) {    out[1] = -out[1];  }  return out;};/** * 变换坐标位置到 shape 的局部坐标空间 * @method * @param {number} x * @param {number} y * @return {Array.<number>} */transformableProto.transformCoordToLocal = function (x, y) {  var v2 = [x, y];  var invTransform = this.invTransform;  if (invTransform) {    vector.applyTransform(v2, v2, invTransform);  }  return v2;};/** * 变换局部坐标位置到全局坐标空间 * @method * @param {number} x * @param {number} y * @return {Array.<number>} */transformableProto.transformCoordToGlobal = function (x, y) {  var v2 = [x, y];  var transform = this.transform;  if (transform) {    vector.applyTransform(v2, v2, transform);  }  return v2;};/** * @static * @param {Object} target * @param {Array.<number>} target.origin * @param {number} target.rotation * @param {Array.<number>} target.position * @param {Array.<number>} [m] */Transformable.getLocalTransform = function (target, m) {  m = m || [];  mIdentity(m);  var origin = target.origin;  var scale = target.scale || [1, 1];  var rotation = target.rotation || 0;  var position = target.position || [0, 0];  if (origin) {    // Translate to origin    m[4] -= origin[0];    m[5] -= origin[1];  }  matrix.scale(m, m, scale);  if (rotation) {    matrix.rotate(m, m, rotation);  }  if (origin) {    // Translate back from origin    m[4] += origin[0];    m[5] += origin[1];  }  m[4] += position[0];  m[5] += position[1];  return m;};var _default = Transformable;module.exports = _default;
 |