Javascript Canvas:在给定坐标上应用缩放 [英] Javascript Canvas : Apply zoom at given coordinates

查看:181
本文介绍了Javascript Canvas:在给定坐标上应用缩放的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在努力使用Vanilla Javascript实现画布缩放(在鼠标滚轮上),但没有成功。



缩放必须应用于的坐标滚轮时鼠标。
之前有人问过,但是考虑到我不能使用 canvasContext.translate 和<$ c的值,我的处境大不相同。 $ c> offsetX 和 offsetY 必须保留其绝对表示形式(未缩放)



我真的很感谢。



在以下代码段中,我提供了当前的和功能失常的实现。当您放大和缩小以保持相同的缩放坐标时,您将看到它的工作原理,但是,一旦将鼠标移至新坐标(当scale = 1时)并继续缩放,新的偏移就会变为错误。



  //启动变量:canvas ref,offsets,scale ... const context = document。 getElementById('c')。getContext('2d'); let scale = 1; let scaleFactor = 0.2; let offsetX = 0; let offsetY = 0; //处理mousenwheel zoomcontext.canvas.onwheel = function(e){e .preventDefault(); //计算比例方向6新值let direction = e.deltaY> 0? 1:-1;比例+ = scaleFactor *方向; //计算新的偏移量(未缩放值)offsetX = e.offsetX-(e.offsetX / scale); offsetY = e.offsetY-(e.offsetY / scale); //应用新的比例尺context.setTransform(1,0,0,1,0,0); context.scale(scale,scale);} //清除画布并绘制两个框//此功能不能做任何更改。函数render(){context.beginPath(); context.clearRect(0,0,context.canvas.width / scale,context.canvas.height / scale); context.rect(100-offsetX,50-offsetY,50,50); context.rect(200-offsetX,50-offsetY,50,50); context.stroke(); document.getElementById( info)。innerHTML =`比例尺:$ {scale}< br>报价:$ {Math.round(offsetX)+’,’+ Math.round(offsetY)}< br> `; requestAnimationFrame(render);} render() 

 < canvas id = c width = 350 height = 150 style = border:1px纯红色;>< / canvas>< div id = info>< / div>  

解决方案

我终于明白了。 。不使用context.translate()即可画布任意坐标缩放。

我附上了我的解决方案,并附带了一点好处:画布平移(光标键滚动)。
我希望对某人有用。



  //初始化变量:canvas ref,offsets,scale ... const context = document.getElementById('c')。getContext('2d'); let scale = 1; let scaleFactor = 0.2; let scrollX = 0; let scrollY = 0; let info = document.getElementById( info); //处理mousenwheel zoomcontext.canvas.onwheel = function(e){e.preventDefault();让previousScale =比例; //计算比例尺方向6新的比例尺值let direction = e.deltaY> 0? 1:-1;比例+ = scaleFactor *方向; //计算新的滚动值scrollX + =(e.offsetX / previousScale)-(e.offsetX / scale); scrollY + =(e.offsetY / previousScale)-(e.offsetY / scale); //以非累积方式应用新比例尺。setTransform(1,0,0,1,0,0); context.scale(scale,scale);} //清除画布并绘制两个框。函数render(){context.beginPath(); context.clearRect(0,0,context.canvas.width / scale,context.canvas.height / scale); context.rect(100-scrollX,50-scrollY,50,50); context.rect(200-scrollX,50-scrollY,50,50); context.stroke(); info.innerHTML =`比例尺:$ {scale}< br>滚动:$ {scrollX},$ {scrollY}< br> `requestAnimationFrame(render);} //处理光标键以移动scrollwindow.onkeydown = function(event){event.preventDefault(); if(event.keyCode == 37)scrollX-= 10;否则if(event.keyCode == 39)scrollX + = 10;否则if(event.keyCode == 38)scrollY-= 10;否则if(event.keyCode == 40)scrollY + = 10;}; context.canvas.focus()render() 

 <画布id = c width = 400 height = 150 style = border:1px纯红色; tabindex = 1>< / canvas>< div id = info>< / div>  


I'm struggling with an implementation of canvas zooming (on mouse wheel), using Vanilla Javascript, without success.

The zoom must be applied on the coordinates of the mouse, when the wheel is rolled. It's been asked here before, but my situation is quite different, considering I can't use canvasContext.translate , and the values of offsetX and offsetY must be kept in its absolute representation (not scaled)

I would really appreciate some light.

In the following snippet, I provide my current and dysfunctional implementation. You will see how it works when you zoom in and out keeping the same zoom coordinates, but as soon as you move the mouse to new coordinates (when scale != 1)and continue zooming, the new offsets become wrong.

// initiate variabks : canvas ref, offsets, scale...
const context   = document.getElementById('c').getContext('2d');
let scale       = 1;
let scaleFactor = 0.2;
let offsetX=0;
let offsetY=0;

// Handle mousenwheel zoom
context.canvas.onwheel= function(e){
  e.preventDefault();
  // calculate scale direction 6 new value
  let direction = e.deltaY > 0 ? 1 : -1;
  scale += scaleFactor * direction;
  // calculatethe new offsets (unscaled values)
  offsetX = e.offsetX - (e.offsetX  / scale);
  offsetY = e.offsetY - (e.offsetY / scale);  
  // apply new scale
  context.setTransform(1, 0, 0, 1, 0, 0);
  context.scale(scale, scale);
}

// clear canvas and draw two boxes
// NO CHANGES CAN BE DONE IN THIS FUNCTION
function render(){
  context.beginPath();
  context.clearRect(0,0,context.canvas.width/scale,context.canvas.height/scale);
  context.rect(100-offsetX,50-offsetY,50,50);
  context.rect(200-offsetX,50-offsetY,50,50);
  context.stroke();
  
  document.getElementById("info").innerHTML=`
    Scale : ${scale} <br>
    Offets : ${ Math.round(offsetX) + ' , ' + Math.round(offsetY)} <br>
  `;
  requestAnimationFrame( render );
}
render()

<canvas id="c" width="350" height="150" style="border: 1px solid red;"></canvas>
<div id="info"></div>

解决方案

I finally got it... canvas arbitrary coordinates scaling without using context.translate()

I attach my solution, with a little bonus : canvas panning (cursor keys scrolling). I hope becomes useful to somebody.

// initiate variables : canvas ref, offsets, scale...
const context   = document.getElementById('c').getContext('2d');
let scale       = 1;
let scaleFactor = 0.2;
let scrollX     = 0;
let scrollY     = 0;

let info        = document.getElementById("info");


// Handle mousenwheel zoom
context.canvas.onwheel =  function(e){
  e.preventDefault();
  let previousScale= scale;
  
  // calculate scale direction 6 new scale value
  let direction = e.deltaY > 0 ? 1 : -1;
  scale += scaleFactor * direction;

  // calculate the new scroll values
  scrollX += ( e.offsetX / previousScale )  - (e.offsetX  / scale);
  scrollY += ( e.offsetY / previousScale ) - ( e.offsetY / scale);
  
  // apply new scale in a non acumulative way
  context.setTransform(1, 0, 0, 1, 0, 0);
  context.scale(scale, scale);
}


// clear canvas and draw two boxes
function render(){
  context.beginPath();
  context.clearRect(0,0,context.canvas.width/scale, context.canvas.height/scale);
  context.rect(100-scrollX,50-scrollY,50,50);
  context.rect(200-scrollX,50-scrollY,50,50);
  context.stroke();
  
  info.innerHTML=`
    Scale : ${scale} <br>
    Scroll: ${scrollX},${scrollY} <br>
  `
  requestAnimationFrame( render );
}

// handlencursor keys to move scroll
window.onkeydown = function(event){
    event.preventDefault();
    if(event.keyCode == 37)      scrollX -=10;
    else if(event.keyCode == 39) scrollX +=10;
    else if(event.keyCode == 38) scrollY -=10;
    else if(event.keyCode == 40) scrollY +=10;
};

context.canvas.focus()
render()

<canvas id="c" width="400" height="150" style="border: 1px solid red;" tabindex="1"></canvas>
<div id="info"></div>

这篇关于Javascript Canvas:在给定坐标上应用缩放的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆