canvas根据坐标点位画图形-canvas拖拽编辑单个图形形状

news2025/1/23 9:28:15
  1. 首先在选中图形的时候需要用鼠标右击来弹出选择框,实现第一个编辑节点功能
    在这里插入图片描述
  • 在components文件夹下新建右键菜单
    在这里插入图片描述
  • RightMenu文件:
<template>
	<div v-show="show" class="right-menu" :style="'top:'+this.y+'px;left:'+this.x+'px'">
		<div @click="handelMenu('editPoint')">编辑节点</div>
		<div @click="handelMenu('stretch')">拉伸</div>
		<div @click="handelMenu('rotate')">旋转</div>
		<div @click="handelMenu('copy')">复制</div>
		<div @click="handelMenu('paste')">粘贴</div>
		<div @click="handelMenu('delete')">删除</div>
	</div>
</template>

<script>
	export default {
		data() {
			return {
				show: false,
				x: 0,
				y: 0,
			}
		},
		
		methods: {
			showModal(x,y) {
				this.x = x;
				this.y = y;
				this.show = true;
			},
			handelMenu(e) {
				this.hideMenu();
				this.$emit('backRightMenu',e);
			},
			hideMenu() {
				this.show = false;
			}
		}
	}
</script>

<style scoped>
	.right-menu {
		width: 100px;
		position: relative;
		background: #fff;
		min-height: 50px;
	}
	.right-menu>div {
		height: 30px;
		line-height: 30px;
		border-bottom: 1px solid rgb(228, 235, 249);
		padding: 0 10px;
		font-size: 13px;
		cursor: pointer;
	}
</style>
  • 在页面中使用:
<right-menu ref="RightMenu" @backRightMenu="backRightMenu"></right-menu>

import RightMenu from '@/components/RightMenu/index';

components: {
	RightMenu
},
  • 在data中定义所需要的变量
rightMenuType: '', //可操作图形状态
isRightMenu: false, //是否可以操作图形
  1. 鼠标右击的时候打开右键菜单
//鼠标右击
rightMenu(e) {
	if (this.type === 'move' && this.activeData.length > 0 && this.rightMenuType === '') {
		this.$refs.RightMenu.showModal(e.offsetX, e.offsetY);
	} else {
		return;
	}
},
  1. 点击选择选项接收值
//右键菜单返回
backRightMenu(e) {
	this.rightMenuType = e;
	this.isRightMenu = true;
	//编辑图形
	switch (e) {
		case 'editPoint':
			this.redrawMap();
			break;
	}
}
  1. redrawMap重绘过程中判断如果在编辑图形的状态,就选中图形并且图形顶点高亮
if(this.activeData.length > 0 && this.isRightMenu) {
	//编辑图形
	switch (this.rightMenuType) {
		case 'editPoint':
			drawMap.drawRectangle(this.activeData, 'editPoint');
			break;
	}
}
  • 效果如下:
    在这里插入图片描述
  1. 接下来实现吸附顶点,首先鼠标移动过程中判断是否吸附顶点,吸附状态下拖动点位可以更改图形点位坐标
// 开启吸附功能 记录是否处于吸附状态
if (this.activeData.length > 0 && ['editPoint'].includes(this.rightMenuType)) {
	this.activeData.map((item, idx) => {
		let result = mathUtils.attractPixel([x, y], item)
		
		if(result.isAttract && this.isMouseClick) {
			if(idx === 0 || idx === this.activeData.length - 1) {
				this.$set(this.activeData,this.activeData.length - 1,[x,y]);
			}
			this.$set(this.activeData,idx,[x,y]);
		}
	})
}
  • 涉及的算法:
// 计算两点距离
dealLength(start, end) {
	var a = end.x - start.x;
	var b = end.y - start.y;
	return Math.sqrt(a * a + b * b);
},
// 鼠标点击位置和目标点相距<=吸附半径则吸附到目标点
attractPixel(point1, pointTarget, pixelArea = adsorptionDistance) {
	const len = this.dealLength({
		x: point1[0],
		y: point1[1]
	}, {
		x: pointTarget[0],
		y: pointTarget[1]
	})
	const finalPoint = len <= pixelArea ? pointTarget : point1
	const isAttract = len <= pixelArea
	return {
		finalPoint,
		isAttract
	}
},
  • 效果如下:
    在这里插入图片描述
  1. 接下来实现在鼠标按下过程中如果触碰了图形的边线,就给点击边线的位置插入一个点位,形成多边形
//鼠标按下判断选中边线按下插入节点
if (this.activeData.length > 0 && ['editPoint'].includes(this.rightMenuType)) {
	const pointData = mathUtils.attractOnCheckLine({x,y}, this.activeData);
	if(pointData && pointData.overIdx >= 0) {
		this.activeData.splice(pointData.overIdx + 1, 0, [x, y])
	}
}
  • 效果如下:
    在这里插入图片描述
  • 涉及算法:
// 计算当前点到所有线段的垂点,小于5px,则吸附
attractOnCheckLine(point, coordinates) {
	for (var i = 0; i < coordinates.length; i++) {
		if (this.checkPoint(coordinates[i], point)) {
			return {
				x: coordinates[i][0],
				y: coordinates[i][1],
				idx: i
			};
		}
	}
	for (var i = 0; i < coordinates.length - 1; i++) {
		var pt = this.pointToSegDist(point.x, point.y, coordinates[i][0], coordinates[i][1],
			coordinates[i + 1][0], coordinates[i + 1][1], Math.pow(adsorptionDistance, 2));
		if (pt) {
			pt.overIdx = i
			return pt;
		}
	}
	return null;
},
checkPoint(target, point) {
	if (point.x >= target[0] - adsorptionDistance &&
		point.x <= target[0] + adsorptionDistance &&
		point.y >= target[1] - adsorptionDistance &&
		point.y <= target[1] + adsorptionDistance) {
		return true;
	} else {
		return false;
	}
},
pointToSegDist(x, y, x1, y1, x2, y2, dist) {
	var cross = (x2 - x1) * (x - x1) + (y2 - y1) * (y - y1);
	if (cross <= 0) return null;
	var d2 = (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1);
	if (cross >= d2) return null;
	var r = cross / d2;
	var px = x1 + (x2 - x1) * r;
	var py = y1 + (y2 - y1) * r;
	var dis = (x - px) * (x - px) + (py - y) * (py - y);
	if (dis <= dist) { // adsorptionDistance * adsorptionDistance
		return {
			x: px,
			y: py
		};
	}
},
  • 接下来插入的点位也可以进行拖拽了,大功告成!!!
    在这里插入图片描述

本节其他文件附下,复制可用:

  • 首页
<template>
	<div id="app">
		<div class="nav-top">
			<div :class="{'nav-sel':type==='move'}" @click="setType('move')">选择</div>
			<div :class="{'nav-sel':type==='rectangle'}" @click="setType('rectangle')">矩形</div>
			<div :class="{'nav-sel':type==='circle'}" @click="setType('circle')">圆形</div>
		</div>
		<div class="draw-box" ref="drawBox">
			<canvas class="canvas-style" ref="canvasMap" @click="mapClick" @mousedown="mapMousedown"
				@mousemove="mapMousemove" @mouseup="mapMouseUp" @dblclick="mapDbclick"
				@mousewheel.prevent="mapMouseWheel" @contextmenu.prevent="rightMenu"></canvas>
		</div>
		<right-menu ref="RightMenu" @backRightMenu="backRightMenu"></right-menu>
	</div>
</template>

<script>
	import drawMap from '@/utils/drawMap.js';
	import mathUtils from '@/utils/mathUtils.js';
	import RightMenu from '@/components/RightMenu/index';
	export default {
		name: 'app',
		data() {
			return {
				type: 'rectangle', //当前可编辑图形的状态
				mouseStartPos: [], //鼠标点击的位置
				mouseMovePos: [0, 0], //鼠标移动位置与图形中心点位置的差值
				mouseClickArr: [], //当前已点击的坐标记录
				drawAllData: [], //当前所有保存的数据
				activeData: [], //当前选中的图形坐标数据
				isMouseClick: false, //是否按住鼠标左键
				nowScale: 100, //初始化滚动大小
				lastScale: 100, //最后一次滚动大小
				rightMenuType: '', //可操作图形状态
				isRightMenu: false, //是否可以操作图形
			}
		},

		components: {
			RightMenu
		},

		mounted() {
			//初始化画板
			const initData = {
				id: this.$refs.canvasMap,
				w: this.$refs.drawBox.clientWidth,
				h: this.$refs.drawBox.clientHeight
			}
			drawMap.initMap(initData);
			this.redrawMap();
		},

		methods: {
			//单击地图
			mapClick(e) {
				let x = e.offsetX
				let y = e.offsetY

				//非操作点击空白


				//点击地图加入点位
				switch (this.type) {
					case 'rectangle':
						this.mouseClickArr.push([x, y])
						if (this.mouseClickArr.length === 3) {
							this.drawRectangle(this.mouseClickArr)
							this.redrawMap()
							this.mouseClickArr = []
						}
						break;
				}
			},
			//鼠标按下
			mapMousedown(e) {
				let x = e.offsetX
				let y = e.offsetY

				if (e.button === 2) {
					// 鼠标右击
					this.redrawMap()
					return
				}

				this.mouseStartPos = [e.offsetX, e.offsetY]

				this.isMouseClick = true; //鼠标左键已按下,可以进行平移操作
				
				//鼠标按下判断选中边线按下插入节点
				if (this.activeData.length > 0 && ['editPoint'].includes(this.rightMenuType)) {
					const pointData = mathUtils.attractOnCheckLine({x,y}, this.activeData);
					if(pointData && pointData.overIdx >= 0) {
						this.activeData.splice(pointData.overIdx + 1, 0, [x, y])
					}
				}

				if (this.type === 'move' && this.isMouseClick) {
					let activePoint = []
					if (this.drawAllData.length > 0) {
						for (const [i, item] of this.drawAllData.entries()) {
							mathUtils.pointInPolygonORLine(this.mouseStartPos, item) === true ? activePoint = item : []
						}
					}
					if (this.activeData.length > 0 && !mathUtils.pointInPolygonORLine(this.mouseStartPos, this
						.activeData)) {
						this.drawAllData = this.drawAllData.concat([this.activeData])
						this.activeData = [];
					} else if (this.activeData.length === 0) {
						this.activeData = activePoint;
						this.drawAllData = this.drawAllData.filter(item => {
							return item !== this.activeData
						})
					}

					this.redrawMap();
				}
			},
			//鼠标移动
			mapMousemove(e) {
				let x = e.offsetX
				let y = e.offsetY

				// 开启吸附功能 记录是否处于吸附状态
				if (this.activeData.length > 0 && ['editPoint'].includes(this.rightMenuType)) {
					this.activeData.map((item, idx) => {
						let result = mathUtils.attractPixel([x, y], item)
						
						if(result.isAttract && this.isMouseClick) {
							if(idx === 0 || idx === this.activeData.length - 1) {
								this.$set(this.activeData,this.activeData.length - 1,[x,y]);
							}
							this.$set(this.activeData,idx,[x,y]);
						}
					})
				}

				//鼠标移动中判断当前是否状态是move,activeData当前选中是否有数据,isMouseClick当前是否可以移动 isRightMenu当前是否不能编辑图形
				if (this.type === 'move' && this.activeData.length > 0 && this.isMouseClick && !this.isRightMenu) {
					//获取图形中心位置
					const center = mathUtils.getPolygonCenter(this.activeData);
					//计算点击位置与图形中心位置的差值,如果差值大于0或小于0代表移动了
					this.mouseMovePos = [x - center[0], y - center[1]]
					//移动图形
					this.movePoint(this.mouseMovePos, this.activeData)
				}

				this.redrawMap({
					x,
					y
				})
			},
			//鼠标抬起
			mapMouseUp(e) {
				this.isMouseClick = false; //禁止移动
				this.mouseStartPos = []; //抬起后开始点击位置清空
				this.mouseMovePos = [0, 0]; //清空两次点位的差值,按下后重新计算
			},
			//鼠标双击
			mapDbclick(e) {
				console.log('鼠标双击', e);
			},
			//鼠标滚轮
			mapMouseWheel(e) {
				if (this.activeData.length === 0) return;
				const wheelDelta = e.wheelDelta //滚轮上下滚动的数值,默认为0,正数为向上滚动,负数为向下滚动
				const interval = this.nowScale <= 50 ? 25 : 50

				if (wheelDelta > 0) {
					if (this.nowScale >= 1600) {
						this.nowScale = 1600
						return
					}
					this.nowScale = parseInt(this.nowScale + 1 * this.nowScale / interval)
				} else {
					if (this.nowScale <= 25) {
						this.nowScale = 25
						return
					}
					this.nowScale = parseInt(this.nowScale - 1 * this.nowScale / interval)
				}

				this.redrawMap()
			},
			//鼠标右击
			rightMenu(e) {
				if (this.type === 'move' && this.activeData.length > 0 && this.rightMenuType === '') {
					this.$refs.RightMenu.showModal(e.offsetX, e.offsetY);
				} else {
					return;
				}
			},
			async redrawMap(point) {
				//canvas重绘
				drawMap.redrawMap();

				//保存滚动后的数据
				this.savePointData();

				//实时画鼠标点位
				point && point.x && drawMap.drawCircle({
					x: point.x,
					y: point.y,
					r: 4,
					fillStyle: '#fff'
				})

				//绘制已经保存的房间数据
				if (this.drawAllData.length > 0) {
					for (const [i, item] of this.drawAllData.entries()) {
						drawMap.drawRectangle(item);
					}
				}

				//绘制正在编辑的数据
				if (this.activeData.length > 0) {
					drawMap.drawRectangle(this.activeData, true);
				}

				//实时的画各类图形
				point && point.x && this.drawNowDrawing(point.x, point.y);

				if(this.activeData.length > 0 && this.isRightMenu) {
					//编辑图形
					switch (this.rightMenuType) {
						case 'editPoint':
							drawMap.drawRectangle(this.activeData, 'editPoint');
							break;
						case 'stretch':
					
							break;
						case 'rotate':
					
							break;
						case 'copy':
					
							break;
						case 'paste':
					
							break;
						case 'delete':
					
							break;
					}
				}
			},
			//保存数据
			savePointData() {
				if (this.activeData.length > 0) {
					const oCenter = mathUtils.getPolygonCenter(this.activeData);
					this.activeData = mathUtils.scalePoint(this.activeData, this.nowScale / this.lastScale, oCenter);
					this.lastScale = this.nowScale
				} else {
					this.nowScale = 100;
					this.lastScale = 100;
				}

			},
			//实时画图形
			drawNowDrawing(x, y) {
				switch (this.type) {
					case 'rectangle':
						if (this.mouseClickArr.length >= 1) {
							const mouseClick = this.mouseClickArr.length === 1 ? [
								[x, y],
								[x, y]
							] : [
								[x, y]
							]
							const newArr = this.mouseClickArr.concat(mouseClick)
							this.drawRectangle(newArr)
						}
						break;
				}
			},
			//画矩形
			drawRectangle(arr) {
				// 画矩形,点选三个点完成一个矩形
				const vPoint = mathUtils.calculateVerticalPoint(arr);
				// 根据第一点算的为第四点 根据第二点算的为第三点
				const point4 = mathUtils.calculatePoint(vPoint, arr[0], arr[2]);
				const point3 = mathUtils.calculatePoint(vPoint, arr[1], arr[2]);
				const rectangleData = [arr[0], arr[1], point3, point4, arr[0]];
				if (this.mouseClickArr.length === 3) {
					this.drawAllData = this.drawAllData.concat([rectangleData])
				}
				drawMap.drawRectangle(rectangleData);
			},
			//图形平移,通过差值计算点位坐标
			movePoint(movePos, data) {
				this.activeData = data.map(item => {
					return [item[0] + movePos[0], item[1] + movePos[1]]
				})
			},
			//设置可编辑类型
			setType(e) {
				this.type = e
			},
			//右键菜单返回
			backRightMenu(e) {
				this.rightMenuType = e;
				this.isRightMenu = true;
				//编辑图形
				switch (e) {
					case 'editPoint':
						this.redrawMap();
						break;
					case 'stretch':

						break;
					case 'rotate':

						break;
					case 'copy':

						break;
					case 'paste':

						break;
					case 'delete':

						break;
				}
			}
		}
	}
</script>

<style>
	html,
	body {
		margin: 0;
		padding: 0;
	}

	.nav-top {
		display: flex;
		align-items: center;
	}

	.nav-top>div {
		padding: 10px;
		border: 1px solid;
		border-radius: 8px;
		margin-right: 20px;
		cursor: pointer;
	}

	.nav-top .nav-sel {
		border: 2px solid #18c1f6;
	}

	.draw-box {
		width: 100vw;
		height: calc(100vh - 64px);
		background: #F1F2F6;
		position: fixed;
		bottom: 0;
	}

	.hidden-icon {
		position: absolute;
		top: 0;
		z-index: -100;
		left: 0;
		visibility: hidden;
	}

	.del-icon {
		width: 16px;
		transform: translate(-8px, -8px);
		user-select: none;
	}
</style>
  • mathUtils.js
import * as turf from "@/utils/turf.es";

let adsorptionDistance = 6
const mathUtils = {
	// 计算两点距离
	dealLength(start, end) {
		var a = end.x - start.x;
		var b = end.y - start.y;
		return Math.sqrt(a * a + b * b);
	},
	// 计算点到线垂点的方法
	calculateVerticalPoint(arr) {
		const point = arr[2]

		var x1 = arr[0][0];
		var y1 = arr[0][1];
		var x2 = arr[1][0];
		var y2 = arr[1][1]
		if (x1 == x2 && y1 == y2) {
			return [point[0], point[1]];
		}
		var m = point[0];
		var n = point[1];
		var a = y2 - y1;
		var b = x1 - x2;
		var c = x2 * y1 - x1 * y2;
		var x3 = (b * b * m - a * b * n - a * c) / (a * a + b * b);
		var y3 = (a * a * n - a * b * m - b * c) / (a * a + b * b);
		return [Math.round(x3 * 100) / 100, Math.round(y3 * 100) / 100];
	},
	// 根据垂点计算平行点
	calculatePoint(vPoint, point, point2) {
		const x = point[0] - vPoint[0] + point2[0]
		const y = point[1] - vPoint[1] + point2[1]
		return [x, y]
	},
	// 判断点是否在多边形内部或者线上
	pointInPolygonORLine(point, polygon) {
		var pt = turf.point(point);
		var poly = turf.polygon([polygon]);
		return turf.booleanPointInPolygon(pt, poly)
	},
	// 获取多边形的中心点
	getPolygonCenter(arr) {
		var polygon = turf.polygon([arr]);
		var center = turf.centerOfMass(polygon);
		return center.geometry.coordinates
	},
	// 获取缩放后的坐标
	scalePoint(oGeo, scale, oCenter) {
		const newGeo = []
		const moveX = oCenter[0] * scale - oCenter[0]
		const moveY = oCenter[1] * scale - oCenter[1]
		for (var item of oGeo) {
			const x = item[0] * scale - moveX
			const y = item[1] * scale - moveY
			newGeo.push([x, y])
		}
		return newGeo
	},
	// 鼠标点击位置和目标点相距<=吸附半径则吸附到目标点
	attractPixel(point1, pointTarget, pixelArea = adsorptionDistance) {
		const len = this.dealLength({
			x: point1[0],
			y: point1[1]
		}, {
			x: pointTarget[0],
			y: pointTarget[1]
		})
		const finalPoint = len <= pixelArea ? pointTarget : point1
		const isAttract = len <= pixelArea
		return {
			finalPoint,
			isAttract
		}
	},
	// 计算当前点到所有线段的垂点,小于5px,则吸附
	attractOnCheckLine(point, coordinates) {
		for (var i = 0; i < coordinates.length; i++) {
			if (this.checkPoint(coordinates[i], point)) {
				return {
					x: coordinates[i][0],
					y: coordinates[i][1],
					idx: i
				};
			}
		}
		for (var i = 0; i < coordinates.length - 1; i++) {
			var pt = this.pointToSegDist(point.x, point.y, coordinates[i][0], coordinates[i][1],
				coordinates[i + 1][0], coordinates[i + 1][1], Math.pow(adsorptionDistance, 2));
			if (pt) {
				pt.overIdx = i
				return pt;
			}
		}
		return null;
	},
	checkPoint(target, point) {
		if (point.x >= target[0] - adsorptionDistance &&
			point.x <= target[0] + adsorptionDistance &&
			point.y >= target[1] - adsorptionDistance &&
			point.y <= target[1] + adsorptionDistance) {
			return true;
		} else {
			return false;
		}
	},
	pointToSegDist(x, y, x1, y1, x2, y2, dist) {
		var cross = (x2 - x1) * (x - x1) + (y2 - y1) * (y - y1);
		if (cross <= 0) return null;
		var d2 = (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1);
		if (cross >= d2) return null;
		var r = cross / d2;
		var px = x1 + (x2 - x1) * r;
		var py = y1 + (y2 - y1) * r;
		var dis = (x - px) * (x - px) + (py - y) * (py - y);
		if (dis <= dist) { // adsorptionDistance * adsorptionDistance
			return {
				x: px,
				y: py
			};
		}
	},
}

export default mathUtils;
  • drawMap.js
let ctxDom, mapCtx; //初始化必要参数

const drawMap = {
	//初始化地图
	initMap({
		id,
		w,
		h
	} = obj) {
		ctxDom = id
		id.width = w
		id.height = h
		mapCtx = id.getContext("2d");
	},
	//地图重绘
	redrawMap() {
		mapCtx.clearRect(0, 0, ctxDom.width, ctxDom.height);
	},
	//画圆
	drawCircle({
		x,
		y,
		r,
		strokeStyle = '#1289ff80', //边框色
		fillStyle = '#fff0', //填充色
	} = obj) {
		mapCtx.beginPath();
		mapCtx.fillStyle = fillStyle;
		mapCtx.setLineDash([]);
		mapCtx.strokeStyle = strokeStyle
		mapCtx.arc(x, y, r, 0, 2 * Math.PI);
		mapCtx.closePath();
		mapCtx.stroke();
		mapCtx.fill();
	},
	drawRectangle(arr, isCheck) {
		mapCtx.strokeStyle = isCheck ? '#1289ff' : '#1289ff80';
		mapCtx.fillStyle = isCheck ? '#ffffff80' : '#fff0';
		mapCtx.lineWidth = 2;
		mapCtx.setLineDash([]);
		mapCtx.lineJoin = 'bevel';
		mapCtx.beginPath();
		mapCtx.moveTo(arr[0][0], arr[0][1]);
		for (let i = 1; i < arr.length; i++) {
			mapCtx.lineTo(arr[i][0], arr[i][1]);
		}
		mapCtx.stroke();
		mapCtx.fill();
		if (isCheck == 'editPoint') {
		  for (let i = 0; i < arr.length; i++) {
		    this.drawCircle({
		      x: arr[i][0],
		      y: arr[i][1],
		      r: 3,
		      strokeStyle: '#1289ff80',
		      fillStyle: '#fff'
		    })
		  }
		}
	},
}

export default drawMap

组件页请参考顶部!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/337365.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PCB设计中的数据单位,层作用,工艺要求,制作过程等简介

PCB中常识 物理结构常识 几乎每层板子都是由两个金属层夹着一个绝缘层&#xff0c;像一个三明治结构。多层板是这种双层板叠加压合的。 常见的层的作用 参考&#xff1a;https://www.21ic.com/article/854059.html PCB电路板一般而言会分成六层&#xff0c;具体为&#x…

第二十四章 java并发常见知识内容(AQS)

JAVA重要知识点AQS介绍AQS的核心思想AQS资源共享方式自定义同步器常见同步工具类Semaphore(信号量)CountDownLatch(倒计时器)CyclicBarrier(循环栅栏)AQS 介绍 AQS 的全称为 AbstractQueuedSynchronizer &#xff0c;翻译过来的意思就是抽象队列同步器。这个类在 java.util.c…

图解 git 常用命令

本文图解 Git 中的最常用命令&#xff0c;如果你稍微理解 Git 的工作原理&#xff0c;这篇文章能够让你理解的更透彻。 基本用法 上面的四条命令在工作目录、暂存目录(也叫做索引)和仓库之间复制文件。 git add files 把当前文件放入暂存区域。 git commit 给暂存区域生成快照…

java集合:Collection:Set+List+Dueue

目录 Collection集合 1.常用方法 2.使用Iterator接口遍历集合元素 3.使用foreach循环遍历集合元素 4.Set集合 4.1 HashSet类 4.2 LinkedHashSet类 4.3 TreeSet类 4.4 EnumSet类 5. List接口 5.1 ListIteractor接口 5.2 Stack类 5.3 Arrays.ArrayList 5.4 Linke…

ChatGPT体验失败的经历

ChatGPT的介绍 最近有一个很热门的话题&#xff0c;而且这个话题内容已经覆盖了多个领域。ChatGPT这个词&#xff0c;最近不断的出现在微博的热搜或者公众号的文章里。那我们先大概了解一下ChatGPT。 ChatGPT是由OpenAI开发的一个人工智能聊天机器人程序&#xff0c;于2022年11…

在Allegro设计界面中如何修改封装焊盘

在Allegro PCB设计界面中修改封装焊盘的方法1、选择菜单Tools→Padstack→Modify Design Padstack...2、然后点击封装上要修改的焊盘&#xff0c;右击选择Edit或者点击Options选项卡下要修改的焊盘&#xff0c;然后点击Edit修改3、修改完焊盘后&#xff0c;选择File→Update to…

PyTorch学习笔记:nn.PReLU——PReLU激活函数

PyTorch学习笔记&#xff1a;nn.PReLU——PReLU激活函数 torch.nn.PReLU(num_parameters1, init0.25, deviceNone, dtypeNone)功能&#xff1a;逐元素对数据应用如下函数公式进行激活 PReLU(x)max⁡(0,x)a∗min⁡(0,x)\text{PReLU}(x)\max(0,x)a*\min(0,x) PReLU(x)max(0,x)a∗…

JS document.write()换行

换行效果&#xff1a; 通过传递多个参数&#xff0c;即可实现换行效果&#xff1a; document.write("<br>",ar) 效果&#xff1a; 示例源码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8&quo…

Vue3 中 导航守卫 的使用

目录前言&#xff1a;一、什么是导航守卫&#xff1f;二、导航守卫有哪几种&#xff1f;1、全局守卫&#xff08;3个&#xff09;全局前置守卫全局解析守卫全局后置钩子2、路由独享守卫&#xff08;1个&#xff09;3、组件内守卫&#xff08;3个&#xff09;beforeRouteEnter(t…

大数据Kylin(二):Kylin安装使用

文章目录 Kylin安装使用 一、Kylin安装要求 二、Kylin安装 1、Kylin安装前环境准备

SpringCloud-Netflix学习笔记12——Hystrix-Dashboard实现服务监控

一、服务监控 hystrixDashboard 除了隔离依赖服务的调用以外&#xff0c;Hystrix还提供了准实时的调用监控&#xff08;Hystrix Dashboard&#xff09;&#xff0c;Hystrix会持续地记录所有通过Hystrix发起的请求的执行信息&#xff0c;并以统计报表和图形的形式展示给用户&…

MikTex+Texmaker环境LaTeX使用bib文件引用参考文献步骤

一、MikTexTexmaker环境 MikTexTexmaker环境是一个LaTeX编辑与编译&#xff0c;以及PDF预览环境。如果还没装好的话&#xff0c;推荐浏览【MiKTeXTexmaker安装】这篇博客去安装此环境。 二、准备bib文件 文件名命名为ref.bib&#xff0c;添加如下内容(作为demo) article{kaelb…

微信小程序nodejs+java+python美食制作教程系统

食谱大全所要实现的功能分析,对于现在网络方便,食谱大全要实现管理员、用户可以直接在平台上进行查看自己所需数据信息,这样既能节省管理的时间,不用再像传统的方式,如果用户想要进行交流信息,必须双方见面进行沟通交流所需的信息,由于很多用户时间的原因,没有办法进行见面沟通…

MySQL_InnoDB引擎

InnoDB引擎 逻辑存储结构 表空间&#xff08;ibd文件&#xff09;&#xff0c;一个mysql实例可以对应多个表空间&#xff0c;用于存储记录、索引等数据。 段&#xff0c;分为数据段&#xff08;Leaf node segment&#xff09;、索引段(Non-leaf node segment)、回滚段(Rollba…

【LeetCode】每日一题(1)

目录 题目&#xff1a; 解题思路&#xff1a; 代码&#xff1a; 写在最后&#xff1a; 题目&#xff1a; 这是他给出的接口&#xff1a; class Solution { public:int fillCups(vector<int>& amount) {} }; 作为一个数学学渣&#xff0c;我想不出厉害的数学算法…

151、【动态规划】AcWing ——2. 01背包问题:二维数组+一维数组(C++版本)

题目描述 原题链接&#xff1a;2. 01背包问题 解题思路 &#xff08;1&#xff09;二维dp数组 动态规划五步曲&#xff1a; &#xff08;1&#xff09;dp[i][j]的含义&#xff1a; 容量为j时&#xff0c;从物品1-物品i中取物品&#xff0c;可达到的最大价值 &#xff08;2…

ChatGPT入门系列(一)——注册

ChatGPT入门教程最近一段时间&#xff0c;OpenAI发布的ChatGPT聊天机器人太火了&#xff0c;连着上了各个平台的热搜榜。这个聊天机器人最大的特点是模仿人类说话风格&#xff0c;同时回答各种问题。有人说ChatGPT是真正的人工智能&#xff0c;它不仅能和你聊天&#xff0c;还是…

我的企业需要一个网站吗?答案是肯定的 10 个理由

如果您的企业在没有网站的情况下走到了这一步&#xff0c;您可能会想&#xff1a;我的企业需要一个网站吗&#xff1f;如果我的企业没有一个就已经成功了&#xff0c;那又有什么意义呢&#xff1f;简短的回答是&#xff0c;现在是为您的企业投资网站的最佳或更重要的时机。网站…

C/C++排序算法(二) —— 选择排序和堆排序

文章目录前言1. 直接选择排序&#x1f351; 基本思想&#x1f351; 具体步骤&#x1f351; 具体步骤&#x1f351; 动图演示&#x1f351; 代码实现&#x1f351; 代码升级&#x1f351; 特性总结2. 堆排序&#x1f351; 向下调整算法&#x1f351; 任意树调整为堆的思想&#…

复现篇--zi2zi

intro: 用GAN学习东亚语言字体。zi2zi(意思是从字符到字符)是最近流行的pix2pix模型在汉字上的应用和扩展。 article:https://kaonashi-tyc.github.io/2017/04/06/zi2zi.html code:https://github.com/kaonashi-tyc/zi2zi pytorch版本:https://github.com/EuphoriaYan/zi2…