ModuleBase.define("Annotation", ["RestServer", "Error", "TextInfo"], function(RestServer,Error,TextInfo) {
/**
* @desc Annotation构造函数。
* @constructor
* @alias Annotation
*/
var Annotation = function(boardId, roomHandle, board) {
this.roomHandle = roomHandle;
this.boardId = boardId; //白板ID
this.shapeType = shapeTypeEnum.mouse; //几何形状 or 操作类型
this.color = 'rgba(0,0,0,1)'; //注释设置颜色,默认值为黑色
this.backgroundColor = '';
this.lineWidth = 2; //线条宽度,默认值为2
this.arrowLength = 10; //设置箭头宽度,默认值为10
this.arrowtype = arrowTypeEnum.end; //箭头类别
this.fillType = fillTypeEnum.none;//是否需要填充
this.fillColor = 'none'; //填充颜色
this.initType = AnnotationInitTypeEnum.full; // 批注层默认填充类型为平铺,铺满整个外部容器
this.shapeArray = []; //批注图形数组
this.redoArray = [];
this.undoArray = []; // 撤销图形数组,用于撤销时恢复记录的操作
this.zr = null; //zrender对象实例
this.annoDiv = null; // 用户传入的白板外部容器div
this.renderDiv = null; // 计算得到的内部使用的白板容器
this.renderBackground = null; // 和renderDiv同样大小的背景层,用于控制背景色或背景图
this.currentIndex = -1 ;
this.drawOrEraser = annoSelectTypeEnum.draw; //注释类型
this.isEraser = false; //橡皮擦按下状态
this.eraserShape = null;
this.eraserImageWidth = 32;
this.eraserImageHeight = 32;
this.otherShapeMap = {}; //其他人
this.screenSize = {
width:0,
height:0
};
this.hlightPointInfo = {
imgUrl:'',
width:'',
height:'',
intervalTime: 200,
isSend:true
}
this.hlightPointShape = null; //TODO 有时间重新整理逻辑 使用map {userId:hlightPointShape} 可以有多个激光笔
this.textTagShape = null;
// 移动端属性
this.arrowLineStartPoint = { //定义arrowline的起始坐标,防止点击不拖动时绘制的问题
x: 0,
y: 0
}
this.currentX = 0;
this.currentY = 0;
this.x = 0;
this.y = 0;
this.shapeData = [];
this.rhombData = [];
this.shapeObj = {};
this.shape = null;
this.imgZlevel = -99999;
this.normalZlevel = 10000;
this.tempHighZlevel = 99999;
this.currActiveImg = null;
this.isAllowEditImg = false;
// 防止图片跳动
this.dragData = {
drag: false,
pos: [0,0]
}
this.shapeGroup = new zrender.Group({
slient: false // 组内子孙元素是否响应鼠标事件
});
this.textInfo = null;
// 缩放的位置信息
this.positionInfo = {
scaleWidth: 0, // 缩放目标宽度
scaleHeight: 0, // 缩放目标高度
zrWidth: 0, // 当前画布的宽度
zrHeight: 0, // 当前画布的高度
scaleRatioX: 1, // 横向缩放比例,缩放目标宽度和当前画布宽度的比值
scaleRatioY: 1, // 纵向缩放比例,缩放目标高度和当前画布高度的比值
scaleRatioXR: 1, // 横向缩放比例,当前画布宽度和缩放目标宽度的比值
scaleRatioYR: 1, // 纵向缩放比例,当前画布宽度和缩放目标宽度的比值,
originalWidth: 0, // 初始的宽度
originalHeight: 0 // 初始的高度
};
// 图片缩放后鼠标捕获的坐标与图片左上角坐标的偏移量
this.imgScaleoffset = {
x: 0,
y: 0
};
this.board = board;
this.backgroundColor = board.backgroundColor;
};
var Successright = zrender.Path.extend({
type: 'Successright',
shape: {
// x, y on the cusp
x:0,
y:0,
width:0,
height:0
},
buildPath: function (path, shape) {
var x1 = shape.x;
var y1 = shape.y + shape.height/3*2;
var x2 = shape.x + shape.width/2;
var y2 = shape.y + shape.height;
var x3 = shape.x + shape.width;
var y3 = shape.y;
path.moveTo(x1,y1);
path.lineTo(x2,y2);
path.lineTo(x3,y3);
}
});
var Failure = zrender.Path.extend({
type: 'Failure',
shape: {
// x, y on the cusp
x: 0,
y: 0,
width:0,
height:0
},
buildPath: function (path, shape) {
var x = shape.x;
var y = shape.y;
var width = shape.width;
var height = shape.height;
var leftX = x - width/2;
var rightX = x + width/2;
var topY = y - height/2;
var bottomY = y + height/2;
path.moveTo(leftX,topY);
path.lineTo(rightX,bottomY);
path.closePath();
path.moveTo(rightX,topY);
path.lineTo(leftX,bottomY);
path.closePath();
}
});
var Arrow = zrender.Path.extend({
type: 'Arrow',
shape: {
// x, y on the cusp
x: 0,
y: 0,
width:0,
height:0
},
buildPath: function (path, shape) {
var x1 = shape.x;
var y1 = shape.y + shape.height/3;
var x2 = shape.x;
var y2 = shape.y + shape.height/3 * 2;
var x3 = shape.x + shape.width/3 * 2;
var y3 = shape.y + shape.height/3 * 2;
var x4 = shape.x + shape.width/3 * 2;
var y4 = shape.y + shape.height;
var x5 = shape.x + shape.width;
var y5 = shape.y + shape.height/2;
var x6 = shape.x + shape.width/3 * 2;
var y6 = shape.y;
var x7 = shape.x + shape.width/3 * 2;
var y7 = shape.y + shape.height/3;
path.moveTo(x1,y1);
path.lineTo(x2,y2);
path.lineTo(x3,y3);
path.lineTo(x4,y4);
path.lineTo(x5,y5);
path.lineTo(x6,y6);
path.lineTo(x7,y7);
path.closePath();
}
});
var Texttag = zrender.Path.extend({
type: 'Texttag',
shape: {
// x, y on the cusp
x: 0,
y: 0,
width:0,
height:0
},
buildPath: function (path, shape) {
var x1 = shape.x;
var y1 = shape.y + shape.height/4;
var x2 = shape.x;
var y2 = shape.y + shape.height/4 * 3;
var x3 = shape.x + shape.width/5 * 4;
var y3 = shape.y + shape.height/4 * 3;
var x4 = shape.x + shape.width/5 * 4;
var y4 = shape.y + shape.height;
var x5 = shape.x + shape.width;
var y5 = shape.y + shape.height/2;
var x6 = shape.x + shape.width/5 * 4;
var y6 = shape.y;
var x7 = shape.x + shape.width/5 * 4;
var y7 = shape.y + shape.height/4;
path.moveTo(x1,y1);
path.lineTo(x2,y2);
path.lineTo(x3,y3);
path.lineTo(x4,y4);
path.lineTo(x5,y5);
path.lineTo(x6,y6);
path.lineTo(x7,y7);
path.closePath();
}
});
/**
* @description 通过外部盒子和内容盒子的宽高,算出内容盒子撑满外部盒子的宽或者高的结果
* @param {int} outWidth 外部容器宽
* @param {int} outHeight 外部容器高
* @param {int} contentWidth 内容的宽
* @param {int} contentHeight 内容的高
*/
function getCompatibleSize(outWidth, outHeight, contentWidth, contentHeight) {
var renderWidth = 0;
var renderHeight = 0;
// 白板的宽高比
var contentRatio = contentWidth / contentHeight;
// 外部容器的宽高比
var outRatio = outWidth / outHeight;
if(contentRatio > 1 && outRatio > 1){
// 说明都是横向
if(contentRatio > outRatio){
// 说明白板比容器比例更宽
// 白板的宽度要撑满容器宽度、上下留白
renderWidth = outWidth;
if(contentWidth > outWidth){
// 白板更宽
renderHeight = contentHeight / (contentWidth / outWidth)
}else{
// 容器更宽,撑满容器后,高也要增加
renderHeight = contentHeight * (outWidth / contentWidth)
}
}else if(contentRatio < outRatio){
// 说明白板比容器比例更窄
// 白板的宽度要撑满容器高度、左右留白
renderHeight = outHeight;
if(contentHeight > outHeight){
// 白板更高
renderWidth = contentWidth / (contentHeight / outHeight)
}else{
// 容器更高
renderWidth = contentWidth * (outHeight / contentHeight)
}
}else{
// 比例相等,那直接撑满容器宽高
renderWidth = outWidth
renderHeight = outHeight
}
// 都要设置白板渲染比例
}else if(contentRatio > 1 && outRatio <= 1){
// 白板横向,容器正方形或竖向的时候
// 白板的宽度要撑满容器宽度、上下留白
renderWidth = outWidth;
if(contentWidth > outWidth){
// 白板更宽
renderHeight = contentHeight / (contentWidth / outWidth)
}else{
// 容器更宽,撑满容器后,高也要增加
renderHeight = contentHeight * (outWidth / contentWidth)
}
}else if(contentRatio < 1 && outRatio > 1){
// 白板竖向,容器横向
// 白板的宽度要撑满容器高度、左右留白
renderHeight = outHeight;
if(contentHeight > outHeight){
// 白板更高
renderWidth = contentWidth / (contentHeight / outHeight)
}else{
// 容器更高
renderWidth = contentWidth * (outHeight / contentHeight)
}
}else if(contentRatio < 1 && outRatio <= 1){
// 白板竖向,容器正方形或者竖向
if(contentRatio < outRatio){
// 白板更窄,撑满容器高度,左右留白
renderHeight = outHeight;
if(contentHeight > outHeight){
// 白板更高
renderWidth = contentWidth / (contentHeight / outHeight)
}else{
// 容器更高
renderWidth = contentWidth * (outHeight / contentHeight)
}
}else{
// 容器更窄,撑满容器宽度,上下留白
renderWidth = outWidth;
if(contentWidth > outWidth){
// 白板更宽
renderHeight = contentHeight / (contentWidth / outWidth)
}else{
// 容器更宽,撑满容器后,高也要增加
renderHeight = contentHeight * (outWidth / contentWidth)
}
}
}else{
if(contentRatio == 1){
if(outRatio > 1){
// 直接撑满高,左右留白
renderHeight = outHeight;
if(contentHeight > outHeight){
// 白板更高
renderWidth = contentWidth / (contentHeight / outHeight)
}else{
// 容器更高
renderWidth = contentWidth * (outHeight / contentHeight)
}
}else{
// 直接撑满宽,上下留白
renderWidth = outWidth;
if(contentWidth > outWidth){
// 白板更宽
renderHeight = contentHeight / (contentWidth / outWidth)
}else{
// 容器更宽,撑满容器后,高也要增加
renderHeight = contentHeight * (outWidth / contentWidth)
}
}
}
}
log.debug('===annotation getCompatibleSize, outWidht: ' + outWidth + ',outHeight: ' + outHeight + ',contentWidth: ' + contentWidth + ',contentHeight: ' + contentHeight + ',renderWidth: ' + renderWidth + ',renderHeight: ' + renderHeight);
return [renderWidth, renderHeight];
}
Annotation.prototype.initAndGetRenderCanvasByBoardAndWrapBox = function() {
var self = this;
var renderCanvas = document.createElement('canvas');
var renderCanvasWidth = 0;
var renderCanvasHeight = 0;
var compatibleSize = getCompatibleSize(self.annoDiv.clientWidth, self.annoDiv.clientHeight, self.board.width, self.board.height);
renderCanvasWidth = compatibleSize[0];
renderCanvasHeight = compatibleSize[1];
renderCanvas.width = renderCanvasWidth;
renderCanvas.height = renderCanvasHeight;
renderCanvas.style.width = renderCanvasWidth + 'px';
renderCanvas.style.height = renderCanvasHeight + 'px';
renderCanvas.style.background = 'rgba(0,0,0,0)';
self.board.setRenderWidthAndHeight(renderCanvasWidth, renderCanvasHeight);
log.debug("===annotation initAndGetRenderCanvasByBoardAndWrapBox, result: bw: " + self.board.width + ',bh: ' + self.board.height + ",ww: " + self.annoDiv.clientWidth + ",wh: " + self.annoDiv.clientHeight + ",rw: " + renderCanvasWidth + ",rh: " + renderCanvasHeight);
return renderCanvas;
}
/**
* @ignore
*/
Annotation.prototype.updateBackgroundColor = function (color) {
if(!this.renderBackground){
return;
}
if(!this.renderBackground instanceof HTMLCanvasElement){
return;
}
var ctx = this.renderBackground.getContext('2d');
if(color){
ctx.fillStyle = 'rgba(' + color + ')';
ctx.fillRect(0, 0, this.renderBackground.width, this.renderBackground.height);
this.backgroundColor = color;
}else{
ctx.clearRect(0, 0, this.renderBackground.width, this.renderBackground.height);
}
}
/**
* @ignore
*/
Annotation.prototype.updateBackgroundImage = function (imageUrl) {
var deferred = when.defer();
log.debug('===annotation updateBackgroundImage, imageUrl:'+ imageUrl);
var self = this;
if(!imageUrl){
deferred.reject('===annotation updateBackgroundImage error, reason: imageUrl is invalid!');
}
if(!this.renderBackground){
deferred.reject('===annotation updateBackgroundImage error, reason: board background is not exist!');
}
if(!this.renderBackground instanceof HTMLCanvasElement){
deferred.reject('===annotation updateBackgroundImage error, reason: board background element is not canvas');
}
try{
this.updateBackgroundColor(this.backgroundColor);
var ctx = this.renderBackground.getContext('2d');
var tempImageEl = document.createElement('img');
tempImageEl.src = imageUrl;
tempImageEl.onload = function(){
var compatibleSize = getCompatibleSize(self.renderBackground.width, self.renderBackground.height, tempImageEl.width, tempImageEl.height);
var startDrawX = (self.renderBackground.width / 2) - (compatibleSize[0] / 2);
var startDrawY = (self.renderBackground.height / 2) - (compatibleSize[1] / 2);
log.debug("===annotation updateBackgroundImage, startX:" + startDrawX + ",startY:" + startDrawY + ",compatibleSize:" + compatibleSize);
ctx.drawImage(tempImageEl, startDrawX, startDrawY, compatibleSize[0], compatibleSize[1]);
deferred.resolve();
}
}catch(err){
log.debug("===annotation updateBackgroundImage, err:" + err);
deferred.reject(err);
}
return deferred.promise;
}
/**
* @desc 初始化annotation对象
* @param {HTMLDivElement} annoDiv - 注释所在的应用层容器,只能传入div元素
* @param {String} annotationInitType - 注释初始化类型 可选值: AnnotationInitTypeEnum.proportional, AnnotationInitTypeEnum.full
*/
Annotation.prototype.init = function(annoDiv, annotationInitType){
var deferred = when.defer();
var self = this;
if(!(annoDiv instanceof HTMLDivElement) && !(annoDiv instanceof HTMLCanvasElement)){
log.error('===annotation init faild, must be given a div or canvas element!');
deferred.reject('Must be given a div or canvas element!');
return deferred.promise;
}
self.annoDiv = annoDiv;
if(annotationInitType && annotationInitType == AnnotationInitTypeEnum.proportional){
self.initType = annotationInitType;
// 如果初始化类型是proportional(成比例)则需要给定一个div元素,以便在此div内部创建批注和背景层
if(!(annoDiv instanceof HTMLDivElement)){
log.error('===annotation init faild, proportional type must be given a div element!')
deferred.reject('Proportional type must be given a div element!');
return deferred.promise;
}
annoDiv.style.display = 'flex';
annoDiv.style.alignItems = 'center';
annoDiv.style.justifyContent = 'center';
// 初始化canvas相关
this.renderDiv = self.initAndGetRenderCanvasByBoardAndWrapBox();
this.renderBackground = self.initAndGetRenderCanvasByBoardAndWrapBox();
this.renderDiv.style.position = 'relative';
this.renderDiv.style.zIndex = 1001;
annoDiv.appendChild(this.renderDiv);
// 背景层处理,用于设置背景色或者背景图
this.renderBackground.style.position = 'absolute';
// TODO 暂时注释,在佳会中设置下面属性,会导致打开文字功能时,背景层canvas会移位
// this.renderBackground.style.left = this.renderDiv.offsetLeft + 'px';
// this.renderBackground.style.top = this.renderDiv.offsetTop + 'px';
this.renderBackground.style.zIndex = 1000;
this.renderBackground.className = 'annotation-canvas-background';
annoDiv.appendChild(this.renderBackground);
}else{
this.renderDiv = annoDiv;
}
self.zr = zrender.init(this.renderDiv);
self.zr.add(self.shapeGroup);
self.positionInfo.originalWidth = self.zr.getWidth();
self.positionInfo.originalHeight = self.zr.getHeight();
//因为self.annoDiv.style.width及self.annoDiv.style.height 获取到的是100%,所以取第一个子节点的宽及高
if(self.annoDiv.style.width == "100%"){
var childDiv= self.annoDiv.firstChild;
self.screenSize.width = parseInt(childDiv.style.width);
self.screenSize.height = parseInt(childDiv.style.height);
log.debug("===Annotation.init(),childDiv.style.width:"+childDiv.style.width+",childDiv.style.height:"+ childDiv.style.height);
}else{
self.screenSize.width = parseInt(self.annoDiv.style.width);
self.screenSize.height = parseInt(self.annoDiv.style.height);
log.debug("===Annotation.init(),annoDiv.style.width:"+annoDiv.style.width+",annoDiv.style.height:"+ annoDiv.style.height);
}
this.updateBackgroundColor(this.backgroundColor);
// 图片拖拽
self.zr.on('mousedown', function(e) {
if(!self.isAllowEditImg){
return;
}
// 画布拖拽的起始位置是 事件对象中的画布的坐标位置
self.dragData.pos = [e.event.zrX, e.event.zrY];
// 画布的拖拽目标
if(e.target && e.target.type && e.target.type == 'image' && e.target.draggable != null){
// 设置当前激活的图片
self.currActiveImg = e.target;
self.currActiveImg.attr('zlevel', self.tempHighZlevel);
// 取图片的父节点,为shapeGroup
var shapeGroup = self.currActiveImg.parent;
// 给当前激活的图片添加高亮边框,其他图片取消高亮边框
shapeGroup.eachChild(function(item){
if(item.type === 'image'){
if(item.id == self.currActiveImg.id){
item.attr('style',{shadowColor:'red',shadowBlur:5});
}else{
item.attr('style',{shadowColor:undefined,shadowBlur:undefined});
}
}
})
if(self.currActiveImg.scale[0] == 1){
self.imgScaleoffset.x = 0;
self.imgScaleoffset.y = 0;
}else{
var scale = self.currActiveImg.scale[0] - 1;
self.imgScaleoffset.x = self.currActiveImg.getWidth() * scale / 2;
self.imgScaleoffset.y = self.currActiveImg.getHeight() * scale / 2;
}
}
if (e.target === undefined) {
self.dragData.drag = false
} else {
self.dragData.drag = true
}
})
self.zr.on('mouseup', function(e) {
if(!self.isAllowEditImg){
return;
}
if(!self.currActiveImg){
return;
}
self.dragData.drag = false;
self.currActiveImg.customPositionX = self.currActiveImg.position[0] - self.imgScaleoffset.x;
self.currActiveImg.customPositionY = self.currActiveImg.position[1] - self.imgScaleoffset.y;
log.debug('===Annotation.drawImg, currActiveImg customPosition: ',[self.currActiveImg.customPositionX, self.currActiveImg.customPositionY].toString())
self.currActiveImg.attr('zlevel', ++self.imgZlevel);
self.roomHandle.sendUpdateAnnotation(self.boardId, self.currActiveImg, shapeTypeEnum.img);
})
self.zr.on('mouseout', function(e) {
if(!self.isAllowEditImg){
return;
}
self.dragData.drag = false;
})
self.zr.on('mousemove', function(e) {
if (self.dragData.drag === false) {
if(self.currActiveImg){
self.currActiveImg.draggable = false;
}
return;
}
if (self.currActiveImg != null && self.isAllowEditImg === true) {
var new_pos = [e.event.zrX, e.event.zrY]
var pos = [
new_pos[0] - self.dragData.pos[0],
new_pos[1] - self.dragData.pos[1]
]
//图片拖动中,区域位置不能移出白板之外,放大缩小图片及重设置白板宽高后还有效。 by roymond 2024/11/7
var xMin = self.currActiveImg.position[0] + pos[0] * self.positionInfo.scaleRatioXR - self.currActiveImg.style.width * (self.currActiveImg.scaleX -1)/2;
var yMin = self.currActiveImg.position[1] + pos[1] * self.positionInfo.scaleRatioYR - self.currActiveImg.style.height * (self.currActiveImg.scaleY -1)/2;
var xMax = xMin + self.currActiveImg.style.width * self.currActiveImg.scaleX;
var yMax = yMin + self.currActiveImg.style.height * self.currActiveImg.scaleY;
if( xMin <0 || yMin<0 || xMax> self.board.width || yMax> self.board.height){
return;
}
//end
self.currActiveImg.position[0] += pos[0] * self.positionInfo.scaleRatioXR;
self.currActiveImg.position[1] += pos[1] * self.positionInfo.scaleRatioYR;
//console.log("===RRRRRRRRR222222222,"+ self.currActiveImg.position[0] +" , " + self.currActiveImg.position[1]);
self.currActiveImg.dirty();
self.dragData.pos = new_pos;
}
})
self.renderDiv.onmousedown = function(e){
if(self.isAllowEditImg){
return;
}
if(self.shapeType == shapeTypeEnum.mouse || self.shapeType == shapeTypeEnum.hlight_point){
return;
}
if(self.shapeType == shapeTypeEnum.eraser){
self.isEraser = true;
}
var shapeObj = {};
var x,y;
/**
* 之前用的是e.clientX - this.getBoundingClientRect().left这种来计算点击坐标
* 其实可以直接使用e.offsetX来
*/
var tempPos = self.handleScaledXY(e.clientX - this.getBoundingClientRect().left, e.clientY - this.getBoundingClientRect().top);
self.currentX = tempPos.x;
self.currentY = tempPos.y;
shapeData = [];
shapeData.push([self.currentX, self.currentY]);
var shape = null;
switch (self.shapeType){
case shapeTypeEnum.failure:
shape = new Failure({
shape:{
x:self.currentX,
y:self.currentY,
width:20,
height:20
},
style: {
stroke: self.color,
lineWidth:self.lineWidth
},
zlevel: self.normalZlevel,
onmouseover:mouseOverForEraser
})
break;
case shapeTypeEnum.success:
shape = new Successright({
shape:{
x:self.currentX - 10,
y:self.currentY - 10,
width:20,
height:20
},
style: {
stroke: self.color,
fill: 'none',
lineWidth:self.lineWidth
},
onmouseover:mouseOverForEraser
})
break;
case shapeTypeEnum.arrow:
shape = new Arrow({
shape:{
x:self.currentX - 15,
y:self.currentY - 10,
width:30,
height:20
},
style: {
stroke: self.color,
fill: self.fillColor,
lineWidth:self.lineWidth
},
zlevel: self.normalZlevel,
onmouseover:mouseOverForEraser
})
break;
case shapeTypeEnum.hlight_texttag:
var userName = self.roomHandle.selfUser.name;
var renderName = userName;
if(userName.split('').length > 7){
renderName = userName.substr(0, 7) + '...';
}
if(self.textTagShape){
self.textTagShape.attr({
shape: {
x:self.currentX - 40,
y:self.currentY - 20
},
style:{
text: renderName
},
zlevel: self.normalZlevel,
textContent: new zrender.Text({
x: self.currentX - 40 + 5,
y: self.currentY - 20 + 13,
style: {
text: renderName,
fill: '#ffffff',
textRect: {
x: self.currentX - 40 + 5,
y: self.currentY - 20 + 13,
width: 50
},
truncate: {
outerWidth: 50
}
},
zlevel: self.normalZlevel
})
});
self.roomHandle.sendAddAnnotation(self.boardId, self.textTagShape, self.shapeType, self.color, self.lineWidth, self.arrowtype, self.fillType);
}else{
self.textTagShape = new Texttag({
shape:{
x:self.currentX - 40,
y:self.currentY - 20,
width:80,
height:40
},
style: {
stroke: "red",
fill: "red",
text: renderName,
truncate:{
outerWidth:50
},
lineWidth:self.lineWidth
},
zlevel: self.normalZlevel,
textContent: new zrender.Text({
x: self.currentX - 40 + 5,
y: self.currentY - 20 + 13,
style: {
text: renderName,
fill: '#ffffff',
textRect: {
x: self.currentX - 40 + 5,
y: self.currentY - 20 + 13,
width: 50
},
truncate: {
outerWidth: 50
}
},
zlevel: self.normalZlevel
}),
onmouseover:mouseOverForEraser
})
self.textTagShape.id = Math.uuid();
self.shapeGroup.add(self.textTagShape);
self.roomHandle.sendAddAnnotation(self.boardId, self.textTagShape, self.shapeType, self.color, self.lineWidth, self.arrowtype, self.fillType);
}
break;
case shapeTypeEnum.rhomb:
shape = new zrender.Polygon({
shape:{
points: [],
smooth:0,
},
style: {
stroke: self.color,
fill: 'none',
lineWidth:self.lineWidth
},
zlevel: self.normalZlevel,
onmouseover:mouseOverForEraser
})
break;
case shapeTypeEnum.line:
shape = new zrender.Arrowline({
shape:{
x1: self.currentX,
y1: self.currentY,
x2: self.currentX,
y2: self.currentY,
arrowlength: 10,
arrowtype: self.arrowtype
},
style: {
stroke: self.color,
lineWidth:self.lineWidth
},
zlevel: self.normalZlevel,
onmouseover:mouseOverForEraser
})
break;
case shapeTypeEnum.polyline:
shape = new zrender.Polyline({
shape:{
points: [],
smooth:0,
},
style: {
stroke: self.color,
lineWidth:self.lineWidth
},
zlevel: self.normalZlevel,
onmouseover:mouseOverForEraser
})
break;
case shapeTypeEnum.rect:
shape = new zrender.Rect({
shape:{
x:self.currentX,
y:self.currentY
},
style: {
stroke: self.color,
fill: self.fillColor,
lineWidth:self.lineWidth
},
zlevel: self.normalZlevel,
onmouseover:mouseOverForEraser
})
break;
case shapeTypeEnum.ellipse:
shape = new zrender.Ellipse({
shape:{
cx:self.currentX,
cy:self.currentY,
rx:0,
ry:0,
},
style: {
stroke: self.color,
fill: self.fillColor,
lineWidth:self.lineWidth
},
zlevel: self.normalZlevel,
onmouseover:mouseOverForEraser
})
break;
default:
break;
}
if(shape){
shape.id = Math.uuid();
self.shapeGroup.add(shape);
}else{
return;
}
self.renderDiv.onmousemove = function(e){
if(self.isAllowEditImg){
return;
}
if(self.shapeType == shapeTypeEnum.eraser){
return;
}
var tempPos = self.handleScaledXY(e.clientX - this.getBoundingClientRect().left, e.clientY - this.getBoundingClientRect().top);
x = tempPos.x;
y = tempPos.y;
shapeData.push([x, y]);
var rhombData = [[self.currentX, self.currentY + (y-self.currentY)/2],[self.currentX + (x - self.currentX)/2, y],[x, self.currentY + (y-self.currentY)/2],[self.currentX + (x - self.currentX)/2, self.currentY]]
switch (self.shapeType){
case shapeTypeEnum.rhomb:
shape.attr('shape',{
points: rhombData
})
break;
case shapeTypeEnum.line:
shape.attr('shape',{
x2:x,
y2:y
})
break;
case shapeTypeEnum.polyline:
shape.attr('shape',{
points: shapeData
})
break;
case shapeTypeEnum.rect:
shape.attr('shape',{
width:x-self.currentX,
height:y-self.currentY
})
break;
case shapeTypeEnum.ellipse:
shape.attr('shape',{
cx:x + (self.currentX-x)/2,
cy:y + (self.currentY-y)/2,
rx:Math.abs(x-self.currentX)/2,
ry:Math.abs(y-self.currentY)/2,
})
break;
default:
break;
}
}
self.renderDiv.onmouseup = function(){
self.renderDiv.onmousemove = null;
self.renderDiv.onmouseup = null;
self.renderDiv.onmouseleave = null;
if(self.isAllowEditImg){
return;
}
if(self.shapeType == shapeTypeEnum.eraser){
self.isEraser = false;
return;
}
var shapeObj = {
shape:shape,
shapeType:self.shapeType,
color:self.color,
lineWidth:self.lineWidth,
arrowtype:self.arrowtype,
fillType:self.fillType,
}
self.shapeArray.push(shapeObj);
self.undoArray.push({
type: 'add',
shapeObj: shapeObj
})
self.redoArray = [];
self.roomHandle.sendAddAnnotation(self.boardId, shape, self.shapeType, self.color, self.lineWidth, self.arrowtype, self.fillType);
}
self.renderDiv.onmouseleave = function(){
self.renderDiv.onmousemove = null;
self.renderDiv.onmouseup = null;
self.renderDiv.onmouseleave = null;
if(self.isAllowEditImg){
return;
}
if(self.shapeType == shapeTypeEnum.eraser){
self.isEraser = false;
return;
}
var preWidth = parseInt(self.renderDiv.style.width);
var preHeight = parseInt(self.renderDiv.style.height);
self.shapeArray.push({
shape:shape,
shapeType:self.shapeType,
color:self.color,
lineWidth:self.lineWidth,
arrowtype:self.arrowtype,
fillType:self.fillType,
});
self.redoArray = [];
self.roomHandle.sendAddAnnotation(self.boardId, shape, self.shapeType, self.color, self.lineWidth, self.arrowtype, self.fillType);
}
}
function mouseOverForEraser(params) {
if(self.shapeType == shapeTypeEnum.eraser && self.isEraser){
for (var i = 0; i < self.shapeArray.length; i++) {
var shapeObj = self.shapeArray[i];
if(shapeObj.shape.id == params.target.id){
self.zr.remove(shapeObj.shape)
self.shapeGroup.remove(shapeObj.shape)
self.roomHandle.sendRemoveAnnotation(self.boardId,self.shapeType,shapeObj.shape.id)
self.undoArray.push({
type: 'delete',
shapeObj: shapeObj
})
self.shapeArray.splice(i,1);
}
}
}
}
self.renderDiv.ontouchstart = function(e){
if(self.isAllowEditImg){
return;
}
e.preventDefault(); // 阻止触摸默认滚动页面事件,防止页面滚动
if(self.shapeType == shapeTypeEnum.mouse || self.shapeType == shapeTypeEnum.hlight_point){
return;
}
if(self.shapeType == shapeTypeEnum.eraser){
self.isEraser = true;
return;
}
//使用更精确的坐标计算
var rect = this.getBoundingClientRect();
var touch = e.touches[0];
var rawX = touch.clientX - rect.left;
var rawY = touch.clientY - rect.top;
var tempPos = self.handleScaledXY(rawX, rawY);
self.currentX = tempPos.x;
self.currentY = tempPos.y;
self.arrowLineStartPoint.x = self.currentX;
self.arrowLineStartPoint.y = self.currentY;
self.shapeData = [];
self.shapeData.push([self.currentX, self.currentY]);
switch (self.shapeType){
case shapeTypeEnum.failure:
self.shape = new Failure({
shape:{
x:self.currentX,
y:self.currentY,
width:20,
height:20
},
style: {
stroke: self.color,
lineWidth:self.lineWidth
},
})
break;
case shapeTypeEnum.success:
self.shape = new Successright({
shape:{
x:self.currentX - 10,
y:self.currentY - 10,
width:20,
height:20
},
style: {
stroke: self.color,
fill: 'none',
lineWidth:self.lineWidth
},
})
break;
case shapeTypeEnum.arrow:
self.shape = new Arrow({
shape:{
x:self.currentX - 15,
y:self.currentY - 10,
width:30,
height:20
},
style: {
stroke: self.color,
fill: self.fillColor,
lineWidth:self.lineWidth
},
})
break;
case shapeTypeEnum.hlight_texttag:
if(self.textTagShape){
self.textTagShape.attr({
shape: {
x:self.currentX - 40,
y:self.currentY - 20
},
style:{
text: self.roomHandle.selfUser.name
}
});
self.roomHandle.sendAddAnnotation(self.boardId, self.textTagShape, self.shapeType, self.color, self.lineWidth, self.arrowtype, self.fillType);
}else{
self.textTagShape = new Texttag({
shape:{
x:self.currentX - 40,
y:self.currentY - 20,
width:80,
height:40
},
style: {
stroke: "red",
fill: "red",
text: self.roomHandle.selfUser.name,
truncate:{
outerWidth:50
},
lineWidth:self.lineWidth
},
})
self.textTagShape.id = Math.uuid();
self.shapeGroup.add(self.textTagShape);
self.roomHandle.sendAddAnnotation(self.boardId, self.textTagShape, self.shapeType, self.color, self.lineWidth, self.arrowtype, self.fillType);
}
if(self.shape){
self.shape = null; // 如果其他形状存在,清空,防止再重复绘制其他画笔
}
break;
case shapeTypeEnum.rhomb:
self.shape = new zrender.Polygon({
shape:{
points: [],
smooth:0,
},
style: {
stroke: self.color,
fill: 'none',
lineWidth:self.lineWidth
},
})
break;
case shapeTypeEnum.line:
self.shape = new zrender.Arrowline({
shape:{
arrowlength: 10,
arrowtype: self.arrowtype
},
style: {
stroke: self.color,
lineWidth:self.lineWidth
},
})
break;
case shapeTypeEnum.polyline:
self.shape = new zrender.Polyline({
shape:{
points: [],
smooth:0,
},
style: {
stroke: self.color,
lineWidth:self.lineWidth
},
})
break;
case shapeTypeEnum.rect:
self.shape = new zrender.Rect({
shape:{
x:self.currentX,
y:self.currentY
},
style: {
stroke: self.color,
fill: self.fillColor,
lineWidth:self.lineWidth
},
})
break;
case shapeTypeEnum.ellipse:
self.shape = new zrender.Ellipse({
shape:{
cx:self.currentX,
cy:self.currentY,
rx:0,
ry:0,
},
style: {
stroke: self.color,
fill: self.fillColor,
lineWidth:self.lineWidth
},
})
break;
default:
break;
}
if(self.shape){
self.shape.id = Math.uuid();
if(self.shapeType == shapeTypeEnum.success || self.shapeType == shapeTypeEnum.failure || self.shapeType == shapeTypeEnum.arrow){
var shapeObj = {
shape:self.shape,
shapeType:self.shapeType,
color:self.color,
lineWidth:self.lineWidth,
arrowtype:self.arrowtype,
fillType:self.fillType,
}
self.shapeArray.push(shapeObj);
self.undoArray.push({
type: 'add',
shapeObj: shapeObj
})
self.roomHandle.sendAddAnnotation(self.boardId, self.shape, self.shapeType, self.color, self.lineWidth, self.arrowtype, self.fillType);
}
self.shapeGroup.add(self.shape);
}else{
return;
}
}
self.renderDiv.ontouchmove = function(e){
if(self.isAllowEditImg){
return;
}
//使用更精确的坐标计算
var rect = this.getBoundingClientRect();
var touch = e.touches[0];
var rawX = touch.clientX - rect.left;
var rawY = touch.clientY - rect.top;
var tempPos = self.handleScaledXY(rawX, rawY);
self.x = tempPos.x;
self.y = tempPos.y;
if(self.shapeType == shapeTypeEnum.eraser){
self.isEraser = true;
var realX = self.x - self.eraserImageWidth / 2;
var realY = self.y - self.eraserImageHeight / 2;
if(self.eraserShape){
self.eraserShape.attr('position', [realX, realY]);
}
self.shapeArray.forEach(function(tempShape){
switch(tempShape.shapeType){
case shapeTypeEnum.line:
var shape = tempShape.shape.shape;
var x1 = shape.x1;
var x2 = shape.x2;
var y1 = shape.y1;
var y2 = shape.y2;
if(x1 < x2 && y1 < y2){
if(self.x >= x1 && self.x <= x2 && self.y >= y1 && self.y <= y2){
self.excuteRemoveAnnotation(tempShape);
}
}else if(x1 > x2 && y1 < y2){
if(self.x >= x2 && self.x <= x1 && self.y >= y1 && self.y <= y2){
self.excuteRemoveAnnotation(tempShape);
}
}else if(x1 < x2 && y1 > y2){
if(self.x >= x1 && self.x <= x2 && self.y >= y2 && self.y <= y1){
self.excuteRemoveAnnotation(tempShape);
}
}else if(x1 > x2 && y1 > y2){
if(self.x >= x2 && self.x <= x1 && self.y >= y2 && self.y <= y1){
self.excuteRemoveAnnotation(tempShape);
}
}
break;
case shapeTypeEnum.polyline:
// console.log('+++SDK shapeType polyline')
var points = tempShape.shape.shape.points;
var minLocationWidth = self.x - self.eraserImageWidth / 2;
var maxLocationWidth = self.x + self.eraserImageWidth / 2;
var minLocationHeight = self.y - self.eraserImageWidth / 2;
var maxLocationHeight = self.y + self.eraserImageWidth / 2;
if(points.length > 0){
points.forEach(function (point){
var pointX = point[0];
var pointY = point[1];
if(pointX >= minLocationWidth && pointX <= maxLocationWidth && pointY >= minLocationHeight && pointY <= maxLocationHeight){
self.excuteRemoveAnnotation(tempShape);
}
})
}
break;
case shapeTypeEnum.success:
var width = tempShape.shape.shape.width;
var height = tempShape.shape.shape.height;
var successX = tempShape.shape.shape.x;
var successY = tempShape.shape.shape.y;
if(self.x >= successX && self.x <= successX + width && self.y >= successY && self.y <= successY + height){
self.excuteRemoveAnnotation(tempShape);
}
break;
case shapeTypeEnum.failure:
var width = tempShape.shape.shape.width;
var height = tempShape.shape.shape.height;
var failureX = tempShape.shape.shape.x;
var failureY = tempShape.shape.shape.y;
if(self.x >= failureX && self.x <= failureX + width && self.y >= failureY && self.y <= failureY + height){
self.excuteRemoveAnnotation(tempShape);
}
break;
case shapeTypeEnum.rhomb:
var pointOne = tempShape.shape.shape.points[0];
var pointTwo = tempShape.shape.shape.points[1];
var pointThree = tempShape.shape.shape.points[2];
var pointFour = tempShape.shape.shape.points[3];
var x1 = pointOne[0];
var x2 = pointThree[0];
var y1 = pointTwo[1];
var y2 = pointFour[1];
if(self.x >= x1 && self.x <= x2 && self.y >= y1 && self.y <= y2){
// console.log('+++SDK 清除菱形1');
self.excuteRemoveAnnotation(tempShape);
break;
}else if(self.x <= x1 && self.x >= x2 && self.y >= y1 && self.y <= y2){
// console.log('+++SDK 清除菱形2');
self.excuteRemoveAnnotation(tempShape);
break;
}else if(self.x >= x1 && self.x <= x2 && self.y <= y1 && self.y >= y2){
// console.log('+++SDK 清除菱形3');
self.excuteRemoveAnnotation(tempShape);
break;
}else if(self.x <= x1 && self.x >= x2 && self.y <= y1 && self.y >= y2){
// console.log('+++SDK 清除菱形4');
self.excuteRemoveAnnotation(tempShape);
break;
}
break;
case shapeTypeEnum.arrow:
var width = tempShape.shape.shape.width;
var height = tempShape.shape.shape.height;
var arrowX = tempShape.shape.shape.x;
var arrowY = tempShape.shape.shape.y;
if(self.x >= arrowX && self.x <= arrowX + width && self.y >= arrowY && self.y <= arrowY + height){
self.excuteRemoveAnnotation(tempShape);
}
break;
case shapeTypeEnum.ellipse:
var cx = tempShape.shape.shape.cx;
var cy = tempShape.shape.shape.cy;
var rx = tempShape.shape.shape.rx;
var ry = tempShape.shape.shape.ry;
// 如果点击点在椭圆范围内
if(self.x >= cx - rx && self.x <= cx + rx && self.y >= cy - ry && self.y <= cy + ry){
self.excuteRemoveAnnotation(tempShape);
}
break;
case shapeTypeEnum.rect:
var rectWidth = tempShape.shape.shape.width;
var rectHeight = tempShape.shape.shape.height;
var rectX = tempShape.shape.shape.x;
var rectY = tempShape.shape.shape.y;
// 如果点击点在矩形范围内
if(rectWidth >= 0 && rectHeight >=0){
if(self.x >= rectX && self.x <= rectX + rectWidth && self.y >= rectY && self.y <= rectY + rectHeight){
self.excuteRemoveAnnotation(tempShape);
}
}else if(rectWidth <= 0 && rectHeight >= 0){
if(self.x >= rectX + rectWidth && self.x <= rectX && self.y >= rectY && self.y <= rectY + rectHeight){
self.excuteRemoveAnnotation(tempShape);
}
}else if(rectWidth >= 0 && rectHeight <= 0){
if(self.x >= rectX && self.x <= rectX + rectWidth && self.y >= rectY + rectHeight && self.y <= rectY){
self.excuteRemoveAnnotation(tempShape);
}
}else if(rectWidth <= 0 && rectHeight <= 0){
if(self.x >= rectX + rectWidth && self.x <= rectX && self.y >= rectY + rectHeight && self.y <= rectY){
self.excuteRemoveAnnotation(tempShape);
}
}
break;
default:
break;
}
})
return;
}
self.shapeData.push([self.x, self.y]);
var rhombData = [[self.currentX, self.currentY + (self.y-self.currentY)/2],[self.currentX + (self.x - self.currentX)/2, self.y],[self.x, self.currentY + (self.y-self.currentY)/2],[self.currentX + (self.x - self.currentX)/2, self.currentY]]
switch (self.shapeType){
case shapeTypeEnum.rhomb:
self.shape.attr('shape',{
points: rhombData
})
break;
case shapeTypeEnum.line:
var shapePoint = {
x1: self.arrowLineStartPoint.x,
y1: self.arrowLineStartPoint.y,
x2:self.x,
y2:self.y
}
self.shape.attr('shape',{
x1: self.arrowLineStartPoint.x,
y1: self.arrowLineStartPoint.y,
x2:self.x,
y2:self.y
})
break;
case shapeTypeEnum.polyline:
self.shape.attr('shape',{
points: self.shapeData
})
break;
case shapeTypeEnum.rect:
self.shape.attr('shape',{
width:self.x-self.currentX,
height:self.y-self.currentY
})
break;
case shapeTypeEnum.ellipse:
self.shape.attr('shape',{
cx:self.x + (self.currentX-self.x)/2,
cy:self.y + (self.currentY-self.y)/2,
rx:Math.abs(self.x-self.currentX)/2,
ry:Math.abs(self.y-self.currentY)/2,
})
break;
case shapeTypeEnum.hlight_point:
var width = self.hlightPointInfo.width;
var height = self.hlightPointInfo.height;
var realX = self.x - width / 2;
var realY = self.y - height / 2;
self.hlightPointShape.attr('position',[realX ,realY]);
if(self.hlightPointInfo.isSend){
self.hlightPointInfo.isSend = false;
self.roomHandle.sendAddAnnotation(self.boardId, self.hlightPointShape, shapeTypeEnum.hlight_point, self.color, self.lineWidth, self.arrowtype, self.fillType);
setTimeout(function(){
self.hlightPointInfo.isSend = true;
}, self.hlightPointInfo.intervalTime)
}
break;
default:
break;
}
}
self.renderDiv.ontouchend = function(){
if(self.isAllowEditImg){
return;
}
if(self.shapeType == shapeTypeEnum.txt || self.shapeType == shapeTypeEnum.hlight_texttag || self.shapeType == shapeTypeEnum.mouse || self.shapeType == shapeTypeEnum.success || self.shapeType == shapeTypeEnum.failure || self.shapeType == shapeTypeEnum.arrow){
return;
}
if(self.shapeType == shapeTypeEnum.eraser){
self.isEraser = false;
return;
}
var shapeObj = {
shape:self.shape,
shapeType:self.shapeType,
color:self.color,
lineWidth:self.lineWidth,
arrowtype:self.arrowtype,
fillType:self.fillType,
}
self.shapeArray.push(shapeObj);
self.redoArray = [];
if(self.shapeType != shapeTypeEnum.hlight_point){
self.undoArray.push({
type: 'add',
shapeObj: shapeObj
})
log.debug("++TTTTTTTTTT111111>>>>>>>>>>>");
self.roomHandle.sendAddAnnotation(self.boardId, self.shape, self.shapeType, self.color, self.lineWidth, self.arrowtype, self.fillType);
}
}
if(self.initType == AnnotationInitTypeEnum.proportional && self.board.backgroundColor != ""){
self.updateBackgroundColor(self.board.backgroundColor);
}
if(self.initType == AnnotationInitTypeEnum.proportional && self.board.backgroundImage != ""){
self.updateBackgroundImage(self.board.backgroundImage);
}
deferred.resolve();
return deferred.promise;
}
// 橡皮擦清除画笔
Annotation.prototype.excuteRemoveAnnotation = function(removeShape){
var self = this;
self.zr.remove(removeShape.shape)
self.shapeGroup.remove(removeShape.shape);
self.roomHandle.sendRemoveAnnotation(self.boardId, self.shapeType, removeShape.shape.id)
self.shapeArray.forEach(function(shapeObj, index){
if(shapeObj.shape.id == removeShape.shape.id){
self.undoArray.push({
type: 'delete',
shapeObj: shapeObj
})
self.shapeArray.splice(index, 1);
}
})
/**
* desc: 解决重连后重复批注删不掉
* by: 王博
* date: 2021/7/15
*/
var tempList = self.zr.storage._displayList;
for(var i in tempList){
if(tempList[i].id == removeShape.shape.id){
self.zr.remove(tempList[i]);
self.shapeGroup.remove(tempList[i])
}
}
}
Annotation.prototype.initEraserShape = function(eraserImgUrl){
var self = this;
self.eraserShape = new zrender.Image({
position: [0, 0],
scale: [1, 1],
style: {
image: eraserImgUrl,
width: self.eraserImageWidth,
height: self.eraserImageHeight
},
draggable: true
})
self.shapeGroup.add(self.eraserShape);
self.eraserShape.id = Math.uuid();
}
Annotation.prototype.removeToBoard = function(removeInfo) {
log.debug('===annotation removeToBoard');
var self = this;
var userKey = 'userId' + removeInfo.operUserId;
var shapeArray = self.shapeArray;
var displayList = self.zr.storage.getDisplayList();
var groupChildren = self.shapeGroup.children();
if(removeInfo.annotationType == shapeTypeEnum.clear){
if(removeInfo.operUserId == self.roomHandle.selfUser.id){
for(var k in self.shapeArray){
self.zr.remove(self.shapeArray[k].shape);
self.shapeGroup.remove(self.shapeArray[k].shape)
}
self.shapeArray = [];
}else{
for(var k in self.otherShapeMap){
if(k == userKey){
for(var j in self.otherShapeMap[k]){
self.zr.remove(self.otherShapeMap[k][j].shape);
self.shapeGroup.remove(self.otherShapeMap[k][j].shape);
for(var i = displayList.length - 1; i >= 0; i--){
if(displayList[i].id == self.otherShapeMap[k][j].shape.id){
self.zr.remove(displayList[i])
}
}
for(var m = groupChildren.length - 1; m >= 0; m--){
if(groupChildren[m].id == self.otherShapeMap[k][j].shape.id){
self.shapeGroup.remove(groupChildren[m])
}
}
}
}
}
}
delete self.otherShapeMap[userKey];
}else if(removeInfo.annotationType == shapeTypeEnum.eraser){
if(self.hlightPointShape && self.hlightPointShape.id == removeInfo.annotationId){
self.clearCurrHlightPoint();
}else if(self.textTagShape && self.textTagShape.id == removeInfo.annotationId){
self.clearCurrHlightPoint();
}else if(removeInfo.operUserId == self.roomHandle.selfUser.id){
for(var k in self.shapeArray){
if(self.shapeArray[k].shape.id == removeInfo.annotationId){
self.zr.remove(self.shapeArray[k].shape);
self.shapeGroup.remove(self.shapeArray[k].shape);
self.shapeArray.splice(k,1);
}
}
}else{
for(var k in self.otherShapeMap){
if(k == userKey){
for(var j in self.otherShapeMap[k]){
if(self.otherShapeMap[k][j].id == removeInfo.annotationId){
self.zr.remove(self.otherShapeMap[k][j].shape);
self.shapeGroup.remove(self.otherShapeMap[k][j].shape);
}
}
}
}
/**
* desc: 解决重连后重复批注删不掉
* by: 王博
* date: 2021/7/15
*/
var tempList = self.zr.storage._displayList;
for(var i in tempList){
if(tempList[i].id == removeInfo.annotationId){
self.zr.remove(tempList[i]);
self.shapeGroup.remove(tempList[i]);
}
}
}
}else if(removeInfo.annotationType == shapeTypeEnum.img){
for(var k in self.otherShapeMap){
if(k == userKey){
for(var j = self.otherShapeMap[k].length - 1; j >= 0; j--){
// 从各个维护的列表中删除当前批注对象
if(self.otherShapeMap[k][j].shape.id == removeInfo.annotationId || (removeInfo.Img && self.otherShapeMap[k][j].shape.id == removeInfo.Img.im.id)){
self.zr.remove(self.otherShapeMap[k][j].shape);
self.shapeGroup.remove(self.otherShapeMap[k][j].shape);
self.otherShapeMap[k].splice(j, 1);
}
}
}
}
}
}
function replaceRgba(obj){
return "rgba(" + obj.r + "," + obj.g + "," + obj.b + "," + parseFloat(obj.a/255) + ")";
}
function replaceRgb(obj){
return "rgb(" + obj.r + "," + obj.g + "," + obj.b + ")";
}
Annotation.prototype.drawTextToBoard = function(annotationInfo) {
var self = this;
var txt = annotationInfo.txt;
var txi = txt.txi
var txs = txi.txs
var objectBase = txt.objectBase.objectBase;
var shapeType = parseInt(txt.objectBase.type);
var lineWidth = parseInt(objectBase.lineWidth);
var arrowtype = parseInt(objectBase.arrow);
var color = replaceRgba(objectBase.lineColor);
var fillColor = replaceRgba(objectBase.fillColor);
var text = new zrender.Text({
style: {
text: txs[0].content,
fontSize: txi.fontSize,
fontStyle: txi.fontStyle,
fontWeight: txi.fontWeight,
fill: replaceRgb(txi.fontColor)
},
position: [txt.objectBase.start.x * self.roomHandle.boardInputXRatio, txt.objectBase.start.y * self.roomHandle.boardInputYRatio],
origin: [txt.objectBase.start.x * self.roomHandle.boardInputXRatio, txt.objectBase.start.y * self.roomHandle.boardInputYRatio],
onmouseover: mouseOverForEraser
})
self.shapeGroup.add(text);
var shapeObj = {
id: annotationInfo.annotationId,
shape: text,
shapeType: shapeType,
lineWidth: lineWidth,
arrowtype: arrowtype,
color: color,
fillColor: fillColor
}
if(annotationInfo.operUserId === self.roomHandle.selfUser.id){
self.shapeArray.push(shapeObj);
}else{
var userKey = 'userId' + objectBase.ownerUserId
if(self.otherShapeMap[userKey]){
self.otherShapeMap[userKey].push(shapeObj);
}else{
self.otherShapeMap[userKey] = [];
self.otherShapeMap[userKey].push(shapeObj);
}
}
function mouseOverForEraser(params) {
if(self.shapeType == shapeTypeEnum.eraser && self.isEraser){
for(var k in self.shapeArray){
if(self.shapeArray[k].shape.id == params.target.parent.id){
self.zr.remove(params.target.parent)
self.shapeGroup.remove(params.target.parent)
self.roomHandle.sendRemoveAnnotation(self.boardId,self.shapeType,self.shapeArray[k].shape.id)
self.undoArray.push({
type: 'delete',
shapeObj: self.shapeArray[k]
})
self.shapeArray.splice(k,1);
}
}
}
}
}
//远端获取的注释,画在画板上
Annotation.prototype.drawToBoard = function(annotationInfo) {
var self = this;
var shapeType = parseInt(annotationInfo.objectBase.type);
var lineWidth = parseInt(annotationInfo.objectBase.lineWidth);
var arrowtype = parseInt(annotationInfo.objectBase.arrow);
var color = replaceRgba(annotationInfo.objectBase.lineColor);
var fillColor = replaceRgba(annotationInfo.objectBase.fillColor);
var shape = null;
function mouseOverForEraser(params) {
if(self.shapeType == shapeTypeEnum.eraser && self.isEraser){
for(var k in self.shapeArray){
if(params.target.id && self.shapeArray[k].shape.id == params.target.id){
self.zr.remove(self.shapeArray[k].shape)
self.shapeGroup.remove(self.shapeArray[k].shape)
/**
* desc: 解决重连后重复批注删不掉
* by: 王博
* date: 2021/7/15
*/
var tempList = self.zr.storage._displayList;
for(var i in tempList){
if(tempList[i].id == params.target.id){
self.zr.remove(tempList[i]);
self.shapeGroup.remove(tempList[i]);
}
}
self.roomHandle.sendRemoveAnnotation(self.boardId,self.shapeType,self.shapeArray[k].shape.id)
self.shapeArray.splice(k,1);
}
}
}
}
switch (shapeType){
case shapeTypeEnum.rhomb:
var currentX = annotationInfo.start.x;
var currentY = annotationInfo.start.y;
var x = annotationInfo.end.x;
var y = annotationInfo.end.y;
log.debug("===annotation.drawToBoard(),room.boardInputXRatio:"+ self.roomHandle.boardInputXRatio+",room.boardInputYRatio:"+self.roomHandle.boardInputYRatio);
log.debug("===annotation.drawToBoard(),shapeTypeEnum.rhomb,currentX:",currentX+",currentY:",currentY+",x:"+x+",y:"+y);
var inputCurrentX = Math.round(currentX * self.roomHandle.boardInputXRatio);
var inputCurrentY = Math.round(currentY * self.roomHandle.boardInputYRatio);
var inputX = Math.round(x * self.roomHandle.boardInputXRatio);
var inputY = Math.round(y * self.roomHandle.boardInputYRatio);
log.debug("===annotation.drawToBoard(),ishapeTypeEnum.rhomb,nputCurrentX:",inputCurrentX+",inputCurrentY:",inputCurrentY+",inputX:"+inputX+",inputY:"+inputY);
var rhombData = [[inputCurrentX, inputCurrentY + (inputY-inputCurrentY)/2],[inputCurrentX + (inputX - inputCurrentX)/2, inputY],[inputX, inputCurrentY + (inputY-inputCurrentY)/2],[inputCurrentX + (inputX - inputCurrentX)/2, inputCurrentY]]
shape = new zrender.Polygon({
shape:{
points: rhombData,
smooth:0,
},
style: {
stroke: color,
fill: 'none',
lineWidth:lineWidth
},
zlevel: self.normalZlevel,
onmouseover:mouseOverForEraser
})
break;
case shapeTypeEnum.line:
var x1 = annotationInfo.start.x;
var y1 = annotationInfo.start.y;
var x2 = annotationInfo.end.x;
var y2 = annotationInfo.end.y;
log.debug("===annotation.drawToBoard(),shapeTypeEnum.line,x1:",x1+",y1:",y1+",x2:"+x2+",y2:"+y2);
var inputx1 = Math.round(x1 * self.roomHandle.boardInputXRatio);
var inputy1 = Math.round(y1 * self.roomHandle.boardInputYRatio);
var inputx2 = Math.round(x2 * self.roomHandle.boardInputXRatio);
var inputy2 = Math.round(y2 * self.roomHandle.boardInputYRatio);
log.debug("===annotation.drawToBoard(),shapeTypeEnum.line,inputx1:",inputx1+",inputy1:",inputy1+",inputx2:"+inputx2+",inputy2:"+inputy2);
shape = new zrender.Arrowline({
shape:{
x1: inputx1,
y1: inputy1,
x2: inputx2,
y2: inputy2,
arrowlength: 10,
arrowtype: arrowtype
},
style: {
stroke: color,
lineWidth:lineWidth
},
zlevel: self.normalZlevel,
onmouseover:mouseOverForEraser
})
break;
case shapeTypeEnum.failure:
var x = annotationInfo.start.x;
var y = annotationInfo.start.y;
var width = annotationInfo.end.x - annotationInfo.start.x;
var height = annotationInfo.end.y - annotationInfo.start.y;
log.debug("===annotation.drawToBoard(),shapeTypeEnum.failure,x:",x+",y:",y+",width:"+width+",height:"+height);
var inputX = Math.round(x * self.roomHandle.boardInputXRatio);
var inputY = Math.round(y * self.roomHandle.boardInputYRatio);
var inputWidth = Math.round(width * self.roomHandle.boardInputXRatio);
var inputHeight = Math.round(height * self.roomHandle.boardInputYRatio);
log.debug("===annotation.drawToBoard(),shapeTypeEnum.failure,inputX:",inputX+",inputY:",inputY+",inputWidth:"+inputWidth+",inputHeight:"+inputHeight);
shape = new Failure({
shape:{
x:inputX,
y:inputY,
width:inputWidth,
height:inputHeight
},
style: {
stroke: color,
lineWidth:lineWidth
},
zlevel: self.normalZlevel,
onmouseover:mouseOverForEraser
})
break;
case shapeTypeEnum.success:
var x = annotationInfo.start.x;
var y = annotationInfo.start.y;
var width = annotationInfo.end.x - annotationInfo.start.x;
var height = annotationInfo.end.y - annotationInfo.start.y;
log.debug("===annotation.drawToBoard(),shapeTypeEnum.success,x:",x+",y:",y+",width:"+width+",height:"+height);
var inputX = Math.round(x * self.roomHandle.boardInputXRatio);
var inputY = Math.round(y * self.roomHandle.boardInputYRatio);
var inputWidth = Math.round(width * self.roomHandle.boardInputXRatio);
var inputHeight = Math.round(height * self.roomHandle.boardInputYRatio);
log.debug("===annotation.drawToBoard(),shapeTypeEnum.success,inputX:",inputX+",inputY:",inputY+",inputWidth:"+inputWidth+",inputHeight:"+inputHeight);
shape = new Successright({
shape:{
x:inputX,
y:inputY,
width:inputWidth,
height:inputHeight
},
style: {
stroke: color,
fill: 'none',
lineWidth:lineWidth
},
zlevel: self.normalZlevel,
onmouseover:mouseOverForEraser
})
break;
case shapeTypeEnum.arrow:
var x = annotationInfo.start.x;
var y = annotationInfo.start.y;
var width = annotationInfo.end.x - annotationInfo.start.x;
var height = annotationInfo.end.y - annotationInfo.start.y;
log.debug("===annotation.drawToBoard(),shapeTypeEnum.arrow,x:",x+",y:",y+",width:"+width+",height:"+height);
var inputX = Math.round(x * self.roomHandle.boardInputXRatio);
var inputY = Math.round(y * self.roomHandle.boardInputYRatio);
var inputWidth = Math.round(width * self.roomHandle.boardInputXRatio);
var inputHeight = Math.round(height * self.roomHandle.boardInputYRatio);
log.debug("===annotation.drawToBoard(),shapeTypeEnum.arrow,inputX:",inputX+",inputY:",inputY+",inputWidth:"+inputWidth+",inputHeight:"+inputHeight);
shape = new Arrow({
shape:{
x:inputX,
y:inputY,
width:inputWidth,
height:inputHeight
},
style: {
stroke: color,
fill: fillColor,
lineWidth:lineWidth
},
zlevel: self.normalZlevel,
onmouseover:mouseOverForEraser
})
break;
case shapeTypeEnum.hlight_texttag:
var user = self.roomHandle.getUser(annotationInfo.objectBase.ownerUserId);
var x = annotationInfo.start.x;
var y = annotationInfo.start.y;
var width = annotationInfo.end.x - annotationInfo.start.x;
var height = annotationInfo.end.y - annotationInfo.start.y;
log.debug("===annotation.drawToBoard(),shapeTypeEnum.hlight_texttag,x:",x+",y:",y+",width:"+width+",height:"+height);
var inputX = Math.round(x * self.roomHandle.boardInputXRatio);
var inputY = Math.round(y * self.roomHandle.boardInputYRatio);
var inputWidth = Math.round(width * self.roomHandle.boardInputXRatio);
var inputHeight = Math.round(height * self.roomHandle.boardInputYRatio);
log.debug("===annotation.drawToBoard(),shapeTypeEnum.hlight_texttag,inputX:",inputX+",inputY:",inputY+",inputWidth:"+inputWidth+",inputHeight:"+inputHeight);
if(!user){
return;
}
if(self.textTagShape){
self.textTagShape.attr({
shape: {
x:inputX,
y:inputY
},
style:{
text: user.name
},
zlevel: self.normalZlevel,
});
}else{
self.textTagShape = new Texttag({
shape:{
x:inputX,
y:inputY,
width:inputWidth,
height:inputHeight
},
style: {
stroke: "red",
fill: "red",
text: user.name,
truncate:{
outerWidth:50
},
lineWidth:lineWidth
},
zlevel: self.normalZlevel,
onmouseover:mouseOverForEraser
})
self.shapeGroup.add(self.textTagShape);
self.textTagShape.id = annotationInfo.objectBase.annotationId;
}
break;
case shapeTypeEnum.polyline:
var points = [];
console.log("===annotation.drawToBoard(),shapeTypeEnum.polyline,points:",points);
for(var k in annotationInfo.points){
var x = annotationInfo.points[k].x;
var y = annotationInfo.points[k].y;
//console.log("===annotation.drawToBoard(),shapeTypeEnum.polyline,x:",x+",y:",y);
var inputX = Math.round(x * self.roomHandle.boardInputXRatio);
var inputY = Math.round(y * self.roomHandle.boardInputYRatio);
//console.log("===annotation.drawToBoard(),shapeTypeEnum.polyline,inputX:",inputX+",inputY:",inputY);
var point = [inputX,inputY]
points.push(point);
}
shape = new zrender.Polyline({
shape:{
points: points,
smooth:0,
},
style: {
stroke: color,
lineWidth:lineWidth
},
zlevel: self.normalZlevel,
onmouseover:mouseOverForEraser
})
break;
case shapeTypeEnum.rect:
var x = annotationInfo.start.x;
var y = annotationInfo.start.y;
var width = annotationInfo.end.x - annotationInfo.start.x;
var height = annotationInfo.end.y - annotationInfo.start.y;
log.debug("===annotation.drawToBoard(),shapeTypeEnum.rect,x:",x+",y:",y+",width:"+width+",height:"+height);
var inputX = Math.round(x * self.roomHandle.boardInputXRatio);
var inputY = Math.round(y * self.roomHandle.boardInputYRatio);
var inputWidth = Math.round(width * self.roomHandle.boardInputXRatio);
var inputHeight = Math.round(height * self.roomHandle.boardInputYRatio);
log.debug("===annotation.drawToBoard(),shapeTypeEnum.rect,inputX:",inputX+",inputY:",inputY+",inputWidth:"+inputWidth+",inputHeight:"+inputHeight);
shape = new zrender.Rect({
shape:{
x:inputX,
y:inputY,
width:inputWidth,
height:inputHeight
},
style: {
stroke: color,
fill: fillColor,
lineWidth:lineWidth
},
zlevel: self.normalZlevel,
onmouseover:mouseOverForEraser
})
break;
case shapeTypeEnum.ellipse:
var startX = annotationInfo.start.x;
var endX = annotationInfo.end.x;
var startY = annotationInfo.start.y;
var endY = annotationInfo.end.y;
log.debug("===annotation.drawToBoard(),shapeTypeEnum.ellipse,startX :",startX+",endX:",endX+",startY:"+startY+",endY:"+endY);
var inputStartX = Math.round(startX * self.roomHandle.boardInputXRatio);
var inputEndX = Math.round(endX * self.roomHandle.boardInputXRatio);
var inputStartY = Math.round(startY * self.roomHandle.boardInputYRatio);
var inputEndY = Math.round(endY * self.roomHandle.boardInputYRatio);
log.debug("===annotation.drawToBoard(),shapeTypeEnum.ellipse,inputStartX :",inputStartX+",inputEndX:",inputEndX+",inputStartY:"+inputStartY+",inputEndY:"+inputEndY);
var rx = (inputEndX - inputStartX)/2;
var ry = (inputEndY - inputStartY)/2;
var cx = inputStartX + rx;
var cy = inputStartY + ry;
shape = new zrender.Ellipse({
shape:{
cx:cx,
cy:cy,
rx:rx,
ry:ry,
},
style: {
stroke: color,
fill: fillColor,
lineWidth:lineWidth
},
zlevel: self.normalZlevel,
onmouseover:mouseOverForEraser
})
break;
case shapeTypeEnum.hlight_point:
var x = annotationInfo.start.x;
var y = annotationInfo.start.y;
var width = self.hlightPointInfo.width;
var height = self.hlightPointInfo.height;
console.log("===annotation.drawToBoard(),shapeTypeEnum.hlight_point,x:",x+",y:",y+",width:"+width+",height:"+height);
var inputX = Math.round(x * self.roomHandle.boardInputXRatio);
var inputY = Math.round(y * self.roomHandle.boardInputYRatio);
var inputWidth = Math.round(width * self.roomHandle.boardInputXRatio);
var inputHeight = Math.round(height * self.roomHandle.boardInputYRatio);
log.debug("===annotation.drawToBoard(),shapeTypeEnum.hlight_point,inputX:",inputX+",inputY:",inputY+",inputWidth:"+inputWidth+",inputHeight:"+inputHeight);
if(!self.hlightPointShape){
self.hlightPointShape = new zrender.Image({
position: [inputX, inputY],
scale: [1, 1],
style: {
image: self.hlightPointInfo.imgUrl,
width: inputWidth,
height:inputHeight
},
draggable: true,
zlevel: self.normalZlevel
})
self.shapeGroup.add(self.hlightPointShape);
self.hlightPointShape.id = annotationInfo.objectBase.annotationId;
}else{
self.hlightPointShape.attr('position',[inputX - inputWidth / 2 ,inputY - inputHeight / 2]);
}
break;
case shapeTypeEnum.img:
console.log("===annotation.drawToBoard(),shapeTypeEnum.img, annotationInfo:",annotationInfo);
var rotate = degree2mathPI(annotationInfo.im.rotate);
var img = null;
var shapeObj = {
id: annotationInfo.im.id,
shape: null,
shapeType: shapeType,
lineWidth: lineWidth,
arrowtype: arrowtype,
color: color,
fillColor: fillColor
}
// 自己的批注图片渲染(在关闭再打开白板时,自己原有图片再次渲染)
if(annotationInfo.objectBase.ownerUserId === self.roomHandle.selfUser.id){
for (var i = 0; i < self.roomHandle.annotation2boardId[annotationInfo.objectBase.objectId].storageArr.length; i++) {
var tempShape = self.roomHandle.annotation2boardId[annotationInfo.objectBase.objectId].storageArr[i];
if (tempShape.annotationType == shapeTypeEnum.img && tempShape.annotationId == annotationInfo.im.id && tempShape.operUserId == self.roomHandle.selfUser.id) {
img = tempShape.imgZrender;
shapeObj.shape = img;
self.shapeArray.push(shapeObj);
break;
}
}
}else{
// 远端用户的图片渲染
img = new zrender.Image({
style: {
image:annotationInfo.im.file_url,
x: annotationInfo.im.x * self.roomHandle.boardInputXRatio,
y: annotationInfo.im.y * self.roomHandle.boardInputYRatio,
width: annotationInfo.im.w * self.roomHandle.boardInputXRatio,
height: annotationInfo.im.h * self.roomHandle.boardInputYRatio
},
zlevel: annotationInfo.im.layer,
id: annotationInfo.im.id,
rotation: rotate,
originX: annotationInfo.im.x * self.roomHandle.boardInputXRatio + annotationInfo.im.w / 2 * self.roomHandle.boardInputXRatio,
originY: annotationInfo.im.y * self.roomHandle.boardInputYRatio + annotationInfo.im.h / 2 * self.roomHandle.boardInputYRatio
});
shapeObj.shape = img
var userKey = 'userId' + annotationInfo.objectBase.ownerUserId;
if(self.otherShapeMap[userKey]){
for(var i = self.otherShapeMap[userKey].length - 1; i >= 0; i--){
// 先删除otherShapeMap里面的已有的图片对象
if(self.otherShapeMap[userKey][i].shape.id === annotationInfo.im.id){
self.otherShapeMap[userKey].splice(i, 1);
}
}
self.otherShapeMap[userKey].push(shapeObj);
}else{
self.otherShapeMap[userKey] = [];
self.otherShapeMap[userKey].push(shapeObj);
}
}
self.shapeGroup.add(img);
self.setAllowEditImg(false);
break;
default:
break;
}
if(shape){
var shapeObj = {
id:annotationInfo.objectBase.annotationId,
shape:shape
}
self.shapeGroup.add(shape);
shape.id = annotationInfo.objectBase.annotationId;
if(annotationInfo.objectBase.ownerUserId == self.roomHandle.selfUser.id){
self.shapeArray.push({
shape:shape,
shapeType:shapeType,
color:color,
lineWidth:lineWidth,
arrowtype:arrowtype,
fillType:fillTypeEnum.none,
});
}else{
var userKey = 'userId' + annotationInfo.objectBase.ownerUserId
if(self.otherShapeMap[userKey]){
self.otherShapeMap[userKey].push(shapeObj);
}else{
self.otherShapeMap[userKey] = [];
self.otherShapeMap[userKey].push(shapeObj);
}
}
}
}
//更新远端获取的注释,更新到画板上 by roymond 2022/8/29
Annotation.prototype.updateDrawToBoard = function(annotationInfo) {
var self = this;
var shapeType = parseInt(annotationInfo.objectBase.type);
switch (shapeType){
case shapeTypeEnum.img:
self.shapeGroup.eachChild(function(child) {
if(child.id === annotationInfo.im.id){
self.shapeGroup.remove(child)
}
})
for(var k in self.shapeArray){
if(self.shapeArray[k].shape.id == annotationInfo.im.id){
self.zr.remove(self.shapeArray[k].shape);
// self.shapeGroup.remove(self.shapeArray[k].shape);
self.shapeArray.splice(k,1);
}
}
var rotate = degree2mathPI(annotationInfo.im.rotate);
var originX = annotationInfo.im.x * self.roomHandle.boardInputXRatio + annotationInfo.im.w * self.roomHandle.boardInputXRatio/2;
var originY = annotationInfo.im.y * self.roomHandle.boardInputYRatio + annotationInfo.im.h * self.roomHandle.boardInputYRatio /2;
var img = new zrender.Image({
style: {
image:annotationInfo.im.file_url,
x: annotationInfo.im.x * self.roomHandle.boardInputXRatio,
y: annotationInfo.im.y * self.roomHandle.boardInputYRatio,
width: annotationInfo.im.w * self.roomHandle.boardInputXRatio,
height:annotationInfo.im.h * self.roomHandle.boardInputYRatio
},
zlevel: annotationInfo.im.layer,
id: annotationInfo.im.id,
rotation: rotate,
origin: [annotationInfo.im.x * self.roomHandle.boardInputXRatio + annotationInfo.im.w * self.roomHandle.boardInputXRatio/2,annotationInfo.im.y * self.roomHandle.boardInputYRatio + annotationInfo.im.h * self.roomHandle.boardInputYRatio /2]
});
if(self.roomHandle.style2annotation[annotationInfo.im.id]){
img.attr('style', JSON.parse(self.roomHandle.style2annotation[annotationInfo.im.id].style));
img.attr('position', JSON.parse(self.roomHandle.style2annotation[annotationInfo.im.id].position));
img.attr('scale', JSON.parse(self.roomHandle.style2annotation[annotationInfo.im.id].scale));
img.attr('rotation', JSON.parse(self.roomHandle.style2annotation[annotationInfo.im.id].rotation));
img.attr('origin', JSON.parse(self.roomHandle.style2annotation[annotationInfo.im.id].origin));
}
self.shapeGroup.add(img);
var shapeObj = {
shape:img,
shapeType:self.shapeType
}
if(annotationInfo.objectBase.ownerUserId === self.roomHandle.selfUser.id){
self.shapeArray.push(shapeObj);
}else{
var userKey = 'userId' + annotationInfo.objectBase.ownerUserId;
if(self.otherShapeMap[userKey]){
for(var i = self.otherShapeMap[userKey].length - 1; i >= 0; i--){
// 先删除otherShapeMap里面的已有的图片对象
if(self.otherShapeMap[userKey][i].shape.id === annotationInfo.im.id){
self.otherShapeMap[userKey].splice(i, 1);
}
}
self.otherShapeMap[userKey].push(shapeObj);
}else{
self.otherShapeMap[userKey] = [];
self.otherShapeMap[userKey].push(shapeObj);
}
}
// 图片属性更新,要把本地缓存的属性也要更新,解决发起人关闭白板后再打开之前的图片位置、缩放、旋转角度丢失问题
if(self.roomHandle.annotation2boardId[annotationInfo.objectBase.objectId]){
for (var i = 0; i < self.roomHandle.annotation2boardId[annotationInfo.objectBase.objectId].storageArr.length; i++) {
var tempShape = self.roomHandle.annotation2boardId[annotationInfo.objectBase.objectId].storageArr[i];
if (tempShape.Img && tempShape.annotationType == shapeTypeEnum.img && (tempShape.Img.im.id == annotationInfo.im.id || tempShape.annotationId == annotationInfo.im.id) && tempShape.operUserId == annotationInfo.objectBase.ownerUserId) {
tempShape.Img.im.x = annotationInfo.im.x;
tempShape.Img.im.y= annotationInfo.im.y;
tempShape.Img.im.w = annotationInfo.im.w;
tempShape.Img.im.h = annotationInfo.im.h;
tempShape.Img.im.rotate = annotationInfo.im.rotate;
break;
}
}
}
break;
default:
break;
}
}
/**
* @desc 注释设置几何形状,如矩形,随机线等 注释类型,如鼠标、注释、橡皮擦
* @param {canvasTypeEnum} type - 几何形 和 注释状态 枚举型
*
* @example
* annotation.setShapeType(shapeTypeEnum.polyline);
*/
Annotation.prototype.setShapeType = function(shapeType,mouserUrl) {
var currentOs = avdEngineHandle.getBrowserDetect().osName;
if(this.shapeType == shapeTypeEnum.hlight_point && this.hlightPointShape){
this.clearCurrHlightPoint();
}
if(this.eraserShape){
this.clearCurrEraser()
}
// 判断是否是移动端访问,移动端没有鼠标,所以创建一个鼠标shape当成鼠标
if(shapeType == shapeTypeEnum.eraser && mouserUrl && currentOs == 'Android' || currentOs == 'iOS'){
this.initEraserShape(mouserUrl)
}
if(this.shapeType == shapeTypeEnum.hlight_texttag && this.textTagShape){
this.clearCurrHlightPoint();
}
var imgUrl = ""
if(mouserUrl){
imgUrl = "url("+mouserUrl+"),auto"
}
if(this.textInfo != null){
if(shapeType == shapeTypeEnum.txt){
this.textInfo.setTextEditEnable(true);
this.zr.handler.proxy.cursor = 'text';
}else{
this.textInfo.setTextEditEnable(false);
}
}else{
avdEngineHandle.eraserCustomIconPath = imgUrl;
}
this.shapeType = parseInt(shapeType);
}
/**
* @desc 清除橡皮擦
*/
Annotation.prototype.clearCurrEraser = function(){
var self = this;
if(self.eraserShape){
self.zr.remove(self.eraserShape);
self.shapeGroup.remove(self.eraserShape);
self.eraserShape = null;
}
}
/**
* @desc 注释设置颜色
* @param {String} value - 颜色,采用rgb和rgba格式
*
* @example
* annotation.setColor('rgba(255,0,0,1');
*/
Annotation.prototype.setColor = function(color) {
this.color = color;
if(this.fillColor != 'none'){
this.fillColor = color;
}
}
/**
* @desc 注释设置颜色透明度
* @param {String} value - 颜色,采用rgb和rgba格式
*
* @example
* annotation.setColor('rgba(255,0,0,1');
*/
Annotation.prototype.setColorOpacity = function(opacity) {
var arr = this.color.split(',');
arr[arr.length - 1] = opacity + ')';
var color = arr.join(',');
console.log(color);
this.color = color;
if(this.fillColor != 'none'){
this.fillColor = color;
}
}
/**
* @desc 注释设置线条宽度
* @param {int} value - 线条宽度
*
* @example
* annotation.setLineWidth(1);
*/
Annotation.prototype.setLineWidth = function(lineWidth) {
this.lineWidth = parseInt(lineWidth);
}
/**
* @desc 注释设置箭头宽度
* @param {int} value - 箭头宽度
*
* @example
* annotation.setArrowLength(10);
*/
Annotation.prototype.setArrowLength = function(value) {
this.arrowLength = parseInt(value);
}
/**
* @desc 注释设置箭头类别
* @param {arrowTypeEnum} value - 箭头类别,枚举型
*
* @example
* annotation.setArrowType(arrowTypeEnum.double);
*/
Annotation.prototype.setArrowType = function(value) {
this.arrowtype = parseInt(value);
}
/**
* @desc 下载白板,带批注和背景
* @example
* annotation.download();
*/
Annotation.prototype.download = function() {
if(this.renderBackground == null && this.annoDiv == null){
return;
}
var backgroundCanvas = document.createElement('canvas');
backgroundCanvas.width = this.renderDiv.width;
backgroundCanvas.height = this.renderDiv.height;
var backgroundCtx = backgroundCanvas.getContext("2d");
if(this.renderBackground){
backgroundCtx.drawImage(this.renderBackground, 0, 0);
}
backgroundCtx.drawImage(this.renderDiv, 0, 0);
downloadimage(backgroundCanvas);
function downloadimage(canvas){
// 图片导出为 png 格式
var type = 'png';
// 返回一个包含JPG图片的<img>元素
var img_png_src = canvas.toDataURL("image/png"); //将画板保存为图片格式的函数
// 加工image data,替换mime type
imgData = img_png_src.replace(_fixType(type),'image/octet-stream');
// 下载后的问题名
var filename = '个人画板_' + (new Date()).getTime() + '.' + type;
// download
saveFile(imgData,filename);
}
/**
* 在本地进行文件保存
* @param {String} data 要保存到本地的图片数据
* @param {String} filename 文件名
*/
function saveFile(data, filename){
var save_link = document.createElementNS('http://www.w3.org/1999/xhtml', 'a');
save_link.href = data;
save_link.download = filename;
var event = document.createEvent('MouseEvents');
event.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
save_link.dispatchEvent(event);
};
/**
* 获取mimeType
* @param {String} type the old mime-type
* @return the new mime-type
*/
function _fixType(type) {
type = type.toLowerCase().replace(/jpg/i, 'jpeg');
var r = type.match(/png|jpeg|bmp|gif/)[0];
return 'image/' + r;
};
}
/**
* @desc 注释设置颜色填充类别
* @param {fillTypeEnum} value - 颜色填充类别,枚举型
*
* @example
* annotation.setFillColor(fillTypeEnum.full);
*/
Annotation.prototype.setFillColor = function(value) {
this.fillType = value;
if(value == fillTypeEnum.none){
this.fillColor = 'none';
} else{
this.fillColor = this.color;
}
}
/**
* @desc 注释清除
*/
Annotation.prototype.clear = function() {
var self = this;
var shapeArray = self.shapeArray;
var displayList = self.zr.storage.getDisplayList();
var groupChildren = self.shapeGroup.children();
for(var i = shapeArray.length - 1; i >= 0; i--){
self.zr.remove(shapeArray[i].shape);
for(var j = displayList.length - 1; j >= 0; j--){
if(displayList[j].id == shapeArray[i].shape.id){
self.zr.remove(displayList[j])
}
}
for(var k = groupChildren.length - 1; k >= 0; k--){
if(groupChildren[k].id == shapeArray[i].shape.id){
self.shapeGroup.remove(groupChildren[k])
}
}
}
self.shapeArray = [];
// self.currentIndex = -1;
self.undoArray = [];
self.redoArray = [];
self.roomHandle.sendRemoveAnnotation(self.boardId,shapeTypeEnum.clear,"")
}
/**
* @desc 注释撤销上一步
*/
Annotation.prototype.undo = function() {
var self = this;
if(self.undoArray.length < 1){
return;
}
var undoObj = self.undoArray.pop();
self.undoShape(undoObj);
}
/**
* @desc 执行撤销批注对象
*/
Annotation.prototype.undoShape = function(undoObj) {
var self = this;
switch (undoObj.type) {
case 'delete':
self.shapeGroup.add(undoObj.shapeObj.shape);
// 添加到shapeArray中
self.shapeArray.push(undoObj.shapeObj);
self.roomHandle.sendAddAnnotation(self.boardId, undoObj.shapeObj.shape, undoObj.shapeObj.shapeType, undoObj.shapeObj.color, undoObj.shapeObj.lineWidth, undoObj.shapeObj.arrowtype, undoObj.shapeObj.fillType);
self.redoArray.push(undoObj);
break;
case 'add':
self.zr.remove(undoObj.shapeObj.shape);
self.shapeGroup.remove(undoObj.shapeObj.shape);
// 从shapeArrry中查找并删除
deleteFromShapeArray(undoObj.shapeObj.shape.id);
self.roomHandle.sendRemoveAnnotation(self.boardId,shapeTypeEnum.eraser,undoObj.shapeObj.shape.id);
self.redoArray.push(undoObj);
break;
default:
break;
}
/**
* @desc 从批注数组中删除指定的批注
* @param {String} shapeId 批注的id
*/
function deleteFromShapeArray(shapeId) {
if(self.shapeArray.length < 1){
return;
}
for(var i = 0; i < self.shapeArray.length; i++){
if(self.shapeArray[i].shape.id === shapeId){
self.shapeArray.splice(i, 1);
}
}
}
}
/**
* @desc 注释重做下一步
*/
Annotation.prototype.redo = function() {
var self = this;
// self.shapeGroup.add(obj.shapeObj.shape);
// self.shapeArray.push(obj.shapeObj);
// self.roomHandle.sendAddAnnotation(self.boardId, obj.shapeObj.shape, obj.shapeObj.shapeType, obj.shapeObj.color, obj.shapeObj.lineWidth, obj.shapeObj.arrowtype, obj.shapeObj.fillType);
if(self.redoArray.length < 1){
return;
}
var redoObj = self.redoArray.pop();
self.redoShape(redoObj);
}
/**
* @desc 执行撤销批注对象
*/
Annotation.prototype.redoShape = function(redoObj) {
var self = this;
switch (redoObj.type) {
case 'delete':
self.zr.remove(redoObj.shapeObj.shape);
self.shapeGroup.remove(redoObj.shapeObj.shape);
// 从shapeArrry中查找并删除
deleteFromShapeArray(redoObj.shapeObj.shape.id);
self.roomHandle.sendRemoveAnnotation(self.boardId,shapeTypeEnum.eraser,redoObj.shapeObj.shape.id);
self.undoArray.push(redoObj);
break;
case 'add':
self.shapeGroup.add(redoObj.shapeObj.shape);
// 添加到shapeArray中
self.shapeArray.push(redoObj.shapeObj);
self.roomHandle.sendAddAnnotation(self.boardId, redoObj.shapeObj.shape, redoObj.shapeObj.shapeType, redoObj.shapeObj.color, redoObj.shapeObj.lineWidth, redoObj.shapeObj.arrowtype, redoObj.shapeObj.fillType);
self.undoArray.push(redoObj);
break;
default:
break;
}
/**
* @desc 从批注数组中删除指定的批注
* @param {String} shapeId 批注的id
*/
function deleteFromShapeArray(shapeId) {
if(self.shapeArray.length < 1){
return;
}
for(var i = 0; i < self.shapeArray.length; i++){
if(self.shapeArray[i].shape.id === shapeId){
self.shapeArray.splice(i, 1);
}
}
}
}
/**
* @desc 设置激光笔
*/
Annotation.prototype.hlightPointInit = function(mouserUrl,width,height,intervalTime) {
var self = this;
self.hlightPointInfo.imgUrl = mouserUrl;
self.hlightPointInfo.width = parseInt(width)?parseInt(width):self.hlightPointInfo.width;
self.hlightPointInfo.height = parseInt(height)?parseInt(height):self.hlightPointInfo.height;
self.hlightPointInfo.intervalTime = parseInt(intervalTime)?parseInt(intervalTime):self.hlightPointInfo.intervalTime;
}
/**
* @desc 清除激光笔
*/
Annotation.prototype.clearCurrHlightPoint = function() {
var self = this;
if(self.hlightPointShape){
self.roomHandle.sendRemoveAnnotation(self.boardId,shapeTypeEnum.eraser,self.hlightPointShape.id)
self.zr.remove(self.hlightPointShape);
self.shapeGroup.remove(self.hlightPointShape);
self.hlightPointShape = null;
}
if(self.textTagShape){
self.roomHandle.sendRemoveAnnotation(self.boardId,shapeTypeEnum.eraser,self.textTagShape.id)
self.zr.remove(self.textTagShape);
self.shapeGroup.remove(self.textTagShape);
self.textTagShape = null;
}
}
/**
* @desc 设置激光笔
*/
Annotation.prototype.startHlightPoint = function(){
var self = this;
self.setShapeType(shapeTypeEnum.hlight_point)
var width = self.hlightPointInfo.width;
var height = self.hlightPointInfo.height;
self.hlightPointShape = new zrender.Image({
position: [-100, -100],
scale: [1, 1],
style: {
image: self.hlightPointInfo.imgUrl,
width: self.hlightPointInfo.width,
height: self.hlightPointInfo.height
},
draggable: true
})
self.shapeGroup.add(self.hlightPointShape);
self.hlightPointShape.id = Math.uuid();
self.renderDiv.onmousemove = function(e){
if(self.isAllowEditImg){
return;
}
if(self.shapeType != shapeTypeEnum.hlight_point){
return;
}
var tempPos = self.handleScaledXY(e.clientX - this.getBoundingClientRect().left, e.clientY - this.getBoundingClientRect().top);
x = tempPos.x;
y = tempPos.y;
var realX = x - width / 2;
var realY = y - height / 2;
self.hlightPointShape.attr('position',[realX ,realY]);
if(self.hlightPointInfo.isSend){
self.hlightPointInfo.isSend = false;
self.roomHandle.sendAddAnnotation(self.boardId, self.hlightPointShape, shapeTypeEnum.hlight_point, self.color, self.lineWidth, self.arrowtype, self.fillType);
setTimeout(function(){
self.hlightPointInfo.isSend = true;
}, self.hlightPointInfo.intervalTime)
}
}
}
Annotation.prototype.changeScreen = function(newWidth,newHeight){
var self = this;
if(self.zr && self.shapeArray.length > 0){
// self.zr.resize();
self.boardReRenderWH(newWidth, newHeight);
for(var k in self.shapeArray){
var x = newWidth/self.screenSize.width;
var y = newHeight/self.screenSize.height;
console.log("===Annotation.changeScreen(),x:"+x+",y:"+y);
self.shapeArray[k].shape.animateTo({
scale: [x, y]
},function(){
console.log('changeScreen');
})
}
}
self.screenSize.width = newWidth;
self.screenSize.width = newHeight;
}
/**
* @desc 上传图片
* @param {String} accessToken 认证串
* @param {object} fileTarget input:file控件选择的图片文件对象
* @returns {object} Promise
*/
Annotation.prototype.uploadImg = function(accessToken, fileTarget){
var deferred = when.defer();
var self = this;
var file = fileTarget.files[0];
if (!file){
var error = new Error(ErrorConstant.upload_filer_required);
deferred.reject(error);
}
// 最大上传文件大小
var MAX_SIZE = 15 * 1024 * 1024;
// 上传文件类型
var FILE_TYPES = ['image/jpeg', 'image/png'];
var fileSize = file.size,
fileType = file.type;
//console.log("=====================file:",file);
log.info('===annotation.uploadImg(),fileSize:'+ fileSize+", fileType"+ fileType);
if (!FILE_TYPES.includes(fileType)) {
fileTarget.value = '';
var error = new Error(ErrorConstant.upload_filer_fileType);
error.message = error.message+",Support jpeg/jpg/png only ";
deferred.reject(error);
}else if(fileSize > MAX_SIZE) {
fileTarget.value = '';
var error = new Error(ErrorConstant.upload_filer_fileSize);
error.message = error.message+",Within 15M only";
deferred.reject(error);
}else {
var restServer = new RestServer();
restServer.uploadFile(accessToken, file).then(function(fileUrl){
fileTarget.value = '';
log.info("===annotation.uploadImg(),fileUrl:" + fileUrl);
var img = new Image();
img.src = fileUrl;
img.onload = function(){
var imgWidth = img.width;
var imgHeight = img.height;
log.info("===annotation.uploadImg(),img width:" + imgWidth+", height:"+ imgHeight);
self.drawImg(fileUrl,imgWidth, imgHeight);
img = null;
deferred.resolve();
}
}).otherwise(function(error){
console.info("===annotation.uploadImg(),error:",error);
deferred.reject(error);
});
}
return deferred.promise;
}
// 本端绘制图片(不包括本端关闭白板后再重新打开白板后,重新渲染自己的图片不会走这里)
Annotation.prototype.drawImg = function(imgUrl,imgWidth, imgHeight){
log.info("===annotation.drawImg(),imgUrl:"+imgUrl+", imgWidth:" + imgWidth+", imgHeight:"+ imgHeight);
var MAX_WIDTH = 150;
var MAX_HEIGHT = 150;
var MAX_WH_RATIO = MAX_WIDTH / MAX_HEIGHT;
var originWHRatio = imgWidth / imgHeight;
var targetWidth = imgWidth;
var targetHeight = imgHeight;
if (imgWidth > MAX_WIDTH || imgHeight > MAX_HEIGHT) {
if (originWHRatio > MAX_WH_RATIO) {
targetWidth = MAX_WIDTH;
targetHeight = Math.round(targetWidth / originWHRatio);
} else {
targetHeight = MAX_HEIGHT;
targetWidth = Math.round(targetHeight * originWHRatio);
}
}
log.info("===annotation.drawImg(),targetWidth:"+targetWidth+", targetHeight:" + targetHeight);
var self = this;
self.shapeType = shapeTypeEnum.img;
var img = new zrender.Image({
style: {
image:imgUrl,
x: 0,
y: 0,
width: targetWidth,
height: targetHeight,
shadowColor: 'red',
shadowBlur: 5
},
zlevel: self.imgZlevel, //zlevel 大的 Canvas 会放在 zlevel 小的 Canvas 的上面。
id: Math.uuid(),
rotation: 0,
originX: 0,
originY: 0
});
var shapeObj = {
shape:img,
shapeType:self.shapeType,
color:self.color,
lineWidth:self.lineWidth,
arrowtype:self.arrowtype,
fillType:self.fillType,
}
self.shapeArray.push(shapeObj);
self.shapeGroup.add(img);
self.undoArray.push({
type: 'add',
shapeObj: shapeObj
})
self.setAllowEditImg(true);
img.attr('zlevel',++self.imgZlevel);
self.currActiveImg = img;
self.shapeGroup.eachChild(function(item){
if(item.type === 'image'){
if(item.id == self.currActiveImg.id){
item.attr('style',{shadowColor:'red',shadowBlur:5});
}else{
item.attr('style',{shadowColor:undefined,shadowBlur:undefined});
}
}
});
self.roomHandle.sendAddAnnotation(self.boardId, img, shapeTypeEnum.img, self.color, self.lineWidth, self.arrowtype, self.fillType);
}
/**
* @desc 设置图片的编辑状态
* @param {Boolean} isAllow 白板是否设置为图片模式,在此模式下画笔不生效,设置画笔时请关闭图片模式
*/
Annotation.prototype.setAllowEditImg = function(isAllow){
var self = this;
if(isAllow == undefined){
this.isAllowEditImg = !this.isAllowEditImg;
}else{
this.isAllowEditImg = isAllow;
}
this.shapeGroup.eachChild(function(child){
if(child.type && child.type !== 'image'){
child.attr('silent', self.isAllowEditImg)
}
})
if(!this.isAllowEditImg){
this.currActiveImg = null;
}else{
this.setShapeType(shapeTypeEnum.img)
}
this.shapeGroup.eachChild(function(item){
if(item.type === 'image'){
if(!self.isAllowEditImg){
item.attr('style',{shadowColor:undefined,shadowBlur:undefined});
}
}
})
if(this.textInfo && this.shapeType === shapeTypeEnum.txt){
this.textInfo.setTextEditEnable(!this.isAllowEditImg)
}
}
Annotation.prototype.getAllowEditImg = function(){
return this.isAllowEditImg;
}
/**
* @desc 缩放当前高亮的图片
* @param {boolean} isEnlarge 是否放大,true为放大,false为缩小
* @param {number} percentage 缩放比例,小数,例如0.1
*/
Annotation.prototype.scaleImg = function(isEnlarge, percentage){
var self = this;
if(!this.isAllowEditImg){
return;
}
if(!this.currActiveImg){
return;
}
var x = this.currActiveImg.scale[0];
var y = this.currActiveImg.scale[1];
if(isEnlarge){
x = x + percentage;
y = y + percentage;
}else{
// 防止x或者y为0后,继续缩小变为负数,导致放大和缩小效果相反了
if(x - percentage <= 0.1 || y - percentage <= 0.1){
return;
}
x = x - percentage;
y = y - percentage;
}
//设置缩放大小
this.currActiveImg.attr('scale',[x,y]);
//设置缩放中心
this.currActiveImg.attr('origin',[this.currActiveImg.style.width/2, this.currActiveImg.style.height/2]);
if(isEnlarge){
this.currActiveImg.customPositionX = this.currActiveImg.customPositionX - this.currActiveImg.style.width/2 * percentage;
this.currActiveImg.customPositionY = this.currActiveImg.customPositionY - this.currActiveImg.style.height/2 * percentage;
}else {
this.currActiveImg.customPositionX = this.currActiveImg.customPositionX + this.currActiveImg.style.width/2 * percentage;
this.currActiveImg.customPositionY = this.currActiveImg.customPositionY + this.currActiveImg.style.height/2 * percentage;
}
self.roomHandle.sendUpdateAnnotation(this.boardId, this.currActiveImg, shapeTypeEnum.img);
}
/**
* @desc 顺时针旋转当前高亮的图片
*/
Annotation.prototype.rotateImg = function(){
var self = this;
if(!this.isAllowEditImg){
return;
}
if(!this.currActiveImg){
return;
}
//设置旋转角度
var rotation = this.currActiveImg.rotation - Math.PI/2;
this.currActiveImg.attr('rotation',[rotation]);
//设置旋转中心
this.currActiveImg.attr('origin',[this.currActiveImg.style.width/2, this.currActiveImg.style.height/2]);
self.roomHandle.sendUpdateAnnotation(this.boardId, this.currActiveImg, shapeTypeEnum.img);
}
/**
* @desc 删除当前高亮的图片
*/
Annotation.prototype.delImg = function(){
if(!this.isAllowEditImg){
return;
}
if(!this.currActiveImg){
return;
}
this.roomHandle.sendRemoveAnnotation(this.boardId, shapeTypeEnum.img, this.currActiveImg.id);
this.shapeGroup.remove(this.currActiveImg);
for(var i = 0; i < this.shapeArray.length; i++){
var tempShapeObj = this.shapeArray[i];
this.undoArray.push({
type: 'delete',
shapeObj: tempShapeObj
})
if(tempShapeObj.shape && (tempShapeObj.shape.id == this.currActiveImg.id)){
this.shapeArray.splice(i, 1);
}
}
this.currActiveImg = null;
}
Annotation.prototype.handleScaledXY = function(x, y) {
var pos = {
x: x,
y: y
}
if(this.positionInfo.scaleRatioX == 1 && this.positionInfo.scaleRatioX == 1){
return pos
}
if(this.positionInfo.scaleRatioX > 1){
pos.x /= this.positionInfo.scaleRatioX
}else if(this.positionInfo.scaleRatioX < 1){
pos.x *= this.positionInfo.scaleRatioXR
}
if(this.positionInfo.scaleRatioY > 1){
pos.y /= this.positionInfo.scaleRatioY
}else if(this.positionInfo.scaleRatioY < 1){
pos.y *= this.positionInfo.scaleRatioYR
}
return pos
}
/**
* @description 根据宽高重新渲染画布及画布内的所有批注
* @param {int} width 宽
* @param {int} height 高
*/
Annotation.prototype.boardReRenderWH = function (width, height) {
/**
* 在执行缩放时,每次都还原到初始大小再进行缩放,每次都在最开始的宽高进行缩放
* 防止:先放大再缩小后点击位置偏移
*/
if(width !== this.positionInfo.originalWidth || height !== this.positionInfo.originalHeight){
console.log('===scale on based position before scale')
this.boardReRenderWH(this.positionInfo.originalWidth, this.positionInfo.originalHeight)
}
var currWidth = this.zr.getWidth();
var currHeight = this.zr.getHeight();
log.debug('===boardReRenderWH, width: '+ width + 'height: ' + height + ' currWidth: ' + currWidth + ' currHeight: ' + currHeight)
var tempInfo = {
scaleWidth: width,
scaleHeight: height,
zrWidth: currWidth,
zrHeight: currHeight,
scaleRatioX: width / currWidth,
scaleRatioY: height / currHeight,
scaleRatioXR: currWidth / width,
scaleRatioYR: currHeight / height,
}
if(width === this.positionInfo.originalWidth && height === this.positionInfo.originalHeight){
tempInfo.scaleRatioXR = 1;
tempInfo.scaleRatioYR = 1;
}
Object.assign(this.positionInfo, tempInfo)
if(this.positionInfo.scaleRatioX == 1 && this.positionInfo.scaleRatioY==1){
return;
}
// 以当前shapeGroup的缩放为基础更新缩放
this.positionInfo.scaleRatioX *= this.shapeGroup.scaleX;
this.positionInfo.scaleRatioY *= this.shapeGroup.scaleY;
this.zr.resize({
width: width,
height: height
});
this.zr.dom.style.width = width +'px';
this.zr.dom.style.height = height +'px';
if(this.renderBackground){
this.renderBackground.width = width;
this.renderBackground.height = height;
this.renderBackground.style.width = width +'px';
this.renderBackground.style.height = height +'px';
if(this.board.backgroundColor){
this.updateBackgroundColor(this.board.backgroundColor);
}
if(this.board.backgroundImage){
this.updateBackgroundImage(this.board.backgroundImage);
}
}
this.shapeGroup.attr({
scaleX: this.positionInfo.scaleRatioX,
scaleY: this.positionInfo.scaleRatioY,
originX: 0,
originY: 0
})
log.debug('===Annotation boardReRenderWH positionInfo: ', this.positionInfo);
}
/**
* @description 开始输入文字
* @param {object} themeConfig 主题样式,用于自定义文字输入框确认和取消按钮,例如:{confirm: {color: '#000000', text: '确定'}, cancel: {color: '#001100', text: '取消'}}
*/
Annotation.prototype.startTextInput = function(themeConfig) {
var self = this;
self.setShapeType(shapeTypeEnum.txt)
if(this.isAllowEditImg){
// 当前为图片编辑模式或者已经初始化过textInfo了,就跳过
return
}
if(!this.isAllowEditImg && this.textInfo != null && this.textInfo.currTextElParentNode != null){
this.textInfo.setTextEditEnable(true);
return;
}
this.textInfo = new TextInfo(themeConfig, this);
this.setShapeType(shapeTypeEnum.txt);
// 判断父元素是否是canvas,如果是canvas则将工具条添加到canvas的兄弟节点
this.textInfo.setParentElement(this.annoDiv);
this.textInfo.setCanvasParentElement(this.annoDiv.tagName === 'CANVAS' ? this.annoDiv.parentElement : this.annoDiv);
this.textInfo.initToolBar();
this.textInfo.setColorChoosePanelDisplay(false);
this.textInfo.setTextEditEnable(true);
this.textInfo.setZrender(self.zr);
this.textInfo.textEventEmitter.on('confirm', function(textInfo){
renderByZrender(textInfo)
})
log.debug('===Annotation.startTextInput success');
function renderByZrender(textInfo) {
var newPos = self.handleScaledXY(textInfo.position[0], textInfo.position[1]);
var textShape = new zrender.Text({
style: {
text: textInfo.content,
fontSize: textInfo.fontSize,
fontStyle: textInfo.fontStyle,
fontWeight: textInfo.fontWeight,
fill: textInfo.fontColor || '#000000' // 添加默认颜色
},
zlevel: self.normalZlevel,
position: [newPos.x, newPos.y],
origin: [newPos.x, newPos.y - 50],
onmouseover: mouseOverForEraser
})
textShape.id = Math.uuid();
self.shapeGroup.add(textShape);
var shapeObj = {
shape:textShape,
shapeType:self.shapeType,
color:self.color,
lineWidth:self.lineWidth,
arrowtype:self.arrowtype,
fillType:self.fillType,
}
self.shapeArray.push(shapeObj);
self.roomHandle.sendAddAnnotation(self.boardId, textShape, shapeTypeEnum.txt, self.color, self.lineWidth, self.arrowtype, self.fillType);
}
function mouseOverForEraser(params) {
if(self.shapeType == shapeTypeEnum.eraser && self.isEraser){
for(var k in self.shapeArray){
if(self.shapeArray[k].shape.id == params.target.parent.id){
self.zr.remove(params.target.parent)
self.shapeGroup.remove(params.target.parent)
self.roomHandle.sendRemoveAnnotation(self.boardId,self.shapeType,self.shapeArray[k].shape.id)
self.undoArray.push({
type: 'delete',
shapeObj: self.shapeArray[k]
})
self.shapeArray.splice(k,1);
}
}
}
}
}
return Annotation;
});