test-whiteboard
Version:
https://gitlab.gridsum.com/gov_law_tech/FrontEnd/whiteboard
335 lines (265 loc) • 9.52 kB
JavaScript
import Mixin from './mixin';
import EventEmitter from './eventEmitter';
import math from 'mathjs';
import Stroke from './stroke';
import WhiteboardLine from './whiteboardLine';
import {canvasTransform} from 'canvas-transform';
class LineDataStore {
constructor() {
this.data = [];
this.maxId = 1;
}
addData(line) {
this.data.push(line);
this.maxId++;
}
getNextId() {
return this.maxId;
}
deleteData(groupId) {
this.data = this.data.filter(function (item) {
return item.groupId != groupId;
});
}
getMaxGroupId() {
if (this.data.length == 0) {
return 0;
}
else {
return this.data[this.data.length - 1].groupId;
}
}
}
export default class LineDrawer extends Mixin(EventEmitter) {
constructor(element, mode, transform) {
super();
this.hasInit = false;
this.canDraw = false;
this.groupIndex = 0;
this.currentGroup = null;
this.root = element;
this.mode = mode;
this.canvas = element;
this.context = element.getContext('2d');
// var grd = this.context.createLinearGradient(0, 0, 175, 50);
// grd.addColorStop(0, "#FF0000");
// grd.addColorStop(1, "#00FF00");
// this.context.fillStyle = grd;
// this.context.fillRect(0, 0, 175, 50);
console.log('line constructor --')
// 创建 临时画布
var cacheCanvas = document.createElement('canvas');
var cacheContext = cacheCanvas.getContext('2d');
cacheCanvas.width = this.canvas.width;
cacheCanvas.height = this.canvas.height;
this.cacheCanvas = cacheCanvas;
this.cacheContext = cacheContext;
this.eventDic = [
'action_deleteLine',
'action_drawLine',
'notify_drawLine',
'notify_deleteLine'
];
this.currentLineData = null;
this.dataStore = new LineDataStore();
this.on('action_deleteLine', this.delete.bind(this));
this.on('action_drawLine', this.draw.bind(this));
this.canvasTransform = transform;
this.canvasTransform.drawCanvas(element);
}
init() {
console.log('line init')
let me = this;
me.hasInit = true
var context = this.context;
var canvas = this.canvas;
var bound = canvas.getBoundingClientRect();
var offsetLeft = bound.left;
var offsetTop = bound.top;
if (me.mode == 'view') {
return;
}
var root = this.root;
root.onmousedown = function (event) {
if (!me.canDraw) {
return;
}
if (event.button == 0) {
//左键按下
offsetLeft = bound.left;
offsetTop = bound.top;
console.log('line ', offsetLeft, offsetTop)
var groupIndex = me.dataStore.getMaxGroupId();
me.groupIndex = groupIndex + 1;
var start = {
x: event.clientX - offsetLeft,
y: event.clientY - offsetTop
};
//使用矩阵 自动计算新的坐标
var reverseMatrix = me.calReverseMatrix()
var newCoord = me.matrixMultiCoor(reverseMatrix, [start.x, start.y])
start.x = newCoord[0];
start.y = newCoord[1];
console.log(start.x, start.y)
console.log('draw start ', JSON.stringify(start))
var stroke = new Stroke();
me.currentLineData = new WhiteboardLine(me.groupIndex, stroke, -1, start);
me.canDraw = true;
console.log('line mousedown ')
}
}
root.onmousemove = function (event) {
if (!me.canDraw) {
return;
}
if (!me.currentLineData) {
return;
}
var currentData = me.currentLineData;
var position = {
x: event.clientX,
y: event.clientY
};
if (position.x != currentData.start.x || position.y != currentData.start.y) {
var stroke = new Stroke();
var id = me.dataStore.getNextId();
var start = {
x: currentData.start.x,
y: currentData.start.y
};
var end = {
x: position.x - offsetLeft,
y: position.y - offsetTop
};
//使用矩阵 自动计算新的坐标
var reverseMatrix = me.calReverseMatrix()
var newCoord = me.matrixMultiCoor(reverseMatrix, [end.x, end.y])
end.x = newCoord[0];
end.y = newCoord[1];
var lineData = new WhiteboardLine(
me.groupIndex,
stroke,
id,
start,
end
);
me.dataStore.addData(lineData);
me.canvasTransform.lineStore = me.dataStore
me.emit('notify_drawLine', lineData);
me.draw(lineData);
me.currentLineData = {
groupId: lineData.groupId,
id: lineData.id,
start: {
x: lineData.end.x,
y: lineData.end.y
},
end: {
x: -1,
y: -1
}
};
// me.emit('notify_drawLine',me.currentLineData);
}
}
root.onmouseup = function (event) {
if (event.button == 0) {
//左键弹起
// me.canDraw = false;
context.closePath();
me.currentLineData = null;
// me.canvasTransform.drawCanvas(canvas); // canvas宽高会改变
//.store();
}
}
}
draw(data) {
//绘制前先保存
var start = data.start;
var end = data.end;
this.context.beginPath();
this.context.moveTo(start.x, start.y);
this.context.lineTo(end.x, end.y);
this.context.stroke();
}
// 重新画线
reDrawLine() {
var me = this
this.canvas.setAttribute('width',this.canvas.width)
this.context.setTransform.apply(this.context,this.canvasTransform.matrix)
me.dataStore.data.forEach(function (item) {
me.draw(item);
})
}
// 删除最近一次画线
delete() {
var groupId = this.groupIndex;
var group = document.getElementById('draw_group_' + groupId);
if(group){
group.remove();
}
if (groupId) {
this.dataStore.deleteData(groupId);
this.canvasTransform.lines = this.dataStore
this.groupIndex = this.dataStore.getMaxGroupId();
this.currentGroup = null;
this.emit('notify_deleteLine', groupId);
this.reDrawLine()
}
}
// 计算逆矩阵
calReverseMatrix(){
var me = this
var matrix = me.canvasTransform.matrix
var oriMat = math.matrix([
[1, 0, 0],
[0, 1, 0],
[0, 0, 1]
])
var curMat = math.matrix([
[matrix[0], matrix[2], matrix[4]],
[matrix[1], matrix[3], matrix[5]],
[0, 0, 1]
])
var revMat = math.divide(oriMat, curMat)
var revMatData = revMat._data
// if(Math.abs(degR) == 90 || Math.abs(degR) == 270)
if (revMatData[0][2] == 0) {
if (matrix[4] != 0) {
revMatData[0][2] = revMatData[1][2] / matrix[4] * matrix[5] * -1
}
else {
revMatData[0][2] = 0
}
}
var reverseMatrix = [revMatData[0][0], revMatData[1][0], revMatData[0][1], revMatData[1][1], revMatData[0][2], revMatData[1][2]]
return reverseMatrix
}
// 计算逆矩阵的坐标
matrixMultiCoor(matrix1, coord) {
var x = 0, y = 0
x = matrix1[0] * coord[0] + matrix1[2] * coord[1] + matrix1[4] * 1
y = matrix1[1] * coord[0] + matrix1[3] * coord[1] + matrix1[5] * 1
return [x, y]
}
active(active) {
if (!this.hasInit && active) {
this.init();
}
if (!active) {
this.canDraw = false;
this.root.style.zIndex = '101';
this.root.style.cursor = 'move';
this.canvasTransform.canMove = true
}
else {
this.root.style.zIndex = '99';
this.root.style.cursor = 'crosshair';
}
if (this.hasInit && active) {
this.canDraw = true;
console.log('line active draw line')
this.canvasTransform.canMove = false
}
}
}