HTML 纯js不失真放大缩小拖拽canvas

本文详细介绍了如何使用纯JavaScript在canvas上实现动态的放大、缩小和拖拽功能,包括鼠标滚轮操作、拖动及图像更换等交互效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

纯js不失真放大缩小拖拽canvas

视频




<div id="canvasrr" style="
 width: 100%;
 height: 100%;
"><canvas></canvas></div>
<script>
// //绑定canvas画布工具
var canvas_set=function(div_id){
  //获取画布对象
  let div_obj=document.getElementById(div_id);
  //获取canvas对象
  let canvas_obj=div_obj.firstChild
  //为canvas对象创建css:用来控制canvas对象的大小
  let canvas_obj_class_name=div_id+'_canvas_class'//定义css类名
  canvas_obj.className=canvas_obj_class_name//赋值类名
  canvas_obj.style.width='100%'
  canvas_obj.style.height='100%'
  canvas_obj.style.position='absolute'
  canvas_obj.style.top='0px'
  canvas_obj.style.left='0px'

  let data_obj={};
  
  data_obj.img = new Image();
  data_obj.div=div_obj
  data_obj.className=canvas_obj_class_name;
  data_obj.canvas=canvas_obj
  data_obj.scale=1;//当前canvas的缩放比例
  data_obj.minScale=0.05;//scale的最小缩放比例
  data_obj.maxScale=100;//scale的最大缩放比例
  data_obj.startX=0;//鼠标滚动操作的时候的x值
  data_obj.startY=0;//鼠标滚动操作的时候的y值
  data_obj.temp_start_x=0//鼠标左击按下操作的时候鼠标的x值
  data_obj.temp_start_y=0;//鼠标左击按下操作的时候鼠标的y值
  data_obj.offsetx=0//鼠标左击按下操作的时候鼠标偏移的x值
  data_obj.offsety=0;//鼠标左击按下操作的时候鼠标偏移的y值
  data_obj.mousedown_flag=false;//鼠标是否按下操作
  data_obj.x_val=0;//鼠标历史拖动x轴的值
  data_obj.y_val=0;//鼠标历史拖动y轴的值
  //判断是否已经创建了这个style节点
  let styleobj_id=div_id+'_canvas_style_id'
  if (document.getElementById(styleobj_id)==null){
    let styleobj = document.createElement('style');//创建style节点
    styleobj.innerHTML=`
    .${data_obj.className} { 
    transform: scale(1.0);
    } `;//设置初始放大倍数为1.0
    document.getElementsByTagName('head')[0].appendChild(styleobj)//将刚才创建的节点添加进<head>节点内
        styleobj.id=styleobj_id;
    data_obj.styleobj=styleobj
  }else{
    let styleobj = document.getElementById(styleobj_id);
    data_obj.styleobj=styleobj
  }
  let ctx = canvas_obj.getContext('2d');
  data_obj.ctx=ctx;

  //绑定绘画函数
  let draw_img=fangdasuoxiaohuabu_draw_img(data_obj)
  data_obj.draw_img=draw_img

  //绑定按下鼠标左键函数
  let mousedown=fangdasuoxiaohuabu_mousedown(data_obj)
  data_obj.mousedown=mousedown
  data_obj.div.addEventListener('mousedown', mousedown);
  //绑定鼠标移动函数
  let mousemove=fangdasuoxiaohuabu_mousemove(data_obj)
  data_obj.mousemove=mousemove
  data_obj.div.addEventListener('mousemove', mousemove);
  //绑定释放鼠标键函数
  
  let mouseup=fangdasuoxiaohuabu_mouseup(data_obj)
  data_obj.mouseup=mouseup
  data_obj.div.addEventListener('mouseup', mouseup);
  //绑定鼠标滚轮操作函数
  let handleScroll=fangdasuoxiaohuabu_handleScroll(data_obj)
  data_obj.handleScroll=handleScroll
  data_obj.div.addEventListener('wheel', handleScroll);
  //绑定点击canvas修改图片函数:弹框输入地址
  let changeimg=fangdasuoxiaohuabu_changeimg(data_obj)
  data_obj.changeimg=changeimg
  ///绑定点击canvas修改图片函数:传参输入地址
  let changeimg2=fangdasuoxiaohuabu_changeimg2(data_obj)
  data_obj.changeimg2=changeimg2
  //绑定重置函数
  let reset=fangdasuoxiaohuabu_reset(data_obj)
  data_obj.reset=reset
  //绑定点击鼠标右键函数 div
  let contextmenu2=fangdasuoxiaohuabu_contextmenu2(data_obj)
  data_obj.contextmenu=contextmenu2
  data_obj.div.addEventListener('contextmenu',contextmenu2)
  //绑定点击鼠标右键函数 canvas
  let contextmenu=fangdasuoxiaohuabu_contextmenu(data_obj)
  data_obj.contextmenu=contextmenu
  data_obj.canvas.addEventListener('contextmenu',contextmenu)
  
return data_obj
  }
  function fangdasuoxiaohuabu_draw_img(data_obj){
    let now_data_obj=data_obj;
    let res_func=function(e){
      //清空画布
      now_data_obj.ctx.clearRect(0, 0, now_data_obj.canvas.width, now_data_obj.canvas.height);
      //放大画布
      now_data_obj.styleobj.innerHTML=`
    .${data_obj.className} { 
    transform: scale(${data_obj.scale});
    } `;
console.log('fangdasuoxiaohuabu_draw_img',now_data_obj.scale)
    // let parentNode = canvas.parentNode;
    // canvas.width =parseInt( parentNode.offsetWidth ); // 实际渲染像素
    // canvas.height = parseInt(parentNode.offsetHeight ); // 实际渲染像素
    // console.log('画布大小:','height:',canvas.width,'width:', canvas.height)
    // canvas.style.height='100%'//`${100/scale}%`//parseInt(parentNode.offsetHeight/scale)// 获取父节点的高度/scale
    // canvas.style.width='100%'//`${100/scale}%`//parseInt(parentNode.offsetWidth/scale);// 获取父节点的宽度
    // canvas.style.top=200-parseInt(parentNode.offsetHeight/scale)/2;// 获取父节点的宽度
    // canvas.style.left=200-parseInt(parentNode.offsetWidth/scale)/2;// 获取父节点的宽度
    
    //这个函数在canvas上绘制图像。在此处,img是一个图像对象,-img.width / 2和-img.height / 2是图像放置的位置。
    // console.log(now_img_info['x'],now_img_info.y,-img.width / 2,-img.height / 2)
    // ctx.draw_img(img, -img.width / 2+now_img_info.x, -img.height / 2+now_img_info.y);
    // ctx.draw_img(img, -img.width / 2-now_img_info.x, -img.height / 2-now_img_info.y);
    
// 绘制缩放后的图形
now_data_obj.ctx.drawImage(now_data_obj.img,0,0);
    }
    return res_func
  }

//绑定鼠标滚动操作的函数
function fangdasuoxiaohuabu_handleScroll(data_obj){
    let now_data_obj=data_obj;
    let res=function(e) {
    e.preventDefault();//阻止默认事件
    data_obj.scale += 0.1 * (e.deltaY < 0 ? 1 : -1);
    if(data_obj.scale < data_obj.minScale) data_obj.scale = data_obj.minScale;
    if(data_obj.scale > data_obj.maxScale) data_obj.scale = data_obj.maxScale;
    data_obj.startX = e.clientX; // 记录鼠标按下的位置
    data_obj.startY = e.clientY;
    // console.log(e.deltaY,startX,startY)
    data_obj.draw_img();
    
}
return res
}

//绑定鼠标左键按下操作的函数
function fangdasuoxiaohuabu_mousedown(data_obj){
    let now_data_obj=data_obj;
let res =function(e) {
    now_data_obj.mousedown_flag = true; // 开始拖动canvas
    now_data_obj.temp_start_x = e.clientX; // 记录鼠标按下的位置
    now_data_obj.temp_start_y = e.clientY;
    now_data_obj.offsetx = now_data_obj.canvas.offsetLeft; // canvas的偏移量
    now_data_obj.offsety = now_data_obj.canvas.offsetTop;
}
return res
}
//绑定鼠标移动操作的函数
function fangdasuoxiaohuabu_mousemove(data_obj){
    let now_data_obj=data_obj;
let res=function(e) {
    if (!now_data_obj.mousedown_flag) return; // 如果未开始拖动,则返回
    var dx =  parseInt((1/data_obj.scale)*(data_obj.temp_start_x-e.clientX)) ; // 计算鼠标移动的距离
    var dy =  parseInt((1/data_obj.scale)*(data_obj.temp_start_y-e.clientY));
    var dx =  parseInt(1*(data_obj.temp_start_x-e.clientX)) ; // 计算鼠标移动的距离
    var dy =  parseInt(1*(data_obj.temp_start_y-e.clientY));
    // console.log('dx:',dx,'(1/scale):',(1/scale))
    // console.log('temp_start_y,e.clientY',temp_start_y,e.clientY)
    data_obj.temp_start_y=e.clientY
    // console.log('temp_start_y,e.clientY',temp_start_y,e.clientY)
    data_obj.temp_start_x=e.clientX
    // console.log('dx:',dx)
    data_obj.x_val= data_obj.x_val+dx
    data_obj.y_val= data_obj.y_val+dy
    // console.log('now_img_info.x  :',now_img_info.x)
    data_obj.canvas.style.left = -data_obj.x_val + 'px'; // 更新canvas的left属性,注意此处应为相对于窗口的偏移量
    data_obj.canvas.style.top = -data_obj.y_val + 'px'; // 更新canvas的top属性,注意此处应为相对于窗口的偏移量
    data_obj.startX = e.clientX; // 更新鼠标的位置
    data_obj.startY = e.clientY;
    data_obj.draw_img(); // 重新绘制canvas上的内容
}
return res
}
//绑定鼠标左键按下后释放的操作函数
function fangdasuoxiaohuabu_mouseup(data_obj){
    let now_data_obj=data_obj;
let res=function(e) {
    now_data_obj.mousedown_flag = false; // 停止拖动canvas
    now_data_obj.startX = null; // 清空鼠标的位置
    now_data_obj.startY = null;
    now_data_obj.offsetX = null; // 清空canvas的偏移量
    now_data_obj.offsetY = null;
    now_data_obj.temp_start_x;
    now_data_obj.temp_start_y;
    now_data_obj.draw_img(); // 重新绘制canvas上的内容
};
return res
}
//弹出对话框输入图片路径
function fangdasuoxiaohuabu_changeimg(data_obj){
    let now_data_obj=data_obj;
let res=function() {
    data_obj.img.src = prompt("请输入新的图片URL:");
    now_data_obj.reset()
}
    return res
}

//传入图片路径修改
function fangdasuoxiaohuabu_changeimg2(data_obj){
    let now_data_obj=data_obj;
let res=function(data) {
    data_obj.img.src = data;
    now_data_obj.reset()
}
    return res
}
//重置参数
function fangdasuoxiaohuabu_reset(data_obj){
    let now_data_obj=data_obj;
let res=function() {
  data_obj.scale=1;//当前canvas的缩放比例
  data_obj.minScale=0.05;//scale的最小缩放比例
  data_obj.maxScale=100;//scale的最大缩放比例
  data_obj.startX=0;//鼠标滚动操作的时候的x值
  data_obj.startY=0;//鼠标滚动操作的时候的y值
  data_obj.temp_start_x=0//鼠标左击按下操作的时候鼠标的x值
  data_obj.temp_start_y=0;//鼠标左击按下操作的时候鼠标的y值
  data_obj.offsetx=0//鼠标左击按下操作的时候鼠标偏移的x值
  data_obj.offsety=0;//鼠标左击按下操作的时候鼠标偏移的y值
  data_obj.mousedown_flag=false;//鼠标是否按下操作
  data_obj.x_val=0;//鼠标历史拖动x轴的值
  data_obj.y_val=0;//鼠标历史拖动y轴的值
  data_obj.draw_img();

}
    return res
}
//鼠标右击  canvas右击
function fangdasuoxiaohuabu_contextmenu(data_obj){
    let now_data_obj=data_obj;
let res=function(e) {
  e.preventDefault(); // 阻止默认的上下文菜单
  alert('Right-click detected at ' + e.clientX + ',' + e.clientY);
  
}
    return res
}
//鼠标右击2 div右击
function fangdasuoxiaohuabu_contextmenu2(data_obj){
    let now_data_obj=data_obj;
let res=function(e) {
  e.preventDefault(); // 阻止默认的上下文菜单
  alert('Right-click detected at ' + e.clientX + ',' + e.clientY);
  
}
    return res
}

  var test=canvas_set('canvasrr')
    test.img.src = 'C:\\Users\\Administrator.BF-202310091844\\Desktop\\ddd.jpg'
    test.img.onload = test.draw_img;
</script>
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值