原生js操作图片缩放,但是transformorigin变化时图片会发生位移,如何解决

zzzl124 2023-04-01 17:05:59
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<meta name="viewport"
			content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
		<title></title>
		<script src="js/mui.min.js"></script>
		<link href="css/mui.min.css" rel="stylesheet" />
		<script type="text/javascript" charset="utf-8">
			mui.init();
		</script>
		<style>
			#image{
				will-change: transform;

			}
		</style>
	</head>
	<body>
		<div style="height: 300px;">
		</div>
		<div id="container" style="align-items: center;">
			<img id="image" style="border: 1px solid red;width: 100%;" 
				src="https://www.akailibrary.com/wp-content/uploads/2020/05/1589443043-3784896.jpg" alt="">
		</div>
	</body>  
	<style>
		#image{
			translate: 0;
		}
	</style>
	<script>
		var isTouch = false; //点击
		var isDoubleTouch = false; //是否为多触点   
		var start = []; //存放触点坐标
		var timer = null;
		var now, delta; //当前时间,两次触发事件时间差
		var startPosition, movePosition, endPosition; //滑动起点,移动,结束点坐标
		//事件声明
		var gesturestart = new CustomEvent('gesturestart');
		var gesturechange = new CustomEvent('gesturechange');
		var gestureend = new CustomEvent('gestureend');
		var swipeMove = new CustomEvent('swipeMove');
		var doubleTouch = new CustomEvent("doubleTouch");
		var doubleTouchReduce = new CustomEvent("doubleTouchReduce");
		let dbcl = 1;//设置双击退出和进入的
		let slsc;//设置滑动放大时的位置
		let trso;//放大起源
		let sc;
		var store = {
			scale: 1
		}; 
		var image = document.getElementById('image');
		//监听touchstart事件
		image.addEventListener('touchstart', function(e) {
			if (e.touches.length >= 2) { //判断是否有两个点在屏幕上
				console.log('两个点在屏幕上');
				isDoubleTouch = true;
				start = e.touches; //得到第一组两个点  闹钟电脑 126... 83...
				console.log('tMatrix[0]',parseFloat(tMatrix[0]));
				
				//  if(tMatrix[0]>1){  
				// 		let rect = image.getBoundingClientRect();
				// 		let left = -rect.left;
				// 		let top = rect.top;
				// 		//第1个点x总长
				// 		let fzcx = e.touches[0].pageX + left;
				// 		//第1个点x相对缩小
				// 		let fxdsx = fzcx/tMatrix[0].toFixed(2)
				// 		console.log('一样的大小',fxdsx);
				// 		//第2个点x总长
				// 		let szcx = e.touches[1].pageX + left;
				// 		//第2个点x相对缩小
				// 		let sxdsx = szcx/tMatrix[0].toFixed(2)
				// 		console.log('一样的大小',sxdsx);
				// 		let top1;
				// 		let fzcy;
				// 		let fxdsy;
				// 		let szcy;
				// 		let sxdsy;
				// 		if(top<0){ 
				// 			 top1 = -top;
				// 			 fzcy = e.touches[0].pageY + top1;
				// 			 fxdsy = fzcy/tMatrix[3].toFixed(2)
				// 			 szcy = e.touches[1].pageY + top1;
				// 			 sxdsy = szcy/tMatrix[3].toFixed(2)
				// 		}else{
				// 			 fzcy = e.touches[0].pageY - top;
				// 			 fxdsy = fzcy/tMatrix[3].toFixed(2)
				// 			 szcy = e.touches[1].pageY - top;
				// 			 sxdsy = szcy/tMatrix[3].toFixed(2)
				// 		} 
				// 		var screenMinPoint1 = getMidpoint1(fxdsx,fxdsy,sxdsx,sxdsy); //获取两个触点中心坐标
				// 		console.log('放大一次后的放大中点',screenMinPoint1)
				// 		gesturestart.midPoint = screenMinPoint1;
				// 		e.target.dispatchEvent(gesturestart);  
				// }else{
					 
					var screenMinPoint = getMidpoint(start[0], start[1]); //获取两个触点中心坐标
					let dycfdzd = [screenMinPoint[0] - e.target.offsetLeft, screenMinPoint[1] - e.target.offsetTop]
					console.log('第一次放大的中点',dycfdzd);
					gesturestart.midPoint = [screenMinPoint[0] - e.target.offsetLeft, screenMinPoint[1] - e.target.offsetTop]; //获取中心点坐标相对目标元素坐标
					e.target.dispatchEvent(gesturestart);  
					
					
				// }
			} else {
				// console.log('一个点在屏幕上');
				delta = Date.now() - now; //计算两次点击时间差
				// console.log('时间差',delta);
				now = Date.now(); 
				startPosition = [e.touches[0].pageX, e.touches[0].pageY]; //点击位置距离屏幕左侧距离,点击位置距离屏幕顶部距离
				// console.log('当前点击的在页面中的位置:',startPosition); 
				// console.log('点击的位置',startPosition[0]);
				
				// let rect = image.getBoundingClientRect();
				// let left = -rect.left;
				// console.log('left',left);
				// if(tMatrix[0]>1){
				// 		let wd = (left + e.touches[0].pageX)/tMatrix[0]; 
				// 		console.log('wd',wd)
						
				// }
			
				
			
						
				
				if (dbcl == 1) {
					if (delta > 0 && delta <= 250) { //双击事件
						// console.log('双击事件放大'); 
						//           clearTimeout(timer);
						doubleTouch.position = [e.touches[0].pageX - e.target.offsetLeft, e.touches[0].pageY - e
							.target.offsetTop
						];
						// console.log('点击位置距离当前所在盒子的距离',doubleTouch.position);
						e.target.dispatchEvent(doubleTouch);
						dbcl = 2;
					} else {
						// console.log('单击退出事件'); 
						// alert('11')
						//                 timer = setTimeout(function(){ //单击事件
						//             e.target.dispatchEvent(oneTouch);
						//          })
					}

				} else {

					if (delta > 0 && delta <= 250) { //双击事件
						// console.log('双击事件缩小');
						clearTimeout(timer);
						doubleTouch.position = [e.touches[0].pageX - e.target.offsetLeft, e.touches[0].pageY - e.target.offsetTop];
						// console.log('点击位置距离当前所在盒子的距离',doubleTouch.position);
						e.target.dispatchEvent(doubleTouchReduce);
						dbcl = 1;
					} else { //滑动事件
						//                 timer = setTimeout(function(){ //单击事件
						//             e.target.dispatchEvent(oneTouch);
						//          })
					}
				}
				isTouch = true;
			}
		}, false);




		//监听touchmove事件
		image.addEventListener('touchmove', function(e) {
			console.log('进入缩放');
			clearTimeout(timer);
			if (e.touches.length >= 2 && isDoubleTouch) { //手势事件
				console.log('缩放');
				var now = e.touches; //得到第二组两个点
				// console.log('now',now); 
				var scale = getDistance(now[0], now[1]) / getDistance(start[0], start[1]); //得到缩放比例
				// console.log('scale缩放比例', scale);
				// var rotation = getAngle(now[0], now[1]) - getAngle(start[0], start[1]); //得到旋转角度差
				gesturechange.scale = scale.toFixed(2);
				// gesturechange.rotation = rotation.toFixed(2);
				
				e.target.dispatchEvent(gesturechange);
			} else if (isTouch) {
				// movePosition = [e.touches[0].pageX, e.touches[0].pageY];
				// endPosition = movePosition;
				// movePosition = [movePosition[0] - startPosition[0], movePosition[1] - startPosition[1]];
				// startPosition = [e.touches[0].pageX, e.touches[0].pageY];
				// swipeMove.distance =[movePosition[0].toFixed(2) , movePosition[1].toFixed(2)];
				// e.target.dispatchEvent(swipeMove);
			}
		}, false);



		/* 两点的距离 */
		function getDistance(p1, p2) {
			var x = p2.pageX - p1.pageX,
				y = p2.pageY - p1.pageY;
			return Math.sqrt((x * x) + (y * y));
		};
		/* 获取中点 */
		function getMidpoint(p1, p2) {
			var x = (p1.pageX + p2.pageX) / 2,
				y = (p1.pageY + p2.pageY) / 2;
			return [x, y];
		}
		/* 获取中点2 */
		function getMidpoint1(x1,y1,x2,y2) {
			var x = (x1 + x2) / 2,
				y = (y1 + y2) / 2;
			return [x, y];
		}










		image.addEventListener('doubleTouch', gesture, false);
		image.addEventListener('doubleTouchReduce', gesture, false);
		image.addEventListener('gesturestart', gesture, false);
		image.addEventListener('gesturechange', gesture, false);
		var tMatrix = [1, 0, 0, 1, 0, 0]; //x缩放,无,无,y缩放,x平移,y平移

		function gesture(event) {
			switch (event.type) {
				case "doubleTouch":
					originLast = event.position;
					// console.log('点击位置距离当前所在盒子的距离',originLast);
					//transformOrigin变形原点,该属性只有在设置了transform属性的时候起作用
					image.style.transformOrigin = event.position[0] + "px " + event.position[1] + "px";
					console.log('进入双击',image.style.transformOrigin)
					tMatrix[0] = 4;
					tMatrix[3] = 4;
					//把数组分隔成字符串
					var temp = tMatrix.join(",");
					// console.log('temp',temp);
					//设置缩放或者3旋转啥的
					image.style.transform = "matrix(" + temp + ")";
					// console.log('image.style.transform',image.style.transform);
					// maxMove(); 
					break;
				case "doubleTouchReduce":
					// console.log('进入缩小');
					tMatrix[0] = 1;
					tMatrix[3] = 1;
					var temp = tMatrix.join(",");
					image.style.transform = "matrix(" + temp + ")";
					break;
					//监听 gesturestart 设置 变换中心	
				case "gesturestart":
					originLast = event.midPoint; 
					// console.log('originLast',originLast);
					 
					image.style.transformOrigin  = event.midPoint[0] + "px " + event.midPoint[1] + "px";
					image.style.translate = event.midPoint[0] + "px " + event.midPoint[1] + "px";
					// image.style.translate =  event.midPoint[0].toFixed(2) + "px " + event.midPoint[1].toFixed(2) + "px";
					// image.style.transformOrigin = 222.182 + "px " + 131.818 + "px";
					console.log('进入双击2',image.style.transformOrigin,image.style.translate);
					
					break; 
				case "gesturechange":  
					sc = parseFloat(event.scale);
					// image.style.transformOrigin = trso;
					if ( sc > 0.6) {
						tMatrix[0] = tMatrix[0] + sc - 1 > 1 && tMatrix[0] + sc - 1 < 10 ? tMatrix[0] + sc - 1 : tMatrix[0];
						// console.log('tMatrix[0]', tMatrix[0])
						tMatrix[3] = tMatrix[3] + sc - 1 > 1 && tMatrix[3] + sc - 1 < 10 ? tMatrix[3] + sc - 1 : tMatrix[3];
						// console.log('tMatrix[3]', tMatrix[3])
						var temp = tMatrix.join(",");  
						// console.log('temp',temp);
						image.style.transform = "matrix(" + temp + ")";
						console.log('image.style.transform',image.style.transform) 
						console.log('情况',tMatrix[0].toFixed(2) )
						image.style.transition = "transform 0.1s linear";
						slsc = 1; 
						// console.log('image.style.transformOrigin',image.style.transformOrigin);
					} else {
						tMatrix[0] = 1;
						console.log('tMatrix[0]', tMatrix[0])
						tMatrix[3] = 1;
						console.log('tMatrix[3]', tMatrix[3])
						var temp = tMatrix.join(",");
						image.style.transform = "matrix(" + temp + ")";
						image.style.transition = "transform 0.1s linear";
						
						// console.log('image.style.transformOrigin',image.style.transformOrigin);
					}
					dbcl = 2;
					break;
				
			}
		}

	</script>


</html>

 

...全文
690 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复
内容概要:本文介绍了一种用于电磁暂态(EMT)研究的第四类全变流器型风力发电系统的通用Simulink仿真模型,旨在构建一个能够准确反映实际风电系统动态特性的简化通用模型。该模型涵盖了风力机、传动链、发电机、全功率变流器及其控制策略等关键组成部分,重点突出系统在电网故障、风速波动等复杂工况下的动态响应能力,适用于风电并网电磁暂态分析、新型电力系统稳定性评估及高比例可再生能源接入场景的研究。模型设计兼顾准确性与仿真效率,便于研究人员快速搭建和调试,推动风电系统建模与控制技术的发展; 适合人群:具备一定电力系统理论基础和MATLAB/Simulink仿真能力,从事新能源发电、电力电子变换、风电并网控制及相关方向的研究生、科研人员及工程技术人员; 使用场景及目标:①开展风电系统在电网扰动下的电磁暂态仿真分析;②研究全功率变流器风电机组的动态行为与控制特性;③支撑新型电力系统中高渗透率风电接入的稳定性与电能质量评估,服务于学术研究、课程教学与工程项目前期仿真验证; 阅读建议:建议读者结合文中提供的模型结构与参数设置,在Simulink环境中动手复现并调试仿真模型,通过设置不同运行工况(如三相短路、低电压穿越、风速突变等)观察系统响应,深入理解全变流器风电机组的建模方法、控制逻辑与动态特性,进而拓展应用于更复杂的多机并网或综合能源系统仿真场景。
源码下载地址: https://pan.quark.cn/s/d18200fd2664 在基于Ubuntu的系统中,针对TCP与UDP网络进行排错对于开发人员及系统维护者而言是日常工作中的关键环节。为了能够迅速地识别并解决网络层面的故障,挑选出合适的辅助工具显得尤为必要。提及的"适用于ubuntu的TCP/UDP排错资源"很可能是指向`mNetAssist`这款应用,从压缩文件清单中包含一个名为`mNetAssist-released.deb`的条目来看,这通常表明该文件是为Debian或Ubuntu平台设计的软件安装包。`mNetAssist`作为一个功能全面的网络监控与排错软件,能够协助用户对TCP/IP网络连接进行检测、剖析以及调试。接下来,我们将对这款软件的各项特性以及其在Ubuntu系统上的安装与运用方法进行详尽的阐述。 为了部署`mNetAssist`,首先需要确认Ubuntu系统已经更新至最新状态,并且已经配置了`apt`软件包管理机制。在终端界面中输入下列指令来执行软件包的安装流程: ```bash sudo apt update sudo apt install dpkg ``` 接着,将`mNetAssist-released.deb`软件包文件传输到Ubuntu系统的某个文件夹内,例如`~/Downloads`目录,随后利用`dpkg`指令进行安装操作: ```bash cd ~/Downloads sudo dpkg -i mNetAssist-released.deb ``` 在安装阶段若遭遇依赖性难题,可能需要借助`apt-get`来处理: ```bash sudo apt-get install -f ``` 完成安装后,用户可以通...
内容概要:本文探讨了Hash算法在芯片行业,特别是网络处理器(NPU)中的性能优化实践,聚焦于如何通过硬件流水线设计实现纳秒级高速哈希查找。文章分析了传统软件哈希方案在高带宽场景下的局限性,提出基于硬件描述语言或高层次综合(HLS)的设计方法,采用CRC32等硬件友好型哈希函数、并行多路哈希、流水线化解耦以及双端口存储结构等核心技术,实现低延迟、无阻塞的数据包处理。通过C++风格的HLS代码示例,展示了从算法选择到资源优化的完整硬件加速逻辑,并深入剖析了循环展开、位宽控制、内存映射和流水线调度等关键实现细节。最后展望了可编程交换机、P4语言支持及TCAM与哈希混合架构等未来发展方向。; 适合人群:具备数字电路基础、熟悉Verilog/SystemVerilog或HLS的芯片设计工程师,以及从事网络芯片、FPGA加速、高性能路由设备研发的技术人员(工作年限1-5年为宜);也适合对硬件加速算法感兴趣的研究人员。; 使用场景及目标:①掌握如何将哈希算法高效映射到硬件逻辑中以满足线速转发需求;②理解流水线设计、资源约束优化、读写冲突规避等在实际芯片项目中的应用;③为开发高性能网络处理器中的流表/路由表查找单元提供技术参考与实现范例。; 阅读建议:学习应结合HLS工具(如Xilinx Vitis HLS)进行代码仿真与综合,重点关注#pragma指令对硬件结构的影响,并对比不同哈希算法在资源占用与序表现上的差异,深入理解“空间换间”的硬件优化本质。
内容概要:本文系统研究了基于粒子群优化(PSO)、灰狼优化(GWO)、鲸鱼优化(WOA)、哈里斯鹰优化(HHO)、蜣螂优化(DBO)和麻雀搜索算法(SSA)六种智能优化算法在无人机三维路径规划中的应用,并在Matlab平台上实现了相应的仿真代码。研究构建了复杂的三维地形与障碍物环境模型,设计了包含路径长度、飞行间、能耗及安全性等多维度的成本函数,通过定义合理的适应度函数与飞行约束条件,对各类算法的路径搜索能力、收敛速度与规划质量进行了全面对比分析。通过仿真实验验证了各算法在静态复杂环境下的性能表现,旨在为实际无人机任务中优化算法的选择提供科学依据和技术支持。; 适合人群:具备一定Matlab编程基础,从事智能优化算法、无人机路径规划、自动化控制及相关领域研究的研究生、科研人员或工程技术人员。; 使用场景及目标:① 掌握主流群智能优化算法在无人机三维路径规划中的建模与实现方法;② 对比分析不同算法在相同复杂环境下的性能差异,为算法选型提供量化依据;③ 为后续研究动态环境路径规划、多无人机协同任务分配等问题奠定理论与技术基础; 阅读建议:建议读者结合提供的Matlab代码逐模块分析算法实现流程,重点关注适应度函数的设计、障碍物规避策略的实现以及多目标成本函数的权衡机制,同可通过调整参数设置或引入新型优化算法进行扩展实验,以深化对算法性能的理解与实际应用能力。

15,976

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 界面
社区管理员
  • 界面
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧