<template>
	<div class="maintenancePlanAdd">
		<div class="panel-body">
			<div class="demo">
				<div class="draw-btn-group">
					<div :class="{active:drawType==''}" :title="vm.$t('utils.choose')" @click="drawTypeChange('')">
						<i class="iconfont icon-move1"></i>
					</div>
					<div :class="{active:drawType=='pen'}" :title="vm.$t('utils.draw')" @click="drawTypeChange('pen')">
						<i class="iconfont icon-brush"></i>
					</div>
					<div :class="{active:drawType=='arrow'}" :title="vm.$t('utils.arrow')" @click="drawTypeChange('arrow')">
						<i class="iconfont icon-arrow-mark"></i>
					</div>
					<div :class="{active:drawType=='text'}" :title="vm.$t('utils.text')" @click="drawTypeChange('text')">
						<i class="iconfont icon-text"></i>
					</div>
					<div :class="{active:drawType=='ellipse'}" :title="vm.$t('utils.circle')" @click="drawTypeChange('ellipse')">
						<i class="iconfont icon-oval"></i>
					</div>
					<div :class="{active:drawType=='rectangle'}" :title="vm.$t('utils.rect')" @click="drawTypeChange('rectangle')">
						<i class="iconfont icon-rect"></i>
					</div>
					<div :class="{active:drawType=='pentagram'}" :title="vm.$t('utils.star')" @click="drawTypeChange('pentagram')">
						<i class="iconfont icon-k-point"></i>
					</div>
					<div @click="uploadImg" :title="vm.$t('utils.upload')">
						<i class="iconfont icon-cus-video"></i>
					</div>
					<div @click="undo" :title="vm.$t('utils.undo')">
						<i class="iconfont icon-undo"></i>
					</div>
					<div @click="clear" :title="vm.$t('utils.clear')">
						<i class="iconfont icon-reset"></i>
					</div>
					<div @click="save" :title="vm.$t('utils.save')">
						<i class="iconfont icon-baocun1"></i>
					</div>
					<ColorPicker v-model="color" />
				</div>
				<canvas id="canvas" :width="width" :height="height"></canvas>
			</div>
			<div class="footer">
				<Button @click="cancel">{{ vm.$t('utils.cancel') }}</Button>
				<Button type="success" @click="save">{{ vm.$t('utils.save') }}</Button>
			</div>
		</div>
		<input type="file" @change="uploadImgChange" id="imgInput" accept="image/*" />
		<img id="img" crossOrigin="Anonymous" :src="imgSrc" />
	</div>
</template>
<script>
	export default {
		name: "BaseCanvas",
		props: {
			bgImg: {
				type: String,
				default: ''
			},
			vm:{
				type:Object,
				default:() => {}
			},
		},
		data() {
			return {
				width: 1160,
				height: 480,
				rect: [],
				canvas: {},
				showMenu: false,
				x: "",
				y: "",
				mouseFrom: {},
				mouseTo: {},
				drawType: '', //当前绘制图像的种类
				canvasObjectIndex: 0,
				textbox: null,
				rectangleLabel: "warning",
				drawWidth: 2, //笔触宽度
				color: "#E34F51", //画笔颜色
				drawingObject: null, //当前绘制对象
				moveCount: 1, //绘制移动计数器
				doDrawing: false, // 绘制状态

				//polygon 相关参数
				polygonMode: false,
				pointArray: [],
				lineArray: [],
				activeShape: false,
				activeLine: "",
				line: {},

				delectKlass: {},
				imgFile: {},
				imgSrc: "",
				penWidth: 5
			};
		},
		created() {
			console.log(this)
		},
		watch: {
			drawType() {
				this.canvas.selection = !this.drawType;
			},
			width() {
				this.canvas.setWidth(this.width)
			},
			height() {
				this.canvas.setHeight(this.height)
			},
			bgImg: {
				handler(n,o){
					if (this.bgImg && this.canvas) {
						var imgElement = document.createElement("img"); //声明我们的图片
						imgElement.crossOrigin = 'Anonymous'
						imgElement.src = this.bgImg
						imgElement.width = this.width
						imgElement.height = this.height
						imgElement.onload = () => {
							var imgInstance = new fabric.Image(imgElement, {
								zIndex: -2,
							});
							this.canvas.add(imgInstance);
						};
					}
				},
				immediate:true
			}
		},
		methods: {
			clear(){
				this.canvas.clear()
			},
			cancel(){
				this.$emit('onCloseModal')
			},
			undo(){
				if(this.canvas.getObjects().length){
					this.canvas.remove(
						this.canvas.getObjects()[this.canvas.getObjects().length - 1]
					)
				}
			},
			save() {
				this.canvas.discardActiveObject();
				this.canvas.requestRenderAll();
				setTimeout(() => {
					var canvas = document.getElementById('canvas')
					var imgData = canvas.toDataURL('png')
					this.$emit('getImg',imgData)
					this.$emit('onSaveCanvas', {
						base64: imgData
					})
				},500)
				
			},
			uploadImg() {
				document.getElementById("imgInput").click();
			},
			// 从已渲染的DOM元素加载图片至canvas
			loadExpImg() {
				var imgElement = document.getElementById("expImg"); //声明我们的图片
				var imgInstance = new fabric.Image(imgElement, {
					selectable: false
					// zIndex:-99,
				});
				this.canvas.add(imgInstance);
			},
			// 从文件加载图片至canvas
			uploadImgChange() {
				// 获取文件
				var eleImportInput = document.getElementById("imgInput");
				this.imgFile = eleImportInput.files[0];
				var imgSrc = "",
					imgTitle = "";
				// 从reader中获取选择文件的src
				if (/\.(jpe?g|png|gif)$/i.test(this.imgFile.name)) {
					var reader = new FileReader();
					var _this = this;
					reader.addEventListener(
						"load",
						function() {
							imgTitle = _this.imgFile.name;
							_this.imgSrc = this.result;
						},
						false
					);
					reader.readAsDataURL(this.imgFile);
				}
				var imgElement = document.getElementById("img"); //声明我们的图片

				imgElement.onload = () => {
					// this.width = imgElement.width
					// this.height = imgElement.height
					var imgInstance = new fabric.Image(imgElement, {
						zIndex: -1,
						selectable: true
					});
					this.canvas.add(imgInstance);
				};
			},
			// 开始绘制时，指定绘画种类
			drawTypeChange(e) {
				this.drawType = e;
				this.canvas.skipTargetFind = !!e
				if (e == "pen") {
					// isDrawingMode为true 才可以自由绘画
					this.canvas.isDrawingMode = true;

				} else {
					this.canvas.isDrawingMode = false;
				}

				if (this.textbox) {
					this.textbox.exitEditing();
				}
			},
			// 鼠标按下时触发
			mousedown(e) {
				// 记录鼠标按下时的坐标
				var xy = e.pointer || this.transformMouse(e.e.offsetX, e.e.offsetY);
				this.mouseFrom.x = xy.x;
				this.mouseFrom.y = xy.y;
				this.doDrawing = true;
				this.canvas.freeDrawingBrush.color = this.color
				this.canvas.freeDrawingBrush.width = this.penWidth
				if (this.drawType == "text") {
					this.drawing();
				}
				if (this.textbox && this.drawType == "text") {
					this.textbox.enterEditing();
					this.textbox.hiddenTextarea.focus();
				} else if (this.textbox && this.drawType !== "text") {
					this.textbox.exitEditing();
				}
				// 绘制多边形
				if (this.drawType == "polygon") {
					this.canvas.skipTargetFind = false;
					try {
						// 此段为判断是否闭合多边形，点击红点时闭合多边形
						if (this.pointArray.length > 1) {
							// e.target.id == this.pointArray[0].id 表示点击了初始红点
							if (e.target && e.target.id == this.pointArray[0].id) {
								this.generatePolygon();
							}
						}
						//未点击红点则继续作画
						if (this.polygonMode) {
							this.addPoint(e);
						}
					} catch (error) {
						console.log(error);
					}
				}
			},
			// 鼠标松开执行
			mouseup(e) {
				var xy = e.pointer || this.transformMouse(e.e.offsetX, e.e.offsetY);
				this.mouseTo.x = xy.x;
				this.mouseTo.y = xy.y;
				this.drawingObject = null;
				this.moveCount = 1;
				if (this.drawType != "polygon") {
					this.doDrawing = false;
				}
			},
			//鼠标移动过程中已经完成了绘制
			mousemove(e) {
				if (this.moveCount % 2 && !this.doDrawing) {
					//减少绘制频率
					return;
				}
				this.moveCount++;
				var xy = e.pointer || this.transformMouse(e.e.offsetX, e.e.offsetY);
				this.mouseTo.x = xy.x;
				this.mouseTo.y = xy.y;
				// 多边形与文字框特殊处理
				if (this.drawType != "text" || this.drawType != "polygon") {
					this.drawing(e);
				}
				if (this.drawType == "polygon") {
					console.log('11111111')
					if (this.activeLine && this.activeLine.class == "line") {
						var pointer = this.canvas.getPointer(e.e);
						this.activeLine.set({
							x2: pointer.x,
							y2: pointer.y
						});

						var points = this.activeShape.get("points");
						points[this.pointArray.length] = {
							x: pointer.x,
							y: pointer.y,
							zIndex: 1
						};
						this.activeShape.set({
							points: points
						});
						this.canvas.renderAll();
					}
					this.canvas.renderAll();
				}
			},
			deleteObj() {
				this.canvas.getActiveObjects().map(item => {
					this.canvas.remove(item);
				});
			},
			transformMouse(mouseX, mouseY) {
				return {
					x: mouseX / 1,
					y: mouseY / 1
				};
			},
			// 绘制多边形开始，绘制多边形和其他图形不一样，需要单独处理
			drawPolygon() {
				this.drawType = "polygon";
				this.polygonMode = true;
				//这里画的多边形，由顶点与线组成
				this.pointArray = new Array(); // 顶点集合
				this.lineArray = new Array(); //线集合
				this.canvas.isDrawingMode = false;
			},
			addPoint(e) {
				var random = Math.floor(Math.random() * 10000);
				var id = new Date().getTime() + random;
				var circle = new fabric.Circle({
					radius: 5,
					fill: "#ffffff",
					stroke: this.color,
					strokeWidth: 0.5,
					left: (e.pointer.x || e.e.layerX) / this.canvas.getZoom(),
					top: (e.pointer.y || e.e.layerY) / this.canvas.getZoom(),
					selectable: false,
					hasBorders: false,
					hasControls: false,
					originX: "center",
					originY: "center",
					id: id,
					objectCaching: false
				});
				if (this.pointArray.length == 0) {
					circle.set({
						fill: "red"
					});
				}
				var points = [
					(e.pointer.x || e.e.layerX) / this.canvas.getZoom(),
					(e.pointer.y || e.e.layerY) / this.canvas.getZoom(),
					(e.pointer.x || e.e.layerX) / this.canvas.getZoom(),
					(e.pointer.y || e.e.layerY) / this.canvas.getZoom()
				];

				this.line = new fabric.Line(points, {
					strokeWidth: 4,
					stroke: this.color,
					class: "line",
					originX: "center",
					originY: "center",
					selectable: false,
					hasBorders: false,
					hasControls: false,
					evented: false,

					objectCaching: false
				});
				if (this.activeShape) {
					var pos = this.canvas.getPointer(e.e);
					var points = this.activeShape.get("points");
					points.push({
						x: pos.x,
						y: pos.y
					});
					var polygon = new fabric.Polygon(points, {
						stroke: this.color,
						strokeWidth: 1,
						fill: "#cccccc",
						opacity: 0.3,
						selectable: false,
						hasBorders: false,
						hasControls: false,
						evented: false,
						objectCaching: false
					});
					this.canvas.remove(this.activeShape);
					this.canvas.add(polygon);
					this.activeShape = polygon;
					this.canvas.renderAll();
				} else {
					var polyPoint = [{
						x: (e.pointer.x || e.e.layerX) / this.canvas.getZoom(),
						y: (e.pointer.y || e.e.layerY) / this.canvas.getZoom()
					}];
					var polygon = new fabric.Polygon(polyPoint, {
						stroke: this.color,
						strokeWidth: 1,
						selectable: false,
						hasBorders: false,
						hasControls: false,
						evented: false,
						objectCaching: false
					});
					this.activeShape = polygon;
					this.canvas.add(polygon);
				}
				this.activeLine = this.line;

				this.pointArray.push(circle);
				this.lineArray.push(this.line);
				this.canvas.add(this.line);
				this.canvas.add(circle);
			},
			generatePolygon() {
				var points = new Array();
				this.pointArray.map((point, index) => {
					points.push({
						x: point.left,
						y: point.top
					});
					this.canvas.remove(point);
				});
				this.lineArray.map((line, index) => {
					this.canvas.remove(line);
				});
				this.canvas.remove(this.activeShape).remove(this.activeLine);
				var polygon = new fabric.Polygon(points, {
					stroke: this.color,
					strokeWidth: this.drawWidth,
					fill: "rgba(255, 255, 255, 0)",
					opacity: 1,
					hasBorders: true,
					hasControls: false
				});
				this.canvas.add(polygon);

				this.activeLine = null;
				this.activeShape = null;
				this.polygonMode = false;
				this.doDrawing = false;
				this.drawType = null;
			},
			drawing(e) {
				if (this.drawingObject) {
					this.canvas.remove(this.drawingObject);
				}
				// if(this.textbox){
				//  this.textbox.exitEditing();
				// }
				var canvasObject = null;
				var left = this.mouseFrom.x,
					top = this.mouseFrom.y,
					mouseFrom = this.mouseFrom,
					mouseTo = this.mouseTo;
				switch (this.drawType) {
					case "arrow": //箭头
						var x1 = mouseFrom.x,
							x2 = mouseTo.x,
							y1 = mouseFrom.y,
							y2 = mouseTo.y;
						var w = x2 - x1,
							h = y2 - y1,
							sh = Math.cos(Math.PI / 4) * 16;
						var sin = h / Math.sqrt(Math.pow(w, 2) + Math.pow(h, 2));
						var cos = w / Math.sqrt(Math.pow(w, 2) + Math.pow(h, 2));
						var w1 = (16 * sin) / 4,
							h1 = (16 * cos) / 4,
							centerx = sh * cos,
							centery = sh * sin;
						/**
						 * centerx,centery 表示起始点，终点连线与箭头尖端等边三角形交点相对x，y
						 * w1 ，h1用于确定四个点
						 */

						var path = " M " + x1 + " " + y1;
						path += " L " + (x2 - centerx + w1) + " " + (y2 - centery - h1);
						path +=
							" L " + (x2 - centerx + w1 * 2) + " " + (y2 - centery - h1 * 2);
						path += " L " + x2 + " " + y2;
						path +=
							" L " + (x2 - centerx - w1 * 2) + " " + (y2 - centery + h1 * 2);
						path += " L " + (x2 - centerx - w1) + " " + (y2 - centery + h1);
						path += " Z";
						canvasObject = new fabric.Path(path, {
							stroke: this.color,
							fill: this.color,
							strokeWidth: this.drawWidth
						});
						break;
					case "pentagram": //五角星
						var x1 = mouseFrom.x,
							x2 = mouseTo.x,
							y1 = mouseFrom.y,
							y2 = mouseTo.y;
						/**
						 * 实现思路  (x1,y1)表示鼠标起始的位置 (x2,y2)表示鼠标抬起的位置
						 * r 表示五边形外圈圆的半径，这里建议自己画个图理解
						 * 正五边形夹角为36度。计算出cos18°，sin18°备用
						 */
						var w = Math.abs(x2 - x1),
							h = Math.abs(y2 - y1),
							r = Math.sqrt(w * w + h * h)
						var cos18 = Math.cos(18 * Math.PI / 180)
						var sin18 = Math.sin(18 * Math.PI / 180)

						/**
						 * 算出对应五个点的坐标转化为路径
						 */
						var point1 = [x1, y1 + r]
						var point2 = [x1 + 2 * r * (sin18), y1 + r - 2 * r * (cos18)]
						var point3 = [x1 - r * (cos18), y1 + r * (sin18)]
						var point4 = [x1 + r * (cos18), y1 + r * (sin18)]
						var point5 = [x1 - 2 * r * (sin18), y1 + r - 2 * r * (cos18)]

						var path = " M " + point1[0] + " " + point1[1]
						path += " L " + point2[0] + " " + point2[1]
						path += " L " + point3[0] + " " + point3[1]
						path += " L " + point4[0] + " " + point4[1]
						path += " L " + point5[0] + " " + point5[1]
						path += " Z";
						canvasObject = new fabric.Path(path, {
							stroke: this.color,
							fill: this.color,
							strokeWidth: this.drawWidth,
							// angle:180,  //设置旋转角度
						});
						break;
					case "ellipse": //椭圆
						// 按shift时画正圆，只有在鼠标移动时才执行这个，所以按了shift但是没有拖动鼠标将不会画圆
						if (e.e.shiftKey) {
							mouseTo.x - left > mouseTo.y - top ? mouseTo.y = top + mouseTo.x - left : mouseTo.x = left +
								mouseTo.y - top
						}
						var radius =
							Math.sqrt(
								(mouseTo.x - left) * (mouseTo.x - left) +
								(mouseTo.y - top) * (mouseTo.y - top)
							) / 2;
						canvasObject = new fabric.Ellipse({
							left: (mouseTo.x - left) / 2 + left,
							top: (mouseTo.y - top) / 2 + top,
							stroke: this.color,
							fill: "rgba(255, 255, 255, 0)",
							originX: "center",
							originY: "center",
							rx: Math.abs(left - mouseTo.x) / 2,
							ry: Math.abs(top - mouseTo.y) / 2,
							strokeWidth: this.drawWidth
						});
						break;
					case "rectangle": //长方形
						// 按shift时画正方型
						if (e.e.shiftKey) {
							mouseTo.x - left > mouseTo.y - top ? mouseTo.y = top + mouseTo.x - left : mouseTo.x = left +
								mouseTo.y - top
						}
						var path =
							"M " +
							mouseFrom.x +
							" " +
							mouseFrom.y +
							" L " +
							mouseTo.x +
							" " +
							mouseFrom.y +
							" L " +
							mouseTo.x +
							" " +
							mouseTo.y +
							" L " +
							mouseFrom.x +
							" " +
							mouseTo.y +
							" L " +
							mouseFrom.x +
							" " +
							mouseFrom.y +
							" z";
						canvasObject = new fabric.Path(path, {
							left: left,
							top: top,
							stroke: this.color,
							strokeWidth: this.drawWidth,
							fill: "rgba(255, 255, 255, 0)",
							hasControls: true
						});
						//也可以使用fabric.Rect
						break;
					case "text": //文本框
						this.textbox = new fabric.Textbox("", {
							left: mouseFrom.x,
							top: mouseFrom.y - 10,
							// width: 150,
							fontSize: 18,
							borderColor: this.color,
							fill: this.color,
							hasControls: true
						});
						this.canvas.add(this.textbox);
						this.textbox.enterEditing();
						this.textbox.hiddenTextarea.focus();
						break;

					default:
						break;
				}

				if (canvasObject) {
					// canvasObject.index = getCanvasObjectIndex();\
					this.canvas.add(canvasObject); //.setActiveObject(canvasObject)
					this.drawingObject = canvasObject;
					this.canvas.getObjects().forEach(i => {
						if (i.isEditing) {
							i.exitEditing()
						}
					})
					// this.canvas.getActiveObject().exitEditing();
				}
			}
		},
		mounted() {
			
			this.$EventBus.$off('doCanvasConfirm')
			this.$EventBus.$on('doCanvasConfirm',() => {
				this.save()
			})
			
			this.$nextTick(() => {
				this.canvas = new fabric.Canvas("canvas");
				this.canvas.selectionColor = "rgba(0,0,0,0.1)";
				this.canvas.on("mouse:down", this.mousedown);
				this.canvas.on("mouse:move", this.mousemove);
				this.canvas.on("mouse:up", this.mouseup);
				// let canvas = this.canvas
				// canvas.on('mouse:wheel', function(opt) {
				//   var delta = opt.e.deltaY;
				//   var zoom = canvas.getZoom();
				//   zoom *= 0.999 ** delta;
				//   if (zoom > 20) zoom = 20;
				//   if (zoom < 0.01) zoom = 0.01;
				//   canvas.zoomToPoint({ x: opt.e.offsetX, y: opt.e.offsetY }, zoom);
				//   opt.e.preventDefault();
				//   opt.e.stopPropagation();
				// });
			})
			document.onkeydown = e => {
				// 键盘 delect删除所选元素
				if (e.keyCode == 46 || e.keyCode == 8) {
					this.deleteObj();
				}
				// ctrl+z 删除最近添加的元素
				if (e.keyCode == 90 && e.ctrlKey) {
					this.canvas.remove(
						this.canvas.getObjects()[this.canvas.getObjects().length - 1]
					);
				}
			};
		}
	};
</script>

<style lang="less">
	.maintenancePlanAdd{
		
		.footer{
			display: none;
			float: right;
			margin-top: 10px;
			
			.ivu-btn{
				margin-left: 20px;
			}
		}
		
		.ivu-color-picker {
			.ivu-icon{
				display: none;
			}
			
			.ivu-input{
				background: none;
				border: none;
				display: flex;
				justify-content: center;
			}
			
			.ivu-color-picker-focused{
				box-shadow: none;
			}
			
			.ivu-color-picker-color{
				height: 20px;
				width: 20px;
				margin-top: 5px;
				cursor: pointer;
			}
		}
		
		.ivu-input-icon-normal+.ivu-input{
			padding: 0;
		}
	
	.el-container {
		flex-direction: column;
	}

	img,
	input {
		display: none;
	}

	.demo {
		display: flex;
		justify-content: center;
		align-items: center;
	}

	canvas {
		border: 1px dashed #b8b8b8;
	}

	.draw-btn-group {
		height: 480px;
		width: 40px;
		display: flex;
		flex-direction: column;
		align-items: center;
		justify-content: flex-start;
		background: #e7e7e7;

		&>div {
			cursor: pointer;
			display: flex;
			justify-content: center;

			&:hover {
				background: #c7c7c7;
			}

			i {
				display: flex;
				background-repeat: no-repeat;
				// background-size: 80%;
				// background-position: 50% 50%;
				height: 40px;
				width: 40px;
				font-size: 22px;
				align-items: center;
				justify-content: center;
			}
		}

		.active {
			background: #c7c7c7;
		}
		}
	}
</style>
