284 lines
6.9 KiB
Java
284 lines
6.9 KiB
Java
var _require = require('detect-browser'),
|
||
detect = _require.detect;
|
||
|
||
var Util = require('./util/index');
|
||
|
||
var Event = require('./core/mixin/event');
|
||
|
||
var Group = require('./core/group');
|
||
|
||
var Timeline = require('./core/mixin/timeline');
|
||
|
||
var renderers = require('./renderers/index');
|
||
|
||
var browser = detect();
|
||
var isFirefox = browser && browser.name === 'firefox';
|
||
|
||
var Canvas = function Canvas(cfg) {
|
||
Canvas.superclass.constructor.call(this, cfg);
|
||
};
|
||
|
||
Canvas.CFG = {
|
||
eventEnable: true,
|
||
|
||
/**
|
||
* 像素宽度
|
||
* @type {Number}
|
||
*/
|
||
width: null,
|
||
|
||
/**
|
||
* 像素高度
|
||
* @type {Number}
|
||
*/
|
||
height: null,
|
||
|
||
/**
|
||
* 画布宽度
|
||
* @type {Number}
|
||
*/
|
||
widthCanvas: null,
|
||
|
||
/**
|
||
* 画布高度
|
||
* @type {Number}
|
||
*/
|
||
heightCanvas: null,
|
||
|
||
/**
|
||
* CSS宽
|
||
* @type {String}
|
||
*/
|
||
widthStyle: null,
|
||
|
||
/**
|
||
* CSS高
|
||
* @type {String}
|
||
*/
|
||
heightStyle: null,
|
||
|
||
/**
|
||
* 容器DOM
|
||
* @type {Object}
|
||
*/
|
||
containerDOM: null,
|
||
|
||
/**
|
||
* 当前Canvas的DOM
|
||
* @type {Object}
|
||
*/
|
||
canvasDOM: null,
|
||
|
||
/**
|
||
* 屏幕像素比
|
||
* @type {Number}
|
||
*/
|
||
pixelRatio: null,
|
||
|
||
/**
|
||
* 渲染器,默认是canvas
|
||
* @type {String}
|
||
*/
|
||
renderer: 'canvas',
|
||
|
||
/**
|
||
* 是否支持 CSS Transform
|
||
* CSS transform 目前尚未经过长时间验证,为了避免影响上层业务,默认关闭,上层按需开启
|
||
*/
|
||
supportCSSTransform: false
|
||
};
|
||
Util.extend(Canvas, Group);
|
||
Util.augment(Canvas, Event, {
|
||
init: function init() {
|
||
Canvas.superclass.init.call(this);
|
||
|
||
this._setGlobalParam();
|
||
|
||
this._setContainer();
|
||
|
||
this._initPainter();
|
||
|
||
this._scale();
|
||
|
||
if (this.get('eventEnable')) {
|
||
this.registerEvent(this);
|
||
}
|
||
},
|
||
_scale: function _scale() {
|
||
if (this._cfg.renderType !== 'svg') {
|
||
var pixelRatio = this.get('pixelRatio');
|
||
this.scale(pixelRatio, pixelRatio);
|
||
}
|
||
},
|
||
_setGlobalParam: function _setGlobalParam() {
|
||
var renderType = this.get('renderer') || 'canvas';
|
||
|
||
if (renderType === 'svg') {
|
||
this.set('pixelRatio', 1);
|
||
} else if (!this.get('pixelRatio')) {
|
||
this.set('pixelRatio', Util.getRatio());
|
||
}
|
||
|
||
this._cfg.renderType = renderType;
|
||
var renderer = renderers[renderType];
|
||
this._cfg.renderer = renderer;
|
||
this._cfg.canvas = this;
|
||
var timeline = new Timeline(this);
|
||
this._cfg.timeline = timeline;
|
||
},
|
||
_setContainer: function _setContainer() {
|
||
var containerId = this.get('containerId');
|
||
var containerDOM = this.get('containerDOM');
|
||
|
||
if (!containerDOM) {
|
||
containerDOM = document.getElementById(containerId);
|
||
this.set('containerDOM', containerDOM);
|
||
}
|
||
|
||
Util.modifyCSS(containerDOM, {
|
||
position: 'relative'
|
||
});
|
||
},
|
||
_initPainter: function _initPainter() {
|
||
var containerDOM = this.get('containerDOM');
|
||
var painter = new this._cfg.renderer.painter(containerDOM);
|
||
this._cfg.painter = painter;
|
||
this._cfg.canvasDOM = this._cfg.el = painter.canvas;
|
||
this.changeSize(this.get('width'), this.get('height'));
|
||
},
|
||
_resize: function _resize() {
|
||
var canvasDOM = this.get('canvasDOM');
|
||
var widthCanvas = this.get('widthCanvas');
|
||
var heightCanvas = this.get('heightCanvas');
|
||
var widthStyle = this.get('widthStyle');
|
||
var heightStyle = this.get('heightStyle');
|
||
canvasDOM.style.width = widthStyle;
|
||
canvasDOM.style.height = heightStyle;
|
||
canvasDOM.setAttribute('width', widthCanvas);
|
||
canvasDOM.setAttribute('height', heightCanvas);
|
||
},
|
||
getWidth: function getWidth() {
|
||
var pixelRatio = this.get('pixelRatio');
|
||
var width = this.get('width');
|
||
return width * pixelRatio;
|
||
},
|
||
getHeight: function getHeight() {
|
||
var pixelRatio = this.get('pixelRatio');
|
||
var height = this.get('height');
|
||
return height * pixelRatio;
|
||
},
|
||
changeSize: function changeSize(width, height) {
|
||
var pixelRatio = this.get('pixelRatio');
|
||
var widthCanvas = width * pixelRatio;
|
||
var heightCanvas = height * pixelRatio;
|
||
this.set('widthCanvas', widthCanvas);
|
||
this.set('heightCanvas', heightCanvas);
|
||
this.set('widthStyle', width + 'px');
|
||
this.set('heightStyle', height + 'px');
|
||
this.set('width', width);
|
||
this.set('height', height);
|
||
|
||
this._resize();
|
||
},
|
||
getPointByEvent: function getPointByEvent(ev) {
|
||
var supportCSSTransform = this.get('supportCSSTransform');
|
||
|
||
if (supportCSSTransform) {
|
||
var pixelRatio = this.get('pixelRatio') || 1; // For Firefox <= 38
|
||
|
||
if (isFirefox && !Util.isNil(ev.layerX) && ev.layerX !== ev.offsetX) {
|
||
return {
|
||
x: ev.layerX * pixelRatio,
|
||
y: ev.layerY * pixelRatio
|
||
};
|
||
}
|
||
|
||
if (!Util.isNil(ev.offsetX)) {
|
||
// For IE6+, Firefox >= 39, Chrome, Safari, Opera
|
||
return {
|
||
x: ev.offsetX * pixelRatio,
|
||
y: ev.offsetY * pixelRatio
|
||
};
|
||
}
|
||
} // should calculate by self for other cases, like Safari in ios
|
||
// TODO: support CSS transform
|
||
|
||
|
||
var _this$getClientByEven = this.getClientByEvent(ev),
|
||
clientX = _this$getClientByEven.x,
|
||
clientY = _this$getClientByEven.y;
|
||
|
||
return this.getPointByClient(clientX, clientY);
|
||
},
|
||
// 获取 touch 事件的 clientX 和 clientY 需要单独处理
|
||
getClientByEvent: function getClientByEvent(ev) {
|
||
var clientInfo = ev;
|
||
|
||
if (ev.touches) {
|
||
if (ev.type === 'touchend') {
|
||
clientInfo = ev.changedTouches[0];
|
||
} else {
|
||
clientInfo = ev.touches[0];
|
||
}
|
||
}
|
||
|
||
return {
|
||
x: clientInfo.clientX,
|
||
y: clientInfo.clientY
|
||
};
|
||
},
|
||
|
||
/**
|
||
* 将窗口坐标转变成 canvas 坐标
|
||
* @param {Number} clientX 窗口x坐标
|
||
* @param {Number} clientY 窗口y坐标
|
||
* @return {Object} canvas坐标
|
||
*/
|
||
getPointByClient: function getPointByClient(clientX, clientY) {
|
||
var el = this.get('el');
|
||
var pixelRatio = this.get('pixelRatio') || 1;
|
||
var bbox = el.getBoundingClientRect();
|
||
return {
|
||
x: (clientX - bbox.left) * pixelRatio,
|
||
y: (clientY - bbox.top) * pixelRatio
|
||
};
|
||
},
|
||
getClientByPoint: function getClientByPoint(x, y) {
|
||
var el = this.get('el');
|
||
var bbox = el.getBoundingClientRect();
|
||
var pixelRatio = this.get('pixelRatio') || 1;
|
||
return {
|
||
clientX: x / pixelRatio + bbox.left,
|
||
clientY: y / pixelRatio + bbox.top
|
||
};
|
||
},
|
||
draw: function draw() {
|
||
this._cfg.painter.draw(this);
|
||
},
|
||
getShape: function getShape(x, y, e) {
|
||
if (arguments.length === 3 && this._cfg.renderer.getShape) {
|
||
return this._cfg.renderer.getShape.call(this, x, y, e);
|
||
}
|
||
|
||
return Canvas.superclass.getShape.call(this, x, y);
|
||
},
|
||
getRenderer: function getRenderer() {
|
||
return this._cfg.renderType;
|
||
},
|
||
_drawSync: function _drawSync() {
|
||
this._cfg.painter.drawSync(this);
|
||
},
|
||
destroy: function destroy() {
|
||
var cfg = this._cfg;
|
||
var containerDOM = cfg.containerDOM;
|
||
var canvasDOM = cfg.canvasDOM;
|
||
|
||
if (canvasDOM && containerDOM) {
|
||
containerDOM.removeChild(canvasDOM);
|
||
}
|
||
|
||
cfg.timeline.stop();
|
||
Canvas.superclass.destroy.call(this);
|
||
}
|
||
});
|
||
module.exports = Canvas; |