konva.js 工具类

import StringUtils from "./StringUtil.js";

class KonvaCanvas {
	/**
	 * 初始化画布
	 * @param {String} domId 容器dom id
	 */
	constructor(domId) {
		this.layer = null;
		this.stage = null;
		this.scale = 1.0;

		this.init(domId);
	}

	/**
	 * 聚焦到指定元素
	 * @param {String} elementId 元素dom id
	 */
	focusOn(elementId) {
		if (!this.layer || !this.stage || !elementId) return;
		var element = this.stage.find("#" + elementId)[0];

		let element_x = StringUtils.isNumeric(element.position().x) ? element.position().x : Number(element.position().x);
		let element_y = StringUtils.isNumeric(element.position().y) ? element.position().y : Number(element.position().y);

		let halfStageWidth = this.stage.width() * 0.5;
		let halfStageHeight = this.stage.height() * 0.5;

		let x = 0;
		let y = 0;
		if (element_x < 0) {
			x = Math.abs(element_x - halfStageWidth);
		} else {
			x = halfStageWidth - element_x;
		}

		if (element_y < 0) {
			y = Math.abs(element_y - halfStageHeight);
		} else {
			y = halfStageHeight - element_y;
		}

		this.stage.scaleX(1.0);
		this.stage.scaleY(1.0);
		this.scale = 1.0;

		this.stage.x(x);
		this.stage.y(y);

		this.layer.draw();
	}

	/**
	 * 绘制图片
	 * @param {String} url 图片路径
	 * @param {String} id 唯一标识
	 * @param {Number} x 横坐标
	 * @param {Number} y 纵坐标
	 * @param {Number} zoom 缩放比例
	 * @param {Number} rotate 旋转角度
	 */
	drawImage(url, id, x = 0, y = 0, zoom = 1.0, rotate = 0) {
		return new Promise((resolve, reject) => {
			var img = new Image();
			img.src = url;

			const that = this;
			img.onload = function () {
				const img_w = img.width * zoom;
				const img_h = img.height * zoom;

				var kImage = new Konva.Image({
					image: img,
					x: x,
					y: y,
					width: img_w,
					height: img_h,
					offset: {
						x: img_w / 2,
						y: img_h / 2,
					},
					scale: {
						x: 1.0,
						y: 1.0,
					},
					id: id,
				});
				kImage.rotate(rotate);
				that.layer.add(kImage);
				console.log(`图片加载完成`);
				that.layer.draw();
				resolve(kImage);
			};
		});
	}

	/**
	 * 更新元素属性信息
	 * @param {String} id 元素id
	 * @param {Object} attr 元素属性 {}
	 */
	updateElement(id, attr) {
		if (!this.layer || !this.stage) return;

		var shape = this.stage.find("#" + id)[0];
		if (shape) {
			if (attr.x) {
				attr.x = isNaN(Number(attr.x)) ? 0 : Number(attr.x);
			} else {
				attr.x = 0;
			}
			if (attr.y) {
				attr.y = isNaN(Number(attr.y)) ? 0 : Number(attr.y);
			} else {
				attr.y = 0;
			}
			if (attr.rotation) {
				attr.rotation = isNaN(Number(attr.rotation)) ? 0 : Number(attr.rotation);
			}
			if (attr.points) {
				let points = [];
				attr.points.forEach(element => {
					let val = Number(element);
					points.push(val);
				});
				attr.points = points;
			}

			attr = {
				...shape.getAttrs(),
				...attr,
			};

			shape.setAttrs(attr);
			this.stage.batchDraw(); //重绘
		}
	}

	/**
	 * 绘制线
	 * @param {Array} points 点位坐标   [x1, y1, x2, y2, x3, y3]
	 * @param {String} id 唯一标识
	 * @param {Number} lineWidth 线宽
	 * @param {String} color 颜色
	 * @returns
	 */
	drawLine(points, id, lineWidth = 1, color = "#72F31D") {
		if (!this.layer) return;

		let points2 = [];
		points.forEach(element => {
			let val = Number(element);
			points2.push(val);
		});
		var line = new Konva.Line({
			points: points2,
			stroke: color,
			strokeWidth: lineWidth,
			lineCap: "round",
			lineJoin: "round",
			tension: 0.5,
			id: id,
		});

		this.layer.add(line);
	}

	/**
	 * 销毁画布
	 */
	destroyed() {
		if (this.layer) {
			this.layer.destroyChildren();
			this.layer.draw();
		}
	}

	// ==========================================  私有方法
	init(domId) {
		if (!domId) {
			return;
		}

		const container = document.getElementById(domId);
		var width = container.clientWidth;
		var height = container.clientHeight;
		var stage = new Konva.Stage({
			container: domId,
			width: width,
			height: height,
			draggable: true,
		});
		var layer = new Konva.Layer();
		stage.add(layer);

		this.stage = stage;
		this.layer = layer;
		this.stage.scaleX(this.scale);
		this.stage.scaleY(this.scale);

		this.stage.on("wheel", e => {
			const direction = e.evt.deltaY > 0 ? -0.08 : 0.08;
			this.scale = this.scale + direction;
			this.scale = this.scale < 0 ? 0 : this.scale;
			this.stage.scaleX(this.scale);
			this.stage.scaleY(this.scale);
			// 以鼠标为锚点缩放
			let pointer = this.stage.getPointerPosition();
			this.stage.x(-((pointer.x - this.stage.x()) * (this.scale / (this.scale - direction)) - pointer.x));
			this.stage.y(-((pointer.y - this.stage.y()) * (this.scale / (this.scale - direction)) - pointer.y));

			this.layer.draw();
		});
	}
	// ==========================================  私有方法 end
}

export default KonvaCanvas;


Logo

欢迎加入西安开发者社区!我们致力于为西安地区的开发者提供学习、合作和成长的机会。参与我们的活动,与专家分享最新技术趋势,解决挑战,探索创新。加入我们,共同打造技术社区!

更多推荐