Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/411.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 画布中的图像在平移时留下平铺轨迹_Javascript_Canvas - Fatal编程技术网

Javascript 画布中的图像在平移时留下平铺轨迹

Javascript 画布中的图像在平移时留下平铺轨迹,javascript,canvas,Javascript,Canvas,我正在尝试创建一个可平移的图像查看器,它也允许放大。如果缩放因子或图像大小使得图像不再在整个画布上绘制,那么我希望画布上不包含指定背景颜色的图像的区域 我当前的实现允许缩放和平移,但会产生一种不必要的效果,即在平移操作过程中,图像会在其后面留下一条平铺轨迹(很像windows纸牌游戏中赢得游戏时的纸牌)。如何清理画布,使图像不会留下痕迹,背景矩形不会在画布中正确渲染 若要重新创建不需要的效果,请将放大设置为显示深灰色背景的某个级别,然后使用鼠标平移图像(鼠标向下拖动) 下面添加了代码片段和Pln

我正在尝试创建一个可平移的图像查看器,它也允许放大。如果缩放因子或图像大小使得图像不再在整个画布上绘制,那么我希望画布上不包含指定背景颜色的图像的区域

我当前的实现允许缩放和平移,但会产生一种不必要的效果,即在平移操作过程中,图像会在其后面留下一条平铺轨迹(很像windows纸牌游戏中赢得游戏时的纸牌)。如何清理画布,使图像不会留下痕迹,背景矩形不会在画布中正确渲染

若要重新创建不需要的效果,请将放大设置为显示深灰色背景的某个级别,然后使用鼠标平移图像(鼠标向下拖动)

下面添加了代码片段和Plnkr链接,供那些想在那里混日子的人使用。


帆布{
边框:实心5px#333;
}
+
-
var canvas=document.getElementById('canvas1');
var context=canvas.getContext(“2d”);
var-imageDimensions={宽度:0,高度:0};
var photo=新图像();
var isDown=假;
var startCoords=[];
var last=[0,0];
var windowWidth=canvas.width;
var windowHeight=canvas.height;
var量表=1;
photo.addEventListener('load',eventPhotoLoaded,false);
photo.src=”http://www.html5rocks.com/static/images/cors_server_flowchart.png";
函数eventPhotoLoaded(e){
imageDimensions.width=photo.width;
imageDimensions.height=photo.height;
纱窗();
}
函数转换比例(增量){
标度+=三角洲;
纱窗();
}
函数drawScreen(){
fillRect(0,0,windowWidth,windowHeight);
context.fillStyle=“#333”;
drawImage(照片,0,0,图像尺寸。宽度*比例,图像尺寸。高度*比例);
}
canvas.onmousedown=函数(e){
isDown=真;
startCoords=[
e、 offsetX-上一个[0],
e、 offsetY-最后一个[1]
];
};
canvas.onmouseup=函数(e){
isDown=假;
最后=[
e、 offsetX-StartWord[0],//设置最后一个坐标
e、 offsetY-StartWord[1]
];
};
canvas.onmousemove=函数(e)
{
如果(!isDown)返回;
var x=e.offsetX;
变量y=e.offsetY;
setTransform(1,0,0,1,
x-星字[0],y-星字[1];
纱窗();
}

您需要重置转换

添加
context.setTransform(1,0,0,1,0,0)在清除画布之前,这将解决您的问题。它将当前变换设置为默认值。然后在绘制图像之前,设置图像的变换

更新: 当与用户输入(如鼠标或触摸事件)交互时,应独立于渲染进行处理。渲染每帧仅触发一次,并对上一次刷新间隔期间发生的任何鼠标更改进行视觉更改。如果不需要,则不进行渲染

如果不需要,请不要使用“保存和还原”

var canvas=document.getElementById('canvas1');
var ctx=canvas.getContext(“2d”);
var photo=新图像();
var mouse={}
mouse.lastY=mouse.lastX=mouse.y=mouse.x=0;
mouse.down=false;
var=true;
var量表=1;
var-imageX=0;
var-imageY=0;
photo.src=”http://www.html5rocks.com/static/images/cors_server_flowchart.png";
函数转换比例(增量){
标度+=三角洲;
更改=正确;
}
//如果有其他鼠标事件处理程序,则在移出时打开鼠标按钮以防止鼠标按钮锁定。
函数mouseEvents(event){//在一个函数中完成所有操作
if(event.type==“mouseup”| | event.type==“mouseout”){
mouse.down=false;
更改=正确;
}否则
如果(event.type==“mousedown”){
mouse.down=true;
}
mouse.x=event.offsetX;
mouse.y=event.offsetY;
如果(鼠标按下){
更改=正确;
}
}
canvas.addEventListener(“mousemove”,mouseEvents);
canvas.addEventListener(“mouseup”,mouseEvents);
canvas.addEventListener(“mouseout”,mouseEvents);
canvas.addEventListener(“mousedown”,mouseEvents);
函数更新(){
requestAnimationFrame(更新);
如果(photo.complete&&changed){
setTransform(1,0,0,1,0,0);
ctx.fillStyle=“#333”;
ctx.fillRect(0,0,canvas.width,canvas.height);
如果(鼠标按下){
imageX+=mouse.x-mouse.lastX;
imageY+=mouse.y-mouse.lastY;
}
setTransform(scale,0,0,scale,imageX,imageY);
ctx.drawImage(照片,0,0);
更改=错误;
}
mouse.lastX=mouse.x
mouse.lastY=mouse.y
}
requestAnimationFrame(更新)
画布{
边框:实心5px#333;
}
+-

调用
context.save
在调用
context.fillRect
之前保存转换矩阵。 然后,无论何时需要绘制图像,都可以调用
context.restore
来还原矩阵

例如:

function drawScreen(){
    context.save();
    context.fillStyle="#333333";
    context.fillRect(0,0, windowWidth, windowHeight);
    context.restore();
    context.drawImage(photo,0,0,imageDimensions.width*scale,imageDimensions.height*scale);
  }
此外,要进一步优化,只需设置一次
fillStyle
,直到更改画布的大小。

Nice code;)

您正在演示中看到“平铺”效果,因为您正在绘制缩放图像
  function clearCanvas() {
      context.clearRect(0, 0, canvas.width, canvas.height);
  }
  canvas.onmousemove = function(e) {
      if(!isDown) return;

      var x = e.offsetX;
      var y = e.offsetY;

      /* !!! */
      clearCanvas();
      context.save();

      context.setTransform(
         1, 0, 0, 1,
         x - startCoords[0], y - startCoords[1]
      );

      drawScreen();
  }
function drawScreen() {
    context.fillRect(0,0, windowWidth, windowHeight);
    context.fillStyle="#333333";
    context.drawImage(photo,0,0,imageDimensions.width*scale,imageDimensions.height*scale);
    /* !!! */
    if (isDown) context.restore();
}